做 RAG(检索增强生成)或者大模型应用落地的兄弟们,最近最头疼的问题应该不是模型不够聪明,而是数据清洗

尤其是 PDF。

你用 PyPDF2 提出来的全是乱码换行;你用 Unstructured 甚至 LangChain 自带的加载器,遇到双栏排版(Two-column layout)直接读成了一行乱序天书;更别提表格了,稍微复杂点的跨页表格,提出来就是一堆无意义的字符串,喂给 LLM 纯属制造幻觉。

最近 IBM Research 开源的 Docling 在技术圈火了。我试用了一周,结论是:这玩意儿可能是目前把 PDF 转成 Markdown(给 LLM 吃的最佳格式)最靠谱的开源方案。

今天不扯概念,直接聊聊它怎么解决“复杂布局”和“表格还原”这两个痛点,以及怎么把它集成到你的 ETL 管道里。


Docling:专治“PDF地狱”,将复杂文档完美转为 Markdown 的工程实践

1. 为什么是 Docling?

以前我们处理 PDF,主流路线有两条:

  1. 基于规则(Rule-based):像 pdfminer,直接读 PDF 的指令流。速度快,但遇到图片扫描件、复杂公式、或者浮动布局,直接歇菜。
  2. 基于视觉(Vision-based):像 PaddleOCRNougat。效果好,但 Nougat 这种端到端模型太重了,而且容易产生幻觉(把识别不清的数字瞎编一个)。

Docling 走了一条中间路线。它结合了专门的布局分析模型(Layout Analysis Models)和文字提取逻辑。它能精准识别出哪里是标题(Header)、哪里是正文(Text)、哪里是表格(Table)。

最关键的是,它的输出目标非常明确:Markdown。 在 LLM 时代,Markdown 自带的结构信息(# 表示层级,| 表示表格)是保留文档语义性价比最高的方式。

2. 快速上手:一行代码转 Markdown

安装非常简单,依赖处理得比 Python OCR 库那帮大爷要干净得多:

Bash

# 建议在 python 3.10+ 环境下运行
pip install docling

最基础的转换脚本,把一个复杂的双栏论文 PDF 转成 Markdown 字符串:

Python

from docling.document_converter import DocumentConverter

source = "test_paper.pdf"  # 也可以是 URL

# 1. 初始化转换器
# 第一次运行会下载默认的布局分析模型 (约 300MB)
converter = DocumentConverter()

# 2. 执行转换
result = converter.convert(source)

# 3. 导出为 Markdown
markdown_output = result.document.export_to_markdown()

print(markdown_output)

跑完你会发现,Docling 最强的地方在于它懂排版。双栏的文字,它会按照人类阅读顺序(先左栏下,再右栏上)拼接,而不是像某些库一样横着读把两栏文字混在一起。

3. 核心杀手锏:表格无损还原

做金融财报分析或者标书处理的,最怕 PDF 里的表格。

Docling 在这块的处理逻辑是:检测到表格 -> 识别单元格结构 -> 重建成 Markdown Table。

如果你的业务不仅需要全文,还需要单独提取表格数据,Docling 提供了很舒服的接口:

Python

import pandas as pd
from docling.document_converter import DocumentConverter

source = "financial_report.pdf"
converter = DocumentConverter()
result = converter.convert(source)

# 遍历文档中识别到的所有表格
for i, table in enumerate(result.document.tables):
    # Docling 已经把表格结构化了
    # 我们可以直接导出为 Pandas DataFrame,方便后续做数据清洗
    df = table.export_to_dataframe()
    
    print(f"--- 表格 #{i+1} ---")
    print(df.head()) # 打印前几行看看
    
    # 甚至可以直接存 csv
    # df.to_csv(f"table_{i}.csv")

这一点对 RAG 系统极其重要。你可以把表格单独切分出来做 Embedding,或者直接把 Markdown 格式的表格喂给大窗口模型(如 Claude-3 或 GPT-4-Turbo),让模型自己去读数,准确率比扔纯文本高得多。

4. 进阶:混合模式(处理扫描件)

要是 PDF 是纯图片的扫描件怎么办?Docling 默认使用 PyPdfium2 提取文本,那是针对“电子原生” PDF 的。

针对扫描件,我们需要开启 OCR 管道。Docling 允许你插拔不同的 OCR 后端(比如 EasyOCR 或 RapidOCR)。

下面的代码展示了如何强制开启 OCR 功能,处理扫描版 PDF:

Python

from docling.datamodel.base_models import InputFormat
from docling.document_converter import DocumentConverter, PdfFormatOption
from docling.datamodel.pipeline_options import PdfPipelineOptions, TableStructureOptions

# 配置 Pipeline 选项
pipeline_options = PdfPipelineOptions()
pipeline_options.do_ocr = True  # 强制开启 OCR
pipeline_options.do_table_structure = True # 强化表格结构识别
# 你甚至可以指定 OCR 的线程数
# pipeline_options.ocr_options.thread_count = 8 

# 绑定格式选项
doc_converter = DocumentConverter(
    format_options={
        InputFormat.PDF: PdfFormatOption(pipeline_options=pipeline_options)
    }
)

# 转换扫描件
result = doc_converter.convert("scanned_invoice.pdf")
print(result.document.export_to_markdown())

注意:开启 OCR 后,处理速度会显著下降(取决于你的 CPU/GPU),但在服务器端做离线处理是完全可接受的。

5. 性能与资源(避坑指南)

作为工程落地的技术总结,必须得说说它的开销和坑。

  1. 启动慢:第一次 convert 时,它会把 PyTorch 模型加载到内存里。如果是做 Serverless 函数(如 Lambda),要考虑冷启动时间。
  2. 内存占用:处理几百页的大 PDF 时,内存峰值可能会飙升。建议在生产环境中对大文件进行拆页处理(比如每 10 页切分一次分别处理)。
  3. 公式支持:虽然官方宣称支持公式,但目前对复杂的 LaTeX 公式还原度不如专门的 NougatMathpix。如果你的场景是纯数学论文,可能需要由 Docling 提取文本,用其他模型补全公式。

6. 总结

Docling 不是那种只有 Demo 能看的玩具,它是目前 Python 生态里工程化程度最好的文档解析工具之一。

对于正在构建知识库、RAG 应用或者数据清洗管道的工程师来说,Docling 解决了一个核心痛点:High Quality Context In, High Quality Answer Out。把 PDF 转成干净的 Markdown,你的 RAG 效果至少能提升 20%。