ColPali 与视觉原生文档 RAG 本节摘要:传统 RAG 把 PDF 解析成文本、切块、嵌向量、存向量,每一步都丢信号:OCR 丢图表数据,切块打断表格行,文本嵌入忽略图。ColPali(Faysse 等人,2024 年 7 月)问了个更简单的问题:为什么非得抽文本?直接用 PaliGemma 嵌入页面图像,用 ColBERT 风格的晚交互做检索,保留文档携带的全部版面、图、字体、格式信号。发表基准:在视觉丰富的文档上,端到端精度比文本 RAG 高 2040%。ColQwen2、ColSmol、VisRAG 延伸了这个模式。本节读视觉原生 RAG 的论点,并搭一个微型 ColPali 式索引器。
本节摘要:传统 RAG 把 PDF 解析成文本、切块、嵌向量、存向量,每一步都丢信号:OCR 丢图表数据,切块打断表格行,文本嵌入忽略图。ColPali(Faysse 等人,2024 年 7 月)问了个更简单的问题:为什么非得抽文本?直接用 PaliGemma 嵌入页面图像,用 ColBERT 风格的晚交互做检索,保留文档携带的全部版面、图、字体、格式信号。发表基准:在视觉丰富的文档上,端到端精度比文本 RAG 高 20~40%。ColQwen2、ColSmol、VisRAG 延伸了这个模式。本节读视觉原生 RAG 的论点,并搭一个微型 ColPali 式索引器。
阅读完本节,你应当能够:
PDF 上的文本 RAG 丢掉了文档的大部分。财报的 Q3 营收增长通常在图表里;医学报告的发现标注在图像上;法律合同的签字区是版面事实,不是文本事实。
文本 RAG 流水线:
五步有损:图表没抓到,表格跨块被打断,多栏版面被拍平,图标注消失。
ColPali 的修法:跳过 OCR,直接嵌页面图像,用 ColBERT 风格的晚交互做检索,让模型在查询时关注细粒度 patch。
ColBERT(Khattab & Zaharia,arXiv:2004.12832)是一种文本检索方法。它不为每文档产一个向量,而是每 token 一个向量。查询时:
这就是 MaxSim 操作。每个查询 token「挑」自己最匹配的文档 token,总分是求和。
优点:召回强,处理 token 级语义。缺点:每文档 N_d 个向量,存储贵。
ColPali(Faysse 等人,arXiv:2407.01449)把 ColBERT 模式用到图像。
文档摄取时:用 PaliGemma 嵌每页,存全部 patch 嵌入。查询时:嵌查询 token,对所有已存页面嵌入算 MaxSim,返回 top-k。
优点:端到端在视觉丰富文档上比文本 RAG 高 20~40%,每个 patch 向量捕获局部版面与内容。缺点:每页 N_p patch × 4 字节 × D 维向量,存储增长快,靠 PQ/OPQ 量化缓解。
ColQwen2(illuin-tech,2024~2025)把 PaliGemma 换成 Qwen2-VL,基座编码器更好,检索更强。ColSmol 是本地/边缘用的小规模变体,约 10 亿参数的 ColSmol 检索器能在消费级 GPU 上跑。
VisRAG(Yu 等人,arXiv:2410.10594)是另一种变体:不在 patch 上做 MaxSim,而是用 VLM 把每页池化成单向量,再双编码器检索。索引更快、存储更小、召回更弱。
质量 vs 成本权衡:ColPali 要质量,VisRAG 要规模。
M3DocRAG(Cho 等人,arXiv:2411.04952)把多模态检索扩到多页多文档推理,跨文档检索页面,为 VLM 组合多页上下文。
ColPali 的配套基准,视觉文档检索评估。任务含财报、科学论文、行政文档、病历、手册,指标是 nDCG@5。
ColPali-v1 在 ViDoRe 上约 80% nDCG@5;同样文档上文本 RAG 约 50~60%。
视觉原生 RAG:
全程无 OCR,图、图表、字体、版面都流进答案。
50 页财报,每页 729 patch、128 维嵌入:
ColPali 每文档存储约 30 倍,大规模下 OPQ/PQ 压到约 5~10 倍,通常可接受。
2026 年其余一切——财报、科学论文、法律合同、病历、UX 文档——视觉原生 RAG 胜。
code/main.py:
def maxsim(query_tokens, page_patches): # query_tokens: (N_q, D), page_patches: (N_p, D), 均归一化 sims = query_tokens @ page_patches.T # (N_q, N_p) 余弦 return sum(sims.max(axis=1)) # 每查询 token 取最大, 求和 def retrieve(query, index, k=5): q_emb = encode_query_tokens(query) # (N_q, D) scores = [(page_id, maxsim(q_emb, patches)) for page_id, patches in index] return sorted(scores, key=lambda x: -x[1])[:k]
def ingest_page(page_image, page_id): patches = paligemma_encode(page_image) # (N_p, D) 每 patch 一向量 store(page_id, patches) # 缓存全部 patch 嵌入 # 无 OCR, 图表/字体/版面全保留
💡 MaxSim 为何强于均值:均值相似度把所有 patch 平均,淹没「这一小块恰好匹配查询关键词」的信号;MaxSim 让每个查询 token 精确找到自己最匹配的 patch 再求和,捕获 token 级语义,这是晚交互胜过双编码器的根源。
def vision_rag(query, index, vlm, k=3): top_k_pages = retrieve(query, index, k) # ColPali MaxSim page_images = [load_image(pid) for pid, _ in top_k_pages] return vlm.answer(query, page_images) # 图表/版面流进答案
工程取舍:视觉丰富文档要质量用 ColPali/ColQwen2;大规模要省存储用 VisRAG;多文档推理用 M3DocRAG;纯文本文档用文本 RAG 更简单。
本节产出 outputs/skill-vision-rag-designer.md。给定文档 RAG 项目,它在 ColPali/ColQwen2/VisRAG/文本 RAG 间选择并估算存储。
存储预算:200 页年报、每页 729 patch、128 维嵌入、4 字节浮点。算原始存储与 PQ 压缩(8×)存储。
MaxSim 增量:MaxSim 是 Σ_i max_j cos(q_i, p_j)。它捕获了什么简单均值相似度捕获不到的?
词级索引:ColPali 按页索引 patch 集。若改成按词索引(像 ColBERT),权衡是什么?
大规模流水线:为 100 万页语料、每查询 500ms 预算设计端到端流水线。选 ColQwen2 还是 VisRAG,论证。
读 M3DocRAG:读 M3DocRAG(arXiv:2411.04952),描述多页注意力模式,与单页 ColPali 检索有何不同。
下一节,我们将进入多模态 RAG 与跨模态检索——把视觉原生 RAG 推广到「用文本查图、用图查视频、用音频查文档」的任意跨模态检索,是企业知识库的未来形态。