我不太愿意把这篇文章写成“又一篇RAG原理搬运”。
你看到标题里带着“图片版”三个字,就应该有个直觉:这讲的不是用图片去图解RAG,而是把图片当成知识库里的主要数据源,做成检索增强生成系统。我在这个方向踩了不少坑,也沉淀出一套能落地的流程,今天一次性讲透。
如果你正在头疼“我有几千张产品图、现场照片、设计稿截图、财报扫描件,想让大模型基于这些内容回答问题”,那这篇文章就是冲着你来的。全文不区分新手老手,只要用过Python、知道大模型API大概怎么回事,就能跟完整个流程。我还会把两条技术路线、核心代码的写法、以及一堆实际运行中才暴露的坑,全部记录下来。
1. 先给传统RAG画个像,再说图片版改了什么
1.1 传统RAG在解决什么问题
大语言模型单独用,有两个扛不住的短板:一是参不到实时或私域的信息,二是面对“不知道”的内容会一本正经地编。你问它上个季度的内部销售数据,它要么说不知道,要么直接从训练记忆里搜一段近似的数字给你,而且语气非常笃定,这是最要命的。
RAG的解决思路其实特别朴素:既然模型自己不知道,那就先从一个外部库里把相关资料检索出来,再把资料和大问题一起喂给模型,让它“看着资料回答”。这就像开卷考试,模型不需要把所有知识记在脑子里,只要会查书、会引用就行。
传统RAG处理的基本都是文本:PDF、Word、网页、数据库记录。流程无非是加载、切块、向量化、存进向量库,然后在用户提问时检索相关的文本片段,拼进Prompt里让大模型回答。这套链路今天已经非常成熟,很多业务场景直接套模板就能跑通。
1.2 图片进来之后,链条哪里断了
图片版RAG的复杂之处在于,图片本身不是文本,向量化方式和检索逻辑全变了。你不可能把一张JPG直接丢进文本向量模型里,也不可能把一张图切成几个文本块去建索引。
最简单的“偷懒”做法,是把图片转成文字再走传统RAG,也就是先OCR提取图中文字,再按文本流程处理。这个方案在纯扫描件场景下能跑,比如文档扫描、表单截图,因为那里面的信息主体就是文字。但如果图片里的核心信息是视觉内容,比如产品的形状、外观缺陷、设计风格、表格结构、图表趋势,OCR只能抽出一堆零散文字,真正的视觉语义全部丢失,检索效果会差得离谱。
所以要真正做“图片版RAG”,必须在链路里同时引入视觉理解能力。这不仅仅是加一个OCR模块,而是要在“向量化”“检索”“重排”这些环节上做多模态改造。
1.3 两条技术路线的总体对比
我把目前实践中最常见的两种方案整理成了一张对比表,你先有个全局概念,后面详细拆解:
| 方案 | 核心思路 | 适合场景 | 建设成本 | 检索精度 | 生成效果 |
|---|---|---|---|---|---|
| 路线A:图转文本 | OCR + 图像描述,把图片变成文本,再走常规文本RAG | 扫描件、含大量文字的截图、产品说明图 | 低,改造少 | 一般,依赖文本抽取质量 | 依赖抽取文本的完整性 |
| 路线B:多模态双塔检索 | 图片和文本各自编码成向量,在同一向量空间做相似度匹配 | 视觉信息占比高的图片库,需要按图像内容检索 | 中高,需要多模态模型资源 | 对纯视觉内容召回更好 | 可在生成时同时传入图片和文本 |
注意:选路线之前,先去看你的图片里到底是“图里有字”重要,还是“图本身的长相”重要。这一步判断错了,后面的技术选型都会跟着歪。
在真实项目里,我做的通常是“路线A + 路线B”混合:OCR和图像描述作为文本补充通道,多模态向量作为视觉检索通道,两条路召回结果做融合,最后统一交给大模型。这个做法容错率最高,尤其在图片质量参差不齐的情况下。
2. 图片知识库的信息抽取,决定了整个系统的天花板
2.1 别迷信OCR,它只是第一层
OCR在中文场景里,遇到印刷体扫描件效果能到98%以上,一旦碰到手写体、倾斜照片、水印压字、复杂背景,准确率直线往下掉。而且OCR抽出的是“文本”,不是“语义”。比如一张产品故障照片上印着“型号X-2000”,OCR只能告诉你图片里有这串字符,却说不清这是哪个零件、什么故障表现。
所以视觉信息抽取必须分层。我实际跑通的做法是三层抽取:
- 第一层:OCR抽文字,包含绝对坐标。
- 第二层:图生文模型(也就是视觉语言模型)从整张图里生成一段自然语言描述,补足“这张图在视觉上长什么样、有哪些对象、什么关系”。
- 第三层:对图片做局部切块,再配合必要的数据处理生成结构化摘要,比如检测表格结构、识别图表趋势。
这三层抽出来的信息合在一起,才能形成一条接近人工阅读理解水准的图片文本摘要。这一步非常关键:图片RAG的检索质量,不是由向量模型决定的,而是由“你从图片里抽出的文本和描述够不够完整、够不够准”决定的。
2.2 图像描述生成,别用它替代OCR,而是让它补位
很多教程让人直接拿视觉语言模型给图片写一句caption,然后把它当文本块存进向量库。这个思路单独用,有两个坑:
第一,描述过于概括。你让模型描述一张控制面板图,它大概率会说“这是一张工业控制面板的照片,上面有多个按钮和指示灯”,然后就没有然后了。真等用户问“右上角那个红色按钮旁边写了什么字”,这种描述完全帮不上忙。
第二,描述的准确性不可控。模型偶尔会脑补图中不存在的细节,这在检索场景里是致命的。因为向量库会把这段幻觉描述当成知识存下来,之后被检索出来给大模型当答案依据,等于把幻觉从源头塞进了答案里。
所以我的做法是,图像描述只负责“场景与视觉语义”的补全,OCR负责“文字精确信息”,两者互不替代。具体Prompt我会让模型按固定结构输出:
图片整体场景:... 主要视觉对象:... 对象之间的空间关系:... 图中的文字内容(交给OCR模块,不在此重复):... 可能的业务标签:...这样输出稳定,也方便后续拼接成检索文本时序列化。
2.3 表格和图表,是最容易翻车的一类图片
如果你要处理的图片里有表格、柱状图、折线图,那OCR得到的只是一堆数字和坐标,拼回来看不出任何趋势和关系。我的经验是:这类图片必须走专门的“表格结构识别”或“图表理解”模型,把它们转成Markdown表格或结构化JSON,再存进知识库。
比如一张销售趋势折线图,OCR可能抽出“1月1200,2月900,3月1500”,但你不知道这是季度走势,也不知道3月比1月上涨了25%。而结构化抽取后,会得到:“趋势描述:2024年第一季度销售额整体先降后升,3月达到峰值1500,环比增长66.7%。”这段描述才是问答系统真正能用的知识。
实战中,我会给表格和图表打一个单独的类型标签,在索引里和普通文本分开存。检索时如果用户问“趋势怎么样”“对比哪个高”,优先从图表摘要里召回;问“具体数字是多少”,则从OCR文本里召回。这种“类型元数据过滤”能明显提升召回相关性。
2.4 切图的粒度把握
文本RAG讲究分块大小,图片RAG同理。一整张A1图纸丢进模型生成描述,大概率丢失细节;切得太碎,又会让上下文断裂,检索时召回一堆局部碎片。
我的经验是:分辨率特别高的图,先按视觉区域做目标检测或显著性区域识别,只对关键区域单独抽取信息。比如一张生产线全景图,先检测出传送带、操作台、故障停机区域,再分别对这些区域生成描述并标注坐标。这样用户问“传送带左侧的设备型号”,系统才能根据区域标签精准召回。
索引里每一个片段都要带上图片路径和区域坐标,这样检索命中后,大模型可以基于该区域生成回答,而不是面对一整张模糊的图。
3. 多模态向量检索与生成链路实现
3.1 双塔模型的选择与向量空间问题
图片版RAG检索环节的核心,是把图片和文本映射到同一个向量空间里。目前最成熟的思路是“双塔模型”:一个图像编码器、一个文本编码器,通过对比学习让同一语义的图像和文本在向量空间里靠近。
我用的是开源社区常见的“对比语言-图像预训练模型”这一类模型,它天然支持图像到文本的跨模态检索。这里有个极其重要的注意事项:query(用户提问)的向量必须和入库图片的向量来自同一个编码器,而且要确保图像编码使用的是同一套预处理流程。否则即便模型一样,图片尺寸、归一化方式不同,向量分布都会偏移,检索结果就是玄学。
具体实践里,我会把图像编码器封装成统一接口,强制固定输入尺寸、归一化参数,并且在索引和检索两段共用同一个接口函数。这一点看起来小,实际上我见过太多项目在检索效果差时反复调阈值,最后才发现是图像预处理不一致。
3.2 构建混合索引
光有多模态向量还不够,我会同时建立多路索引:
- 图像语义向量索引:存CLIP式视觉向量;
- 文本摘要向量索引:存OCR结果 + 图像描述拼接后的文本向量;
- 标签与元数据索引:存图片类型、区域坐标、时间、业务来源等结构化字段。
这三路索引单独建,检索时各自召回TopK,再通过加权合并得到最终候选集。比如用户问“上周生产线的停机故障有哪些”,语义索引会召回视觉上像故障场景的图片,文本索引会召回描述里含“停机”“故障”字样的记录,元数据索引则把上周时间范围的图片全部捞出来。三者取并集再按权重排序,效果比单一向量检索高一个档次。
3.3 检索、重排与Prompt组装
召回阶段解决的是“找得全”,但“找得准”还要靠重排。我通常的做法是:第一轮用向量检索召回50到100条候选,然后交给一个跨编码器重排,或者直接用大模型对候选打相关性分,最后只保留Top5到Top10。
重排之后是关键一步:怎么把这些图片信息组装给大模型。两种模式我会混用:
- 文本组装模式:把OCR结果、图像描述、图像结构摘要拼成文字,并标注图片来源和位置信息,让大模型基于文字回答。这个模式下,图片本身不需要传给模型,适合纯文本接口的大模型。
- 多模态组装模式:如果生成端支持图像输入,直接把命中的原图连同文字摘要一起传给模型,让它可以“亲眼看见”图片再回答。这个效果更稳,尤其是涉及空间关系、颜色、视觉细节的问题。
我强烈建议所有做图片版RAG的人,优先选择多模态组装模式,而不是只做文本组装。哪怕文字摘要写得再好,模型看不见原图,终究是在“隔着窗户看房间”。
# 伪代码:图片RAG的完整检索与生成链路 def generate_answer(question): # 1. 查询向量化(编码器与索引段一致) query_vec = image_embedder.encode_text(question) # 2. 多路检索 visual_hits = vector_index.search(query_vec, top_k=50) text_hits = text_index.search(text_embedder.encode(question), top_k=50) meta_hits = metadata_index.filter(tags=question_tags, time_range=extract_time(question)) # 3. 合并候选,并取并集 candidates = merge_union(visual_hits, text_hits, meta_hits) # 4. 重排截断 top_candidates = rerank(candidates, question)[:8] # 5. 组装上下文(文本摘要 + 原始图片路径) context_text = build_context(top_candidates) context_images = [item.image_path for item in top_candidates] # 6. 调用多模态大模型生成 answer = multimodal_llm.generate(question, context_text, context_images) return answer这段伪代码的每一行,背后都对应一个真实模块。你别小看第4步的重排,如果你的候选里有元数据过滤进来的大量无关图片,不重排直接塞给大模型,生成的答案会被无效信息干扰,出现答非所问、来回绕的问题。重排器哪怕很笨,比如只用关键词交叠率打分,也比不重排好得多。
3.4 评估你的系统,不能只靠肉眼
图片RAG的评估比文本RAG更麻烦,因为“有没有检索到正确图片”这件事,需要人去看,很难完全自动判定。我目前用的一套轻量评估方案包含三层:
- 召回评估:针对一批典型问题,人工标注每道题对应的正确答案图片,然后看Top20检索结果里是否包含正确答案,算Recall@20。
- 生成评估:让大模型生成答案后,判断答案所需的关键信息是否都在召回图片中。这一步可以用一个评判模型自动打分。
- 对比基线:至少保留一组纯文本RAG结果做对照。很多最优效果不是绝对的,而是相对基线的提升。
我每次迭代模型或索引策略时,都会先跑一遍这三层评估,再决定要不要上线。千万不要因为“测了几个问题效果还行”就直接部署,图片库一多,检索分布的偏移会让你措手不及。
4. 实际项目里最容易踩的七个坑
4.1 中英文混杂的图片,检索效果骤降
很多中文产品图片上混着英文型号、中文说明、日文标签。多模态模型在处理中英文混合文本时,OCR识别率常见的问题是中文部分识别准确但英文小字被吞掉,或者反过来。我的土办法是把OCR结果按语言分开存储,检索时对中文query优先匹配中文段,对英文型号专门建一个“型号别名索引”。看起来不高级,但在实际业务里非常好用。
4.2 相似度阈值是玄学,回溯调试是常态
很多人在检索时设置一个“相似度大于0.75才放行”的阈值。这个数值其实和你的向量模型、数据分布、候选数量强相关,直接抄别人的参数没有意义。正确做法是:先召回,不设阈值,把TopK结果的分数分布打印出来,看正负样本的分界线大致落在哪,再决定阈值。而且阈值建议作为配置参数放到环境变量里,方便线上调整。
4.3 图片向量和文本向量空间对齐问题
如果用了开源的对比语言-图像模型,但自己造了一个新的文本编码器做文本索引,检索时就会发现图片索引和文本索引的分数完全不是一个量级。合并排序时,要么用归一化分数,要么干脆不同路的分数先各自独立排序,再用加权秩融合法合并。我比较推荐后者,因为它对分数尺度不敏感,合并后不会出现某一类候选永远霸榜的情况。
4.4 图片描述模型会“一本正经胡说八道”
图像描述模型是有幻觉的,尤其在光线差、分辨率低、物体遮挡的场景下。我的经验是给描述模型设置拒绝选项:如果它对图片内容置信度低,就输出“不确定”,而不要硬编一段描述。然后在索引阶段,把这种不确定的描述的打分权重调低,避免污染检索结果。宁缺毋滥,这是图片RAG的一条铁律。
4.5 高分辨率大图直接卡爆内存
一张几十MB的测绘图纸,直接塞进视觉模型,轻则内存溢出,重则整个任务超时。遇到这种情况,我不会整图喂进模型,而是先切分瓦片,把大图分割成小区域分别抽取信息,再在大模型生成阶段引用对应区域。此外,流程图、架构图这种信息密度极高的图片,我还会单独转成文本拓扑描述。
4.6 生成环节的引用溯源,必须在索引时就埋好伏笔
图片RAG生成的答案如果让用户看到一张图片来源,可信度会高很多。但这个能力不是生成阶段自动产生的,而是在构建索引时就把“图片路径、区域坐标、OCR文本来源”存进元数据。每次检索命中的片段都会携带这些溯源信息,生成时才拼进答案模板里。别等系统上线了才想起来要做溯源,那时候索引里没有相关信息,改起来成本极高。
4.7 隐私与脱敏,必须前置
图片知识库里经常混着手写个人信息、内部单据、人脸照片。这类内容一旦被检索出来并送入大模型,就有泄露风险。我现在的做法是建库前先跑一轮人脸检测和敏感信息识别,对命中隐私的图片直接打码并移除关键区域,再进入索引流程。这个环节不能省,尤其是要把系统开放给外部用户时,脱敏做不好就是安全事故。
5. 一套可以直接抄作业的流程清单
如果你现在要启动一个图片版RAG项目,我建议你按下面这个顺序推进,每完成一步就设置一个检查点。
- 业务抽样:从真实图片库里随机抽两百张,先人工标注“信息主体是文字还是视觉”,判断走哪条路线。
- 抽取通道建设:同时接入OCR、图像描述、表格结构识别三类模块,输出统一JSON格式。
- 索引设计:先想清楚要回答哪些问题,反向设计需要哪些元数据字段,再决定向量索引结构。
- 检索策略:建立图像向量、文本向量、元数据三路索引,实现加权融合。
- 重排调优:准备五十个真实问题,人工标注正确答案,跑一轮召回评估,记录初始基线。
- 生成链路:接入支持图像输入的大模型,把文本摘要和原图一起传入,做多模态问答。
- 上线监控:记录每个query的召回率、答案引用率、用户反馈评分,持续迭代。
提示:千万不要跳过第二步直接做第四步。如果信息抽取的质量不过关,再好的检索模型也救不回来。检索只是把“已经抽出来的好信息”找出来,它不能凭空变出信息。
整个图片版RAG的工程架构,说到底是一个“信息抽取”问题加一个“信息路由”问题。前者决定了知识库的上限,后者决定了问答系统的下限。我见过太多团队把预算堆在检索模型上,却不愿意花力气优化OCR和图像描述模块,最后系统上线后被一张模糊的照片打回原形。
如果你在做的图片库以视觉信息为主,那么在模型选型时多花点时间测试不同图像编码器对细节的敏感度,比反复调Prompt和阈值更有效。我在一次设备图纸问答项目中,仅仅把图像编码器换了一个参数规模更大的开源模型,Recall@20就直接从四成提高到七成,这是任何检索技巧都补不回来的差距。
最后再说一个私藏的小技巧:给每张图片生成描述时,尝试生成多个候选,再用另一个模型投票选出最靠谱的一条。这种方法会多花一点推理成本,但能显著降低描述幻觉对检索的污染。我个人实测下来,单条描述的错误率约在8%左右,五选一投票之后可以压到3%以内。如果你的知识库图片质量参差不齐,这个方法值得一试。