假设你正在用 RAG 做一个企业知识库助手。用户问:"去年三季度销售报表里那张折线图,哪个月的增长率最高?" 你打开文档,答案就在那张 PNG 图里。但你的 RAG 管道只能检索文字,于是它只找到了图片周围的说明文字,然后把图片本身忽略了。用户得到一段答非所问的回复。

这个问题我踩过。最早我以为多模态 RAG 就是把图片转成文字,然后一切照旧。后来我发现,事情远没有这么简单——不同方案的信息保留量、检索精度、工程复杂度差距极大,选错方案,你的系统可能看起来能工作,但在真实场景里一戳就破。
多模态 RAG 到底在解决什么问题?
传统 RAG 的流程是:
- 把文档切块,用文本 embedding 向量化,存入向量库。
- 查询时把用户问题也变成向量,在库里找最相似的文本块。
- 把检索到的文本块拼进 prompt,让大模型生成答案。
这套流程默认了一个假设:所有知识都是文字。但现实世界的信息从来不是。一张流程图、一张发票扫描件、一段视频截图,它们的核心信息藏在视觉结构里,用文字描述会丢东西。
多模态 RAG 要做的事,就是让检索系统能够直接处理图像、视频这些非文本模态,或者至少在检索时利用它们的视觉特征,而不是只靠旁边的文字说明。
方案一:用 CLIP 把图文塞进同一个向量空间
我第一次听说 CLIP 的时候,觉得这思路简直天才。OpenAI 用 4 亿对图文数据训练了一个双塔模型:一个图像编码器、一个文本编码器,通过对比学习让匹配的图文对在向量空间里离得近,不匹配的离得远。训练完成后,图片和文本可以被映射到同一个向量空间。
这意味着你可以直接用文本查询去检索图片。比如把用户问题 "这张折线图里哪个月增长率最高" 编码成向量,然后和所有图片的向量做相似度计算,最接近的那张图就是答案。
实际落地时,你需要先把所有图片切成单独的文件,用 CLIP 的 image encoder 生成向量存进向量库。查询时用 text encoder 编码问题,然后做 ANN 检索。
但这里有一个坑:CLIP 理解的是图片的全局语义,它对颜色、形状、空间关系非常不敏感。你让它检索 "左上方有个红色圆圈的图",它大概率抓瞎。CLIP 擅长的是匹配 "这是一只猫" 和猫的照片,而不是理解复杂的视觉细节。
这意味着:如果你的文档里大多数是自然图片,CLIP 够用;但如果你的文档里有大量图表、界面截图、票据,CLIP 的表现会让你失望。
方案二:把图片“翻译”成文本,然后一切照旧
我最早想当然的方案就是这个:用 OCR 提取图片里的文字,再用一个图像描述模型(比如 BLIP)生成一段文字说明,然后把这段文字塞进原有 RAG 的文档切块流程里。查询时只做纯文本检索,命中后再把原图交给多模态大模型去回答。
这个方案的优点是显而易见的:工程改动极小,可以复用你已有的文本 embedding、向量库和检索链路。而且对于发票、PDF 扫描件这类以文字为主的内容,OCR 提取出来的文字几乎就是完整信息,效果很好。
缺点也很致命:图像描述模型生成的是 "概括性" 的文字,它不会描述每个像素的位置、颜色、字体大小。比如一张复杂的架构图,描述可能变成 "一张包含多个模块的架构图,有箭头连接"——这等于没说。你丢失了图表的精确结构,而结构往往才是答案。
这个方案适合什么场景?适合图片里的信息主要承载在文字上的情况。比如合同扫描件、PPT 截图、包含大段文字的流程图。如果你的图片信息承载在视觉元素上(折线的趋势、柱子的高低、图片中某个物体的位置),这个方案就不够。
方案三:用重排序模型弥补文本检索的瞎眼
既然纯文本检索会漏掉视觉信息,那不如先用文本检索拉回一堆候选,再用一个多模态模型对每个候选重新打分。这就是重排序(re-ranking)的思路。
具体做法是:第一阶段用传统的文本检索(比如基于 OCR 文本)快速召回 top 20 个候选图片;第二阶段把用户问题和候选图片一起喂给一个多模态交叉编码器(比如 CLIP 的变体,或者一个视觉语言模型如 LLaVA),让它输出一个相关性分数,按分数重新排序,取 top 3 送去给大模型生成。
这个方案的关键在于第二阶段的多模态模型真的能“看”图片,所以它能捕捉到纯文本检索遗漏的视觉线索。比如用户问 "哪个柱子最高",第一阶段的 OCR 文本里可能没有这个词,但第二阶段的视觉模型能看懂柱状图。
代价是延迟。多模态重排模型通常比文本相似度计算慢得多,每张候选图都要过一遍视觉编码器。如果你有 20 个候选,就要跑 20 次。所以这个方案通常作为精排,只用在小集合上。
方案四:让模型直接在图片上做检索——ColPali
如果你追求最原汁原味的视觉检索,我推荐你了解一下 ColPali。这是 2024 年的一篇论文,思路非常大胆:干脆放弃 OCR 和图像描述,直接让视觉语言模型把整页文档图像编码成一组 token 向量,查询时用每个 token 和文档的 token 做细粒度的匹配(late interaction)。
具体来说,ColPali 用了一个类似 LLaVA 的视觉语言模型,把一张文档图片切成若干 patch,每个 patch 编码成一个向量。查询文本也被编码成 token 向量。然后用 ColBERT 式的 late interaction 机制,计算每个查询 token 与所有文档 patch 的相似度,取最大值后求和,作为最终相关性分数。
这个方案的好处是:你不需要 OCR,不需要图像描述,文档里哪怕是一个像素级的细节(比如图表的斜率、某个按钮的位置)都能被保留在 patch 向量里。而且因为用的是视觉语言模型,它天然理解图文混合的版面。
缺点也很现实:计算量大。文档图片的 patch 数量比文本块多得多,索引体积和检索延迟都比纯文本高一个数量级。而且目前 ColPali 还在学术阶段,工具链不像传统 RAG 那么成熟,你需要自己搭不少工程。
一张表对比四种方案
| 方案 | 信息保留度 | 工程复杂度 | 检索延迟 | 适用场景 |
|---|---|---|---|---|
| CLIP 多模态嵌入 | 中等(全局语义) | 低 | 低 | 自然图片、通用概念 |
| OCR + 图像描述 | 依赖文字比例 | 极低 | 低 | 扫描件、文字型图表 |
| 多模态重排序 | 较高 | 中 | 中 | 对精度要求高的场景 |
| ColPali | 高(像素级) | 高 | 高 | 复杂版面、视觉细节关键的文档 |
我最早以为多模态 RAG 的瓶颈是 embedding 模型不够好,后来发现真正的问题在于“匹配什么”。CLIP 匹配的是全局语义,OCR 匹配的是文字内容,而很多真实查询需要的是视觉结构的精确匹配。想通这一点后,我才明白为什么 ColPali 这种方案会诞生——它不是为了炫技,而是因为现有的方案在视觉结构检索上确实有根本性缺失。
三个常被问到的坑
多模态 RAG 和直接用多模态大模型(如 GPT-4V)有什么区别?
多模态大模型每次只能看有限的几张图,无法覆盖整个知识库。RAG 的价值在于先检索再生成:从百万文档里挑出最相关的几个,让大模型只聚焦在这几个上。这样既省 token,又能保证知识库是动态更新的。
怎么评估一个多模态 RAG 系统好不好?
文本 RAG 常用的召回率、命中率指标可以沿用。多模态场景还需要增加一个维度:检索结果是否真的包含回答所需的信息。你可以人工标注一些“问题-相关图片”的测试集,然后看检索的 Recall@k。更严格的做法是让一个多模态大模型来评估检索到的图片能否回答该问题。
视频也能这么检索吗?
可以,但更麻烦。视频要先抽帧,每一帧当一张图处理。还需要考虑时间信息——哪一帧对应哪个时刻。目前的主流做法是抽取关键帧,然后对关键帧做多模态索引。但这样会丢失动作信息,目前还没有特别优雅的解决方案。
多模态 RAG 并不是一个“装上就能用”的组件,而是一个需要根据你的数据形态做取舍的架构决策。如果你只需要处理扫描件,OCR 方案足够;如果你的文档里有大量复杂图表,我建议你用重排序或者 ColPali 做精排。别一上来就追求最“高级”的方案——先搞清楚你的用户查询到底需要哪种信息,再选择对应的保留方式。
这个领域还在快速演进。ColPali 这种“直接对图像做检索”的思路,很可能在未来一两年成为主流。但今天,工程上最稳妥的路依然是:先用最便宜的方案跑通,再根据实际失败案例逐步升级检索策略。
原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/212.html