Docling pour le RAG
Du document aux chunks prêts pour le retrieval : quel chunker choisir, comment dimensionner avec le bon tokenizer, comment survivent tables et citations, quelle intégration convient et quel vector store apparier — vérifié contre les concepts officiels de chunking et la référence de sérialisation.
1. Quelle voie RAG vous convient ?
| Situation | Voie | Pourquoi |
|---|---|---|
| Déjà sur LangChain | langchain-docling DoclingLoader | Loader officiel ; mode DOC_CHUNKS natif, mode MARKDOWN + splitter d'en-têtes en repli. |
| Déjà sur LlamaIndex | DoclingReader + Docling Node Parser | Le Reader charge JSON sans perte ou Markdown avec perte ; le parser en fait des Nodes. |
| Déjà sur Haystack | Convertisseur docling-haystack | Docling comme composant convertisseur Haystack. |
| Sans framework / store maison | HybridChunker direct | Contrôle total : chunkez, contextualisez, embeddez, upsertez partout (Qdrant, Milvus, Chroma, Pinecone…). |
| Fichiers de chunks vite requis | CLI --to chunks | Sans Python : chunks hybrides ou hiérarchiques depuis le terminal. |
| Ingestion massive à l'échelle | Data Prep Kit + Docling | Pipelines chunk + tokenize pour grands corpus. |
2. Où se situe Docling dans le RAG
Un pipeline RAG a six étapes ; Docling possède les trois premières — celles qui décident la qualité avant tout embedding. Deux philosophies : exporter en Markdown puis re-splitter (p. ex. MarkdownHeaderTextSplitter de LangChain), ou chunker natif sur le DoclingDocument. Le natif préserve tableaux, en-têtes et provenance que le re-split Markdown perd en silence : préférez-le sauf motif.
- Parsing — layout, ordre de lecture, tableaux, formules, images → un DoclingDocument structuré.
- Sérialisation / chunking — chunks structurels avec en-têtes, captions et provenance (ou export Markdown/HTML/JSON pour re-split).
- Enrichissement texte —
contextualize()préfixe le contexte d'en-têtes pour que chaque chunk vaille seul. - Embeddings → store → retrieval → génération — votre modèle, votre store, votre framework ; agnostiques à Docling.
3. Conversion : gardez le DoclingDocument
Pour un pipeline programmatique, convertissez en Python et gardez l'objet document — les chunkers opèrent dessus, pas sur des fichiers :
docling convert report.pdf --to mdfrom docling.document_converter import DocumentConverter
converter = DocumentConverter()
result = converter.convert("report.pdf")
document = result.document
4. Choisir l'export : Markdown, JSON, HTML, DocTags
Les exports sont des raccourcis sur sérialiseurs (MarkdownDocSerializer etc.). Pour le RAG, le choix compte surtout pour les tableaux. Si les cellules d'en-tête fusionnées décident des réponses, préférez HTML ou JSON à Markdown — ou gardez Markdown mais répétez les en-têtes au chunking (section 7). Sérialiseurs personnalisables : sous-classez BaseTableSerializer et amis pour un contrôle total (voir l'exemple avancé chunking & sérialisation).
| Export | Spans de table | Usage RAG |
|---|---|---|
| export_to_markdown() | Aplatis — pas de syntaxe de spans ; cellules fusionnées rendues vides | Voie texte par défaut ; bien sauf si les en-têtes fusionnés comptent. |
| export_to_html() | Préservés — rowspan/colspan natifs | Meilleur export texte quand les cellules fusionnées portent du sens. |
| export_to_dict() / JSON | Préservés sans perte — TableData complet avec spans | Voie sans perte (mode JSON du Reader LlamaIndex) ; payloads les plus lourds. |
| DocTags / Docling Language | Préservés — tokens de continuation OTSL | Format compact préservant la structure pour tooling natif Docling. |
5. Comparatif des chunkers
Tous les chunkers natifs implémentent BaseChunker (chunk() → flux de chunks, contextualize() → texte enrichi), donc les intégrations style LlamaIndex acceptent tout chunker intégré, propre ou tiers par la même interface.
| Chunker | Stratégie | Quand |
|---|---|---|
| HybridChunker (défaut) | Structure hiérarchique + split conscient des tokens si trop gros + fusion si trop petits | Défaut pour le RAG. Équilibré, conscient des en-têtes et tables. |
| HierarchicalChunker | Un chunk par élément ; fusionne les items de liste (opt-out via merge_list_items) | Granularité fine par élément, avec métadonnées complètes. |
| LineBasedTokenChunker | Respecte les lignes ; ne coupe une ligne que si elle seule dépasse la limite | Tables, code, logs, listes : tout ce qui est orienté lignes. |
| TrivialChunker | Chunking minimal de base | Débogage et benchmarks, pas du retrieval en production. |
| Re-split Markdown | Exporte en Markdown puis re-splitte (p. ex. MarkdownHeaderTextSplitter) | Seulement quand un composant aval exige une entrée Markdown. |
6. HybridChunker en profondeur (défaut)
Fonctionnement : partir des chunks hiérarchiques, puis une passe ne splitte que les surdimensionnés (conscient des tokens) et une autre ne fusionne que les peers sous-dimensionnés successifs aux mêmes en-têtes & captions. Paramètres clés :
Embeddez le texte contextualisé, pas chunk.text :
Deux notes opérationnelles : l'avertissement transformers « Token indices sequence length … » au chunking est une fausse alerte documentée (voir la FAQ officielle), et définissez TOKENIZERS_PARALLELISM=false pour taire les avertissements de fork en serveurs.
tokenizer— alignez sur le tokenizer de votre modèle d'embeddings (section 9). Par défaut dérive les limites du tokenizer.max_tokens— plafond par chunk ; c'est la forme enrichie (contextualisée) qui doit tenir.merge_peers=True— fusionne les peers petits ; mettez False pour des splits stricts.repeat_table_header=True— chaque chunk de table commence par la ligne d'en-tête (section 7).omit_header_on_overflow=False— saute l'en-tête pour les lignes qui tiennent sans mais débordent avec (tables larges, budgets stricts).serializer_provider— p. ex. tables Markdown viaChunkingSerializerProviderpour contrôler la forme du texte.
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) # en-têtes préfixés — EMBEDDEZ CECI
vector = embed(enriched)
7. Tables en RAG : en-têtes, spans, formats
Démos résolues : chunking hybride (répétition sur CSV large incluse), chunking par lignes, extraction de tables.
docling convert data.csv --to md- Répétez les en-têtes (
repeat_table_header=True, défaut) : chaque chunk d'une table divisée commence par la ligne d'en-tête, donc chaque chunk s'auto-décrit pour le modèle. - Échappatoire de débordement (
omit_header_on_overflow=True) : pour tables larges, les lignes qui tiennent sans l'en-tête mais débordent avec la sautent — efficacité sans casser les lignes. - Cellules fusionnées : Markdown aplatis les spans ; si elles comptent, chunkez depuis la sérialisation HTML/JSON ou un sérialiseur de tables propre.
- Alternative par lignes :
LineBasedTokenChunkeravec préfixe répété garde les lignes type CSV intactes, avec la même logique viaomit_prefix_on_overflow.
8. Métadonnées & citations (DocMeta)
Chaque chunk porte dl_meta — gardez-le dans le payload vectoriel ; il transforme « une réponse » en « une réponse avec source ». La provenance inclut pages et bounding boxes par item : assez pour des citations « page 3 » ou du surlignage de région (voir visual grounding). Ne sacrifiez jamais les métadonnées pour « gagner de la place » : sans elles, citer est impossible.
| Champ | Contient | Usage |
|---|---|---|
| headings | Chemin d'en-têtes, p. ex. ["3.2 AI models"] | Labels de section, préfixes de contexte, filtres. |
| origin | Mimetype, nom de fichier, hash binaire | Identité du document, dedup, liens source. |
| doc_items | Self refs, labels, provenance : page_no, bbox, charspan | Citations de page, surlignage bbox, visual grounding. |
9. Tokenizers : alignez votre modèle d'embeddings
La règle est absolue : dimensionnez les chunks avec le tokenizer de votre modèle d'embeddings. Des tokenizers disparates dimensionnent mal en silence et cassent les décisions de fusion/split. À grande échelle, le pipeline chunk+tokenize de Data Prep Kit applique le même principe en batch.
| Tokenizer | Installation | Remarques |
|---|---|---|
HuggingFace (HuggingFaceTokenizer) | pip install "docling-core[chunking]" | Voie par défaut. max_tokens optionnel — dérivé du tokenizer. Exemple : sentence-transformers/all-MiniLM-L6-v2 (aussi défaut CLI). |
OpenAI / tiktoken (OpenAITokenizer) | pip install "docling-core[chunking-openai]" | Exige max_tokens explicite (fenêtre de contexte, p. ex. 128 * 1024 pour 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. Intégrations frameworks
LangChain — langchain-docling : Deux modes : DOC_CHUNKS (défaut — un Document LangChain par chunk natif, métadonnées intactes) et MARKDOWN (un Document par fichier ; splitter ensuite, p. ex. avec MarkdownHeaderTextSplitter sur #/##/###). Flow complet dans l'exemple officiel RAG LangChain (Milvus + Mixtral) et le guide LangChain.
LlamaIndex — Reader + Node Parser : DoclingReader peuple des Documents LlamaIndex (JSON sans perte ou Markdown avec perte) ; le Docling Node Parser les convertit en Nodes connaissant le format. Toute implémentation BaseChunker s'emboîte dans la même interface. Voir l'exemple officiel RAG LlamaIndex.
Haystack et le reste : Haystack fournit Docling comme composant convertisseur (exemple, docs d'intégration). Au-delà des trois grands : txtai, Kotaemon, DocETL, Vectara, Semantica, Hector, haiku.rag, Bee, CrewAI, Langflow, Open WebUI, spaCy, NVIDIA, RAG du cookbook Granite et Data Prep Kit intègrent tous Docling — parcourez l'index officiel des intégrations.
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, # chunks natifs (défaut)
chunker=HybridChunker(tokenizer=tokenizer),
)
docs = loader.load() # un Document LangChain par chunk, dl_meta en metadata
from llama_index.readers.docling import DoclingReader
reader = DoclingReader(export_type="json") # sans perte ; "markdown" avec perte
documents = reader.load_data("report.pdf")
11. Vector stores : exemples résolus
Le store n'affecte jamais Docling — chunks + embeddings s'upsertent partout. Exemples officiels pour :
| Store | Exemple | Remarques |
|---|---|---|
| Milvus | RAG avec Milvus | Aussi le store de l'exemple LangChain (docling.db local, index FLAT). |
| Weaviate | RAG avec Weaviate | Recherche vectorielle + hybride natives. |
| Qdrant | Retrieval avec Qdrant | Recette centrée retrieval. |
| OpenSearch | RAG avec OpenSearch | Recherche + vecteur dans un moteur. |
| MongoDB + VoyageAI | RAG avec MongoDB | Atlas Vector Search + embeddings VoyageAI. |
| Azure AI Search | RAG avec Azure AI Search | Retrieval managé sur Azure. |
| Chroma / Pinecone / autres | — | Pas de recette officielle ; même motif : embeddez contextualize(chunk), upsertez texte + DocMeta. |
12. Chunks depuis le CLI (sans Python)
--chunks-type accepte hybrid (défaut) ou hierarchical ; le tokenizer par défaut est sentence-transformers/all-MiniLM-L6-v2. La conversion distante (docling convert-remote / docling-serve) supporte les mêmes options côté serveur. Voir le chercheur de commandes.
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. Checklist d'ingestion en production
- Tokenizer == modèle d'embeddings. Toujours. Revérifiez à chaque changement de modèle.
- Embeddez la sortie de
contextualize(); gardezchunk.textà part pour l'affichage. - Gardez DocMeta (headings, page_no, bbox, origin) dans le payload pour les citations.
- Répétez les en-têtes de table ; pour les tables à cellules fusionnées utilisez la source HTML/JSON.
- Taillez le coût de conversion :
--no-ocrpour les PDF numériques, sautez les enrichissements inutiles, convertissez en batch et pré-téléchargez les modèles (docling-tools models download --all). - Scale-out : chunk+tokenize de Data Prep Kit pour les corpus ;
/v1/convert/sourcede docling-serve avec--to chunksderrière une file pour les services. - PII d'abord : détectez et obfusquez les PII avant d'embedder (voir l'exemple PII) — une fuite ne se dés-embedde pas.
14. Dépannage de l'ingestion RAG
- Réponses sans contexte / chunks « orphelins » — vous avez embeddé
chunk.text; passez àcontextualize()et vérifiez les en-têtes. - Tables mal répondues — activez
repeat_table_header; vérifiez les cellules fusionnées (Markdown aplatis les spans → utilisez HTML/JSON). - Avertissement transformers de longueur — fausse alerte documentée, ignorable (FAQ officielle).
- Chunks trop gros/petits pour le modèle — mismatch de tokenizers ; fixez celui du modèle et ajustez
max_tokens. - Citations impossibles — métadonnées perdues à l'upsert ; persistez
dl_meta(page_no, headings, origin). - Ingestion trop lente — voir conversion lente : coupez OCR/enrichissements inutiles, utilisez le GPU, batchez.
15. FAQ RAG
Par quel chunker commencer ?
chunk.text ou contextualize() — qu'embedder ?
chunker.contextualize(chunk) pour les embeddings. Il préfixe le chemin d'en-têtes et rend le chunk autonome. Gardez chunk.text pour l'affichage.Faut-il LangChain / LlamaIndex / Haystack ?
Export Markdown + splitter ou chunking natif ?
Comment la structure des tables survit-elle ?
repeat_table_header), soignez le débordement (omit_header_on_overflow), et sourcez les tables depuis HTML/JSON si les cellules fusionnées comptent. LineBasedTokenChunker est le spécialiste des données par lignes.Comment les réponses citent-elles les pages ?
dl_meta de chaque chunk (headings, page_no, bbox, origin) dans le payload et renvoyez-le avec les hits. La provenance porte les citations jusqu'au surlignage bbox.Quel vector store fonctionne avec Docling ?
Comment scaler l'ingestion ?
Vérifié avec Docling v2.129.0 · Dernière vérification 2026-09-22 · Source officielle