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
Step 1

1. Quelle voie RAG vous convient ?

SituationVoiePourquoi
Déjà sur LangChainlangchain-docling DoclingLoaderLoader officiel ; mode DOC_CHUNKS natif, mode MARKDOWN + splitter d'en-têtes en repli.
Déjà sur LlamaIndexDoclingReader + Docling Node ParserLe Reader charge JSON sans perte ou Markdown avec perte ; le parser en fait des Nodes.
Déjà sur HaystackConvertisseur docling-haystackDocling comme composant convertisseur Haystack.
Sans framework / store maisonHybridChunker directContrôle total : chunkez, contextualisez, embeddez, upsertez partout (Qdrant, Milvus, Chroma, Pinecone…).
Fichiers de chunks vite requisCLI --to chunksSans Python : chunks hybrides ou hiérarchiques depuis le terminal.
Ingestion massive à l'échelleData Prep Kit + DoclingPipelines chunk + tokenize pour grands corpus.
2
Step 2

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 textecontextualize() 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
Step 3

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 md
from docling.document_converter import DocumentConverter

converter = DocumentConverter()
result = converter.convert("report.pdf")
document = result.document
4
Step 4

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).

ExportSpans de tableUsage RAG
export_to_markdown()Aplatis — pas de syntaxe de spans ; cellules fusionnées rendues videsVoie texte par défaut ; bien sauf si les en-têtes fusionnés comptent.
export_to_html()Préservés — rowspan/colspan natifsMeilleur export texte quand les cellules fusionnées portent du sens.
export_to_dict() / JSONPréservés sans perte — TableData complet avec spansVoie sans perte (mode JSON du Reader LlamaIndex) ; payloads les plus lourds.
DocTags / Docling LanguagePréservés — tokens de continuation OTSLFormat compact préservant la structure pour tooling natif Docling.
5
Step 5

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.

ChunkerStratégieQuand
HybridChunker (défaut)Structure hiérarchique + split conscient des tokens si trop gros + fusion si trop petitsDéfaut pour le RAG. Équilibré, conscient des en-têtes et tables.
HierarchicalChunkerUn 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.
LineBasedTokenChunkerRespecte les lignes ; ne coupe une ligne que si elle seule dépasse la limiteTables, code, logs, listes : tout ce qui est orienté lignes.
TrivialChunkerChunking minimal de baseDébogage et benchmarks, pas du retrieval en production.
Re-split MarkdownExporte en Markdown puis re-splitte (p. ex. MarkdownHeaderTextSplitter)Seulement quand un composant aval exige une entrée Markdown.
6
Step 6

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 via ChunkingSerializerProvider pour 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
Step 7

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 : LineBasedTokenChunker avec préfixe répété garde les lignes type CSV intactes, avec la même logique via omit_prefix_on_overflow.
8
Step 8

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.

ChampContientUsage
headingsChemin d'en-têtes, p. ex. ["3.2 AI models"]Labels de section, préfixes de contexte, filtres.
originMimetype, nom de fichier, hash binaireIdentité du document, dedup, liens source.
doc_itemsSelf refs, labels, provenance : page_no, bbox, charspanCitations de page, surlignage bbox, visual grounding.
9
Step 9

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.

TokenizerInstallationRemarques
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
Step 10

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_milvus
pip install llama-index-readers-docling llama-index-node-parser-docling
pip install docling-haystack
from 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
Step 11

11. Vector stores : exemples résolus

Le store n'affecte jamais Docling — chunks + embeddings s'upsertent partout. Exemples officiels pour :

StoreExempleRemarques
MilvusRAG avec MilvusAussi le store de l'exemple LangChain (docling.db local, index FLAT).
WeaviateRAG avec WeaviateRecherche vectorielle + hybride natives.
QdrantRetrieval avec QdrantRecette centrée retrieval.
OpenSearchRAG avec OpenSearchRecherche + vecteur dans un moteur.
MongoDB + VoyageAIRAG avec MongoDBAtlas Vector Search + embeddings VoyageAI.
Azure AI SearchRAG avec Azure AI SearchRetrieval managé sur Azure.
Chroma / Pinecone / autresPas de recette officielle ; même motif : embeddez contextualize(chunk), upsertez texte + DocMeta.
12
Step 12

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 hybrid
docling convert report.pdf --to chunks --chunks-type hybrid --chunks-max-tokens 512 --chunks-tokenizer sentence-transformers/all-MiniLM-L6-v2
13
Step 13

13. Checklist d'ingestion en production

  • Tokenizer == modèle d'embeddings. Toujours. Revérifiez à chaque changement de modèle.
  • Embeddez la sortie de contextualize() ; gardez chunk.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-ocr pour 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/source de docling-serve avec --to chunks derriè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
Step 14

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
Step 15

15. FAQ RAG

Par quel chunker commencer ?
HybridChunker avec le tokenizer de votre modèle d'embeddings. Défaut à raison : structure, taille, en-têtes et tables. Ne passez à Hierarchical (par élément) ou LineBased (contenu linéaire) que pour un besoin précis.
chunk.text ou contextualize() — qu'embedder ?
Toujours 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 ?
Non. Ce sont des commodités : loaders, readers et convertisseurs autour des mêmes chunkers. Une douzaine de lignes HybridChunker + votre appel d'embeddings + n'importe quel store forment un pipeline complet.
Export Markdown + splitter ou chunking natif ?
Le natif préserve tables, en-têtes, provenance et spans que l'export Markdown aplatis ou perd. Re-split Markdown seulement quand un composant exige une entrée Markdown.
Comment la structure des tables survit-elle ?
Répétez les en-têtes (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 ?
Persistez le 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 ?
N'importe lequel. Docling produit chunks + métadonnées ; les stores ne gardent que des vecteurs. Les recettes officielles couvrent Milvus, Weaviate, Qdrant, OpenSearch, MongoDB et Azure AI Search — Chroma, Pinecone et autres suivent le même motif.
Comment scaler l'ingestion ?
Conversion batch, modèles pré-téléchargés, GPU pour layout/OCR, pas d'enrichissements inutiles — plus chunk+tokenize de Data Prep Kit pour les corpus ou sortie chunks de docling-serve derrière une file pour les services.

Vérifié avec Docling v2.129.0 · Dernière vérification 2026-09-22 · Source officielle