用 Docling 处理 RAG 文档,原来这么简单
做 RAG 知识库时,我们经常需要导入 PDF、DOCX、PPTX 等文档。
很多人会认为,只要把文档中的文字提取出来,再进行切分和向量化,就可以放进知识库了。
但问题是:文字被提取出来,不代表文档已经被正确解析。
一份 PDF 不只有文字,还可能包含标题、段落、表格、图片、页眉页脚和多栏排版。如果这些结构在解析时被打乱,后续的文本切分和检索也会受到影响。
这正是 Docling 要解决的问题。
一、PDF 能读取,为什么还不能直接用于 RAG?
PDF 更像是一种“页面展示格式”。它关注的是文字和图片应该显示在页面的什么位置,并不一定按照我们阅读文章的顺序保存内容。
因此,使用简单的文本提取方式处理复杂 PDF 时,可能出现这些情况:
• 标题和正文混在一起; • 双栏内容的阅读顺序错乱; • 表格被拆成零散文本; • 页眉、页脚和页码混入正文; • 扫描版 PDF 无法直接提取文字。
这些问题看起来只是“排版乱了”,实际上会继续影响后面的文本切分和检索。
RAG 的文档处理,不只是把文字读出来,还要尽量保留文字原本的结构和顺序。
二、Docling 是什么?
Docling 是一个开源的文档解析与转换工具。
它可以读取 PDF、DOCX、PPTX、XLSX、HTML、图片等多种格式,并将文档转换成统一的结构化内容。
可以把 Docling 理解成一名“文档整理员”:
• 找出文档中的文字; • 判断哪些是标题、正文、列表和表格; • 恢复内容的阅读顺序; • 将处理结果转换成 Markdown、JSON 等格式。
Docling 解析完成后,会生成一个统一的文档对象:DoclingDocument。
这个对象不仅保存文档中的文字,还可以保存标题层级、表格、图片、页面位置和来源信息等结构。
因此,Docling 和普通文本提取工具最大的区别是:
普通工具更关注“提取了哪些文字”,Docling 更关注“这些文字在文档中是什么结构”。
需要注意的是,Docling 不是大模型,也不是向量数据库,更不是完整的 RAG 框架。它主要负责原始文档进入 RAG 之前的解析和转换工作。
三、Docling 是怎样处理一份文档的?
Docling 处理文档的过程,可以简单概括为四步。
1. 读取文档
首先读取 PDF、DOCX 等原始文件,并根据文件格式选择对应的处理方式。
2. 分析页面内容
对于 PDF 等复杂文档,Docling 会分析页面布局,尝试识别:
• 标题; • 正文; • 列表; • 表格; • 图片; • 代码和公式; • 内容的阅读顺序。
在 Docling 内部,这些文档元素通常会带有对应的英文标识,也就是 DocItemLabel:
title | |
section_header | |
textparagraph | |
list_item | |
table | |
picture | |
code | |
formula |
需要注意:一级标题和二级标题并不是两个不同的标签。
它们通常都属于 section_header,再通过 level=1、level=2 等层级信息进行区分。
3. 生成结构化文档
识别完成后,Docling 会把结果整理成统一的 DoclingDocument。
可以把它理解成下面这种结构:
文档(DoclingDocument)├── 文档标题(title)├── 一级标题一(section_header,level=1)│ ├── 正文段落(text)│ ├── 列表项(list_item)│ └── 表格(table)└── 一级标题二(section_header,level=1) └── 二级标题(section_header,level=2) ├── 图片(picture) ├── 代码(code) └── 公式(formula)这里展示的是一种便于理解的简化结构。实际解析结果会根据原始文档的内容和排版发生变化。
4. 导出处理结果
最后,可以把文档导出为 Markdown、JSON、HTML 或纯文本等格式。
对于 RAG 入门场景,Markdown 是一种比较直观的选择。因为它可以清楚地表示标题、列表和表格,也方便后续进行文本切分。
整个过程可以概括为:
原始文档 ↓读取内容 ↓识别布局与结构 ↓生成 DoclingDocument ↓导出 Markdown 或转换为 LangChain Document四、用 Docling 解析一份 PDF
Docling 的基础使用并不复杂。
1. 安装 Docling
pip install doclingDocling 支持 Windows、Linux 和 macOS。第一次处理 PDF 时,默认可能会自动下载所需模型,因此需要保证当前环境能够正常访问网络。
2. 解析并保存为 Markdown
假设当前目录下有一份名为 设备操作手册.pdf 的文件,可以使用下面的代码进行解析:
from pathlib import Pathfrom docling.document_converter import DocumentConverter# 原始文档和输出文件source = Path("设备操作手册.pdf")output = Path("设备操作手册.md")# 创建转换器并解析文档converter = DocumentConverter()document = converter.convert(source).document# 导出并保存为 Markdownmarkdown_content = document.export_to_markdown()output.write_text(markdown_content, encoding="utf-8")print(f"解析完成:{output}")这段代码主要做了三件事:
1. DocumentConverter():创建文档转换器;2. convert():读取并解析原始文档;3. export_to_markdown():将解析结果转换成 Markdown。
最终会在当前目录生成:
设备操作手册.md打开这个 Markdown 文件,就可以直接查看 Docling 识别出的标题、正文、列表和表格结构。
3. 转换为 LangChain 的 Document 对象
如果后面要接入 LangChain,可以使用 Docling 官方提供的 DoclingLoader,不需要先手动保存 Markdown,再重新读取。
先安装对应的集成包:
pip install langchain-docling然后加载 PDF:
from langchain_docling.loader import DoclingLoader, ExportTypeloader = DoclingLoader( file_path="设备操作手册.pdf", export_type=ExportType.DOC_CHUNKS,)documents = loader.load()print(type(documents[0]))print(documents[0].page_content)print(documents[0].metadata)loader.load() 返回的是一个 LangChain Document 列表。
每个 Document 主要包含两部分:
• page_content:当前文档块的文本内容;• metadata:来源、标题、页码等元数据。
这里使用的 ExportType.DOC_CHUNKS 会把文档处理成多个文本块,每个文本块对应一个 LangChain Document,更适合后续向量化和检索。
如果希望整份文件只生成一个 LangChain Document,可以改为:
export_type=ExportType.MARKDOWN五、Docling 处理前后有什么区别?
例如,原本的一条故障记录是:
故障代码:E01故障原因:电源异常处理方法:检查供电线路使用简单的文本提取方式后,内容可能变成:
E01检查供电线路页码 12电源异常文字基本都被提取出来了,但原本的阅读顺序和字段关系已经被打乱。
经过 Docling 解析后,内容更可能保持为结构清晰的形式:
故障代码:E01故障原因:电源异常处理方法:检查供电线路如果原始内容是一张表格,Docling 还可以将其导出为类似下面的 Markdown:
| 故障代码 | 故障原因 | 处理方法 || --- | --- | --- || E01 | 电源异常 | 检查供电线路 |所以,Docling 的价值并不是让文档中的文字变多,而是:
尽量保留标题、段落、表格以及内容之间原本的结构关系。
六、为什么解析后的内容更适合 RAG?
在 RAG 知识库中,文档通常要经过下面几个步骤:
文档解析 ↓文本切分 ↓向量化 ↓检索 ↓大模型生成答案文档解析是整个流程的起点。
如果一条故障记录在解析时已经被打乱,后续切分时可能变成两个不完整的文本块:
文本块一:E01,电源异常文本块二:检查供电线路当用户询问:
E01 故障应该怎么处理?检索系统可能只找到“E01,电源异常”,却没有同时找到对应的处理方法。
如果 Docling 保留了完整的内容结构,后续切分时就更容易获得完整信息:
故障代码:E01故障原因:电源异常处理方法:检查供电线路这样可以为后续的向量化和检索提供质量更好的输入数据。
因此,更准确的说法不是“使用 Docling 就一定能提高 RAG 准确率”,而是:
Docling 可以改善文档解析质量,为后续文本切分和检索打好基础。
七、总结
做 RAG 时,很多人会把注意力放在大模型、Embedding 模型和向量数据库上,却容易忽略最前面的文档解析。
但一份 PDF 能够打开、能够复制文字,并不代表它已经适合直接切分和检索。
Docling 所做的事情,就是把面向人阅读的复杂文档,转换成结构更加清晰、方便程序处理的数据。
它的核心流程并不复杂:
读取文档 ↓识别布局和结构 ↓生成 DoclingDocument ↓导出 Markdown 或 LangChain DocumentDocling 不负责向量检索,也不负责生成答案。它更像是连接原始文档和 RAG 知识库之间的一名“文档整理员”。
夜雨聆风