Guide
Chunking RAG : taille des chunks, recouvrement, méthodes
Découper ses documents pour un RAG : taille des morceaux, recouvrement, découpage par structure ou par sens, réglages de départ.
Mis à jour le
Le chunking, ou découpage, consiste à couper vos documents en morceaux avant de les indexer. C'est le réglage qui pèse le plus sur la qualité d'un RAG : un morceau trop petit perd son contexte, un morceau trop grand noie l'information utile. Il n'existe pas de taille universelle ; il existe une méthode pour trouver la vôtre.
Ce que disent les bibliothèques
| Outil | Réglage de départ | Source |
|---|---|---|
LlamaIndex (SentenceSplitter) |
taille 1 024, recouvrement 20 (valeurs par défaut) | documentation LlamaIndex |
LangChain (RecursiveCharacterTextSplitter, tutoriel RAG) |
chunk_size=1000, chunk_overlap=200 |
tutoriel LangChain |
| Essais d'Anthropic sur la récupération contextuelle | morceaux de « quelques centaines de jetons », 800 jetons dans leur calcul de coût | Anthropic, 19/09/2024 |
Ces valeurs ne sont pas des recommandations universelles : ce sont des points de départ. LlamaIndex résume le compromis ainsi : des morceaux plus petits donnent des plongements plus précis ; des morceaux plus grands donnent des plongements plus généraux, qui peuvent manquer les détails fins.
Les quatre familles de découpage
1. Par longueur. On coupe tous les N jetons ou caractères. Simple et prévisible, mais la coupure tombe au milieu d'une phrase ou d'un tableau. LangChain le propose (découpage par jetons ou par caractères).
2. Récursif. On essaie de garder les grandes unités entières (paragraphes), et l'on descend aux phrases puis aux mots seulement si l'unité est trop longue. C'est le point de départ que la documentation LangChain recommande dans la plupart des situations.
3. Par structure du document. On coupe selon les titres d'un fichier Markdown, les balises d'une page HTML, les éléments d'un JSON, les fonctions d'un code source. LangChain et LlamaIndex ont des découpeurs dédiés (MarkdownNodeParser, HTMLNodeParser, CodeSplitter chez LlamaIndex). Pour des documents bien titrés (procédures, contrats, documentation), c'est souvent le plus naturel : un morceau correspond à une section.
4. Par le sens. On calcule la proximité de sens entre phrases voisines et l'on coupe là où elle chute. LlamaIndex fournit SemanticSplitterNodeParser, dont l'exemple de documentation utilise buffer_size=1 et breakpoint_percentile_threshold=95. Plus coûteux à l'indexation, puisqu'il faut calculer des plongements pour chaque phrase.
Deux variantes utiles
- Découpage hiérarchique. LlamaIndex propose
HierarchicalNodeParser, avec dans son exemple trois niveaux de taille :chunk_sizes=[2048, 512, 128]. On cherche sur les petits morceaux, précis, puis on peut remonter au morceau parent pour donner plus de contexte au modèle. - Fenêtre de phrases.
SentenceWindowNodeParserindexe des phrases seules mais garde en métadonnée les phrases voisines (window_size=3dans l'exemple), que l'on rend au modèle au moment de répondre.
Le recouvrement : utile, pas automatique
Le recouvrement (overlap) répète la fin d'un morceau au début du suivant, pour ne pas couper une idée en deux. Il a un prix : plus de morceaux, donc un index plus gros et des plongements plus nombreux à calculer. Les deux bibliothèques n'ont d'ailleurs pas le même réflexe : 200 dans le tutoriel LangChain, 20 par défaut chez LlamaIndex. Mesurez son effet plutôt que de le fixer au jugé.
Le problème du morceau orphelin
Un morceau isolé perd souvent son contexte. Anthropic prend l'exemple d'un extrait de rapport financier qui dit que « le chiffre d'affaires a augmenté de 3 % sur le trimestre » sans préciser ni l'entreprise ni la période. Sa réponse, la récupération contextuelle : faire rédiger par un modèle, pour chaque morceau, une courte phrase de contexte ajoutée avant l'indexation. Dans leurs essais, cela a réduit de 35 % les échecs de récupération sur les 20 premiers résultats, et de 49 % en y ajoutant une recherche par mots-clés.
Méthode pour choisir
- Rassemblez une cinquantaine de questions réelles, avec pour chacune le passage qui contient la réponse.
- Indexez vos documents avec deux ou trois réglages (par exemple : récursif à deux tailles, puis par structure).
- Pour chaque réglage, mesurez combien de fois le bon passage figure dans les résultats récupérés.
- Si vous réduisez la taille, augmentez le nombre de résultats : LlamaIndex, dans son exemple, divise la taille par deux et passe
similarity_top_kde 2 à 4. - Gardez le réglage qui gagne, et refaites l'essai quand la nature de vos documents change.
La mesure elle-même est détaillée dans Évaluer un RAG. Pour les documents mis en page (tableaux, colonnes, scans), le découpage dépend d'abord de l'extraction : voir RAG sur des PDF.
Exemple de code (LlamaIndex)
D'après la documentation LlamaIndex, on change les réglages globaux avant de construire l'index :
from llama_index.core import Settings
Settings.chunk_size = 512
Settings.chunk_overlap = 50
Puis, à l'interrogation : index.as_query_engine(similarity_top_k=4).
Questions fréquentes
Quelle est la bonne taille de chunk pour un RAG ?
Il n'existe pas de taille universelle. LlamaIndex part de 1 024 avec un recouvrement de 20 et explique que des morceaux plus petits donnent des plongements plus précis, des morceaux plus grands des plongements plus généraux. Testez deux ou trois tailles sur vos propres questions.
Si je réduis la taille des chunks, faut-il changer autre chose ?
Oui : LlamaIndex conseille alors d'augmenter le nombre de résultats récupérés (similarity_top_k). Son exemple divise la taille par deux et passe de 2 à 4 résultats.
Sources
Pages consultées pour écrire cet article :
- https://docs.langchain.com/oss/python/integrations/splitters
- https://docs.langchain.com/oss/python/langchain/rag
- https://developers.llamaindex.ai/python/framework/optimizing/basic_strategies/basic_strategies/
- https://developers.llamaindex.ai/python/framework/module_guides/loading/node_parsers/modules/
- https://www.anthropic.com/news/contextual-retrieval