做 RAG 项目的人,大概率都遇到过这样的尴尬:文档库辛辛苦苦爬完了,结果一查里面全是扫描件、盖章单据、带表格的 PDF 和花花绿绿的配图。直接丢给文本提取器,吐出来的是乱码;丢给 embedding 模型,图片直接变成无意义的占位符;狠一点上 OCR,结果表格结构全丢,检索回来的答案根本对不上号。
这篇就是来解决这个问题的。作为 RAG 数据导入与解析系列的第二篇,我把“图文内容怎么进知识库”这件事拆开聊透。我会讲清楚两条主线:一是图片和扫描件怎么解析——传统 OCR 和现在流行的多模态大模型各有什么适用边界;二是 PDF 解析工具的选型逻辑——我实测过一批主流方案,最后会给出九种工具的优缺点和适用场景。全文基于我做过的真实项目,该给的参数、该避的坑、该抄的作业都会交代清楚。
1. 先搞清楚:你的文档到底卡在哪一层
很多人在数据导入阶段就翻车,不是因为工具不行,而是连自己要解析的内容属于什么类型都没想清楚。RAG 的数据源可以按解析难度粗略分几层,每一层的处理策略完全不同。
1.1 四层解析难度模型
我一般把待解析的文档分成四层:
- 第一层:纯文本型 PDF 或网页,文字层完整,直接提取即可,这属于“白送分”。
- 第二层:带版式的 PDF,有分栏、页眉页脚、表格,文字层虽然存在,但提取逻辑要考虑阅读顺序和结构还原。
- 第三层:扫描型 PDF 和图片,只有图像没有文字层,必须走 OCR 或视觉模型解析。
- 第四层:内容里掺杂大量图表、公式、票据、手写体,普通 OCR 搞不定,需要具备版面理解能力的专业模型或工具组合。
在动手选工具之前,我建议你先抽样 20 到 50 个代表性文件,跑一遍简单的文本层检测:用pypdf直接抽取文本,如果抽出来的字数接近总页数乘以每页平均字数的水平,说明至少有一层文本可用;如果抽出来几十个字甚至空白,那基本锁定是扫描件或纯图片。
这一步的价值在帮你提前判断,后面所有工具选型和策略设计都不会跑偏。
1.2 解析失败往往不是模型问题,而是前置策略问题
我见过不少团队在 OCR 和模型上反复调优,效果始终上不去,最后发现根因是路线错了。举个例子:一个合同文档库里,前面十几页是扫描件,后面几页是电子签章页。有人直接上多模态大模型整本解析,每页都要走视觉推理,慢且贵,效果还不稳定。更合理的做法是先把文档按页切分,逐页检测文字层覆盖率,分类路由——有文本层的走快速提取,没有的才走 OCR 或视觉模型。
我把这种思路叫“先分类、后解析”。这不仅省时间省预算,更关键的是它能让你对不同质量的输入分别做阈值设置。比如扫描件允许一定的字错误率,纯文本页则要求高保真提取。分类路由的思路会贯穿全文所有方案。
2. 图片解析:OCR 与多模态大模型的分工与选型
图片解析是 RAG 导入里最容易被低估的一环。实际项目里,图片往往不是简单的“有没有字”的问题,而是“字在什么位置、什么版式、什么背景下”的问题。处理图片,本质上是在做“版面理解”而不是“文字抠取”。
2.1 传统 OCR 的适用场景与局限
传统 OCR 这些年进化得非常快,以 PaddleOCR、Tesseract、商用云 OCR 为代表。它们各自有鲜明的优缺点:
| 工具 | 擅长场景 | 明显的短板 | 推荐度 |
|---|---|---|---|
| PaddleOCR | 中文、印刷体、标准票据、轻量部署 | 复杂版面、表格结构还原弱 | 开源首选 |
| Tesseract | 英文、多语言基础识别 | 中文版式理解弱,需大量调参 | 备选 |
| 百度/腾讯云 OCR | 营业执照、身份证、手写体、高精度识别 | 有成本和数据外传顾虑 | 商用场景 |
| 搜狗OCR等桌面工具 | 单张图片、低频率需求 | 不适合批量自动化 | 日常辅助 |
传统 OCR 的真正问题有三个:
一是丢版面。识别出来的文字是一个一个“块”,块与块之间的关联关系、表格行列属性、阅读顺序,需要你自己用坐标信息重建。很多工具导出的是带bbox坐标的 JSON,但后续重建版面的工程量不小。
二是抗干扰能力有限。深色背景、印章文字叠压、艺术字体、斜排文字,识别率会明显下降。印章叠字这个问题,我实测过 PaddleOCR 和多家云 OCR,在合同类文档上普遍识别得七零八落。
三是和 RAG 检索的目标冲突。RAG 要的是语义单元,而不是文字流。OCR 结果如果只是大段吐字出来,没有结构,后续拆分和向量化效果会很差。所以单纯上 OCR 并不能解决 RAG 的问题,它必须搭配版面后处理。
2.2 多模态大模型:图片解析的“新解法”
多模态大模型(比如 Qwen-VL、GPT-4o、Claude 等视觉版本)给图片解析带来的是一种范式改变。它们不只是从图片里抠文字,而是能理解整张图的语义结构:这是一个表格,表头是什么,哪几行是数据;这是一个产品示意图,箭头指向哪里,旁边的标注对应什么内容。
用多模态大模型解析图片的核心优势有三个:
- 直接输出结构化文本,可以要求它输出 Markdown 表格、JSON 结构,甚至是带语义的摘要。
- 抗干扰强,印章叠字、背景纹理、复杂版面,视觉理解模型通常比传统 OCR 更稳健。
- 自带语义,解析结果可以直接作为 RAG 的 chunk 输入,几乎不用再做二次清洗。
当然也有代价:速度慢、成本高。一张复杂图片可能耗时十几秒甚至更久,token 费用随图片复杂度和模型规格上升明显。
2.3 我的实战选型策略:分级调用
我的做法是建一个图片解析的“分级路由”:
- 简单图片、文字清晰、无表格,用 PaddleOCR 或云 OCR 快速识别,便宜且速度快。
- 中等复杂度图片、有表格或简单版面,先用传统 OCR 抽字,再配合规则或小模型重建结构。
- 复杂图片、票据稠密、版面混乱、需要上下文推理,上多模态大模型,一次性生成结构化输出。
这个分级策略在实际项目里能省下 60% 左右的算力成本。有人问为什么不全部走多模态大模型,核心原因是贵和慢。在每天要解析几万张图片的场景下,全部走视觉模型要么预算爆炸,要么延迟不可接受。
补充一个参数参考:我用 Qwen-VL 系列模型做表格图片解析时,单图分辨率尽量保持 1024 以上,温度调到接近 0,指令里明确要求“按原表格结构输出 Markdown”,效果要比默认参数稳得多。
3. PDF 解析工具九选一:实测体验与选型建议
PDF 解析是 RAG 数据导入的重头戏。工具选错了,要么解析得支离破碎,要么在表格上彻底翻车。我梳理了当前主流的九种方案,按使用场景分成三类:轻量文本提取、重结构还原、商用与全能型。
3.1 轻量文本提取类:pypdf / pdfplumber / pdfminer.six
pypdf是原来的 PyPDF2 的继任者,胜在极简,几行代码就能把文本抽出来。优点是安装轻、依赖少、处理简单的文字型 PDF 非常快。缺点也很明显:面对复杂版式,它的输出顺序经常是乱的,表格直接变一坨文字。
pdfplumber是我个人最常用的工具之一。它把页面上的每个字符、线条、矩形都提取成带坐标的对象,可以精确地按坐标重建布局。尤其适合处理有明确框线结构的表格,能拿到表格的行列坐标,再配合规则拼出结构化的二维数据。缺点是大文件处理速度偏慢,内存占用高。
pdfminer.six是底层解析库,LTTextBox、LTFigure 这些对象层级可以让你精细控制布局分析。它的优势是灵活,几乎每个解析环节都可以定制;劣势是 API 偏底层,开发效率不高。
这三个工具都属于“要自己动手做后处理”的范畴,适合文档结构相对规整、工程师愿意花时间调规则的项目。
3.2 重结构还原类:PyMuPDF / Camelot / Marker
PyMuPDF(fitz)是我在多数项目里的首选底座。它支持把每一页渲染成高清图片,可以精确切割区域并导出,还自带轻量文本提取功能。很多复杂的图片型 PDF,我会先用 PyMuPDF 把页面渲染成 PNG,再把图片交给 OCR 或多模态模型去解析。这种“PDF 转图片再转认知”的路线,绕开了 PDF 内部文本层的各种兼容性问题。
Camelot专注表格提取。它有两种模式:Lattice 模式针对有框线的表格,准确率非常高;Stream 模式针对无框线、靠空白对齐的表格,效果波动较大。Camelot 的强项是输出结构化表格数据,非常适合财报、单据类 PDF。但它依赖 Ghostscript,部署时容易被环境问题绊住。
Marker是我近两年用下来最惊艳的开源项目之一。它能把 PDF 完整转换为 Markdown,自动识别标题、段落、表格、图片引用,同时生成对应的文本块级别的坐标信息。效果接近我理想中的“RAG 预处理神器”。它对运行环境要求不低,最好有 GPU,且大文件处理速度仍然偏慢,但输出质量确实对得起算力开销。
3.3 商用与 RAG 专用型:Unstructured / LlamaParse / Adobe Extract API
Unstructured是 RAG 生态里被提及最多的工具。它的核心价值不是“解析”,而是“把解析结果按 RAG 的需求切成元素块”,比如 Title、NarrativeText、Table 这些类型,还内置了表格提取和 OCR 支持。缺点是框架层级多,部分模块抽象程度高,一旦行为不符合预期,排查成本略高。
LlamaParse是 LlamaIndex 同门的云端解析服务,支持解析复杂表格、嵌入图片和扫描件,输出 Markdown。它在英文场景效果优秀,中文场景我实测有波动,但如果你的文档是英文财报、论文,这个工具能省很多事。
Adobe Extract API是 Adobe PDF 服务家族的 API 产品,对版式还原和表格识别非常精准,是工业界商用效果最好的封闭方案之一。缺点是收费、闭环生态,也不太好做细粒度定制。
下表是九种工具的一句话总结:
| 工具 | 最佳场景 | 不要用于 |
|---|---|---|
| pypdf | 快速抽文本、文字层完整 | 表格、扫描件 |
| pdfplumber | 规整表格、坐标级布局分析 | 超大文件、复杂嵌套版式 |
| pdfminer.six | 底层布局定制、科研级控制 | 快速原型 |
| PyMuPDF | 页面渲染、区域裁剪、多模态配合 | 结构化文本输出 |
| Camelot | 纯表格提取、财务单据 | 无框线复杂排版 |
| Marker | 整本转 Markdown、RAG 高质量预处理 | 弱机器上的批量任务 |
| Unstructured | RAG 生态内做文档元素切分 | 追求极致表格精度 |
| LlamaParse | 英文复杂文档、云端快速集成 | 中文复杂排版、成本敏感场景 |
| Adobe Extract API | 商业级版式还原、表格高精度 | 预算有限、需深度定制 |
3.4 选型决策树
选型其实可以浓缩成几个问题:
- 文档有没有文字层?没有就直接考虑 PyMuPDF 渲染图片 + 多模态或 OCR。
- 表格重要吗?重要就优先看 Camelot、Marker、Adobe Extract API。
- 需要和 RAG 生态深度集成吗?要就选 Unstructured,能省掉大量清洗环节。
- 预算和技术能力如何?开源组合拳 PyMuPDF + PaddleOCR + Marker 通常够用且可控。
有朋友问能不能只用一个工具解决所有问题。我的答案很明确:不能迷信单一工具。真实文档千奇百怪,一套组合策略远胜一个全能工具。我的默认组合是 PyMuPDF 负责渲染和文本提取,Marker 负责整本高质量转换,表格和复杂页面用多模态模型兜底,这一套组合在中文合同、英文论文、财报场景都跑得很稳。
4. 解析结果如何接入 RAG 流水线
解析只是第一步,解析完的文本怎么进入向量库、怎么保证检索质量,是整个链路里更考验细节的环节。
4.1 从解析结果到 Chunk 的关键处理
解析输出通常要先做三件事:
- 清洗。去掉页眉页脚、页码、页眉横线、乱码字符。这一步看似无关紧要,实际上对 embedding 效果影响很大。页眉页脚混入正文会导致 chunk 语义偏移,尤其是页码这种高频无意义 token,会稀释向量权重。
- 切分。按语义单元切,而不是按固定字数硬切。Marker 或 Unstructured 输出的块类型正好可以作为切分边界。表格通常单独成一个 chunk,图片说明和正文分开。固定 512 字切分适合纯文本,但对表格和图文混排是灾难。
- 结构化补全。给每个 chunk 带上元数据,比如来源文件名、页码、所属章节、文档类型。这不仅是追溯需要,还能在检索时做基于元数据的过滤,提升准确率。
4.2 表格和 OCR 结果的“二次向量化”
表格进 RAG 一直是个老大难。直接丢 Markdown 表格文本进去,embedding 模型经常抓不住行列语义。我的做法是对表格做两次处理:
- 第一次,把表格转成自然语言的描述,比如“2023年Q2营收为3.2亿,同比增长15%”,这个描述会被向量化,用于语义检索。
- 第二次,保留一份原始表格的结构化数据,比如 JSON,作为检索命中的“附件证据”。用户提问时,先召回自然语言描述,再联动附上原始表格,效果要比单纯检索表格文本好很多。
同理,OCR 出来的结果如果只是文字流,我也建议尽量做结构化重构后再入库。比如合同的结构是“甲方、乙方、金额、期限”,OCR 识别后应该把这些字段映射成结构化键值,而不是一段乱字。
4.3 数据质量验证的四个指标
RAG 的检索效果和入库质量强相关。我每次搭完解析流程都会跑一组质量验证:
- 覆盖率:所有文档是否都被成功解析?解析失败比例是否在可控范围?
- 准确率:抽样对比原文和解析结果,尤其是数字、金额、专有名词,OCR 场景下错误率是否超标?
- 结构完整度:表格行列是否对齐?段落顺序是否正确?大文档是否被错误切断?
- 检索命中率:拿一批测试问题做召回验证,看答案能否回回到正确的 chunk 上。
这四个指标我会做成自动化的流水线,每次数据更新后自动跑一轮,一旦指标下跌就定位到是哪个环节出了问题。没有这一步,后面的 RAG 效果再差你都不知道该从哪里排查。
5. 常见问题与排查技巧实录
把我在真实项目里踩过的坑整理成速查表,这些都属于“文档里不会写、但实操一定会遇到”的问题。
| 现象 | 根因 | 解决方案 |
|---|---|---|
| PDF 提取出来是乱码 | 字体编码非标准,缺嵌入字体 | 改 PyMuPDF 渲染成图片后走 OCR 或视觉模型 |
| 中文 OCR 准确率低 | 未加载中文语言包 | PaddleOCR 默认支持中文,Tesseract 需显式指定 chi_sim |
| 表格提取串行错位 | 无框线表格用 Lattice 模式误判 | 换 Camelot Stream 模式,或用多模态模型重建 |
| 多模态解析超时 | 单图分辨率过大、模型输入限制 | 先压缩到合适分辨率,分块处理复杂版面 |
| 扫描 PDF 整本解析慢 | 每页都走 OCR,无差别处理 | 先检测文本层覆盖率,分类路由,只在无文本层页面走 OCR |
| 嵌入图片被直接丢弃 | 解析工具默认忽略图片对象 | 用 PyMuPDF 单独提取图片对象,送 OCR 或视觉模型 |
| chunk 切分切断表格 | 按固定字数切分,不考虑语义边界 | 表格单独成块,配合自然语言描述二次向量化 |
| 解析结果与原文对不上 | 页码、页眉混入正文 | 清洗阶段按坐标规则过滤页眉页脚 |
再单独强调一个我在工程上反复遇到的坑:多模态模型做 OCR 时,如果把整页 A4 扫描件压缩到很小的分辨率,复杂小字会糊成一团,识别率骤降。我处理扫描件时的经验是,先检测原始 DPI,物理尺寸和文字密度的关系,再决定缩放比例。单页 A4 扫描件通常保持 1024 到 1536 像素的宽度比较稳妥,再低的清晰度,省下来的成本都会变成返工成本。
另一个容易被忽略的问题是格式间的边界 case。比如 PDF 里嵌入了扫描页面和文本页交错的情况,很多工具会误判整本都是扫描件,导致无谓的算力消耗。我采用的策略是按页分类,统计每页字符数,超过阈值判断为文本页,否则进入 OCR 队列。这个过程对整本 PDF 按页拆分后做并行决策,效率提升非常明显。
工具链本身的工程细节也值得注意。PyMuPDF 渲染页面时,matrix参数决定输出图片的分辨率,默认值是 72 DPI,输出很模糊,我一般设置 2.5 到 3 倍缩放,让渲染图保持 200 DPI 左右的清晰度。Camelot 解析表格之前,必须确认 Ghostscript 是否正常安装,否则会出现解不开或超时的神秘错误。Marker 跑大文档时,建议按章节拆分后再处理,避免内存溢出和排队过久。
6. 最后分享一点个人心得
做 RAG 数据导入和解析,大部分时间其实不是在和算法作斗争,而是在和各种奇奇怪怪的文档作斗争。不同客户、不同行业的文档千奇百怪,你很难找到一套万年不变的配置,所以“先分类、后解析、再验证”这个三步套路,比任何单个工具都重要。
我个人的体会是,千万不要把解析这一步当成可一次性完成的离线任务。真实场景里,文档库每周都在变,今天新增几份扫描合同,明天补一批带复杂表格的财报,解析流程必须具备良好的可观测性和模块化设计。每类文档的解析结果好坏,应该有独立的日志和评价指标,而不是黑箱式地一股脑灌进向量库。
最后再分享一个小技巧:如果你做的是中文场景,请特别关注表格型 PDF。中英文表格的排版习惯差异很大,中文表格经常出现合并单元格、竖排表头、大段备注文字,这对所有解析工具都是考验。我在遇到这种文档时,通常会把它直接交给多模态大模型做结构化输出,再人工抽检几页确认质量。实践证明,这类“重难点文档单独特殊处理”的策略,远比在通用工具上反复调参来得靠谱。