Aller au contenu
Cercle IA Tech · RAG Un site du réseau Cercle IA Tech

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. SentenceWindowNodeParser indexe des phrases seules mais garde en métadonnée les phrases voisines (window_size=3 dans 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

  1. Rassemblez une cinquantaine de questions réelles, avec pour chacune le passage qui contient la réponse.
  2. Indexez vos documents avec deux ou trois réglages (par exemple : récursif à deux tailles, puis par structure).
  3. Pour chaque réglage, mesurez combien de fois le bon passage figure dans les résultats récupérés.
  4. 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_k de 2 à 4.
  5. 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 :

  1. https://docs.langchain.com/oss/python/integrations/splitters
  2. https://docs.langchain.com/oss/python/langchain/rag
  3. https://developers.llamaindex.ai/python/framework/optimizing/basic_strategies/basic_strategies/
  4. https://developers.llamaindex.ai/python/framework/module_guides/loading/node_parsers/modules/
  5. https://www.anthropic.com/news/contextual-retrieval

À lire aussi