Architecturer un RAG Haute Précision : Stratégies de Découpage et Re-Ranking
Comment concevoir des pipelines RAG de production qui éliminent les hallucinations et maximisent la pertinence.
1. Dépasser le découpage naïf par nombre de caractères
Découper un document tous les 500 ou 1000 caractères est la première chose enseignée dans tout tutoriel RAG, et c’est aussi la principale source d’échecs de recherche en production. Le découpage à taille fixe n’a aucune notion de ce qu’est réellement une phrase, une ligne de tableau ou un bloc de code, si bien qu’il tranche régulièrement au milieu d’une définition, sépare un titre du paragraphe qu’il introduit, ou coupe une signature de fonction de son corps. Le modèle d’embedding doit alors représenter un fragment incohérent, et aucun re-ranking en aval ne peut récupérer un sens sémantique déjà détruit au moment de l’ingestion.
La solution consiste à découper selon la structure réelle du document : on analyse d’abord le document en ses unités logiques (titres, paragraphes, éléments de liste, lignes de tableau, blocs de code) en s’appuyant sur la grammaire propre au format source, qu’il s’agisse d’un arbre Markdown, du DOM HTML, ou d’un extracteur de mise en page PDF qui préserve l’ordre de lecture. Les chunks sont ensuite construits en empilant ces unités jusqu’à un budget de tokens cible, sans jamais scinder une unité en son milieu. Cette seule pratique améliore souvent la précision de recherche plus qu’une mise à niveau du modèle d’embedding, car elle corrige l’entrée au lieu de compenser ses défauts en aval.
Un second levier, souvent négligé, est le découpage sémantique : on calcule les embeddings de phrases consécutives et on place une frontière de chunk au point où la similarité cosinus entre phrases adjacentes chute sous un seuil, signe d’un changement de sujet. Cette approche est plus coûteuse que le découpage par règles, puisqu’elle exige un appel d’embedding par phrase à l’ingestion, mais pour de la prose dense et peu structurée comme des contrats juridiques ou des articles scientifiques, elle produit des chunks nettement plus cohérents que n’importe quelle heuristique à taille fixe.
Quelle que soit la stratégie retenue, attachez toujours le contexte parent en métadonnées plutôt que de vouloir rendre chaque chunk autosuffisant. Un chunk devrait porter le titre du document, le chemin de la section et l’URL source comme champs structurés à côté du vecteur, afin qu’un fragment étroit puisse être correctement attribué et étendu au moment de la requête sans alourdir l’embedding lui-même.
2. Récupération par document parent et en-têtes contextuels
Les petits chunks se récupèrent bien, car un fragment étroitement délimité produit un embedding plus net qui correspond plus précisément à des requêtes spécifiques, mais ils se génèrent mal, car ils manquent de contexte pour que le modèle de langage puisse raisonner correctement. Le patron du document parent résout cette tension en indexant de petits chunks enfants pour la recherche, tout en stockant un pointeur vers un chunk parent plus large (une section entière, ou plusieurs paragraphes voisins) qui est récupéré et transmis au modèle une fois qu’un chunk enfant est retrouvé.

