多模态 RAG 怎么做?

多模态RAG怎么做?图片、表格和Markdown图像如何入库?
你试过问AI系统一个问题,结果它给你来一段"根据文档内容无法确定"吗?
比如问"去年Q3哪个供应商交付准时率最高",AI愣了半天,最后回答"该文档主要讨论供应链管理的基本概念"。这不是AI不够聪明,是你上传的Excel表格在它眼里就是一团乱码。
多模态RAG要解决的就是这个问题——怎么让AI真正读懂你的图片、表格、图表?
答案在入库环节。
文档入库不是简单上传,而是一条精密的数据处理流水线
很多人以为入库就是:上传文件→等待几秒→搞定。
大错特错。
真正的入库要经过六个环节,每个环节都可能挖坑。

文件上传只是开始。系统得先确认你传的是PDF还是Word还是图片,格式不对后面全废。
格式校验检查文件完整性。损坏的PDF、乱码的编码都要在这里拦截。
Layout解析是很多人容易忽略的环节。它要弄清文档的排版结构——哪里是标题、哪里是正文、哪里是页眉页脚、哪里有水印。这一步没做好,后面切分出来的东西就是一团浆糊。
我之前做过一个项目,就是在这个环节偷懒了。结果用户搜"财务分析",把页眉里的"财务分析报告"也搜出来了,检索结果乱得一塌糊涂。
清洗去噪去掉无关内容。页码、公司Logo、装饰性边框,统统剔除。留着你就是在污染向量数据库。
Chunking把文档切成适合检索的小块。切成多大?怎么切?这里面的门道能单独写一篇文章。
Metadata入库是把标题、作者、时间、来源这些信息附加到Chunk上。没有Metadata,你连"这条记录是哪篇文档的"都搞不清。
任何一个环节出问题,最终检索效果都会打折扣。数据处理管线的质量,比你换一百个embedding模型都重要。
图片入库的三条路径——不是所有图片都用同一种方式处理
你的文档里可能有三种完全不同的图片:截图、流程图、数据图表。
处理方式能一样吗?
不一样。但很多人偏偏用同一种方式处理,结果图片检索效果参差不齐。
目前主流有三条路:

第一条路:OCR识别
适合截图、带文字的图片。把图片里的文字提取出来,变成纯文本入库。
优点是文字信息完整保留。缺点是你拿到的是"一堆文字",图片本身的视觉信息——颜色、布局、图表类型——全部丢失。
第二条路:图像描述生成
把图片扔给多模态模型,让它生成一段描述。
适合流程图、架构图这类"看图说话"的图片。
问题是描述质量完全取决于模型能力。描述太粗,检索不到;描述太细,又容易产生幻觉。你得反复调prompt,直到满意为止。
第三条路:混合方案
图片同时走OCR和描述生成两条线,提取出的文字和描述都入库。
这是目前最稳妥的做法。文字信息不走样,视觉语义也不丢失。
但这里有个坑:图表类图片的Caption和上下文信息同等重要。
比如文档里有一张折线图,旁边写着"图3-2:2024年Q1-Q4营收增长趋势"。你只处理图片本身,完全忽略这个Caption,那别人搜"营收增长"可能就搜不到这张图。
配图描述决定图表能否被正确检索和理解。
表格入库的精髓——保持"结构"而不是变成"乱码"
表格是多模态RAG的重灾区。
把Excel表格直接转成纯文本,就像把乐高积木拆散后随意堆在一起——结构消失了,意义也消失了。
"供应商A 95%、供应商B 87%、供应商C 92%"——这是纯文本。
请问哪个供应商准时率最高?你问AI,AI得回去数百分比,还得比较大小。人能做,AI不一定能做对。
因为表格的结构信息没了。列是什么、行的从属关系、数值的计量单位,全丢了。
表格入库的正确姿势是结构化抽取。

把表格转成JSON或类似的结构化格式。每列的表头作为字段名,每行作为独立记录,数值类型标注清楚。
这样AI就知道:哦,"准时率"是一列,"供应商"是一列,要比较准时率我直接查"准时率"字段的最大值就行。
表头信息和行列关系必须作为Metadata一起入库。
有人说我表格里还有合并单元格、嵌套表头怎么办?这确实麻烦,但原则不变:尽量保留原始结构,实在不行就"降级"处理——按单元格拆成键值对,至少比纯文本强。
按文档结构切分——Chunking不是砸碎而是拆解
现在到了Chunking环节。
什么是Chunk?就是你把一篇长文档切成的小块。每块入库后单独有向量,可以被检索。
切分方式直接决定检索质量。
固定长度切分最偷懒:每隔N个字符或N个Token就切一刀。
后果是什么?一句话可能从中间劈开,专业术语可能截成两段。"SSO单点登录系统"变成"SSO单点..."——检索的时候搜"SSO"能匹配,搜"单点登录"就匹配不上了。
聪明人都按文档结构切分。

Markdown按H1/H2/H3标题层级切分。每个标题下的内容天然是一个语义单元,切在这里刚好不会破坏完整性。
代码按函数、类、包来切。一个函数的逻辑是完整的,你不能把函数头和函数体拆到两个Chunk里。
PDF按章节或页切。如果PDF有目录导航,按章节切;没有的话按页切,至少页内语义是连贯的。
表格单独处理。表格作为独立Chunk,不要混入正文。因为表格里的信息是结构化的,混进正文就乱套了。
推荐块大小:通用文本400-512 Token,代码约100 Token。
还需要Overlap——相邻Chunk之间重叠一部分。防止一条关键信息刚好在Chunk边界上,前不巴村后不巴店。重叠区域建议15%-25%,视文档性质调整。
按结构切分就像拆书架时按书脊分类——你要找"架构设计"的书,直接去Architect书架就行。
固定长度切分就像随机砍成50cm一段——你找到的可能是一句话的前半截。
Parent-Child Chunk——召回精度和上下文完整性的两全之法
Chunking有个天然矛盾:
你想检索精准,Chunk就得小。小Chunk语义集中,匹配度高。
你想上下文完整,Chunk就得大。大Chunk包含更多信息,不容易断章取义。
鱼和熊掌怎么兼得?
Parent-Child Chunk策略登场。

原理很简单:用小Chunk检索,用大Chunk提供上下文。
具体做法:
- 先把文档切成大块——比如一整页或一整个章节
- 把大块再切成小块——按段落或按语义单元
- 小块入库生成向量,用于检索
- 大块也入库,但大块不做检索,只提供完整上下文
检索时,用户问题先匹配小Chunk。匹配到之后,把小Chunk对应的大Chunk整个取出来,作为上下文喂给LLM。
类比一下:
图书馆找书时,目录卡片帮你快速定位——卡片上只有书名、作者、分类,你一眼就能找到目标书架。这卡片就是子Chunk。
找到书架后,整本书给你看——完整的章节内容、前后逻辑、参考资料都在里面。这本书就是父Chunk。
没有目录你得翻遍整库,没有书你只能看到干巴巴的标题。
异常处理与降级策略——让系统"优雅地失败"
入库过程中会遇到各种意外:空文件、格式损坏、乱码、解析失败。
怎么处理?
分级处理,每级都有兜底。

空文件——直接拒绝入库,通知上传者重新传。别让空记录污染数据库。
格式不支持——先建议用户转换成支持的格式,比如把.pages转成PDF,把老版.doc转成.docx。如果用户坚持要入库,尝试通用解析器。
解析失败——进入人工队列或调用备用解析器重试。最多重试2-3次,还不行就标记异常,不影响其他文档入库。
乱码率高——尝试OCR识别或格式转换。PDF转图片再识别,图片重新编码再解析。仍然失败,降级为纯文本入库——虽然效果差,至少有东西可用。
Chunking异常——当按结构切分失败时,改用固定长度切分作为兜底。固定长度切分是"最差情况下的最优解",总比程序崩溃强。
核心原则:任何环节的失败都要有明确的处理路径,不能静默丢弃数据。
系统要告诉用户"哪里出了问题、为什么、怎么解决"。而不是给一个暧昧的错误码,让用户摸不着头脑。
多模态RAG真正难的地方不在于用什么模型,而在于如何让文档"完整且结构化"地进入系统。
我踩过的坑告诉我:入库这条流水线打磨好了,AI的回答自然会更准确。相反,如果入库就是草草了事,指望后面靠调prompt来弥补,基本是痴人说梦。
所以下次你的RAG系统答非所问,先别急着调prompt。
看看入库那条流水线,是不是哪里漏了。
