首页
/ Docling 的 RAG 集成实战:文档转换、检索级切块与三大框架 Loaders 详解

Docling 的 RAG 集成实战:文档转换、检索级切块与三大框架 Loaders 详解

2026-09-04 11:12:16作者:仰钰奇

本篇基于 Docling 仓库中 RAG 集成参考文档(rag.md),讲清楚在检索增强生成(RAG)场景下 Docling 的完整用法:先完成文档转换、再产出带元数据(标题层级、页码)的检索就绪块(chunk)。读完后你将掌握三种现成框架 Loader(LangChain / LlamaIndex / Haystack)的接法、何时应绕过 Loader 直接使用 HybridChunker,以及如何在完全无本地模型的情况下通过 Service Client 远程切块构建 RAG 索引。

RAG 的两步走:转换 + 带元数据切块

对于 RAG,你通常想要两件事:

  1. 转换文档——把 PDF、DOCX 等原始文件解析为结构化中间表示 DoclingDocument
  2. 切分为检索就绪的块——按文档结构拆分,并且保留标题面包屑(headings)与页码等元数据。

Docling 的设计让这两步解耦:转换由 DocumentConverter 完成,切块由 chunker 类族完成(见 docling/chunking/init.py),框架 Loader 则把这两步封装成“convert + chunk”的一体化调用,让你不必手写胶水代码。两种路线的取舍:

  • 省事路线:使用各框架的现成 Loader,一行安装即用;
  • 控制路线:自己调用 DocumentConverter + HybridChunker,可自由选择切块策略与分词器(tokenizer),并与你的 embedding 模型对齐。

框架 Loaders:三个现成组件

Docling 与主流 RAG 框架的官方集成组件如下(来自 rag.md 的对照表):

框架 安装包 组件
LangChain langchain-docling DoclingLoader
LlamaIndex llama-index-readers-docling(+ llama-index-node-parser-docling DoclingReader + Docling node parser
Haystack docling-haystack Docling converter 组件

各框架集成在仓库文档中另有说明页,可结合阅读:LangChain 集成LlamaIndex 集成,以及配套示例 rag_langchain.ipynbrag_llamaindex.ipynbrag_haystack.ipynb

LangChain:DoclingLoader

pip install langchain-docling
from langchain_docling import DoclingLoader
from langchain_docling.loader import ExportType

loader = DoclingLoader(
    file_path=["report.pdf", "https://example.com/paper.pdf"],
    export_type=ExportType.DOC_CHUNKS,   # chunked; or ExportType.MARKDOWN
)
docs = loader.load()                     # list[langchain_core.documents.Document]
# each chunk keeps metadata: source, headings, page numbers

两个关键参数:

  • file_path 支持本地路径与 http(s) URL 的混合输入;
  • export_type 决定输出形态:ExportType.DOC_CHUNKS 直接产出切块后的 Document 列表(每个块保留 source、headings、页码元数据,可直接送入 embedder),ExportType.MARKDOWN 则导出 Markdown 文本、交由 LangChain 侧自行切块。docs/concepts/chunking.md 中也把“导出 Markdown 后自定义切块”列为与原生 chunker 并列的第一种切块路线。

LlamaIndex:DoclingReader + DoclingNodeParser

LlamaIndex 的集成是“读写分离”的双组件设计(详见 llamaindex.md):Reader 负责把文件读成 Docling 数据模型,Node Parser 再基于 Docling 结构知识把文档解析为 LlamaIndex Node(即 embedding 用的 chunk)。

pip install llama-index-readers-docling llama-index-node-parser-docling
from llama_index.readers.docling import DoclingReader
from llama_index.node_parser.docling import DoclingNodeParser

reader = DoclingReader()
nodes = DoclingNodeParser().get_nodes_from_documents(
    reader.load_data(file_path="report.pdf")
)

rag.md 的说明看,Reader 支持两种填充方式:无损序列化 Docling 数据模型(如 JSON),或导出为简化格式(如 Markdown,有损)。选择无损模式可以保留完整结构信息供下游节点解析使用。

Haystack:converter 组件

pip install docling-haystack

Haystack 侧是一个 Docling converter 组件,用法是把它放进 Haystack 的索引(indexing)流水线中;它会直接输出切块后的文档,可无缝接入后续的 writer / embedder 节点,无需额外的切块步骤。

注意(原文档提示):这些第三方 Loader 的包名与 API 可能随版本变化,接入前请以各框架官方的 Docling 集成文档中当前的导入路径为准。

跳过 Loaders:直接使用 HybridChunker

如果你已经用 DocumentConverter 完成了转换(例如需要精细控制流水线、选择 OCR 引擎、启用 heading 层级推断等),又只需要切块,就直接调用 HybridChunker 自己——这正是 rag.md “When to skip the loaders”一节推荐的做法。它的优势:

  • 每个块显式暴露 headings(标题面包屑)source page(来源页码)
  • 可以自选 tokenizer,与你的 embedding 模型对齐,从而精确控制块大小。

代码:切块 + 上下文增强

from docling.chunking import HybridChunker
from docling_core.transforms.chunker.tokenizer.huggingface import HuggingFaceTokenizer

tokenizer = HuggingFaceTokenizer.from_pretrained(
    model_name="sentence-transformers/all-MiniLM-L6-v2",
    max_tokens=512,
)
chunker = HybridChunker(tokenizer=tokenizer, merge_peers=True)

for chunk in chunker.chunk(result.document):
    embed_text = chunker.contextualize(chunk)   # heading-prefixed text to embed
    print(chunk.meta.headings)                  # heading breadcrumb
    print(chunk.meta.origin.page_no)            # source page

要点说明(结合 chunking/init.pydocs/concepts/chunking.md):

  • docling.chunking 直接再导出 docling-coreBaseChunkerBaseChunkHierarchicalChunkerHybridChunker 等类型,因此只安装 docling 包即可使用;
  • BaseChunker 接口只有两个方法:chunk(dl_doc) -> Iterator[BaseChunk]contextualize(chunk) -> strcontextualize 返回带标题前缀的增强文本,通常是喂给 embedding 模型的输入——它能显著提升检索命中率,因为块文本自带了章节上下文;
  • merge_peers=True 会合并“标题相同且偏小的相邻块”;
  • tokenizer 传的是 BaseTokenizer 对象。docling-core 2.8.0 起 tokenizer API 有变更,直接传字符串不再有效

若使用 OpenAI 系 tokenizer(需 pip install 'docling-core[chunking-openai]'):

import tiktoken
from docling_core.transforms.chunker.tokenizer.openai import OpenAITokenizer

tokenizer = OpenAITokenizer(
    tokenizer=tiktoken.encoding_for_model("text-embedding-3-small"),
    max_tokens=8192,
)

HybridChunker 的算法内涵

docs/concepts/chunking.md 的描述看,HybridChunker 并非简单的按字数切块,而是一个两趟(two-pass)的混合策略:

  1. 起点是分层切块:先用 HierarchicalChunker 基于 DoclingDocument 的结构(章节、标题、列表项)生成初始块,并自动附带 headers 与 captions 等文档元数据;
  2. 第一趟:按需拆分——仅当块超过 tokenizer 给出的 token 上限时才拆分;
  3. 第二趟:按需合并——把标题(和 captions)相同的偏小块合并,可通过 merge_peers 关闭。

此外它还提供两个表格相关参数,对宽表场景很实用:

  • repeat_table_header(默认 True):表格跨块时,在每个块开头重复表头,让每个块自含表格结构上下文;
  • omit_header_on_overflow(默认 False):在 repeat_table_header=True 基础上,当某行“不带表头能装下、带表头会溢出”时,为该特定行省略表头,最大化 token 利用率。

同族的 LineBasedTokenChunker(同样从 docling.chunking 导出)则面向表格、代码、日志等结构化内容:优先保持整行不被切断,支持为每个块附加重复前缀(如表头),并通过 omit_prefix_on_overflow 处理溢出。更多可运行示例见 hybrid_chunking.ipynbline_based_chunking.ipynbadvanced_chunking_and_serialization.ipynb

远程切块:Service Client 的 chunk()

对于“远程/大规模转换来喂 RAG 索引”的场景,rag.md 推荐直接用 Service Client 的 chunk()——它返回检索就绪的块,调用方机器上不需要任何本地模型。相关参考见 service-client.md

基本用法

from docling.service_client import ChunkerKind

response = client.chunk(source="report.pdf", chunker=ChunkerKind.HYBRID)
# ChunkerKind.HYBRID or ChunkerKind.HIERARCHICAL

源码印证

service_client/client.py 可以看到 ChunkerKind 是一个字符串枚举,只有两个取值:

class ChunkerKind(str, Enum):
    HYBRID = "hybrid"
    HIERARCHICAL = "hierarchical"

chunk() 的实现(client.py#L1019-L1026)本质上是一次“提交 + 等待结果”的任务调用:

def chunk(
    self,
    source: SourceType,
    chunker: ChunkerKind,
    options: ConvertDocumentsRequestOptions | None = None,
) -> ChunkDocumentResponse:
    job = self.submit_chunk(source=source, chunker=chunker, options=options)
    return job.result(timeout=self._job_timeout)

即:先通过 submit_chunk 提交远程切块任务得到 ConversionJob 句柄,再在默认 job_timeout=300.0 秒内等待结果。source 支持本地路径、http(s) URL 等多种形态,与 convert() 一致。

服务端切块参数的默认值

datamodel/service/chunking.pyHybridChunkerOptions 可确认远程切块的服务端默认行为,与本地 HybridChunker 的示例保持一致:

  • max_tokens:每块最大 token 数,为 None 时自动从 tokenizer 提取;
  • tokenizer:HuggingFace 模型名,默认 sentence-transformers/all-MiniLM-L6-v2(可换成如 Qwen/Qwen3-Embedding-0.6B 以对齐你的 embedding 模型);
  • merge_peers:默认 True,合并标题相同的偏小相邻块。

BaseChunkerOptions 还暴露了几个影响块文本形态的开关(chunking.py#L23-L61):

  • use_markdown_tables:用 Markdown 表格而非三元组序列化表格;
  • use_markdown_images:在块内启用图片引用,并给含图块加 has_image 元数据,便于识别图文块;
  • image_placeholder:关闭 Markdown 图片序列化时使用的占位文本,默认 ![IMAGE]
  • include_raw_text:响应中同时返回 raw_texttext(上下文增强后)两个字段。

客户端侧的错误处理与本地 SDK 不同:Service Client 抛出类型化异常(ConversionErrorServiceUnavailableErrorTaskTimeoutErrorUsageLimitExceededErrorResultExpiredError 等,均定义在 service_client/exceptions.py),捕获基类 DoclingServiceClientError 即可统一处理。相关行为有专门测试覆盖,例如 test_service_client_fake_service.pytest_service_client_sdk_unit.py;远程调用的更多实战示例见 examples/service_client/chunk.pybatch.py

选型小结

结合 rag.md 的决策框架,可以这样选择:

场景 推荐路线 依据
快速接入 LangChain / LlamaIndex / Haystack 应用 框架 Loaders 封装 convert + chunk,免写胶水代码
需要精细控制流水线(OCR 引擎、heading 层级、VLM 等)再切块 DocumentConverter + HybridChunker 每块自带 headings 与页码,tokenizer 可对齐 embedding 模型
大规模/远程转换构建 RAG 索引,本机无 GPU/模型 Service Client chunk(ChunkerKind.HYBRID) 调用端零本地模型,服务侧保留热模型与并发

最后再强调原文档的一条重要提示:第三方 Loader 的包名与 API 可能变化,接入前请以各框架当前版本的 Docling 集成文档为准;本地 SDK 侧的 chunking 依赖 feat-chunking extra(若仅用 docling-core 则安装 docling-core[chunking]),OpenAI tokenizer 另需 chunking-openai extra。

登录后查看全文
热门项目推荐
相关项目推荐