Accueil / Articles

Réclassement dans RAG : la fenêtre étroite où les encodeurs croisés sont réellement utiles

Le réclassement dans RAG ne sert qu’à améliorer la situation entre un plafond de rappel et un plafond K. Ce qu’est un « Phantom Hit » et comment mesurer ces deux limites pour vos propres requêtes en une après-midi.

Éditeur : REACTAPP.TOP13 min de lecture3018 mots

Sources: Reranking in RAG — Cross-Encoders, the K Threshold, and the Recall Ceiling in Production Systems

Un encodeur croisé ne permet d’aider un pipeline RAG que dans une bande étroite : le taux de rappel de la première étape doit être suffisamment élevé, et le nombre de candidats transmis doit rester suffisamment faible. En dehors de cette bande, le réordonneur n’a rien à corriger ou commence plutôt à nuire. Ce qui suit décrit le mécanisme, un mode de défaillance appelé « Phantom Hits », ainsi qu’une méthode pour mesurer tout cela à l’aide de vos propres données.

Imaginez un système RAG qui a trouvé la bonne réponse. Il n’y a eu ni erreur ni document perdu. La réponse se trouve simplement à la position 37 dans la liste des résultats, tandis que le LLM ne lit que les cinq premières, de sorte qu’en pratique elle n’existe pas. Aucun alerte n’est déclenchée, car selon tous les critères de suivi, la requête a réussi.

Ce n’est pas une particularité d’un déploiement particulier. Cela découle de la manière dont l’architecture est conçue. La recherche vectorielle est conçue pour placer la bonne réponse parmi les 50 à 200 meilleurs résultats, pas nécessairement en tête de liste, ce qui fait que tout processus se terminant par la récupération des résultats laisse la qualité de la réponse au hasard.

La réaction habituelle est d’ajouter un outil de réclassement. Cela implique un encodeur croisé, environ douze lignes de code, une légère amélioration du score nDCG, et le problème est résolu. Cette réaction n’est pas fausse en soi, car le réclassement échoue effectivement. Elle est cependant erronée car le réclassement fonctionne dans une fenêtre de fonctionnement étroite que presque personne ne mesure. Ci-dessous, vous verrez comment fonctionne cette deuxième étape plus coûteuse, où se situent les limites de cette fenêtre, et comment savoir en une après-midi du côté de chaque limite se trouve votre système.

Le réclassement n’est pas une meilleure recherche vectorielle

Un réclassificateur repose sur une architecture différente, activée uniquement après la récupération des résultats et appliquée à un petit ensemble de candidats.

Le bi-encodeur présent dans votre système de recherche vectorielle actuel encode la requête et chaque document de manière indépendante, à l’avance et hors ligne. Cela permet une rapidité d’exécution et une capacité à gérer des millions de documents. Le inconvénient est qu’il ne prend jamais en compte ni la requête ni le document ensemble.

Le cross-encodeur fait le contraire : il lit les deux en même temps, token par token, ce qui lui permet de détecter des négations, des contradictions numériques et des subtilités que le bi-encodeur ne peut pas voir. En contrepartie, il doit effectuer ce travail séparément pour chaque candidat au moment de la requête.

Cela donne le processus en deux étapes bien connu. La récupération réduit à moindre coût le champ de recherche à 50 à 200 candidats, en visant le taux de rappel : ne pas perdre la bonne réponse. Le réclassement trie ensuite ce petit ensemble à un coût plus élevé, en visant la précision : parmi ceux qui restent, choisir le véritable meilleur.

La deuxième étape n’est pas non plus une amélioration gratuite. Au-delà d’un certain nombre de candidats, l’encodeur croisé commence à traiter le bruit comme un signal, et la qualité diminue réellement. Décider d’ajouter un réclassement relève d’un calcul technique effectué sur vos données, et non d’un réflexe.

Pourquoi la récupération ne peut pas être l’étape finale

Un symptôme qui apparaît constamment dans les systèmes RAG en production est le suivant : « Le modèle hallucine, même si les informations se trouvent dans notre base de données. » Dans la plupart des cas analysés en profondeur, le modèle ne inventait rien de son propre chef. Le document correct se trouvait parmi les cinquante meilleurs résultats affichés, mais pas parmi les cinq meilleurs présentés au générateur.

La cause est d’ordre architectural. Le bi-encodeur calcule l’embedding d’un document au moment de l’indexation, avant même qu’une question n’existe. Lors de la recherche, il compare deux résumés compressés plutôt que le texte réel de la question avec le texte réel du document.

Un exemple classique de ce qui se perd : la requête indique « bon marché » tandis que le document mentionne « 500 $ par nuit ». Pour les vecteurs, il s’agit dans les deux cas du prix d’une chambre d’hôtel, ce qui les fait se rapprocher. La contradiction n’apparaît que lorsque quelqu’un lit les deux textes côte à côte, ce que le bi-encodeur ne fait jamais par conception.

Un modèle d’incorporation plus performant ne résoudra pas ce problème, car il s’agit d’un compromis délibéré. La récupération vise à maximiser le taux de rappel, c’est-à-dire les chances que le document approprié se trouve parmi ceux retournés, et ce à moindre coût même pour des millions de documents. Mettre le document correct en tête de liste n fait tout simplement pas partie de ses objectifs.

Recall@50 et precision@5 mesurent des choses différentes et répondent à des questions distinctes. Les confondre est la raison pour laquelle les équipes finissent par devoir recourir à une couche supplémentaire pour résoudre un problème que celle-ci ne peut pas traiter.

Le défaut réside dans le fait que le bi-encodeur ne considère jamais le couple ensemble, alors voyons ce que gagne un modèle qui prend en compte ce couple.

Le bi-encodeur catalogue, le cross-encodeur lit

Pensez à la procédure de recrutement. Le bi-encodeur incarne un recruteur qui classe mille CV dans des dossiers avant même que la description de l’emploi n’existe : rapidement, de manière superficielle, et en peu de temps. Le cross-encodeur incarne le responsable des recrutements avec dix finalistes, en lisant chaque CV côte à côte avec l’offre d’emploi, ligne par ligne. Ce n’est qu’à ce moment-là que les incohérences que le recruteur n’avait pas pu voir apparaissent.

Mécaniquement, la différence est évidente. Un cross-encodeur combine la requête et le document en une seule séquence, selon le format canonique [CLS] requête [SEP] document [SEP], puis la fait passer par un seul transformateur.

Au niveau interne, c’est l’attention croisée qui effectue le travail : chaque token de requête peut s’attacher directement à chaque token de document et inversement. Le résultat n’est pas un vecteur à comparer, mais un seul logit, un nombre brut non normalisé exprimant le degré de confiance du modèle quant à la pertinence de ce couple particulier.

Ainsi, le bi-encodeur produit une représentation tandis que le cross-encodeur émet un jugement. Il s’agit d’une différence quant à ce que le modèle est capable de percevoir, et non d’une différence de degré.

Une conséquence en découle immédiatement. Un score de cross-encodeur ne peut pas être précalculé ni indexé, car il dépend du couple spécifique de requête et de document plutôt que du document seul. Chaque requête nécessite une itération complète pour chaque candidat, ce qui est des dizaines à cent fois plus coûteux par couple qu’une comparaison de vecteurs.

Le schéma qui explique la conception en deux étapes rend l’échelle claire. Selon l’étude Sentence-BERT de 2019 de Reimers et Gurevych, trouver le couple le plus similaire parmi 10 000 phrases nécessite environ 50 millions de comparaisons, ce qui correspond à environ 65 heures avec un modèle BERT complet et à environ 5 secondes avec une architecture de type SBERT.

Mémorisez cette valeur sous sa forme exacte, car des variantes arrondies circulent, comme « 10 millions de documents et 50 heures ». La différence est qualitative : le goulot d’étranglement réside dans le nombre de paires à évaluer, et non dans la taille du corpus.

C’est pourquoi un encodeur croisé ne sert jamais de première étape. Il n’est pas moins performant, mais son exécution sur un corpus entier est trop coûteuse. Et comme son coût est élevé par paire, tout dépend du nombre de paires qui lui sont fournies et de sa position dans le pipeline.

Deux étapes, deux budgets

Le réordonneur intervient après la récupération des résultats et avant le LLM. La recherche renvoie les k meilleurs candidats, où k représente le nombre de documents transmis d’une étape à l’autre, généralement entre 50 et 200. Le réordonneur réorganise ensuite cette liste et envoie les résultats au générateur à une position située entre 3 et 20.

Cette cascade n’a pas vu le jour avec les LLM, ce qui témoigne de leur maturité. Le principe du « filtre bon marché, puis juge coûteux » provient de l’époque du Learning-to-Rank, où la deuxième étape consistait en un ensemble d’arbres de décision basés sur des caractéristiques construites manuellement, plutôt qu’un modèle de type transformer. Le moteur a changé, mais l’architecture est restée identique.

Le réclassement neuronal a une date de naissance précise. En 2019, l’article « Passage Re-ranking with BERT » a utilisé BERT comme classificateur binaire sur des paires de requête et de passage, améliorant le MRR@10 de 27 % par rapport au meilleur résultat disponible à l’époque. C’est à ce moment-là que la deuxième étape a cessé d’être une opération d’optimisation pour devenir une couche à part entière.

La mise en œuvre commerciale la plus connue aujourd’hui est le réclasseur phare de Cohere. Au fil des versions, ce qui a le plus changé, c’est une seule configuration : la fenêtre d’entrée est passée de quelques centaines de tokens à plus de 32 000, avec une limite de 4 096 pour les versions v3 et v3.5. Il s’agit d’un véritable changement de conception, car cela augmente la taille des blocs qui peuvent être évalués sans troncature, permettant ainsi une segmentation moins agressive et une perte de contexte réduite.

Les fournisseurs parlent moins de ce qui viendra ensuite. Les prix indiqués pour un même modèle varient de dix fois ou plus selon les sources externes, allant d’une fraction de centime à deux dollars et demi par mille recherches, en fonction de celui qui effectue le calcul et de ce qu’il inclut dans une « recherche ».

Une règle simple s’applique : si vous ne pouvez pas reproduire les calculs du fournisseur avec votre propre trafic, vous n’avez pas de chiffre exact, vous avez seulement une estimation. Il existe également un piège de facturation : les documents dépassant la limite sont divisés en parties, et chaque partie est facturée séparément, de sorte qu’une seule demande de réclassement logique peut se transformer en plusieurs facturations.

La forme à retenir est la suivante : récupérer à bas coût à grande échelle, réclasser à coût élevé sur un ensemble restreint, et ne laisser le LLM voir que ce qui survit aux deux étapes. Cela semble être une solution par défaut sûre, mais il existe un seuil au-delà duquel elle cesse de fonctionner, dans une direction que presque personne ne prévoit.

Les résultats fantômes et le point où la réclassification commence à nuire

La logique conventionnelle veut que plus vous fournissez de candidats au système de réclassification, plus vous êtes en sécurité. Le modèle étant plus précis que la recherche vectorielle, avec K égal à 500 ou 1 000, il ne peut certainement pas se tromper. Cette intuition est fausse, et les preuves à l’encontre sont bien documentées.

La publication de 2024 intitulée « Drowning in Documents » (Jacob et ses collaborateurs) indique que, à mesure que K augmente, la qualité du réordonneur s’améliore, atteint un pic, puis diminue de manière visible. Lorsque l’ensemble des documents était scanné de manière aveugle, le simple algorithme BM25 parvenait à surpasser un encodage croisé considéré comme le meilleur disponible. Il convient cependant de garder à l’esprit une réservation : ce résultat provient de scans aveugles sur des ensembles de données académiques et professionnelles, et il ne dit pas grand-chose sur un processus typique où K ne dépasse guère quelques centaines.

Cette défaillance a un nom : les « Phantom Hits ». Le réordonneur attribue avec assurance son score le plus élevé à un document n’ayant aucun lien avec la requête, ni au niveau lexical ni au niveau sémantique.

Les auteurs suggèrent une source probable et prennent soin de la qualifier d’hypothèse et non de cause confirmée. Ils soulignent la méthode d’entraînement, qu’ils nomment biais d’exposition. Les outils de réclassification sont entraînés de manière contrastive à l’aide de négatifs difficiles, des documents qui ressemblent de manière trompeuse à la bonne réponse mais sont erronés sur le fond, ce qui fait que le modèle devient expert en différences microscopiques.

Dans un environnement de production, cette expertise a des effets néfastes. Face à un négatif simple, du bruit purement aléatoire qu’il a à peine rencontré pendant l’entraînement, le modèle ne dispose d’aucun point de référence et commence à deviner. Un modèle formé à distinguer des jumeaux est impuissant face à l’arrivée d’un inconnu.

Le bord opposé est tout aussi réel et n’annule pas le premier. Plusieurs analyses indépendantes situent le seuil minimal de rentabilité pour le réclassement autour de recall@50 = 0,85. En dessous de ce chiffre, il n’y a rien qui vaille la peine d’être trié, car le document correct n’a jamais fait partie de l’ensemble à traiter. Les seuils exacts varient d’une source à l’autre en raison des différences de corpus, et leur origine est importante : blogs et expérience de terrain, et non revue par des pairs. Utilisez-les comme hypothèses à tester sur vos propres données, et jamais comme faits établis.

Ces deux constats ne sont pas contradictoires. Ce sont les deux extrémités d’une même fenêtre de fonctionnement. En dessous du seuil de rappel, le réclassement n’a rien sur quoi travailler. Au-delà du seuil K, il commence à causer des dommages. Le réclassement n’est pas une amélioration monotone, et supposer qu’il en apporte toujours davantage revient à commettre la même erreur en croyant aveuglément aux références fournies par un fournisseur, car dans les deux cas on remplace les mesures par des croyances populaires.

Étant donné que trop de réclassifications peuvent nuire et que trop peu ne suffisent pas, nous avons besoin d’une vision claire du plafond de ce que cette étape peut corriger.

Le plafond de la récupération des informations, et ce que représentent réellement ces 67 pour cent

Un outil de réclassification est un éditeur, pas un journaliste. Il peut réorganiser des matériaux déjà collectés, mais il ne peut pas créer ce que personne n’a apporté.

Ce principe, le plafond de la récupération des informations, semble anodin jusqu’à ce qu’on le compare aux statistiques les plus marquantes du secteur. Anthropic a décrit dans son rapport sur la récupération contextuelle un processus de 2024 dans lequel le taux d’échec de récupération des 20 meilleurs résultats est passé de 5,7 à 1,9 pour cent, soit une réduction de 67 pour cent.

Ce chiffre est souvent cité à l’appui des réclassifications. Cependant, lorsqu’on le décompose par étapes, il raconte une autre histoire, sans pour autant être faux.

Le parcours était le suivant : les embeddings contextuels ont réduit le taux à 3,7 pour cent, l’ajout de BM25 l’a abaissé à 2,9 pour cent, et ce n’est qu’alors que le reranking a permis d’atteindre 1,9 pour cent. Le reranking seul couvre donc la dernière étape, de 2,9 à 1,9 pour cent. Ces deux valeurs restent valables car elles mesurent des domaines différents : les 67 pour cent correspondent au résultat de l’ensemble du système et non d’une seule couche.

Cette distinction a une réelle importance opérationnelle. Avant de présenter les « 67 pour cent » lors d’une revue d’architecture, sachez que vous promettez l’effet de quatre modifications combinées, dont trois interviennent avant le reranking et contribuent pour la majeure partie à l’amélioration.

Les auteurs soulignent eux-mêmes cette limitation : le graphique présente une moyenne sur des domaines variés, et la variance entre eux est importante. Une autre précaution à prendre en compte, d’après les données disponibles, est le fait que chaque valeur de qualité pour les outils de réclassement commerciaux est fournie par les vendeurs, sur leurs propres ensembles de données et avec leur propre méthode de récupération en première étape. Aucune évaluation indépendante à l’échelle du marché n’existe.

Aucun critère externe ne vous permettra de savoir comment se comporte le réclassement dans votre système, il vous faut donc le tester vous-même.

Un calcul que vous pouvez effectuer lundi matin

Toute la complexité de ce sujet se résume à une procédure reproductible. C’est la rareté avec laquelle les équipes la mettent en œuvre qui explique pourquoi le débat sur le fait de savoir si le réclassement est utile persiste.

Étape un : mesurez le recall@50 et la précision@5 sur une centaine de requêtes de production étiquetées. Utilisez vos propres journaux d’activité ainsi que votre propre combinaison de termes et d’intents, et non un benchmark public. Si le recall@50 est clairement inférieur à 0,85, corrigez d’abord le processus de récupération, par le biais du chunking, de la recherche hybride ou des embeddings, plutôt que d’ajouter une couche supplémentaire.

Étape deux : recherchez le signe distinctif. Un recall@50 élevé associé à une précision@5 faible correspond précisément au profil pour lequel le reranking existe. Le bon document se trouve bien dans le pool, mais il occupe simplement une position trop basse.

Étape trois : choisissez le modèle en toute conscience. Une API hébergée permet un démarrage rapide sans aucune opération à gérer, mais vos données quittent votre infrastructure. Un reranker auto-hébergé offre un contrôle sur les coûts et la confidentialité, mais vous devez vous occuper des GPU et de leur entretien. Il s’agit davantage d’une décision liée à la conformité et au budget que d’une question de qualité du modèle.

Essayer cela est également peu coûteux. Le réclassement local peut être réalisé en une douzaine de lignes environ :

from sentence_transformers import CrossEncoder

reranker = CrossEncoder("BAAI/bge-reranker-large", max_length=512)

def rerank(query, docs):
    pairs = [(query, d.page_content) for d in docs]   # pair: query + candidate
    scores = reranker.predict(pairs)                  # one logit per pair
    return sorted(zip(docs, scores), key=lambda x: x[1], reverse=True)

Trois erreurs se produisent le plus fréquemment. La première consiste à gonfler les valeurs de K « juste par précaution ». Une autre est de réordonner les résultats après que le contexte a été tronqué, ce qui fait que le modèle évalue un préfixe plutôt que le document lui-même. La troisième consiste à considérer les scores du cross-encoder comme des seuils absolus comparables entre différentes requêtes, ce qui est particulièrement dangereux car cela fonctionne bien en démonstration mais échoue en production.

Il en existe une moins évidente également : l’affirmation « le réordonneur ne sert à rien » est parfois due à un bug numérique et non à un problème d’architecture. Un cas décrit dans le guide de migration de Sentence-Transformers concernait une fonction sigmoïde calculée en bfloat16 qui sature, ce qui rassemble les scores les plus élevés et randomise en fait leur ordre. Une fois que le format float32 a été utilisé avant l’activation, le classement est revenu à un ordre normal, loin du hasard.

Tout cela ne nécessite que des mesures, sans modification de l’architecture.

Que cela signifie pour l’architecte

Retour à la position 37. Le document bloqué là n’a jamais été un problème du modèle de génération. C’était un problème d’ordre de traitement.

  • Un cross-encoder n’est pas une meilleure embedding. Il s’agit d’une architecture distincte, déclenchée après la récupération, qui lit la requête et le document ensemble et renvoie un verdict plutôt qu’une représentation. Aucune amélioration de la qualité de l’embedding ne permet d’obtenir ce que procure la lecture côte à côte du couple.
  • Le reranking doit avoir sa place bien définie. La récupération reste peu coûteuse et large, le reranking reste coûteux et restreint, et la structure des coûts de cette cascade constitue l’idée fondamentale.
  • Avoir plus de candidats n’est pas une solution par défaut fiable. Au-delà d’un certain nombre K, la qualité diminue réellement, et l’explication réside dans la manière dont ces modèles sont entraînés.
  • Le plafond est fixe. Ce que la première étape n’a pas pu récupérer ne peut être retrouvé par un réclassificateur, quel que soit l’argument avancé par le fournisseur.
  • Vos données constituent la référence. Une après-midi passée à calculer le taux de rappel@50 et la précision@5 sur cent requêtes étiquetées suffit à mettre fin à un débat qui pourrait sinon durer des semaines.

De nombreuses équipes considèrent le réclassage comme une fonctionnalité standard, intégrée à tout système RAG de la même manière qu’un cache. C’est une habitude erronée. La vision la plus juste apparaît lorsque l’on considère ensemble ces deux seuils : un plancher en dessous duquel la couche n’a rien à corriger, et un plafond au-delà duquel elle commence à altérer les résultats. En bref, le réclassage est conditionnel, jamais automatique.

Une lacune persiste. Dans les données examinées ici, aucun indicateur de performance spécifique pour le polonais n’a été présenté, et chaque chiffre multilingue correspond à une moyenne sur des dizaines de langues. Pour un corpus en langue polonaise, ou pour toute langue moins répandue, mesurer les performances sur ses propres données n’est pas seulement recommandé : c’est la seule option possible.