1. 为什么图文与 PDF 解析是 RAG 落地最脏最累的活做过 RAG 项目的人都有一个共识模型选型、向量库搭建、检索策略调优这些环节网上教程一抓一大把照着抄基本能跑通。但真正让项目卡壳、延期、甚至翻车的往往是最不起眼的一步——数据导入与解析。尤其是当你面对的是图文混排的 PDF、扫描件、带表格的合同、带公式的论文时你会发现前面所有漂亮的架构设计都在这一刻变得苍白。我前后经手过六七个 RAG 知识库项目从企业内部制度问答到合同关键字段抽取从技术文档检索到问卷 OCR 识别踩过的坑几乎都集中在解析层。一个很典型的场景客户给了一批 PDF 制度文件你以为直接丢进解析器就完事了结果打开一看有的是原生电子版有的是扫描件有的扫描件还带水印和倾斜有的表格跨页断裂有的图里嵌着关键信息。这时候你才会真正理解为什么说 RAG 的瓶颈不在检索而在数据入口。这篇内容就是把我这些年做图文与 PDF 解析的经验系统梳理一遍。核心围绕三件事展开OCR 怎么选、多模态大模型在解析里扮演什么角色、九种主流 PDF 解析工具到底该怎么选型。适合正在做 RAG 知识库、需要处理大量非结构化文档的开发者也适合刚接触 RAG 想搞清楚数据层门道的朋友。我不会只告诉你“用某某工具”而是把每个选择背后的逻辑、参数怎么定、坑在哪里都讲清楚让你能直接抄作业。2. 图文与 PDF 解析的整体设计思路拆解2.1 先搞清楚你的 PDF 到底是哪一类很多人一上来就问“哪个 PDF 解析工具最好”这个问题本身就问错了。PDF 不是一个格式它是一堆格式的容器。同样是 .pdf 后缀内部结构可能天差地别。我在动手之前一定会先做一次文档分类把待处理的 PDF 分成三大类因为不同类别的处理路径完全不同。第一类是原生电子版 PDF也就是从 Word、LaTeX、网页打印导出的那种。这类 PDF 内部有完整的文本层文字是可选中、可复制的解析器能直接读取字符流。处理这类文档最省事甚至不需要 OCR直接用文本提取工具就能拿到高质量内容。第二类是扫描版 PDF本质是一堆图片打包成的 PDF。里面的“文字”其实是像素没有任何文本层。这类必须走 OCR 或者多模态大模型识别。扫描件的质量差异极大有的 300dpi 清晰扫描有的手机拍照歪歪扭扭还带阴影识别难度天差地别。第三类是混合型 PDF也是最恶心的一类。同一个文件里有的页面是原生文本有的页面是扫描图有的页面文字是文本层但表格是图片。这种文档如果只用单一策略处理必然有一部分内容丢失。提示动手前先用工具批量检测 PDF 是否含文本层能省掉大量无用功。判断方法很简单用 PyMuPDF 读取每页的文本如果某页提取出的字符数接近零基本可以判定是扫描页。2.2 解析策略为什么要分层设计搞清楚文档类型之后解析策略就应该分层。我的习惯是把整个解析流程拆成四层文本层提取、版面分析、OCR 识别、结构化重组。这四层不是每个文档都要全走一遍而是根据文档类型按需组合。文本层提取优先。只要 PDF 有文本层就先把它抽出来这是成本最低、准确率最高的方式。PyMuPDF、pdfplumber 这类库在这一层表现很好。但要注意文本层提取出来的内容往往是乱序的尤其是多栏排版、带页眉页脚的文档直接抽出来会串行。版面分析是承上启下的关键。它的任务是判断页面上哪些区域是正文、哪些是标题、哪些是表格、哪些是图片、哪些是页眉页脚。这一步做不好后面 OCR 和重组都会受影响。传统方案用规则和投影分析现在越来越多用深度学习模型做版面检测。OCR 识别只针对图片区域。这里有个重要原则能不用 OCR 就不用 OCR。OCR 会引入识别错误而错误一旦进入向量库检索出来的内容就是错的模型再强也救不回来。所以只有当文本层确实拿不到内容时才动用 OCR。结构化重组是把前面拿到的碎片拼回有语义的文档。表格要还原成表格标题要建立层级图片要保留位置和说明。这一步直接决定了 chunk 切分的质量而 chunk 质量又直接决定检索效果。2.3 多模态大模型改变了什么多模态大模型的出现让 PDF 解析这件事的逻辑发生了根本变化。以前我们做解析是“先识别文字再理解结构”现在是“直接让模型看图说话”。像 GPT-4V、Qwen-VL 这类模型你把一页 PDF 截图丢进去它能直接输出结构化的 Markdown表格、标题、正文分得清清楚楚。这个变化的意义在于它把版面分析和 OCR 两步合并成了一步而且对复杂版面的理解能力远超传统方案。尤其是那种图文混排、表格嵌套、带公式的页面传统 OCR 加规则的方式几乎无解多模态模型却能处理得不错。但多模态大模型不是银弹。它的成本高一页 PDF 调一次 API 的费用可能是传统 OCR 的几十倍它的速度慢大批量文档处理时延迟明显它还有幻觉问题偶尔会“脑补”出原文没有的内容。所以我的实践原则是多模态大模型用在最难啃的页面上简单页面走传统流程。这种混合策略能在成本和效果之间取得平衡。3. OCR 选型从 Tesseract 到多模态的完整对比3.1 传统 OCR 引擎的适用边界传统 OCR 引擎里Tesseract 是绕不开的名字。它开源、免费、支持多语言社区资料丰富。但说实话Tesseract 在中文场景下的表现只能算及格。它对清晰、规整、无旋转的印刷体识别率还行一旦遇到倾斜、模糊、复杂背景错误率就飙升。而且 Tesseract 的版面分析能力很弱多栏排版经常串行。PaddleOCR 是我在中文场景下更推荐的选择。它由国内团队开发对中文的识别效果明显优于 Tesseract尤其是对表格和版面结构的处理更成熟。PaddleOCR 提供了检测、识别、版面分析、表格识别等一整套能力而且有轻量级模型可以在 CPU 上跑部署成本可控。百度 OCR、腾讯 OCR 这类云服务适合对准确率要求高、又不想自己维护模型的场景。它们的识别效果通常比开源方案好一截尤其是对复杂版面和手写体的处理。代价是要按调用量付费而且数据要上传到云端涉及敏感文档时需要考虑合规问题。注意OCR 语言包的选择很关键。处理中文文档时一定要确认加载了中文语言包。我见过有人用默认的英文包跑中文 PDF结果识别出一堆乱码还找不到原因。福昕这类 PDF 编辑器需要单独下载 OCR 语言包PaddleOCR 则要在初始化时指定 lang 参数。3.2 云 OCR 与本地 OCR 的取舍云 OCR 和本地 OCR 的选择本质上是在准确率、成本、数据安全三者之间做权衡。我整理了一张对比表方便你根据自己的场景快速判断。维度本地开源 OCR云 OCR 服务多模态大模型识别准确率中等依赖文档质量高复杂版面表现好很高理解语义处理速度快可批量并行受网络和配额限制慢逐页调用成本一次性部署边际成本低按量付费量大成本高最贵按 token 计费数据安全数据不出本地需上传云端需上传云端复杂版面弱较强强表格还原需额外处理部分支持支持好部署难度中等低低我的经验是大批量、格式规整、非敏感的文档走本地 OCR小批量、格式复杂、对准确率要求高的走云 OCR最难啃的少量页面走多模态大模型。这种分层策略在实际项目里最经济也最稳。3.3 OCR 预处理决定成败的隐形环节很多人 OCR 效果差问题不在引擎而在预处理。扫描件直接丢给 OCR和经过预处理再丢给 OCR识别率能差出二三十个百分点。预处理主要做几件事。图像去噪和二值化。扫描件常有噪点、阴影、底色不均二值化能把图像转成黑白让文字和背景分离。OpenCV 的 adaptiveThreshold 比全局阈值更适合处理光照不均的文档。倾斜校正。扫描时纸张放歪了文字就是斜的OCR 识别率会大幅下降。用霍夫变换检测文本行角度然后旋转校正这一步对手机拍照的文档尤其重要。分辨率调整。OCR 引擎对分辨率有最佳区间一般 300dpi 左右效果最好。分辨率太低文字糊成一团太高则处理慢且可能引入噪声。如果原图分辨率不够可以适当上采样但别指望能把糊的字变清晰。版面切分。把页面切成文本区、表格区、图片区分别处理。表格区单独走表格识别文本区走 OCR图片区保留原图。这样能避免表格线被当成文字识别。import cv2 import numpy as np def preprocess_for_ocr(image_path): img cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) # 去噪 img cv2.fastNlMeansDenoising(img, h10) # 自适应二值化 binary cv2.adaptiveThreshold( img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 31, 10 ) # 倾斜校正 coords np.column_stack(np.where(binary 128)) angle cv2.minAreaRect(coords)[-1] if angle -45: angle 90 angle (h, w) binary.shape[:2] center (w // 2, h // 2) M cv2.getRotationMatrix2D(center, angle, 1.0) rotated cv2.warpAffine( binary, M, (w, h), flagscv2.INTER_CUBIC, borderModecv2.BORDER_REPLICATE ) return rotated这段预处理代码我在多个项目里复用对扫描件的识别率提升很明显。当然具体参数要根据文档特点微调比如噪点多的文档 h 值可以调大文字细的文档二值化窗口要调小。4. 多模态大模型在 PDF 解析中的实战用法4.1 什么场景该上多模态大模型多模态大模型不是用来替代 OCR 的而是用来解决 OCR 解决不了的问题。我总结了几类必须上多模态的场景。复杂表格。跨页表格、合并单元格、嵌套表头这些用传统表格识别工具经常还原错乱。多模态模型能理解表格的语义结构还原准确率高很多。图文混排且图中有信息。比如产品手册里参数写在图上或者流程图里嵌着关键步骤。传统 OCR 只能识别文字理解不了图文的对应关系多模态模型能一起处理。公式和特殊符号。学术论文里的数学公式传统 OCR 基本无能为力多模态模型能转成 LaTeX。低质量扫描件。模糊、倾斜、有遮挡的文档传统 OCR 错误率高多模态模型的鲁棒性更好。反过来纯文本、格式规整的页面就没必要上多模态用传统方案又快又便宜。4.2 提示词设计决定输出质量用多模态大模型解析 PDF提示词的设计直接决定输出质量。我踩过的坑是一开始提示词写得太简单比如“请提取这页 PDF 的文字”结果模型输出的格式五花八门有的用 Markdown有的用纯文本表格还原得也不稳定。后来我固定了一套结构化提示词模板效果稳定很多。核心思路是明确告诉模型输出格式是什么、表格怎么表示、图片怎么标注、公式怎么处理。你是一个专业的文档解析助手。请将这张 PDF 页面图片转换为结构化的 Markdown 格式。 要求 1. 标题用 # ## ### 表示层级根据字号和位置判断 2. 正文段落保持原顺序不要合并或拆分 3. 表格用 Markdown 表格语法还原保持行列对应关系 4. 图片用 [图片: 简要描述] 标注描述图片内容 5. 数学公式用 LaTeX 表示行内用 $ $独立公式用 $$ $$ 6. 页眉页脚和页码忽略不要输出 7. 如果某部分无法识别用 [无法识别] 标注不要编造内容 请直接输出 Markdown不要添加任何额外说明。这套提示词的关键在于最后一条“不要编造内容”。多模态模型的幻觉在文档解析里很致命它会“脑补”出原文没有的文字一旦进入知识库就是污染。明确禁止编造能压住大部分幻觉。4.3 成本控制与批量处理策略多模态大模型按 token 计费一页 PDF 截图转成 base64 后 token 数不小大批量处理成本很可观。我算过一笔账一页 A4 扫描件图片编码后大约消耗 1000 到 2000 个视觉 token加上输出 token单页成本在几分钱到一毛钱之间。一千页文档就是几十到上百块一万页就是几百到上千块。控制成本的核心思路是只把多模态用在刀刃上。具体做法是先用轻量方案做一遍预判能提取文本层的直接提取能 OCR 且置信度高的直接 OCR只有那些文本层为空、OCR 置信度低、或者版面复杂的页面才送去多模态模型。另一个技巧是图片压缩。多模态模型对图片分辨率有上限超过上限会被压缩所以没必要传超大图。把页面截图压到模型支持的最佳分辨率既能省 token 又不影响识别效果。一般长边压到 1500 到 2000 像素就够了。批量处理时还要注意并发控制。多模态 API 通常有速率限制并发太高会被限流。我的做法是用队列加信号量控制并发数同时做好失败重试。重试要区分错误类型限流错误退避重试内容错误直接跳过并记录。5. 九种 PDF 解析工具选型全对比5.1 工具选型的四个核心维度选 PDF 解析工具我一般看四个维度文本提取质量、版面理解能力、表格处理能力、部署与成本。这四个维度覆盖了 RAG 场景下最关心的点。文本提取质量决定基础内容准不准。版面理解能力决定多栏、图文混排能不能正确处理。表格处理能力决定结构化数据能不能还原。部署与成本决定能不能规模化落地。不同工具在这四个维度上各有侧重没有全能选手。所以选型的关键不是找“最好的”而是找“最适合你文档特点的”。5.2 九种工具逐一拆解PyMuPDFfitz。文本提取的首选速度快、依赖少、API 简洁。对原生电子版 PDF 的文本提取质量很高还能提取图片、获取页面坐标。缺点是版面分析能力弱表格处理基本靠坐标自己拼。适合作为解析流程的第一层。pdfplumber。表格提取能力比 PyMuPDF 强能基于线条和文字位置还原表格结构。对规整表格效果好复杂表格会力不从心。速度比 PyMuPDF 慢适合表格多的文档。PaddleOCR。中文 OCR 的性价比之王。检测、识别、版面分析、表格识别一条龙有轻量模型能 CPU 跑。适合大批量中文扫描件处理。缺点是复杂版面仍需调优表格还原偶尔出错。Tesseract。老牌开源 OCR多语言支持好但中文效果一般版面分析弱。适合英文文档或者作为备选方案。百度 OCR / 腾讯 OCR。云服务识别准确率高复杂版面和手写体表现好。适合对准确率要求高、数据不敏感的场景。按量付费量大成本高。MinerU。专门为 RAG 场景设计的 PDF 解析工具对学术论文、技术文档的处理很到位公式、表格、图注都能较好还原。开源可本地部署适合处理论文类文档。Marker。基于深度学习的 PDF 转 Markdown 工具版面理解和表格还原能力强输出格式干净。速度较慢对硬件有要求适合质量优先的场景。Unstructured。功能全面的文档解析库支持多种格式PDF 解析支持多种策略。生态好和 LangChain 等框架集成方便。缺点是 PDF 解析质量依赖底层引擎需要配置。多模态大模型GPT-4V / Qwen-VL 等。复杂版面的终极方案理解能力强但成本高、速度慢、有幻觉。适合作为兜底方案处理最难啃的页面。5.3 选型决策表与组合策略把上面的分析整理成决策表方便你快速定位。文档特点首选方案备选方案说明原生电子版纯文本PyMuPDFpdfplumber直接提取文本层原生电子版表格多pdfplumberPyMuPDF 坐标拼接表格提取更强扫描件中文规整PaddleOCR云 OCR性价比高扫描件中文复杂云 OCR多模态大模型准确率优先扫描件英文TesseractPaddleOCR英文场景够用学术论文带公式MinerUMarker公式还原好图文混排复杂版面Marker多模态大模型版面理解强最难啃的少量页面多模态大模型人工校对兜底方案多格式混合文档Unstructured按类型分流生态好实际项目里我很少只用一种工具而是组合使用。典型流程是PyMuPDF 先提取文本层判断哪些页面需要 OCR需要 OCR 的页面走 PaddleOCRPaddleOCR 置信度低的页面送多模态模型表格页面用 pdfplumber 或 MinerU 单独处理。这种流水线式的组合策略能在成本和质量之间取得最好的平衡。6. 完整实操流程与关键环节实现6.1 从 PDF 到结构化 Markdown 的完整流水线我把整个解析流程串成一个可复现的流水线你可以直接参考这个结构搭建自己的解析模块。第一步是文档预检。遍历 PDF 每一页用 PyMuPDF 提取文本统计每页字符数。字符数大于阈值的标记为文本页接近零的标记为扫描页。同时记录每页是否含图片、图片面积占比。第二步是文本页处理。文本页直接用 PyMuPDF 提取但要做后处理去除页眉页脚通过位置和重复内容判断、合并断行、恢复段落。多栏排版的页面要用版面分析确定阅读顺序。第三步是扫描页处理。扫描页先做图像预处理然后走 OCR。OCR 结果要带置信度低置信度的区域标记出来。表格区域单独切出来走表格识别。第四步是复杂页兜底。OCR 置信度低、或者版面分析判定为复杂的页面截图送多模态模型。模型输出直接作为该页的解析结果。第五步是结构化重组。把各页的解析结果按顺序拼接统一成 Markdown 格式。标题层级要跨页保持连续表格要处理跨页断裂图片要保留引用关系。第六步是质量校验。抽样检查解析结果重点看表格是否错乱、公式是否丢失、文字是否有大量识别错误。发现问题回溯到对应环节调整。import fitz # PyMuPDF def classify_pdf_pages(pdf_path, text_threshold50): doc fitz.open(pdf_path) page_types [] for page_num, page in enumerate(doc): text page.get_text() char_count len(text.strip()) images page.get_images() image_area sum( page.get_image_bbox(img).get_area() for img in images ) if images else 0 page_area page.rect.get_area() image_ratio image_area / page_area if page_area else 0 if char_count text_threshold: page_types.append((text, page_num)) elif image_ratio 0.5: page_types.append((scan, page_num)) else: page_types.append((mixed, page_num)) doc.close() return page_types这段分类代码是整个流水线的入口跑一遍就能知道文档的构成后续按类型分流处理。6.2 表格解析的难点与破解表格是 PDF 解析里最容易翻车的部分。我遇到过的表格问题包括跨页断裂、合并单元格、无边框表格、嵌套表头、表格里嵌图片。每一种都有对应的处理思路。跨页表格的处理关键是识别表头重复。很多文档跨页时会在新页重复表头解析时要检测到重复表头并合并。判断方法是比较相邻页表格的首行内容如果高度相似就认为是同一张表的延续。无边框表格最难因为没有线条可依赖只能靠文字对齐关系推断。pdfplumber 的 text 策略能处理一部分但准确率有限。这种表格我一般直接送多模态模型让它理解表格结构。合并单元格在 Markdown 里没有原生语法通常用空单元格或者重复内容表示。解析时要记录合并信息重组时再决定怎么表示。如果下游是向量库其实可以接受一定程度的表格结构损失因为检索时更关注内容而非格式。实操心得表格解析不要追求 100% 还原。RAG 场景下表格内容能被检索到、语义能被理解就够了。花大量精力去完美还原表格格式性价比很低。我通常的做法是把表格转成“表头: 值”的键值对形式这种形式对检索最友好。6.3 图片与图注的关联处理RAG 知识库能不能存图片这是很多人问的问题。答案是能但要处理好。图片本身不能直接进向量库需要转成文本描述或者多模态向量。我的做法是图片用多模态模型生成描述描述文本和图注一起作为该图片的检索内容。图片原图存对象存储向量库里存描述文本加图片 URL。检索命中描述后返回图片链接供展示。图注的关联也很重要。很多文档里图片和它的说明文字是分开的解析时要根据位置关系把它们关联起来。一般图注在图片下方或上方距离最近的文字块大概率是图注。def extract_images_with_captions(page): images page.get_images(fullTrue) results [] for img in images: bbox page.get_image_bbox(img) # 查找图片下方最近的文本块作为图注 caption min_dist float(inf) for block in page.get_text(blocks): block_rect fitz.Rect(block[:4]) if block_rect.y0 bbox.y1: dist block_rect.y0 - bbox.y1 if dist min_dist and dist 50: min_dist dist caption block[4].strip() results.append({ bbox: bbox, caption: caption, image: img }) return results这段代码把图片和它下方的图注关联起来距离阈值 50 像素是根据常见排版定的实际项目里可以调整。7. 常见问题与排查技巧实录7.1 解析质量问题的排查思路解析出问题时排查要按层次来不要一上来就换工具。我的排查顺序是先看原始 PDF 类型判断对不对再看预处理到不到位然后看工具参数配没配对最后才考虑换方案。文字乱码或串行。先确认 PDF 是不是多栏排版如果是多半是阅读顺序判断错了。检查版面分析环节看有没有正确识别分栏。另外确认字体编码有些 PDF 用了特殊编码提取出来就是乱码这种情况只能走 OCR。OCR 识别率低。先看图像质量是不是分辨率太低或者太模糊。然后看预处理二值化和倾斜校正做了没有。再看语言包中文文档有没有加载中文包。最后看 OCR 引擎选择Tesseract 中文效果差就换 PaddleOCR。表格错乱。先判断表格有没有边框无边框表格传统工具处理不好直接上多模态。有边框的检查线条检测参数线条太细或太浅可能检测不到。跨页表格检查表头合并逻辑。内容丢失。检查是不是有页面被判定为空白跳过了或者图片区域的内容没被提取。有些 PDF 的文字是以矢量图形绘制的文本层提取不到需要走 OCR。7.2 性能与成本优化技巧大批量文档处理时性能和成本是绕不开的。我总结了几个实用的优化点。并行处理。PDF 页面之间相互独立可以多进程并行。Python 的 multiprocessing 或者 concurrent.futures 都能用。注意 OCR 模型加载有开销每个进程加载一次模型不要每页都加载。缓存中间结果。解析流程分多步每步的结果都缓存下来。这样调整某一步的参数时不用从头跑。我用文件哈希做 key把每页的解析中间结果存本地调试时省大量时间。按需调用云服务。云 OCR 和多模态都按量付费要严格控制调用量。先用本地方案跑一遍只把失败的页面送云端。同时做好去重相同内容的页面不要重复调用。分辨率权衡。OCR 和多模态对分辨率都有最佳区间太高浪费算力太低影响识别。一般 OCR 用 300dpi多模态长边 1500 到 2000 像素这个区间性价比最高。7.3 常见问题速查表问题现象可能原因排查方向解决方案提取文本为空扫描件无文本层检查字符数走 OCR 流程文字乱码字体编码特殊检查字体信息改用 OCR多栏串行阅读顺序错误检查版面分析用版面检测模型OCR 错误多图像质量差检查分辨率倾斜预处理后重试表格错乱无边框或跨页检查表格结构多模态模型处理公式丢失OCR 不支持公式检查页面类型MinerU 或多模态处理速度慢单进程串行检查并发配置多进程并行成本过高云服务调用多统计调用量本地优先云端兜底内容重复页眉页脚未去除检查重复内容位置加内容双重过滤图片信息丢失图片未处理检查图片提取多模态生成描述这张表基本覆盖了我遇到过的绝大多数问题排查时按表走能快速定位。8. 我踩过的坑和几条实在建议做 RAG 数据解析这几年有几个坑我印象特别深分享出来帮你少走弯路。第一个坑是过度依赖单一工具。早期我迷信某个工具能包打天下结果遇到混合型 PDF 就傻眼了。后来才明白解析一定是组合拳没有哪个工具能通吃所有文档。现在我的解析模块里同时集成了四五种工具按页面类型分流稳定性高很多。第二个坑是忽视预处理。有次处理一批手机拍照的文档OCR 识别率惨不忍睹我以为是引擎不行换了好几个引擎都没改善。后来加了倾斜校正和去噪识别率直接上了一个台阶。预处理这步看着不起眼实际影响巨大。第三个坑是追求完美解析。一开始我总想把每个表格、每个公式都完美还原花了很多时间调参数。后来发现 RAG 场景下检索效果对解析精度的敏感度没那么高内容大致正确、语义完整就能用。把精力花在检索和生成环节收益更大。第四个坑是忽略成本核算。有次项目用了云 OCR 加多模态跑完一批文档发现费用超预算好几倍。后来改成分层策略简单页面走本地复杂页面才上云成本降了七八成效果几乎没损失。最后分享一个实用技巧建立解析质量评估集。从你的文档里挑几十页有代表性的人工标注正确结果每次调整解析方案后跑一遍评估集看准确率变化。这样调优有依据不会凭感觉瞎调。评估集不用大覆盖各种文档类型就行几十页足够反映问题。解析这层做扎实了后面的检索和生成才有意义。数据入口的质量决定了整个 RAG 系统的天花板。