Docling für RAG
Vom Dokument zu retrieval-fertigen Chunks: Welcher Chunker passt, wie Chunks mit dem richtigen Tokenizer bemessen werden, wie Tabellen und Zitate überleben, welche Framework-Integration sitzt und welcher Vektor-Store dazu passt — geprüft gegen die offiziellen Chunking-Konzepte und die Serialisierungs-Referenz.
1. Welcher RAG-Weg passt?
| Situation | Weg | Warum |
|---|---|---|
| Bereits auf LangChain | langchain-docling DoclingLoader | Offizieller Loader; DOC_CHUNKS-Modus chunkt nativ, MARKDOWN-Modus + Header-Splitter als Fallback. |
| Bereits auf LlamaIndex | DoclingReader + Docling Node Parser | Reader lädt verlustfrei JSON oder verlustbehaftet Markdown; Parser macht daraus Nodes. |
| Bereits auf Haystack | docling-haystack-Konverter | Docling als Haystack-Konverter-Komponente. |
| Framework-frei / eigener Store | HybridChunker direkt | Volle Kontrolle: chunken, kontextualisieren, embedden, überall upserten (Qdrant, Milvus, Chroma, Pinecone …). |
| Chunk-Dateien schnell brauchen | CLI --to chunks | Kein Python: hybride oder hierarchische Chunks direkt aus dem Terminal. |
| Massen-Ingestion im großen Maßstab | Data Prep Kit + Docling | Chunk- + Tokenize-Pipelines für große Korpora. |
2. Wo Docling in RAG sitzt
Eine RAG-Pipeline hat sechs Stufen; Docling besitzt die ersten drei — jene, die Antwortqualität entscheiden, bevor ein Embedding existiert. Zwei Chunking-Philosophien: nach Markdown exportieren und nachsplitten (z. B. LangChains MarkdownHeaderTextSplitter) oder nativ auf dem DoclingDocument chunken. Natives Chunken erhält Tabellen, Überschriften und Provenienz, die Markdown-Nachsplitten still fallen lässt — bevorzugen, sofern kein Grund dagegenspricht.
- Parsen — Layout, Lesereihenfolge, Tabellen, Formeln, Bilder → ein strukturiertes DoclingDocument.
- Serialisieren / chunken — strukturbewusste Chunks mit Überschriften, Captions und Provenienz (oder Markdown-/HTML-/JSON-Export zum Nachsplitten).
- Text anreichern —
contextualize()stellt Überschriftenkontext voran, sodass jeder Chunk allein steht. - Embedden → speichern → retrieven → generieren — eigenes Embedding-Modell, Vektor-Store und Framework; Docling-agnostisch.
3. Umwandeln: DoclingDocument behalten
Für eine programmatische Pipeline in Python umwandeln und das Dokumentobjekt behalten — Chunker arbeiten darauf, nicht auf Dateien:
docling convert report.pdf --to mdfrom docling.document_converter import DocumentConverter
converter = DocumentConverter()
result = converter.convert("report.pdf")
document = result.document
4. Export wählen: Markdown, JSON, HTML, DocTags
Exporte sind Kurzformen über Serializer (MarkdownDocSerializer u. a.). Für RAG zählt die Wahl vor allem bei Tabellen. Falls verbundene Header-Zellen Antworten entscheiden, HTML oder JSON statt Markdown bevorzugen — oder Markdown behalten, aber beim Chunken Tabellen-Header wiederholen (Abschnitt 7). Serializer sind anpassbar: BaseTableSerializer u. a. subklassieren für volle Kontrolle (siehe Advanced-Chunking-&-Serialization-Beispiel).
| Export | Tabellen-Spans | RAG-Nutzen |
|---|---|---|
| export_to_markdown() | Abgeflacht — keine Span-Syntax; überspannte Zellen rendern leer | Standard-Textpfad; ok, sofern verbundene Header egal sind. |
| export_to_html() | Erhalten — native rowspan/colspan | Bester Textexport, wenn verbundene Zellen Bedeutung tragen. |
| export_to_dict() / JSON | Verlustfrei erhalten — volles TableData inkl. Spans | Verlustfreier Pfad (LlamaIndex-Reader-JSON-Modus); schwerste Payloads. |
| DocTags / Docling Language | Erhalten — OTSL-Fortsetzungstokens | Kompaktes strukturerhaltendes Format für Docling-natives Tooling. |
5. Chunker-Vergleich
Alle nativen Chunker implementieren BaseChunker (chunk() → Chunk-Strom, contextualize() → angereicherter Text), sodass LlamaIndex-artige Integrationen jeden eingebauten, eigenen oder Dritt-Chunker über dieselbe Schnittstelle nehmen.
| Chunker | Strategie | Wann wählen |
|---|---|---|
| HybridChunker (Standard) | Hierarchische Struktur + tokenizer-bewusstes Splitten bei Übergröße + Mergen bei Untergröße | Standard für RAG. Ausgewogen, überschriften- und tabellenbewusst. |
| HierarchicalChunker | Ein Chunk je Dokumentelement; mergt Listeneinträge (opt-out via merge_list_items) | Feingranular, elementweise Chunks mit vollen Metadaten. |
| LineBasedTokenChunker | Hält Zeilengrenzen; splittet eine Zeile nur, falls sie allein das Limit sprengt | Tabellen, Code, Logs, Listen — alles Zeilenstrukturierte. |
| TrivialChunker | Minimales Basis-Chunken | Debuggen und Benchmarking, kein Produktions-Retrieval. |
| Markdown-Nachsplitten | Nach Markdown exportieren, dann splitten (z. B. MarkdownHeaderTextSplitter) | Nur wenn eine Framework-Pipeline Markdown-Input verlangt. |
6. HybridChunker im Detail (Standard)
So arbeitet er: Von hierarchischen Chunks starten, dann ein Durchlauf splittet nur übergroße Chunks (token-bewusst) und ein weiterer mergt nur untergroße aufeinanderfolgende Peers mit gleichen Überschriften & Captions. Wichtige Parameter:
Den kontextualisierten Text embedden, nicht chunk.text:
Zwei operative Hinweise: Die transformers-Warnung „Token indices sequence length …“ beim Chunken ist ein dokumentierter Fehlalarm (siehe offizielle FAQ), und TOKENIZERS_PARALLELISM=false setzen, um Fork-Warnungen in Servern zu beruhigen.
tokenizer— auf den Tokenizer des Embedding-Modells abstimmen (Abschnitt 9). Standard leitet Limits vom Tokenizer ab.max_tokens— Cap je Chunk; die angereicherte (kontextualisierte) Form sollte passen.merge_peers=True— untergroße Peers mergen; für striktes Splitten auf False.repeat_table_header=True— jeder Tabellen-Chunk startet mit der Header-Zeile (Abschnitt 7).omit_header_on_overflow=False— Header für Zeilen droppen, die ohne passen, mit aber überlaufen (breite Tabellen, strikte Budgets).serializer_provider— z. B. Markdown-Tabellen viaChunkingSerializerProviderzur Chunk-Text-Formkontrolle.
from docling.chunking import HybridChunker
chunker = HybridChunker()
chunks = list(chunker.chunk(document))
print(len(chunks), chunks[0].text[:120])
for chunk in chunker.chunk(document):
enriched = chunker.contextualize(chunk) # Überschriften vorangestellt — DAS embedden
vector = embed(enriched)
7. Tabellen in RAG: Header, Spans, Formate
Ausgearbeitete Demos: Hybrid-Chunking (inkl. Header-Wiederholung an breiter CSV), zeilenbasiertes Chunking, Tabellenextraktion.
docling convert data.csv --to md- Header wiederholen (
repeat_table_header=True, Standard): Jeder Chunk einer geteilten Tabelle startet mit der Header-Zeile, sodass jeder Chunk fürs Embedding-Modell selbstbeschreibend ist. - Overflow-Notausgang (
omit_header_on_overflow=True): Für breite Tabellen überspringen Zeilen, die ohne Header passen, mit aber überlaufen, den Header — Token-Effizienz ohne Zeilenbruch. - Verbundene Zellen: Markdown flacht Spans ab; falls verbundene Header zählen, Tabellen aus HTML-/JSON-Serialisierung chunken oder eigenen Tabellen-Serializer nutzen.
- Zeilenbasierte Alternative:
LineBasedTokenChunkermit wiederholtem Präfix hält CSV-artige Zeilen intakt und kennt dieselbe Overflow-Logik viaomit_prefix_on_overflow.
8. Metadaten & Zitate (DocMeta)
Jeder Chunk trägt dl_meta — im Vektor-Payload behalten; es macht aus „einer Antwort“ eine „Antwort mit Quelle“. Provenienz enthält Seitennummern und Bounding-Boxen je Item — genug für „Seite 3“-Zitate oder Quellregion-Highlighting (siehe Visual Grounding). Metadaten nie zum „Platzsparen“ droppen: ohne sie sind Zitate unmöglich.
| Feld | Enthält | Nutzen für |
|---|---|---|
| headings | Überschriftenpfad, z. B. ["3.2 AI models"] | Abschnittslabels, Kontextpräfixe, Filter. |
| origin | Mimetype, Dateiname, Binary-Hash | Dokumentidentität, Dedup, Quelllinks. |
| doc_items | Self-Refs, Labels, Provenienz: page_no, bbox, charspan | Seitenzitate, Bounding-Box-Highlighting, Visual Grounding. |
9. Tokenizer: zum Embedding-Modell passen
Die Regel ist absolut: Chunks mit dem Tokenizer des Embedding-Modells bemessen. Gemischte Tokenizer bemessen Chunks still falsch und brechen Merge-/Split-Entscheidungen. Im großen Maßstab wendet die Data-Prep-Kit-Chunk+Tokenize-Pipeline dasselbe Prinzip im Batch an.
| Tokenizer | Installation | Hinweise |
|---|---|---|
HuggingFace (HuggingFaceTokenizer) | pip install "docling-core[chunking]" | Standardpfad. max_tokens optional — vom Tokenizer abgeleitet. Beispiel: sentence-transformers/all-MiniLM-L6-v2 (auch CLI-Standard). |
OpenAI / tiktoken (OpenAITokenizer) | pip install "docling-core[chunking-openai]" | Braucht explizite max_tokens (Context-Window, z. B. 128 * 1024 für gpt-4o). |
from transformers import AutoTokenizer
from docling_core.transforms.chunker.tokenizer.huggingface import HuggingFaceTokenizer
from docling.chunking import HybridChunker
EMBED_MODEL_ID = "sentence-transformers/all-MiniLM-L6-v2"
tokenizer = HuggingFaceTokenizer(
tokenizer=AutoTokenizer.from_pretrained(EMBED_MODEL_ID),
max_tokens=512,
)
chunker = HybridChunker(tokenizer=tokenizer, merge_peers=True)
10. Framework-Integrationen
LangChain — langchain-docling: Zwei Modi: DOC_CHUNKS (Standard — ein LangChain-Document je nativem Chunk, Metadaten erhalten) und MARKDOWN (ein Document je Datei; downstream splitten, z. B. mit MarkdownHeaderTextSplitter auf #/##/###). Voller Flow im offiziellen LangChain-RAG-Beispiel (Milvus + Mixtral) und der LangChain-Anleitung.
LlamaIndex — Reader + Node Parser: DoclingReader befüllt LlamaIndex-Documents (verlustfrei JSON oder verlustbehaftet Markdown); der Docling Node Parser macht daraus mit Formatwissen Nodes. Jede BaseChunker-Implementierung passt an dieselbe Schnittstelle. Siehe offizielles LlamaIndex-RAG-Beispiel.
Haystack und der Rest: Haystack liefert Docling als Konverter-Komponente (Beispiel, Integrations-Docs). Jenseits der großen drei: txtai, Kotaemon, DocETL, Vectara, Semantica, Hector, haiku.rag, Bee, CrewAI, Langflow, Open WebUI, spaCy, NVIDIA, Granite-Cookbook-RAG und Data Prep Kit integrieren alle Docling — stöbern im offiziellen Integrationsindex.
pip install langchain-docling langchain-huggingface langchain_milvuspip install llama-index-readers-docling llama-index-node-parser-doclingpip install docling-haystackfrom transformers import AutoTokenizer
from docling_core.transforms.chunker.tokenizer.huggingface import HuggingFaceTokenizer
from docling.chunking import HybridChunker
from langchain_docling import DoclingLoader
from langchain_docling.loader import ExportType
tokenizer = HuggingFaceTokenizer(
tokenizer=AutoTokenizer.from_pretrained("sentence-transformers/all-MiniLM-L6-v2")
)
loader = DoclingLoader(
file_path=["https://arxiv.org/pdf/2408.09869"],
export_type=ExportType.DOC_CHUNKS, # native Chunks (Standard)
chunker=HybridChunker(tokenizer=tokenizer),
)
docs = loader.load() # ein LangChain-Document je Chunk, dl_meta in metadata
from llama_index.readers.docling import DoclingReader
reader = DoclingReader(export_type="json") # verlustfrei; "markdown" für verlustbehaftet
documents = reader.load_data("report.pdf")
11. Vektor-Stores: ausgearbeitete Beispiele
Der Store beeinflusst Docling nie — Chunks + Embeddings upserten überall. Offizielle Beispiele existieren für:
| Store | Beispiel | Hinweise |
|---|---|---|
| Milvus | RAG mit Milvus | Auch Store im LangChain-Beispiel (lokales docling.db, FLAT-Index). |
| Weaviate | RAG mit Weaviate | Native Vektor- + Hybrid-Search-Optionen. |
| Qdrant | Retrieval mit Qdrant | Retrieval-fokussiertes Rezept. |
| OpenSearch | RAG mit OpenSearch | Suche + Vektor in einer Engine. |
| MongoDB + VoyageAI | RAG mit MongoDB | Atlas Vector Search + VoyageAI-Embeddings. |
| Azure AI Search | RAG mit Azure AI Search | Managed Retrieval auf Azure. |
| Chroma / Pinecone / andere | — | Kein offizielles Rezept; gleiches Muster: contextualize(chunk) embedden, Text + DocMeta upserten. |
12. Chunks aus der CLI (ohne Python)
--chunks-type nimmt hybrid (Standard) oder hierarchical; der Tokenizer steht standardmäßig auf sentence-transformers/all-MiniLM-L6-v2. Remote-Conversion (docling convert-remote / docling-serve) unterstützt dieselben Chunk-Optionen serverseitig. Siehe die Befehlssuche.
docling convert report.pdf --to chunks --chunks-type hybriddocling convert report.pdf --to chunks --chunks-type hybrid --chunks-max-tokens 512 --chunks-tokenizer sentence-transformers/all-MiniLM-L6-v213. Produktions-Checkliste für Ingestion
- Tokenizer == Embedding-Modell. Immer. Bei jedem Modellwechsel erneut prüfen.
contextualize()-Output embedden,chunk.textdaneben für Anzeige speichern.- DocMeta behalten (headings, page_no, bbox, origin) im Payload für Zitate.
- Tabellen-Header wiederholen; für Merged-Cell-Tabellen HTML-/JSON-Quelle nutzen.
- Conversions-Kosten trimmen:
--no-ocrfür digitale PDFs, ungenutzte Enrichments überspringen, batch-umwandeln und Modelle vorab laden (docling-tools models download --all). - Scale-out: Data-Prep-Kit-Chunk+Tokenize für Korpora; docling-serve-
/v1/convert/sourcemit--to chunkshinter einer Queue für Services. - PII zuerst: PII vor dem Embedden erkennen und obfuskieren (siehe PII-Beispiel) — ein Leak lässt sich nicht un-embedden.
14. RAG-Ingestion-Fehlerbehebung
- Antworten ohne Kontext / „Waisen“-Chunks —
chunk.textgeembeddet; aufcontextualize()wechseln und Überschriften prüfen. - Tabellenantworten falsch —
repeat_table_headeraktivieren; Merged Cells prüfen (Markdown flacht Spans ab → HTML/JSON nutzen). - Transformers-Sequenzlängen-Warnung — dokumentierter Fehlalarm, gefahrlos ignorierbar (offizielle FAQ).
- Chunks zu groß/klein fürs Embedding-Modell — Tokenizer-Mismatch; Chunker-Tokenizer aufs Embedding-Modell setzen und
max_tokensjustieren. - Keine Zitate möglich — Metadaten beim Upsert gedroppt;
dl_meta(page_no, headings, origin) persistieren. - Ingestion zu langsam — siehe Umwandlung ist langsam: ungenutzte OCR/Enrichments deaktivieren, GPU nutzen, batchen.
15. RAG-FAQ
Mit welchem Chunker starten?
chunk.text oder contextualize() — was embedden?
chunker.contextualize(chunk) für Embeddings. Es stellt den Überschriftenpfad voran und macht Chunks retrieval-fähig in sich. chunk.text für Anzeige behalten.Brauche ich LangChain / LlamaIndex / Haystack überhaupt?
Markdown-Export + Text-Splitter vs. natives Chunken?
Wie bleibt Tabellenstruktur im Retrieval?
repeat_table_header), Overflow beachten (omit_header_on_overflow), und Tabellen aus HTML/JSON sourcen, wenn Merged Cells zählen. LineBasedTokenChunker ist der Spezialist für zeilenorientierte Daten.Wie zitieren Antworten Seiten?
dl_meta (headings, page_no, bbox, origin) im Vektor-Payload persistieren und mit Hits zurückgeben. Provenienz trägt Seitenzitate bis Bounding-Box-Highlighting.Welcher Vektor-Store passt zu Docling?
Wie skaliere ich Ingestion?
Verifiziert mit Docling v2.129.0 · Zuletzt geprüft 2026-09-22 · Offizielle Quelle