文档加载远不止“打开文件”
在 RAG 链路中,原始资料首先要经过文档解析。很多检索问题表面上像是 Embedding 不够强,向前追查却会发现:标题被当成正文,双栏内容顺序错乱,表格被拆成一串无意义数字,甚至扫描页根本没有识别出文字。
因此,文档加载至少包含四件事:读取文件、恢复结构、清理噪声、补充元数据。它的目标不是得到一大段字符串,而是输出能继续分块和检索的标准记录。
先分清数据类型
不同来源不能用同一种方式处理。
- TXT、Markdown 和结构规范的 HTML 通常已有明确文本与层级。
- Word、PDF 包含文字、图片、表格和版式信息,需要专门解析。
- CSV、Excel 和数据库属于结构化数据,应保留行列、字段类型和主键语义。
- 扫描件和图片没有可直接复制的文本,需要 OCR。
- 音频、视频要先做语音识别,并保留时间戳。
一个简单的路由器可以先按文件类型和内容特征选择解析器:
defchoose_parser(file):iffile.suffix==".pdf"andis_scanned_pdf(file):return"layout_ocr_parser"iffile.suffix==".pdf":return"pdf_layout_parser"iffile.suffixin{".docx",".odt"}:return"office_parser"iffile.suffixin{".md",".txt"}:return"plain_text_parser"raiseValueError(f"unsupported file:{file.suffix}")这里不能只看扩展名。一个 PDF 可能同时包含可复制文本和扫描图片,甚至同一页上两种内容并存。生产系统通常会按页检测:有文本层就先抽取,没有文本层或文本质量很差时再走 OCR。
为什么 PDF 特别难
HTML 天然包含标题、段落和表格标签,而 PDF 更接近一张“如何把字符画到页面上”的说明书。阅读器看见的是排版后的页面,解析器拿到的可能只是字符、字体和坐标。
这会产生几个典型问题。
阅读顺序不可靠
双栏页面中的文本抽取顺序可能变成“左栏第一行、右栏第一行、左栏第二行……”。人眼能根据版面判断顺序,程序必须先识别文本块,再重建阅读流。
表格没有真正的单元格
有些 PDF 里的表格只是若干文字加几条线。直接抽取后,表头和数据会混在一起:
产品 版本 状态 A 2.1 可用 B 1.8 停止维护更理想的结果应保留表格结构:
| 产品 | 版本 | 状态 |
|---|---|---|
| A | 2.1 | 可用 |
| B | 1.8 | 停止维护 |
公式、图片和跨页内容容易丢失
公式可能被拆成多个字符,流程图只有图片没有替代文本,跨页表格还可能重复表头或断开一行。页眉、页脚、水印和页码则会混入正文,在每个分块中反复出现。
一条更稳健的解析流水线
文档复杂时,可以把解析过程拆开,而不是期待单个工具一次完成所有工作。
1. 文件检测
先识别 MIME 类型、编码、是否加密、页数和文件大小,再判断是否存在文本层。对异常文件应记录失败原因,避免静默产生空文档。
2. 版面分析
版面模型负责识别标题、正文、列表、表格、图片、页眉页脚等区域,并推断阅读顺序。它决定后续内容是怎样被串起来的。
3. 文本抽取与 OCR
可复制文本优先直接抽取,扫描区域再用 OCR。OCR 之前还可以做旋转校正、去噪和分辨率调整。中文文档要特别检查相似字符、标点和数字,例如0/O、1/l的误识别。
4. 专项结构恢复
表格、公式和图表可以交给专门模型。对于真正影响问答的图片,还应生成简短说明,并关联原页码;装饰图标则不必进入知识库。
5. 清洗与标准化
清理不是无差别删除。页眉页脚可以按跨页重复频率识别,连字符断行可以合并,但代码块中的换行必须保留。所有规则都应能够回溯到原页,便于抽样检查。
输出什么结构最合适
Markdown 适合保留标题、列表、代码块和表格,也便于人工查看;JSON 适合携带元数据和接入后续流水线。实践中可以同时保留二者:正文使用 Markdown,外层使用 JSON。
{"document_id":"ops-manual-v3","page":18,"section_path":["部署","启动服务"],"content_type":"paragraph","text":"启动服务前,应检查配置文件与环境变量。","source_uri":"docs/ops-manual-v3.pdf","parser":"layout-parser-2","parsed_at":"2026-09-27"}section_path能帮助结构化分块,page和source_uri用于引用,parser与parsed_at则方便追踪某次解析结果。若更换了解析器,可以按版本重建索引并比较效果。
工具怎样选
文档解析工具大致可分为三类。
第一类是底层库,如 PyMuPDF、pdfminer.six、python-docx。它们速度快、控制粒度细,适合版式稳定或需要自定义规则的项目。
第二类是综合解析工具,如 MinerU、Docling、Marker、Unstructured。它们通常集成版面识别、表格与公式处理,适合复杂文档,但要评估模型体积、运行环境和中文效果。
第三类是托管解析服务。它们接入方便,也可能提供更复杂的结构恢复能力,但需要考虑数据是否可以上传、调用成本、速率限制和服务稳定性。
选择时不要只看一份演示文档。应准备自己的测试集,至少覆盖:普通文本 PDF、扫描件、双栏文章、跨页表格、公式、混合中英文和带水印页面。
怎样验收解析结果
仅检查“是否提取出文字”远远不够。更有效的验收方法是同时做结构检查和问答检查。
checks={"empty_page_rate":count_empty_pages(records)/total_pages,"heading_count":count_headings(records),"table_count":count_tables(records),"replacement_char_rate":count("�")/total_chars,}随后抽样对照原文件,检查阅读顺序、标题层级、表格和页码。最后再用一组问题验证:能否检索到包含正确答案的片段。解析结果“看起来整齐”,不代表它一定适合检索。
小结
文档解析是 RAG 的数据入口,也是一切下游质量的上限。可靠的做法是先判断文档类型,再分别处理文本层、OCR、版面和特殊结构,最后输出带来源、层级和页码的标准记录。
当解析结果能被人工复核、能追溯到原文、也能稳定支持后续分块时,才算真正完成了“加载文档”。