1. 为什么 RAG 的成败往往卡在 PDF 解析这一步
做 RAG 的人大概都有过这种体验:向量库搭好了,embedding 模型选好了,检索链路也跑通了,结果一问问题,模型答得驴唇不对马嘴。回头一查,问题根本不在检索,也不在生成,而是最上游那一环——PDF 压根没被正确读出来。表格串行了,双栏排版被读成单栏,页眉页脚混进正文,公式变成一堆乱码字符。你后面所有的精排、重排、混合检索,全都建立在一堆垃圾文本上,再精妙的架构也救不回来。
pdf-inspector这个工具,就是冲着这个痛点来的。它做的事情说起来很朴素:把 PDF 里的内容尽可能还原成结构化的 Markdown,让你在进入 chunk 切分和向量化之前,手里拿到的是一份干净、有层级、可追溯的文本。关键词里那几个词其实已经把它的定位说清楚了——RAG、PDF、Markdown、OCR。它不是一个通用 PDF 阅读器,也不是一个排版工具,它是专门服务于 RAG 数据预处理这一环的解析器。
这篇文章适合谁看?如果你正在搭 RAG 知识库,尤其是那种文档来源以 PDF 为主(合同、论文、技术手册、财报、产品说明书)的场景,那这篇基本就是给你写的。如果你只是偶尔转个 PDF 看看,那可能用不上这么重的东西。我会从 PDF 解析为什么难讲起,然后拆解 pdf-inspector 的工作机制,再给出一套可以直接抄的接入流程,最后重点讲那些文档里不会写、但实际跑起来一定会遇到的坑。全文基于常见工程实践展开,具体 API 以你实际拿到的版本为准。
先说一个反直觉的结论:在 RAG 项目里,PDF 解析的投入产出比,往往比换一个更强的 embedding 模型还要高。我见过太多团队花两周调检索参数,效果提升 3 个点,结果把解析器换掉,召回率直接涨 20 个点。原因很简单,检索的前提是"库里有正确的东西",库里全是错的,检索再准也是错的。
2. PDF 为什么这么难解析:从文件结构说起
2.1 PDF 本质是"打印描述",不是"文档结构"
很多人以为 PDF 里存的是"标题、段落、表格"这些语义信息,其实完全不是。PDF 的全称是 Portable Document Format,它的设计目标是"在任何设备上打印出来长得一样",所以它存的是绘制指令:在坐标 (x, y) 处画一个字符,用某个字体,某个字号,某个颜色。至于这个字符属于标题还是正文,属于第几段,PDF 本身根本不关心。
这就导致一个根本性问题:解析 PDF 本质上是一个逆向工程过程。你得从一堆带坐标的字符碎片里,反推出"这是一行""这是一个段落""这是一个两栏布局""这是一个表格"。没有哪个解析器能做到 100% 准确,区别只在于谁猜得更合理。
2.2 三种 PDF,三种难度
实际工作中遇到的 PDF,难度差异极大,我一般分成三类:
| 类型 | 特征 | 解析难度 | 典型来源 |
|---|---|---|---|
| 原生文本型 | 文字可选可复制,有内嵌字体 | 低 | Word 导出、LaTeX 编译 |
| 扫描图像型 | 整页是图片,文字不可选 | 高,必须 OCR | 纸质扫描、传真件 |
| 混合型 | 部分页文本、部分页扫描,或文本层叠加在图像上 | 最高 | 拼接文档、老档案 |
原生文本型看着简单,但坑也不少。比如双栏论文,如果解析器按 y 坐标从上往下读,会把左栏第一行和右栏第一行拼在一起,读出来就是"本文提出了一种方法 实验结果如表 1 所示"这种精神分裂的句子。再比如表格,PDF 里表格根本没有"单元格"概念,就是一堆绝对定位的文字,你得靠对齐关系去猜行列。
扫描图像型就更直接了,必须走 OCR。但 OCR 本身也有精度问题,尤其是中文、公式、特殊符号。关键词里出现了"以下 ocr 代码识别不了韩文""php ocr 识别验证码""java 使用百度 ocr 识别上传合同文件"这些,说明 OCR 在实际业务里是个高频刚需,而且坑特别多。pdf-inspector 这类工具的价值,就在于它把"判断该用文本层还是该走 OCR"这件事自动化了。
2.3 为什么输出 Markdown 而不是纯文本
这里要专门解释一下,为什么这类工具普遍选择 Markdown 作为输出格式,而不是直接吐纯文本。
纯文本丢掉了结构。一个标题和一段正文,在纯文本里长得一模一样,chunk 切分的时候你没法按语义边界切,只能按固定字数硬切,结果就是一句话被拦腰截断,检索时两边都召不回。Markdown 用#、##、-、|这些符号把层级、列表、表格保留了下来,你在切 chunk 的时候就可以按标题层级切,一个二级标题下的内容作为一个语义块,召回质量完全不一样。
而且 Markdown 是纯文本,天然适合塞进 prompt。你把解析结果直接喂给大模型,模型能看懂## 标题是什么意思,能看懂表格。关键词里"markdown 表格转换 excel""markdown 数学公式插件""github markdown callout"这些热搜,也侧面说明 Markdown 已经成了 LLM 时代事实上的中间格式。
3. pdf-inspector 到底在做什么:核心能力拆解
3.1 它解决的不是"转换",而是"还原"
市面上 PDF 转 Markdown 的工具一抓一大把,但大多数是"能转就行",转出来能看,但没法用于 RAG。pdf-inspector 的定位更偏工程化,它关注的是还原质量和可追溯性。
所谓还原质量,是指它要尽量判断出:哪些文字是标题,哪些是正文,哪些是页眉页脚(这些要丢掉),哪些是表格,哪些是代码块。所谓可追溯性,是指解析出来的每一段内容,最好能对应回原 PDF 的页码甚至坐标,这样用户问问题时,你能告诉他"这个答案来自第 12 页",而不是干巴巴一段文字。
3.2 文本层优先,OCR 兜底
一个成熟的 PDF 解析流程,一定是先判断有没有文本层,有就用文本层,没有才走 OCR。原因很实在:文本层是 PDF 自带的,100% 准确,零成本;OCR 是识别出来的,有错误率,还慢还费算力。
pdf-inspector 这类工具通常会在页级别做判断:这一页提取出来的文字数量低于某个阈值(比如少于 50 个字符),就认为它是扫描页,转去走 OCR 通道。这个阈值不能设死,因为有些页确实只有一张图加一行图注,字符少但不需要 OCR。实际调的时候,我一般会结合"文字密度"和"图像覆盖率"两个指标一起判断。
3.3 版面分析:把"坐标"翻译成"结构"
这是最核心也最难的部分。解析器拿到一页的所有字符及其坐标后,要做几件事:
- 行合并:把 y 坐标接近、x 坐标连续的字符合并成一行。
- 段落合并:把行间距正常、缩进一致的行合并成一段。
- 栏检测:通过 x 坐标的分布,判断这页是单栏还是多栏。
- 表格识别:通过字符的对齐规律,识别出表格的行列结构。
- 页眉页脚剔除:出现在页面顶部/底部固定位置、且在多个页面重复出现的文本,判定为页眉页脚。
每一步都是启发式规则加统计判断,没有银弹。这也是为什么不同工具解析同一份 PDF,结果可能天差地别。
3.4 输出结构:标题层级怎么来的
Markdown 的标题层级(#、##、###)不是 PDF 里带的,是解析器推断出来的。常见推断依据有几个:字号明显大于正文、加粗、独立成行、上下有较大留白、编号模式(如"第一章""1.1")。把这些信号加权打分,分数高的判为标题,再根据字号大小排序决定是几级标题。
这里有个经验:不要完全信任自动推断的层级。我一般会在解析后加一步人工抽检,尤其是文档结构复杂的场景。因为一旦层级错了,后面按标题切 chunk 就会全乱。
4. 把 pdf-inspector 接进 RAG 流水线的完整流程
4.1 整体链路长什么样
先给一张我常用的链路图(文字描述):
PDF 文件 → pdf-inspector 解析 → Markdown(带页码元数据) → 清洗(去页眉页脚残留、修表格) → 按标题层级切 chunk → 附加元数据(来源、页码、标题路径) → embedding → 向量库 → 检索 + 重排 → 喂给 LLM关键点在于:解析和切分是两件事,不要混在一起做。有些工具边解析边切,结果切出来的块没法调整。正确做法是先拿到完整的 Markdown,再单独做切分,这样切分策略可以随时改,不用重新解析。
4.2 环境准备与依赖
具体安装方式以你拿到的版本为准,但通用思路是:Python 环境(建议 3.10+),装好解析库本身,如果涉及 OCR 还要装对应的 OCR 引擎和语言包。中文场景一定要确认语言包装全了,否则会出现"识别不了韩文"这类问题——本质是语言模型没加载对应语种。
提示:OCR 语言包不是装得越多越好。加载的语言越多,内存占用越大,识别速度越慢,而且容易把形近字认错。按你的实际文档语种来装。
4.3 解析阶段的关键参数
解析时我一般会关注这几个可调项:
- 是否启用 OCR:纯文本型文档可以关掉,省时间。
- OCR 触发阈值:每页最少字符数,低于则走 OCR。
- 是否保留页眉页脚:RAG 场景一律不保留。
- 表格输出格式:Markdown 表格还是 HTML 表格。表格复杂时 HTML 更保真,但 Markdown 更省 token。
- 图片处理:图片是丢弃、保留占位符,还是走图注 OCR。
这里重点说图片。关键词里有个热搜叫"rag 知识库能存储图片嘛",这问题问得很实在。答案是:能,但不是直接存图片,而是存图片的描述或图注。纯图片没法做文本检索,你得用多模态模型给图片生成一段文字描述,或者提取图注文字,把这段文字存进向量库,图片本身存对象存储,检索命中后把图片一起返回。pdf-inspector 在解析时如果能保留图片位置和图注,对后续做多模态 RAG 帮助很大。
4.4 切分策略:按标题切,不按字数切
拿到 Markdown 后,切 chunk 我强烈建议按标题层级切,而不是按固定字数切。具体做法:
- 以二级标题(
##)为一级切分点,每个二级标题下的内容作为一个大块。 - 如果某个大块超过 token 上限(比如 800 token),再按三级标题或段落细分。
- 每个 chunk 头部带上"标题路径",比如"第三章 > 3.2 节 > 具体小节",这样检索时上下文更完整。
- chunk 之间保留一定重叠(overlap),一般 10%~15%,防止边界信息丢失。
按字数硬切的坏处,前面说过了,会把语义单元切碎。按标题切的好处是每个 chunk 语义自洽,检索时命中率高,喂给 LLM 时也不会出现半句话。
4.5 元数据设计:别忘了页码
这一步很多人偷懒不做,后面一定后悔。每个 chunk 至少要带这几个元数据:
| 字段 | 说明 | 用途 |
|---|---|---|
| source | 源文件名 | 区分不同文档 |
| page | 起始页码 | 答案溯源 |
| heading_path | 标题路径 | 提供上下文 |
| chunk_id | 唯一标识 | 去重、更新 |
有了 page 字段,用户问"这个结论哪来的",你能直接答"来自《XX 报告》第 23 页"。这个体验差距是巨大的,也是 RAG 产品能不能被信任的关键。
5. 实测中一定会踩的坑与排查思路
5.1 表格解析错位:最常见的翻车现场
表格是 PDF 解析的重灾区。我遇到过最离谱的一次,一份财务报表,解析出来数字全串行了,营收和成本对调,如果直接喂给模型,生成的财务分析完全是错的。
排查思路是这样的:先看原始 PDF 里表格是"真表格"还是"用空格对齐的假表格"。真表格(有边框线)相对好识别,假表格(纯靠空格对齐)极难,因为解析器分不清"这是表格的一列"还是"这是一段文字里的空格"。
处理办法:对关键表格,解析后做一次校验,比如检查每行的列数是否一致,不一致的标记出来人工核对。或者对表格区域单独走一次结构化提取,不要依赖通用解析。
5.2 双栏论文读串行
学术论文基本都是双栏,这是解析器的经典难题。表现是:左栏和右栏的文字被交替拼接,读起来完全不通顺。
判断方法很简单:解析出来的文本,如果读起来逻辑跳跃、句子接不上,八成是栏检测失败。解决办法是找支持栏检测的解析模式,或者在解析前先做版面分析,把页面按栏切开再分别解析。有些工具提供"阅读顺序"参数,可以手动指定。
5.3 页眉页脚污染
页眉页脚如果没剔除干净,会污染每一个 chunk。想象一下,每个 chunk 开头都是"XX 公司内部资料 第 X 页 机密",检索时这些词会干扰相似度计算。
剔除逻辑一般是:统计每页顶部/底部固定区域出现的文本,如果同一段文字在超过 50% 的页面出现,判定为页眉页脚。但有些文档页眉是章节名,每页不同,这种就剔不掉,得靠位置规则(比如页面顶部 5% 区域内的文字一律丢弃)。
5.4 OCR 识别错误:中文和公式是重灾区
OCR 对中文的识别,尤其是生僻字、繁体字、竖排文字,错误率明显高于英文。公式更是灾难,∑、∫、上下标基本认不对。
应对策略:对公式密集的文档(比如数学教材、物理论文),不要指望 OCR,要么找带公式识别的专用工具,要么干脆把公式区域截图,用多模态模型转成 LaTeX。关键词里"自然语言处理课本 pdf""cst 仿真设计理论与实践 pdf"这类,大概率公式很多,解析时要特别小心。
5.5 解析慢:大文档的时间成本
一份 500 页的扫描 PDF,走 OCR 可能要几十分钟甚至更久。如果文档量大,解析会成为整个流水线的瓶颈。
优化思路:解析任务异步化,不要阻塞主流程;已经解析过的文档做缓存,用文件哈希做 key,避免重复解析;OCR 部分可以并行,多进程或多线程跑。关键词里"rag 瓶颈"这个词很说明问题,很多人的 RAG 瓶颈根本不在检索,而在数据预处理。
6. 让解析结果真正服务于检索的几个进阶技巧
6.1 给 chunk 加上下文前缀
单纯一段文字,检索时容易歧义。比如 chunk 内容是"该指标同比增长 15%",脱离上下文根本不知道说的是什么指标。解决办法是在 chunk 前面加上下文前缀,比如"《2024 年财报》第三章 营收分析:该指标同比增长 15%"。这个前缀在 embedding 时一起编码,检索命中率会明显提升。
这个技巧本质上是把"标题路径"用自然语言表达出来,让向量模型能理解 chunk 的语境。
6.2 表格单独建索引
表格内容和正文的检索需求不一样。正文是语义检索,表格往往是精确查询("2023 年 Q3 营收是多少")。所以我会把表格单独抽出来,转成结构化的键值对或 JSON,存一份到支持结构化查询的地方,检索时正文走向量、表格走精确匹配,两条路并行。
6.3 保留原文位置,支持高亮回溯
如果解析时保留了每个 chunk 对应的原文坐标,前端就能做到"点击答案,跳转到 PDF 对应位置并高亮"。这个功能对专业用户(律师、研究员、财务)价值极高,是他们愿不愿意用你产品的分水岭。pdf-inspector 这类工具如果输出里带坐标信息,一定要留着,别嫌麻烦。
6.4 定期回归测试解析质量
解析器不是配好就一劳永逸的。文档来源会变,PDF 生成工具会变,解析效果也会波动。我建议建一个小型的回归测试集:挑 20 份有代表性的文档,人工标注关键内容,每次解析器升级或参数调整后,跑一遍看召回率有没有下降。这个投入不大,但能避免"悄悄变差"这种最难查的问题。
7. 关于工具选型的一点个人看法
市面上 PDF 解析方案大致分三档:纯开源库(灵活但效果参差)、云服务 API(效果好但按量收费、有数据合规顾虑)、专用工具(介于两者之间)。pdf-inspector 属于第三类,它的价值在于把 RAG 场景的常见需求做了针对性优化,省去你自己拼装各种库的功夫。
选型时我的判断标准就三条:解析质量能不能满足你的文档类型、能不能保留页码等元数据、出问题能不能定位和调整。第一条决定能不能用,第二条决定好不好用,第三条决定敢不敢用在生产环境。
最后分享一个我踩过的坑:早期我图省事,用了一个"一键转 Markdown"的工具,转出来看着挺漂亮,结果上线后发现表格全错、页码全丢,用户问"哪来的"我答不上来,只能推倒重来。从那以后我的原则是:解析环节宁可慢一点、麻烦一点,也要保证结构完整和可追溯。因为这是整条 RAG 链路的地基,地基歪了,上面盖得再高都是危房。
如果你现在正在做 RAG,文档又是 PDF 为主,我建议你花半天时间,拿几份最有代表性的文档,把 pdf-inspector 这类工具跑一遍,重点看表格、双栏、页眉页脚这三块的处理效果。这三块过了,后面的路会顺很多。