
Un document de cinquante pages ne s'indexe pas d'un bloc : son embedding se dilue, et la recherche remonte un pavé entier là où il fallait un paragraphe. Le chunking découpe chaque document en morceaux — assez petits pour un embedding net, assez grands pour rester compréhensibles. Ce guide présente trois stratégies — taille fixe, par phrases, par sections —, explique le rôle décisif du recouvrement, et donne le critère pour choisir selon votre corpus. C'est l'étape qui pèse le plus sur la qualité d'un RAG : un mauvais découpage plombe tout ce qui suit. Public visé : développeur qui prépare un corpus nettoyé pour l'indexation.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Pourquoi le chunking conditionne la qualité d'un RAG.
- Le découpage par taille fixe et le rôle du recouvrement.
- Le découpage par phrases, qui ne casse jamais une phrase.
- Le découpage par sections, qui respecte la structure du document.
- Choisir la stratégie adaptée à votre corpus.
Prérequis
Section intitulée « Prérequis »- Python 3.10+ — le chunking de ce guide tient en bibliothèque standard.
- Avoir un corpus extrait et nettoyé à découper.
Pourquoi le chunking est décisif
Section intitulée « Pourquoi le chunking est décisif »Le RAG cherche par similarité : il compare le vecteur d'une question aux vecteurs des morceaux indexés. Or un vecteur résume tout le texte qu'il représente en un point unique.
Un chunk trop gros mélange plusieurs idées : son vecteur est une moyenne floue qui ne ressemble fortement à aucune question précise. Un chunk trop petit perd son contexte : « il faut redémarrer le service » ne dit pas lequel. Entre les deux, il existe une taille où le vecteur capte une idée nette — et c'est tout l'enjeu du chunking.
Cette étape n'a rien d'intelligent : c'est du découpage de chaîne de caractères. Mais elle décide de ce que la recherche pourra, ou non, retrouver. Un mauvais chunking ne se rattrape pas en aval.
Le découpage par taille fixe
Section intitulée « Le découpage par taille fixe »La stratégie la plus simple : une fenêtre glissante d'un nombre fixe de mots. On avance dans le texte, on prend N mots, on recommence.
def chunk_taille_fixe(texte, taille=60, recouvrement=12): """Découpe par fenêtre fixe de N mots, avec recouvrement entre voisins.""" if recouvrement >= taille: raise ValueError("le recouvrement doit être inférieur à la taille") mots = texte.split() pas = taille - recouvrement chunks, debut = [], 0 while debut < len(mots): chunks.append(" ".join(mots[debut:debut + taille])) if debut + taille >= len(mots): break debut += pas return chunksSon avantage est sa robustesse : elle marche sur n'importe quel texte, structuré ou non. Son défaut : elle coupe à l'aveugle, parfois en plein milieu d'une phrase. C'est là qu'intervient le recouvrement.
Le rôle du recouvrement
Section intitulée « Le rôle du recouvrement »Sans recouvrement, une idée à cheval sur deux chunks est perdue : sa première moitié finit un chunk, sa seconde ouvre le suivant, et aucun des deux vecteurs ne la capte entièrement.
Le recouvrement (overlap) règle cela : les derniers mots d'un chunk réapparaissent au début du suivant. Une idée coupée par la frontière se retrouve intacte dans au moins un chunk.
chunks = chunk_taille_fixe(texte, taille=25, recouvrement=5)# Les 5 derniers mots du chunk 1 sont aussi les 5 premiers du chunk 2.Le recouvrement a un coût — du texte dupliqué, donc des chunks en plus — mais il est presque toujours rentable. Un recouvrement de l'ordre de 10 à 20 % de la taille du chunk est un bon point de départ. Une seule contrainte : il doit rester inférieur à la taille, sinon le découpage n'avance plus.
Le découpage par phrases
Section intitulée « Le découpage par phrases »Couper en plein milieu d'une phrase produit des chunks bancals. Le découpage par phrases l'interdit : il regroupe des phrases entières sans jamais en casser une, jusqu'à un budget de mots.
def chunk_par_phrases(texte, max_mots=60): """Regroupe des phrases entières sans dépasser un budget de mots.""" phrases = segmenter_phrases(texte) # voir le guide sur le nettoyage chunks, courant, compte = [], [], 0 for phrase in phrases: n = len(phrase.split()) if courant and compte + n > max_mots: chunks.append(" ".join(courant)) courant, compte = [], 0 courant.append(phrase) compte += n if courant: chunks.append(" ".join(courant)) return chunksUn chunk se ferme dès que la phrase suivante ferait dépasser le budget. Chaque chunk est donc une suite de phrases complètes — toujours lisible. La contrepartie : une phrase très longue peut, à elle seule, dépasser le budget. C'est rare et acceptable ; mieux vaut une phrase entière trop longue qu'une phrase tronquée.
Le découpage par sections
Section intitulée « Le découpage par sections »Quand le document est déjà structuré — du Markdown avec des titres —, le meilleur découpage est celui que l'auteur a déjà fait. Le chunking par sections coupe sur les titres : une section, un chunk.
def chunk_par_sections(markdown): """Découpe un Markdown sur ses titres : un chunk par section.""" sections, titre, corps = [], "(préambule)", [] for ligne in markdown.splitlines(): if ligne.lstrip().startswith("#"): if any(l.strip() for l in corps): sections.append({"titre": titre, "texte": "\n".join(corps).strip()}) titre, corps = ligne.lstrip("#").strip(), [] else: corps.append(ligne) if any(l.strip() for l in corps): sections.append({"titre": titre, "texte": "\n".join(corps).strip()}) return sectionsChaque chunk garde le titre de sa section — un contexte précieux, qu'on peut préfixer au texte avant de l'indexer. C'est la stratégie la plus qualitative quand elle s'applique : elle suit le sens du document. Sa limite est évidente : elle exige un document structuré. Sur de la prose continue, sans titres, elle n'a rien sur quoi s'appuyer.
Choisir la bonne stratégie
Section intitulée « Choisir la bonne stratégie »Aucune stratégie n'est universellement meilleure : le bon choix dépend de la nature du corpus.
| Corpus | Stratégie adaptée | Pourquoi |
|---|---|---|
| Markdown, HTML structuré, code | Par sections | Suit le découpage voulu par l'auteur |
| Prose continue, articles | Par phrases | Respecte l'unité de sens minimale |
| Texte hétérogène, sans structure | Taille fixe + recouvrement | Robuste, marche partout |
La règle de décision est simple. Le document a une structure exploitable ? Découpez par sections. Sinon, c'est de la prose ? Découpez par phrases. Et dans le doute, ou face à un corpus mélangé, la taille fixe avec recouvrement est le repli fiable. Beaucoup de pipelines combinent les trois selon le type de document rencontré.
Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
| La recherche remonte des pavés | Chunks trop gros | Réduire la taille, viser une idée par chunk |
| Chunks incompréhensibles isolés | Chunks trop petits, contexte perdu | Augmenter la taille, préfixer le titre |
| Idées coupées aux frontières | Pas de recouvrement | Ajouter 10–20 % de recouvrement |
ValueError sur le recouvrement | Recouvrement ≥ taille | Le rendre strictement inférieur |
| Chunking par sections vide | Document sans titres | Basculer sur phrases ou taille fixe |
À retenir
Section intitulée « À retenir »- Le chunking décide de ce que la recherche pourra retrouver — il ne se rattrape pas en aval.
- La taille fixe est robuste mais coupe à l'aveugle ; le recouvrement corrige les coupures.
- Le découpage par phrases ne casse jamais une phrase — idéal pour la prose.
- Le découpage par sections suit la structure de l'auteur — le plus qualitatif quand il s'applique.
- Le bon choix dépend du corpus : structuré, prose, ou hétérogène.
- Préfixer le titre de section à un chunk enrichit son vecteur à peu de frais.