Accueil / Articles

Pourquoi RAG échoue avec des documents réels : segmentation, recherche hybride, réclassement et évaluations.

Pourquoi RAG échoue avec des documents réels et les solutions pour y remédier : une conception en deux phases, les choix de segmentation, la recherche hybride, le réclassement et l’évaluation de la récupération seule.

Éditeur : REACTAPP.TOP7 min de lecture1518 mots

Sources: Production-Ready RAG Architecture: Core Patterns Explained

Pourquoi les démos échouent avec des données réelles

Les tutoriels sur RAG fonctionnent généralement avec un PDF bien organisé ou un extrait de Wikipédia, ce qui n’est pas un test réel. En appliquant le même processus à des documents internes authentiques, présentant un format inégal, des tickets de support et des wikis internes complexes, les réponses deviennent souvent incomplètes, inventées ou clairement fausses. Deux principes expliquent presque tous les échecs en environnement de production.

  1. RAG est d’abord un système de récupération d’informations et seulement ensuite un système de génération de texte. Lorsque le système récupère un contexte incorrect, le modèle a presque aucune chance de donner une réponse juste, quelle que soit sa capacité.
  2. La qualité globale est limitée par l’étape la plus faible, et non par la moyenne des étapes. Un modèle d’embedding performant ne peut pas compenser un outil de segmentation qui divise une phrase en deux.

Deux phases

Chaque système RAG se divise en une phase d’indexation hors ligne et une phase de recherche en ligne :

Indexing (offline):   documents → chunks → embeddings → vector store
Query (online):       question → embedding → retrieval → context assembly → LLM

Les configurations de production ajoutent du cache, un réclassement, des mécanismes de contrôle, une surveillance ainsi que de la logique de secours autour de ce noyau, mais celui-ci reste la base de tout le reste, et aucun outil ultérieur ne peut corriger une base faible.

Le découpage en blocs est le plus rentable

La plupart des systèmes échouent dans le découpage en blocs, et cet échec reste invisible jusqu’à ce que l’on débogue une réponse incorrecte trois étapes plus tard. Cela est important car les modèles d’incorporation fonctionnent le mieux sur des segments cohérents, les fenêtres de contexte sont limitées, les blocs trop gros introduisent du bruit, tandis que ceux qui sont trop petits excluent les faits environnants nécessaires à une réponse.

Le découpage en blocs de taille fixe coupe tous les N tokens avec une superposition de 10 à 20 pour cent. C’est simple et prévisible, mais il ignore les limites des phrases et des paragraphes, ce qui peut le pousser à diviser une définition sans s’en rendre compte. C’est un point de départ courant, mais rarement le meilleur.

Le découpage récursif ou hiérarchique tente d’abord des ruptures naturelles, avec des double sauts de ligne, puis des simples sauts de ligne, ensuite des phrases, puis des mots, et n’utilise d’autres méthodes que lorsque une section reste trop grande. La plupart des frameworks l’adoptent aujourd’hui par défaut, et c’est une amélioration évidente par rapport à un découpage à taille fixe pure.

Le découpage tenant compte de la structure suit le propre layout du document : en-têtes, sections, blocs de code et tableaux. Pour les documents techniques et le Markdown, il gagne souvent haut la main. Conservez des liens entre éléments parents et enfants afin de pouvoir cibler un petit fragment précis avant d’élargir à toute la section parente lorsque plus de contexte est nécessaire.

Le découpage sémantique utilise un modèle d’embedding ou un LLM pour identifier où le sujet change réellement et effectuer la séparation à cet endroit. Il produit les fragments les plus cohérents, mais à un coût supplémentaire réel, car chaque décision de séparation nécessite une appel au modèle ; il est donc généralement réservé aux corpus où la qualité de la récupération justifie ces dépenses.

Paramètres par défaut judicieux :

  • Commencez par une segmentation récursive ou tenant compte de la structure, et évitez celle à taille fixe.
  • Visez des blocs d’environ 300 à 800 tokens, puis ajustez en fonction de votre propre ensemble d’évaluation et non d’un chiffre tiré d’un blog.
  • Stockez des métadonnées pour chaque bloc, telles que le document source, le titre de la section ainsi que le numéro de page ou de paragraphe. Le filtrage et les citations en ont besoin par la suite.
  • Rassemblez un petit ensemble de questions réelles et examinez ce qui est récupéré avant d’utiliser le modèle d’embedding. Une mauvaise segmentation gâche silencieusement les résultats, il faut donc la corriger avant d’ajuster quoi que ce soit par la suite.

Embeddings et bases de données vectorielles

Les modèles d’incorporation placent le texte dans un espace à haute dimension où la proximité sémantique devient une proximité géométrique, généralement évaluée par la similarité cosinus ou le produit scalaire. Le modèle est important, mais la qualité des données et le découpage en segments comptent généralement davantage que le choix du modèle utilisé dans le processus. Les grandes familles comprennent des modèles ouverts polyvalents, des embeddings spécifiques à des domaines tels que le droit, la médecine ou le code, ainsi que des API propriétaires. Choisissez en fonction du vocabulaire de votre domaine, et non uniquement en fonction du classement sur les listes de meilleurs performances.

La véritable fonction d’un stockage de vecteurs est de permettre des recherches approximatives rapides du voisin le plus proche, car une comparaison brute et exacte ne fonctionne pas au-delà d’un petit ensemble de données. La plupart des systèmes utilisent des index basés sur des graphes tels que HNSW ou des index basés sur des clusters comme IVF, afin qu’une requête n’ait pas à être comparée à chaque vecteur. Le compromis consiste en un risque faible et ajustable de manquer le véritable voisin le plus proche, en échange d’un temps de traitement sub-linéaire. On ajuste rarement ce paramètre dès le début, mais savoir qu’il existe est utile lorsque l’on se demande pourquoi le fragment apparemment correct n’a pas été récupéré.

Lors du choix d’un système de stockage, demandez s’il filtre sur les métadonnées, s’il prend en charge nativement des recherches hybrides vecteur+mots-clés (BM25), à quel point il est facile de l’exécuter localement par rapport à une version gérée, ainsi que quelles sont les fonctionnalités de persistance, de réplication et d’échelle adaptées à votre volume de données. Parmi les options courantes figurent Qdrant, Weaviate, Pinecone, Chroma, pgvector et OpenSearch k-NN.

Au début, la marque du magasin compte moins que quatre autres éléments : des données bien organisées, une segmentation solide, des métadonnées appropriées, ainsi qu’un moyen de combiner la recherche vectorielle et la recherche par mots-clés. La recherche hybride est présente dans pratiquement toutes les implementations sérieuses, car la recherche vectorielle pure échoue à retrouver des éléments littéraux tels que les codes d’erreur, les SKU et les IDs de produits, que la recherche par mots-clés traite facilement. La fusion des scores denses et spars est généralement contrôlée par un seul poids, permettant ainsi à une requête de privilégier le sens ou les termes exacts en fonction du cas d’usage. Une approche hybride conceptuelle se présente ainsi, bien que l’API exacte varie selon le magasin :

# Conceptual shape of a hybrid query — exact API varies by vector store
results = vector_store.hybrid_search(
    query=user_question,
    alpha=0.5,          # weight between dense (1.0) and keyword (0.0) search
    filters={"doc_type": "runbook", "product": "checkout-service"},
    top_k=25,
)

Au-delà de la similarité top-k

Le fait de sélectionner les k fragments les plus proches marque le début du processus de récupération, mais pas sa fin. Les données réelles continuent de soulever les mêmes problèmes : le fragment le plus proche n’est pas nécessairement le plus utile, les faits d’une réponse sont répartis sur plusieurs fragments, les modèles accordent trop peu d’attention au contenu situé au milieu d’un contexte long, même s’il y est présent (effet de l’élément perdu au milieu), et le modèle d’embedding peut ne pas comprendre le vocabulaire de votre domaine.

Techniques à prendre en compte, approximativement en fonction du retour sur investissement en effort :

  • Reclassement. On récupère un grand ensemble de candidats, disons les 20 à 50 meilleurs et parfois 100, à l’aide d’une recherche vectorielle peu coûteuse, puis on réévalue leurs scores à l’aide d’un cross-encoder ou d’un petit LLM avant de n’en retenir que ceux qui seront intégrés dans la requête. Cela fait systématiquement partie des meilleures améliorations à apporter à un pipeline. Un cross-encoder évalue en même temps la requête et le document, ce qui est bien plus précis que de comparer deux vecteurs calculés séparément, mais il doit être exécuté une fois par candidat et ne peut pas couvrir toute une collection. La recherche à l’aide d’un bi-encoder est peu coûteuse mais approximative et permet de réduire le champ des recherches, tandis que le cross-encoder est coûteux mais précis et ne prend en compte que ce qui reste.
  • Recherche hybride, combinant des vecteurs denses avec une recherche par mots-clés dispersés afin que les tokens exacts ne soient pas laissés au hasard.
  • Transformation de la requête : réécrire la question, générer un document de réponse hypothétique et effectuer une recherche dessus (au style HyDE), ou diviser une question complexe en sous-questions récupérées indépendamment.
  • Filtrage des métadonnées, qui réduit le nombre de candidats en fonction du type de document, de la période de date ou du produit avant que la recherche vectorielle ne soit lancée, et non après.
  • Récupération du document parent, en effectuant une correspondance sur un petit fragment précis mais en retournant sa section parente plus large afin que le contexte soit complet.
  • Évaluation de la récupération en elle-même

    Un ensemble d’évaluation est supérieur à l’intuition. Rédigez de 20 à 50 questions réalistes, notez quels fragments doivent être récupérés pour chacune d’elles, et vérifiez directement si le bon fragment figure parmi les 5 ou les 10 meilleurs (Recall@k). Ajoutez un juge basé sur un LLM pour évaluer la pertinence uniquement une fois que l’inspection manuelle vous a donné confiance. Si la qualité de la récupération n’est jamais mesurée en dehors de la qualité de la réponse, on consacre du temps à optimiser le mauvais étape. Des outils comme Ragas couvrent des métriques spécifiques au RAG, vous évitant ainsi de devoir construire tout le système manuellement.

    LlamaIndex ou LangChain, conceptuellement

    LlamaIndex est axé sur les données, offrant des abstractions bien définies pour les moteurs d’indexation, de récupération et de requêtes ; il s’adapte naturellement lorsque le problème principal consiste en une grande quantité de documents nécessitant une bonne récupération. LangChain, quant à lui, est polyvalent, né des concepts de chaînes et d’agents, et dispose d’un écosystème d’intégration bien plus vaste. Il est plus flexible, mais aussi plus lourd lorsque la seule fonctionnalité requise est la récupération. Aucun des deux n’est magique, car ils exploitent tous deux les mêmes principes fondamentaux. Choisissez-en un, maîtrisez bien ses concepts et évitez le dogmatisme, car les connaissances architecturales restent valables quel que soit le syntaxe que vous utilisez.

    Résumé

    1. L’indexation et la consultation sont des phases distinctes, il convient donc de les concevoir séparément.
    2. Le découpage en blocs est un choix de conception essentiel, et non une option par défaut du framework.
    3. Les bases de données vectorielles font partie de l’infrastructure, et les avantages proviennent du filtrage et de la recherche hybride, et non du nom de la marque.
    4. La qualité de la récupération doit être mesurée séparément, indépendamment de la qualité de la réponse.
    5. Les frameworks sont des outils et non l’architecture ; apprenez donc les modèles et considérez l’outil comme remplaçable.