这段时间又帮几个朋友排查RAG项目效果翻车的问题绕来绕去最后都卡在同一个环节数据导入和解析。很多人把注意力全放在 embedding 模型和检索策略上却忽略了最前面的那一步——喂进去的到底是干净的文本还是一堆乱码。尤其是图文混排的 PDF、扫描件、带复杂表格的合同处理不好你后续做多少优化都白搭因为索引里存的就是错的向量。这篇文章是系列的第二篇专门聊图文与 PDF 解析。我核心想解决的问题有三个什么时候该上 OCR、多模态大模型在这种场景里到底扮演什么角色以及目前能用的九种 PDF 工具里各自适合哪类文件。主打一个可以直接抄作业的选型思路。1. PDF解析为什么是RAG项目里不可回避的第一道坎1.1 检索效果差先别急着换模型我见过太多团队的做法是这样的PDF 文件直接丢给 LangChain 的PyPDFLoader抽出一堆文本然后按字符数切块embedding 进向量库。表面看流程跑通了但一检索就发现结果驴唇不对马嘴。原因大多数不在模型而在解析环节把你的原始信息搞丢了或者搞乱了。PDF 本身是一个排版格式它的“文本”并不像 Word 或 Markdown 那样天然有序。它的文本可能被切割成碎片、按视觉位置排列也可能根本就是一张图片。如果你不先做解析层面的处理后面索引的质量就无从谈起。这也是我为什么把这一篇单独拿出来写的原因。你可能会想解析嘛不就是提取文本还真不是。在 RAG 场景里解析要做的是“把文档内容转化为语义上连续、结构上可分割的文本单元”。这个定义意味着你必须处理版面顺序、表格结构、页眉页脚干扰、扫描图像识别等一系列问题。任何一个环节掉链子你喂给 embedding 模型的就不是干净的句子而是一团乱码。1.2 “知识库能不能存图片”背后的真实问题在写这一篇之前我扫了一圈大家在搜索框里常问的问题出现频率很高的是类似“RAG 知识库能存储图片嘛”这种。说实话这个问题本身就隐含了一个理解误区。RAG 知识库当然可以存图片。你可以把图片转成一张 embedding 向量存进去也可以用多模态模型做图文联合检索。但在绝大多数实际业务场景里用户想从图片里拿到的其实是“图中的文字信息”比如扫描合同里的条款、产品手册里的参数表。如果你只是把整张图片塞给向量库而不做 OCR 或版面理解检索时根本没法命中图片内部的文字细节。所以章节目录写着 OCR 和多模态大模型本质上就是回答这个问题让知识库不仅能存图片还能读懂图片里的内容并把内容变成可检索的文本。理解了这个前提你才会知道为什么本节标题里的每一步都有它的具体价值。2. 动手之前先分清PDF的四种形态选错工具等于白干2.1 数字原生文本型PDF白送的文本层PDF 文件从生成方式上可以分成完全不同的两类。一类叫“数字原生 PDF”比如你用 Word 转出来的或者浏览器打印网页得到的。这类 PDF 内部包含一个文本层文字是真实可选的复制粘贴就能用。这种文件理论上解析成本最低直接用文本提取工具就能拿走内容。但“最低”不等于“不用管”。我遇到过很多文本层完整但版面非常混乱的 PDF多栏排版、文字间有大量空白、表格被切成了多个不相邻的片段。如果你直接按页提取纯文本原文语义顺序会被打乱后续切块也会跟着出偏差。所以即使是文本型 PDF也要考虑版面分析和阅读顺序还原的问题。如果你拿到的 PDF 是从方正排版系统、InDesign 这类专业排版工具导出的还得额外小心文字乱码问题。这些 PDF 可能使用了自定义编码的字体映射标准文本提取工具拿到的是诡异符号。遇到这种情况宁可走扫描件的处理路径也别在文本提取上死磕。2.2 纯扫描图像型与混合型该OCR就OCR第二种是纯扫描图像型 PDF。这种文件本质上是一叠图片打包在一起没有文本层你选中一段“文字”复制出来是一张图。典型例子是扫描仪扫描的纸质合同、传真件、老书影印本。对这种文件唯一可行的解析路径就是 OCR——光学字符识别。比纯扫描件更反直觉的是混合型 PDF同一个文件里前半部分是数字原生的文本页后半部分是扫描图片页。这种情况在招投标文件、审计报告里非常常见。如果你不做预判直接拿文本提取工具处理整个文件后半段的扫描页会全部变成空白信息直接丢失拿 OCR 工具处理整个文件前半段反而可能因为重复识别而变慢变乱。我在实际操作里的做法是先跑一个轻量探测脚本从前中后分别抽几页检查是否包含文本层对整份 PDF 做一个“文本层覆盖率”的判断。覆盖率低于某个阈值就整份文件送 OCR覆盖率介于中间就逐页分流处理。后面第五节我会给一个流水线思路。2.3 复杂版面型多栏、公式、表格处理策略第三种类型是复杂版面型 PDF特征非常明显双栏甚至三栏排版、大量公式、嵌套表格、页眉页脚信息交错。典型场景是学术论文、技术标准、产品白皮书。这类文件最大的坑在于“阅读顺序还原”。直接用最基础的 PDF 文本提取工具按元素在页面上的坐标排序输出你得到的内容很可能是把先捞到的右栏文字排在左栏前面把页眉插在正文中间把表格单元格按乱七八糟的顺序吐出来。这种乱序文本一旦进入 RAG 的切块环节会直接破坏语义连贯性检索效果可想而知。处理复杂版面目前比较靠谱的是两条路一是用专门做版面分析的解析框架如 Unstructured 或 Marker 这类工具它们会对页面做元素检测再重新排序二是直接把整页视觉内容交给多模态大模型让它输出 Markdown 或 JSON 结构。前者确定性高、成本低后者对极端版面的鲁棒性更强但速度和成本需要评估。3. OCR与多模态大模型从“认字”到“理解版面”3.1 传统OCR的两步走文本检测与识别先说传统 OCR。它的完整管线一般分为两个大步骤文本检测把图片里的文字区域框出来和文本识别把框出来的区域转成字符。业界常用开源方案是 PaddleOCR 和 Tesseract。PaddleOCR 在中文场景下表现明显更好自带版面分析方向分类的能力对竖排文字也有支持。很多只调过一次 OCR 接口的人会高估它的能力上限。传统 OCR 本质上只解决“把像素变成文字”的问题它不负责理解这段文字在版面里是什么角色。它不知道哪个区域是标题、哪个是表格、哪个是页脚注释。所以在做 RAG 数据导入时我一般建议把传统 OCR 和多模态大模型分开看待OCR 是“认字工具”解决的是扫描件有没有文本可用多模态大模型是“理解工具”解决的是版面结构怎么还原。另外一个落地细节是PaddleOCR 这类工具对图片质量非常敏感。300 DPI 的扫描件和 72 DPI 的截图识别准确率能差出好几个百分点。如果你的输入是压缩过的扫描图片最好先做预处理灰度化、去噪、纠正倾斜角度。这是传统 OCR 工程里性价比最高的优化手段。3.2 多语言识别常见的坑比如韩文大家经常在网上搜到类似“以下ocr代码识别不了韩文 from paddlex create_pipeline”的问题。这种问题我一看就知道原因PaddleOCR 的默认模型是中文模型你直接用默认参数去跑韩文扫描件当然识别不了。多语言 OCR 不是“一个模型通吃”它会按语言加载不同的识别模型。搜索引擎里出现这类高频问题说明不少人默认 OCR 工具“什么语言都能处理”。实际的情况是你在初始化识别模型时得显式指定语言类型或者下载对应的多语言模型。PaddleOCR 官方仓库提供了包括韩文、日文、英文等在内的多语言模型识别前需要单独下载并加载。如果你处理的是中英混排、日韩文夹杂的文档我更推荐先用语言检测脚本对每页文本做判断再按内容路由到不同的 OCR 模型。而且一定要保留原始图片因为任何 OCR 都会出错后续如果发现识别质量问题你还能回炉重跑而不是拿着已经丢掉的图片唉声叹气。3.3 多模态大模型在解析里的定位多模态大模型入局之后图文解析的玩法确实变了。GPT-4o、Qwen-VL、InternVL 这些模型可以直接输入图片输出识别后的文字甚至结构化描述。它们的优势不在“认识单个文字”的准确率而在对整体版面的理解能力。举一个实际案例一篇双栏论文你需要把每个栏的文字按阅读顺序整理出来并保留标题层级。传统 OCR 加上规则可以实现但规则非常脆弱换个版式可能就要重新调参数。多模态模型则可以直接“看图说话”告诉你了哪些是标题、哪些是正文、表格长什么样。这种能力对 RAG 的文档解析来说是质的变化。但也有坑。多模态大模型不是专门为 OCR 设计的在生僻字、极小字号、复杂数学符号上它的识别准确率可能不如专用 OCR 模型。它还存在“幻觉”问题即会自己脑补不存在的文字这在准确率敏感的场景里很致命。所以我的实际经验是用多模态做版面理解和结构化用传统 OCR 做纯字符识别两者配合而不是二选一。3.4 合同类文档的关键字段抽取经验这里顺便讲一个高频场景从合同里抽取收入、单位、时间等关键字段。市面上的做法分两种流派。一派是直接调用云厂商 OCR 接口比如百度 OCR 的合同识别 API。另一派是先做版面分析和字段锚定再用 LLM 做结构化提取。只用云 OCR 接口有个隐蔽问题它对“字段”的理解和你的业务需求不一定相同。比如那个知名的报错“error_msg: file format error”很多用户在调用合同识别接口时传了 PDF 文件但接口要求的是图片文件。你需要先对 PDF 做渲染转图片再上传识别。这一步不做接口直接卡死而且报错信息不会明确告诉你该怎么做。走 LLM 提取路线时我自己的经验是不要直接让模型读整页图片。尽量先通过 OCR 拿到带坐标的文本块然后按空间位置拼接成段落再交给 LLM。这样做的好处是保留版面顺序信息、减少幻觉空间LLM 只做最后的字段映射工作量可控错误也更容易定位。4. 九种PDF工具逐个拆解该用哪个一眼看清4.1 轻量文本提取三兄弟先说三个做基础文本提取最常用的库PyMuPDF、pdfplumber、pypdf。PyMuPDF 也就是 fitz是我在绝大多数项目里的首选。它解析速度快得惊人同时保留文本坐标、字体、颜色这些布局信息还内置了简单的版面重建功能。一篇几百页的 PDF用它提取文本是毫秒级的事。它的内核基于 MuPDF对复杂 PDF 的渲染兼容性也很强很多别的库解析失败的文件它都能打开。pdfplumber 的特点是“慢但准”。它特别适合处理表格。它能精确到字符级别的坐标提供表格网格探测能力能应对很多带边框的规范表格。缺点是性能开销大一个上百页的文件跑起来能明显卡顿。所以我的用法是pdfplumber 只负责表格密集的页面常规页面不要用它。pypdf 是最轻量、最纯粹的选择。它只能做最基础的文本提取和页面合并切割几乎不提供版面分析能力。它的价值在于没有过多的依赖部署简单适合做 PDF 的预处理骨架比如拆分页面、获取页数、做简单的文本提取。在复杂版面面前它和 PyMuPDF 的差距会非常明显。4.2 表格专用工具如果你的文档里表格占比高只靠上面的通用库很难产出高质量结果这时候要看 Camelot 和 tabula-py。Camelot 的设计思路是把 PDF 页面当成图片一样分析网格线然后重建表格行列。它对有线框的“线型表格”命中率很高能输出非常精确的单元格内容。它也有一个缺点参数敏感。table_areas、flavor这些参数不调一批样本直接跑全量文档效果极不稳定。所以用 Camelot 前一定要准备一批标注好的样本页面来做参数调优。tabula-py 底层依赖 Java 的 tabula-java它提取表格的策略偏“按间距识别”而不是按线框识别。这意味着它更适合无线框、靠空白对齐的表格。对线框表格如果线框恰好不完整它很容易把相邻列并到一起。实用建议是同一个表格两种工具都跑一遍对比输出哪个更符合原始结构再选择批量处理方案。4.3 面向RAG的全流程解析框架接下来是四个面向 RAG 场景的全流程框架Unstructured、LlamaParse、LangChain 内置的 PDFLoader 系列、MinerU。Unstructured 是我个人在 RAG 项目里用得最多的框架。它会自动走“元素检测——分类——提取”的流程把一个 PDF 页面拆分成标题、正文、表格、图片、页脚等不同元素然后按类别输出。配合它的 partition 函数你可以直接把版面结构保留下来再转成自定义的切块逻辑。它对混合型文档的支持也比较好能自动判断哪些区域走 OCR。LlamaParse 是有官方托管服务的商业解析框架由 LlamaIndex 团队出品。它最独特的地方是支持用自然语言描述你的解析策略直接输出 Markdown 格式的解析结果。比如你告诉它“把表格转换成 Markdown 表格保留嵌套结构”它就能照做。对复杂版面、扫描件的处理能力都很强但因为是云服务涉及敏感文档时要注意数据合规问题。LangChain 内置的PyPDFLoader、PDFMinerLoader这类工具本质上就是前文那些底层库的封装。它们的价值是方便你快速跑通 Demo价值上限不高。如果你已经理解了底层工具的能力就明白它们只适合做早期原型的 MVP不适合直接上生产。MinerU 是这两年开源社区里很亮眼的一个项目把版面分析、OCR、公式识别、阅读顺序还原整合在了一条流水线里。它能够直接输出 Markdown 格式对学术论文和扫描件表现相当好。它的部署有一定门槛但效果已经逼近商业解析 API而且完全可以在本地跑适合对数据隐私敏感的场景。4.4 九种工具选型总表为了方便对比我把这九个工具整理成一个选型表格。我在实际项目里做技术评审时一般就是按这张表的维度来打分工具定位强项弱项适合场景PyMuPDF (fitz)轻量文本提取极快保留坐标信息无版面语义理解大批量文本型PDF秒级提取pdfplumber精确字符级提取表格探测能力强慢资源占用高表格密集页面精细提取pypdf极简单文本处理官方稳定依赖少功能过于基础PDF拆页、页数统计、MVP原型Camelot线框表格提取网格重建精度高参数敏感需调优带完整边框的规范表格tabula-py空白对齐表格提取无线框表格效果好Java依赖列错位风险无边框排版表格Unstructured全流程版面解析框架元素分类完善生态好对极端版面仍需调参数RAG项目生产级解析主链路LlamaParse商业托管解析服务自然语言控制输出格式云服务数据出域复杂版面/需Markdown输出的场景LangChain PDFLoader框架封装工具快速跑通RAG Demo能力上限低原型验证不推荐生产MinerU开源本地完整解析方案版面分析OCR公式一体化部署部署门槛较高学术论文、隐私敏感文档5. 我目前在用的图文导入流水线5.1 第一步文件拓扑预判我不会一上来就对整个 PDF 跑解析而是先做一次“文件拓扑预判”。具体包括三件事页数、是否包含文本层、每页是否包含图片对象。这段逻辑可以用 PyMuPDF 跑代码量不大但能节省后面几个小时的无效计算。基于这些信息我可以把文件分到几条处理路径里。比如文本层层覆盖率高→快速文本路径覆盖率中等→逐页分流路径完全没有文本层→整份 OCR 路径。在实际项目里这一步做得好后面所有工具的性能都会稳定很多。5.2 第二步分路径解析文本型页面走 PyMuPDF 提取重点注意阅读顺序的还原。如果发现版面是双栏就要配合坐标排序做重构或者直接把页面交给 Unstructured 让它做智能元素分析效率更高。扫描型页面走 OCR。我的常规方案是先做图片预处理然后调用 PaddleOCR 获取带坐标和置信度的文本块最后按位置顺序拼接。如果是合同、发票这类需要抽取关键字段的文档我会直接调用专门的结构化识别接口宁可多花一点成本也要减少后期 LLM 的纠错负担。5.3 第三步清洗与切块解析完之后我做三件事过滤页眉页脚和页码合并被错误的切碎的标题与段落把表格转成 Markdown 形式而不是纯文本。这三件事做完文本质量才能满足切块的要求。切块策略我基本不做固定长度硬切而是优先按标题层级做语义切块。标题和层级信息来源于解析阶段保留的版面元素。这样切出来的每一段都有明确的主题边界向量检索的召回质量会比无脑按字符切好不少。保留元数据也非常关键页码、来源文件名、解析方式、章节路径这些都是后续做过滤和引用溯源的基础。5.4 几个实际落地细节说几个经常被忽略的落地细节。一是很多人不知道 PDF 里的字体编码可能不标准在 PyMuPDF 中提取时如果发现个别文本乱码优先尝试page.get_text(rawdict)近底层的数据有时能捞回更多有效信息。二是对超长 PDF 建议先按页拆分处理处理完再合并结果避免单页异常引起全流程失败。三是所有解析步骤都要加日志和报错兜底批量导入数据这种场景“静默失败”比报错的破坏性大得多。6. 解析后的清洗与元数据管理6.1 版面上的“噪声”处理PDF 解析完成后文本里通常混着不少版面噪声页眉页脚、页码、水印、运行页眉、版权信息。这些东西如果不清洗最后都会进 embedding 成为检索干扰项。比如用户搜“第 3 章 模型架构”结果把每页底部的“chapter_3.draft_v6.doc”都召回来了毫无意义。我的清洗方式是两层第一层基于位置和字体特征把重复出现在每页固定位置的元素识别为页眉页脚并剔除第二层基于规则把“第 X 页 共 Y 页”“第 1 章 概述”这类导航性文本从正文块中剥离。这两层做完再把剩下的内容做一次空白压缩和非法字符过滤得到的就是可以进入切块管线的干净正文。6.2 表格转Markdown而不是纯文本我再强调一次表格最好转换成 Markdown 格式不要转成纯文本。RAG 检索本质上是语义相似度检索你把表格碾成一行行纯文本每个单元格就被切得支离破碎检索时很难还原出“哪一列的哪个单元格对应哪一行”。转成 Markdown 表格之后至少每行还保留了列的结构语义对于一个三列的对比表检索到其中一个单元格时上下文里还能带上对应的表头信息效果会好非常多。如果表格特别复杂嵌套单元格跨行跨列我建议直接截取该区域的图片配合多模态大模型生成结构化描述而不是强行用文本工具还原。6.3 有关图片、元数据和知识库形态的经验前面提到过“RAG 知识库能不能存图片”这个问题这里说最后的结论。可以存图片但要让图片能被文本检索机制命中必须同时把图片内的文字抽取出来建立文本索引。如果图片中的重要信息是图表、流程图这种没法用文字表达的结构那就得借助视觉模型做图向量的联合检索。另外还有一个容易被忽视的知识库形态问题有些信息适合结构化存储比如部门关系、产品架构、知识之间的层级关联。RAG 的向量检索并不擅长表达这种关系。你看搜索引擎里高频出现的“kg知识库、rag知识库和结构知识库区分以及应用场景”本质上就是在问这个问题。我的实际经验是把解析出来的文本按实体关系抽取后喂给图数据库再配合 RAG 做混合检索才能覆盖“语义模糊查询”和“精确关系查询”两种需求。解析阶段保留的元数据在这种混合架构里是关键的关联桥梁。最后说点我个人的体会。图文和 PDF 解析这个环节最大的特点就是“情况永远比你预想的多”。同一个工具换一份文档就可能出现完全不同的表现。所以别指望找到一个万能武器而是要把工具组合、预判分流、清洗兜底这套流程跑通。按这个思路把你的导入管线搭出来之后你会明显感觉到后续的检索质量上了个台阶。这个系列后面的文章我会接着讲文本切块策略和向量检索细节到时候再和大家细化聊。