La plupart des tutoriels RAG s'arrêtent à la démo. On découpe par nombre de tokens, on remplit une base de données vectorielle, et on s'arrête là. Cela fonctionne lorsqu'un utilisateur pose une question simple comme « Quelle est la politique de retour ? » dans une FAQ bien structurée. Mais tout s'effondre quand quelqu'un colle la moitié d'un contrat pour interroger la troisième clause, ou quand un développeur saisit un code d'erreur obscur dans votre recherche de documentation.
Les fenêtres de tokens fixes coupent les accords juridiques en plein milieu d'une phrase. Les gros chunks enterrent les références d'API sous des paragraphes de bruit. Pire encore, une récupération lente pousse les utilisateurs à abandonner leur requête avant même que le modèle ne commence à générer. Nous l'avons appris à nos dépens. Lorsque nous sommes passés d'une approche basée sur l'espoir à une approche basée sur la mesure pour notre couche de récupération, nous avons réduit la latence de 40 % et porté le rappel à 95 %. Voici précisément ce qui a changé.
Découpage intelligent
Arrêtez de considérer la taille des chunks comme un nombre magique. Une fenêtre de 512 tokens n'a aucun sens pour un document juridique où une seule clause s'étend sur plusieurs paragraphes, et elle est tout aussi inutile pour une documentation d'API où la signature d'une fonction et sa description de deux lignes devraient rester groupées. Nous sommes passés à un découpage sensible à la structure (structure-aware splitting).
Pour les textes juridiques, le découpage récursif respecte la hiérarchie du document. Les clauses restent intactes. Pour la documentation d'API, nous utilisons un découpage sensible aux fonctions (function-aware splitting) qui maintient les signatures, les paramètres et les exemples ensemble en tant qu'unités atomiques. Les tickets de support et les données conversationnelles nécessitent des limites sémantiques, en découpant là où le sujet change plutôt qu'à un nombre de caractères arbitraire. Le résultat est que chaque chunk contient suffisamment de contexte pour être utile, sans pour autant diluer le signal. Votre modèle d'embedding a un budget d'attention limité. Consommez-le intelligemment.
Récupération hybride
La recherche vectorielle excelle à trouver du contenu conceptuellement similaire. Posez une question sur les requêtes de base de données lentes et elle fera remonter des guides d'optimisation des performances. Mais demandez « Error 0x80070057 » et la recherche sémantique dérivera vers des sujets sans rapport, car les embeddings denses gèrent mal les correspondances exactes. À l'inverse, le BM25 cible parfaitement les chaînes exactes et les termes rares, mais il n'a aucune idée que « latence » et « temps de réponse lent » signifient la même chose.
Nous exécutons les deux en parallèle et les fusionnons via le Reciprocal Rank Fusion. Le RRF est simple et efficace. Il prend les listes classées de chaque méthode et attribue un score aux documents en fonction de leur position, offrant ainsi une chance équitable aux meilleurs candidats de chaque système. Après la fusion, nous appliquons un reranker cross-encoder sur les résultats combinés et ne renvoyons que les cinq meilleurs. Le reranker ajoute environ cinquante millisecondes de latence, mais a amélioré notre rappel de 15 %. Ce compromis est largement rentabilisé par la qualité de la génération.
Expansion de requête
Les utilisateurs sont très mauvais pour formuler des requêtes. Ils utilisent des abréviations, font des fautes de frappe ou condensent trois questions en un long monologue. Si vous recherchez exactement ce qu'ils ont tapé, vous passerez à côté des documents dont ils ont réellement besoin.
Nous transformons désormais chaque requête avant qu'elle n'atteigne l'index. Premièrement, nous générons plusieurs versions reformulées de la question originale pour couvrir les synonymes et les tournures alternatives. Deuxièmement, nous décomposons les questions complexes en sous-questions plus petites. Une requête telle que « Pourquoi le remboursement échoue-t-il pour les clients internationaux et comment puis-je le corriger ? » devient deux recherches distinctes : l'une sur les échecs de remboursement internationaux et l'autre sur les étapes de remédiation. L'expansion de requête à elle seule a fait passer notre rappel de 78 % à 94 %. La leçon est simple : ne faites pas confiance au premier jet de l'utilisateur. Aidez-le.
Arrêtez de deviner, commencez à chercher
La taille des chunks, le pourcentage de chevauchement, le seuil top-k et la profondeur du reranker interagissent de manières impossibles à ajuster manuellement. Nous avons passé trop de temps à débattre pour savoir si 256 tokens étaient préférables à 512, tout en ignorant le paramètre de chevauchement qui, lui, détruisait la cohérence.
Nous avons remplacé l'intuition par l'optimisation bayésienne. Au lieu de la recherche par grille (grid search), qui gaspille de la puissance de calcul sur des zones manifestement mauvaises, les méthodes bayésiennes construisent un modèle probabiliste de ce qui fonctionne et recherchent activement la frontière de Pareto qui maximise le rappel tout en minimisant la latence. Pour notre stack, cela a signifié trouver la combinaison spécifique de taille de chunk, de chevauchement et de top-k qui nous donnait un rappel de 95 % sans exploser notre budget de latence. Différents cas d'utilisation se sont positionnés sur différents points de cette frontière. Les chatbots orientés clients privilégiaient la vitesse. La recherche juridique interne privilégiait le rappel. L'optimisation automatisée nous a permis de satisfaire les deux sans copier-coller manuel de fichiers de configuration.
Les résultats
Les chiffres parlent d'eux-mêmes. Notre Recall@10 est passé de 78 % à 95 %. La latence p95 est tombée de 850 millisecondes à 320 millisecondes. Et parce que le modèle recevait enfin un contexte pertinent au lieu de bruit, le taux d'hallucination est passé de 12 % à 3 %. Une meilleure récupération ne rend pas seulement les réponses plus rapides. Elle les rend exactes.
Que faire ensuite
Si vous reconstruisez votre couche de récupération, commencez par ici :
- Découpez selon la structure du document, et non selon le nombre de tokens. Adaptez votre stratégie de découpage à la forme de vos données.
- Utilisez la recherche hybride. Combinez la recherche vectorielle et le BM25, fusionnez-les avec le Reciprocal Rank Fusion, et effectuez un reranking avant la génération.
- Élargissez les requêtes pour une meilleure couverture. Reformulez et décomposez avant même de lancer la recherche.
- Construisez un « golden dataset » pour vos tests. Vous ne pouvez pas optimiser ce que vous ne mesurez pas.
- Optimisez les paramètres avec des outils automatisés. La recherche bayésienne trouvera de meilleurs réglages que votre intuition.
La récupération n'est pas un simple fichier de configuration que l'on paramètre une fois pour toutes. C'est une infrastructure, et l'infrastructure mérite la même rigueur que le code de production : tests, mesures et optimisation continue. Traitez-la ainsi, et votre système RAG cessera d'être une simple démo pour devenir un véritable produit.
Communauté d'apprentissage optionnelle : GyaanSetu AI
