PDF-to-RAG Pipeline#
The PDF-to-RAG pipeline is Docling's primary workflow for preparing documents for retrieval-augmented generation. It chains four core subsystems — document conversion, hierarchical chunking, tokenizer-aware splitting, and vector store ingestion — into a reusable pattern. The canonical end-to-end example is docs/examples/rag_langchain.ipynb.
PDF ──► DocumentConverter ──► DoclingDocument ──► HybridChunker ──► DocChunk[]
│
VectorStore ◄── embed(contextualize(chunk)) ◄──┘
│
Retriever ──► LLM
Step 1: PDF Conversion#
DocumentConverter is the entry point. It accepts a file path or URL and returns a ConversionResult whose .document field is a DoclingDocument — the canonical, schema-versioned JSON representation carrying all texts, tables, pictures, and page-level provenance.
For RAG use cases the most important pipeline option is do_table_structure=True, which activates table structure recognition (TableFormer V1/V2 or Granite Vision) . Other useful options:
| Option | Purpose |
|---|---|
do_table_structure | Extract table cell grids (required for table chunking) |
do_ocr | Enable OCR for scanned PDFs |
do_code_enrichment / do_formula_enrichment | Enrich code blocks and math formulas |
pdf_backend | Select backend: docling_parse (default), pypdfium2, threaded_docling_parse |
See the PDF pipeline options reference for the full option set, and the table structure recognition guide for backend selection.
Step 2: Chunking with HybridChunker#
HybridChunker (importable as from docling.chunking import HybridChunker) applies tokenization-aware refinements on top of document-structure-based hierarchical chunking . It produces DocChunk objects, each with a text field and a meta: DocMeta field.
Key constructor parameters :
| Parameter | Default | Description |
|---|---|---|
tokenizer | HuggingFaceTokenizer("sentence-transformers/all-MiniLM-L6-v2") | Controls split boundaries |
max_tokens | derived from tokenizer | Hard cap per chunk |
merge_peers | True | Merge undersized sibling chunks |
repeat_table_header | True | Repeat header rows across table chunks |
omit_header_on_overflow | False | Drop header when row + header exceeds budget |
serializer_provider | ChunkingSerializerProvider() | Controls table-to-text serialization |
Embedding text: The text you embed should be the context-enriched form from chunker.contextualize(chunk), which prepends the in-scope section headings to chunk.text .
Step 3: Tokenizer Configuration#
The chunker tokenizer must match the embedding model's tokenizer. Token counts used for splitting are only meaningful relative to the embedding model's context window .
HuggingFace tokenizer (docling_core/transforms/chunker/tokenizer/huggingface.py):
from docling_core.transforms.chunker.tokenizer.huggingface import HuggingFaceTokenizer
from transformers import AutoTokenizer
tokenizer = HuggingFaceTokenizer(
tokenizer=AutoTokenizer.from_pretrained("sentence-transformers/all-MiniLM-L6-v2"),
max_tokens=512, # optional; defaults to model max if omitted
)
OpenAI / tiktoken (docling_core/transforms/chunker/tokenizer/openai.py) — requires pip install docling-core[chunking-openai] :
# import tiktoken
# from docling_core.transforms.chunker.tokenizer.openai import OpenAITokenizer
# tokenizer = OpenAITokenizer(
# tokenizer=tiktoken.encoding_for_model("gpt-4o"),
# max_tokens=128 * 1024,
# )
Both implement the same BaseTokenizer interface (count_tokens, get_max_tokens, get_tokenizer).
ℹ️ HuggingFace transformers may warn
"Token indices sequence length is longer than the specified maximum sequence length"during chunker initialization — this is a false alarm; see the FAQ .
Step 4: Table Chunking Strategies#
Table serialization is the dominant quality lever for RAG pipelines with heavy table content .
Default: Triplet Serialization (avoid for table-heavy docs)#
TripletTableSerializer (the default in ChunkingDocSerializer) emits flat "**Column**, row = value" strings. This destroys cell-to-column-header bindings that carry the semantic payload of structured tables .
Recommended: Markdown Serialization#
Use a custom ChunkingSerializerProvider with MarkdownTableSerializer to preserve column headers in each chunk :
from docling_core.transforms.chunker.hierarchical_chunker import (
ChunkingDocSerializer, ChunkingSerializerProvider,
)
from docling_core.transforms.serializer.markdown import MarkdownParams, MarkdownTableSerializer
class MDTableSerializerProvider(ChunkingSerializerProvider):
def get_serializer(self, doc):
return ChunkingDocSerializer(
doc=doc,
table_serializer=MarkdownTableSerializer(),
params=MarkdownParams(compact_tables=True),
)
chunker = HybridChunker(
tokenizer=tokenizer,
repeat_table_header=True,
serializer_provider=MDTableSerializerProvider(),
)
With repeat_table_header=True, each chunk from a split table begins with the column header row . See the advanced chunking and serialization docs for additional strategies .
LineBasedTokenChunker (for structured text / wide tables)#
LineBasedTokenChunker preserves line boundaries — useful for tables, code, and logs . Key parameters:
prefix: text prepended to every chunk (e.g., table header row)omit_prefix_on_overflow=True: drop the prefix for rows that exceed the token budget with it — keeps row intact; use when line integrity > context consistency
Step 5: Chunk Provenance and Metadata#
Every DocChunk carries a DocMeta with three-layer traceability back to the source PDF :
DocChunk.meta
├── doc_items: list[DocItem] # source nodes this chunk covers
│ └── .prov: list[ProvenanceItem]
│ ├── page_no: int # 1-indexed page
│ ├── bbox: BoundingBox # l/t/r/b coordinates
│ └── charspan: (int, int)
├── headings: list[str] # section headings in scope
└── origin: DocumentOrigin # filename, mimetype, binary_hash
This chain enables RAG pipelines to cite the exact page and bounding box for any retrieved chunk. The LangChain integration stores this as dl_meta in the LangChain Document.metadata dict .
DocMeta.excluded_embed and excluded_llm class-level lists control which fields flow into contextualize() — by default only headings is included in the embedding string .
Step 6: Vector Store Ingestion (LangChain)#
The DoclingLoader from langchain-docling handles conversion + chunking in one call:
from langchain_docling import DoclingLoader
from langchain_docling.loader import ExportType
from docling.chunking import HybridChunker
from docling_core.transforms.chunker.tokenizer.huggingface import HuggingFaceTokenizer
from transformers import AutoTokenizer
EMBED_MODEL_ID = "sentence-transformers/all-MiniLM-L6-v2"
loader = DoclingLoader(
file_path=["https://arxiv.org/pdf/2408.09869"],
export_type=ExportType.DOC_CHUNKS, # one LangChain doc per chunk
chunker=HybridChunker(
tokenizer=HuggingFaceTokenizer(
tokenizer=AutoTokenizer.from_pretrained(EMBED_MODEL_ID)
)
),
)
splits = loader.load()
ExportType.MARKDOWN is the alternative — returns one LangChain document per PDF, then split externally with MarkdownHeaderTextSplitter . Use DOC_CHUNKS (default) for document-native grounding; use MARKDOWN when you need custom splitting logic.
After loading, ingest into any LangChain-compatible vector store (Milvus, FAISS, Chroma, etc.) using the same EMBED_MODEL_ID that was used for the tokenizer .
Key Source Files#
| Component | File |
|---|---|
HybridChunker | docling_core/transforms/chunker/hybrid_chunker.py |
TripletTableSerializer, ChunkingSerializerProvider, ChunkingDocSerializer | docling_core/transforms/chunker/hierarchical_chunker.py |
LineBasedTokenChunker | docling_core/transforms/chunker/line_chunker.py (see line-based chunking example) |
HuggingFaceTokenizer | docling_core/transforms/chunker/tokenizer/huggingface.py |
OpenAITokenizer | docling_core/transforms/chunker/tokenizer/openai.py |
DocChunk / DocMeta | docling_core/transforms/chunker/doc_chunk.py |
| E2E LangChain RAG example | docs/examples/rag_langchain.ipynb |
| Hybrid chunking example | docs/examples/hybrid_chunking.ipynb |
| Line-based chunking example | docs/examples/line_based_chunking.ipynb |
| PDF pipeline options | Pipeline options reference |
| Chunk provenance details | Document Chunk Metadata and Provenance |
| Table serialization options | Table Export and Serialization |