
Qualifier les réponses d'un assistant documentaire : ce qu'un banc d'essai a changé
- Hub Insights
- 🤖 Intelligence Artificielle
- Qualifier les réponses d'un assistant documentaire : ce qu'un banc d'essai a changé
Le point de départ est un assistant documentaire (outil qui répond à vos questions en s'appuyant sur vos propres documents) déjà en service chez un client. Il était branché sur un corpus métier (l'ensemble des documents dans lesquels il avait le droit de puiser) de plusieurs centaines de pages réglementaires et de RSE (responsabilité sociétale des entreprises). Les utilisateurs lui posaient des questions, il répondait. De ce point de vue, tout allait bien.
Mais une question s'est vite imposée : ces réponses étaient-elles seulement fondées ? Personne, dans les équipes, n'avait de moyen concret pour le vérifier. Tout reposait sur quelques retours d'utilisateurs interrogés au fil de l'eau, sur des questions choisies un peu au hasard, une évaluation entièrement subjective, faute de mieux.
Pour répondre à cette question, nous avons commencé par mesurer. Résultat : environ 1 réponse fiable sur 2. Quelques mois et quelques corrections plus tard, ce taux dépassait 9 sur 10.
Voici comment, dans l'ordre où les choses se sont produites, avec les surprises rencontrées en chemin.
TL;DR — EN BREF
- Un RAG est une chaîne à deux maillons : un moteur de recherche qui trouve les documents, un modèle qui rédige à partir d'eux. La qualité du premier plafonne tout le reste.
- Première mesure sur un banc de 140 questions métier : environ une réponse fiable sur deux, alors que l'assistant tournait déjà en production.
- Structurer le contexte transmis au modèle (prompt recadré sur le vocabulaire métier, sources datées, format de réponse imposé) a porté le taux à 7 sur 10, en dégradant la latence au passage.
- Rendre la recherche adaptative (classification de la question, top-k dynamique, re-ranking hybride, repli sur score faible) a dépassé 9 sur 10 et résorbé la latence.
- Deux surprises : le juge automatique n'est pas un instrument étalonné, et le référentiel lui-même contenait des réponses de référence fausses.
Pour comprendre la suite, deux minutes sur le fonctionnement d'un RAG
Si vous savez déjà ce qu'est un RAG, sautez cette section.
RAG signifie Retrieval-Augmented Generation, « génération augmentée par la récupération ».
L'idée est de ne pas demander au modèle de langage de répondre de mémoire. À la place, quand une question arrive, le système commence par chercher dans les documents de l'entreprise les passages susceptibles de contenir la réponse : c'est la phase de retrieval, la récupération.
Puis il transmet ces passages au modèle avec une consigne du type « réponds à cette question en t'appuyant uniquement sur ces extraits » : c'est la phase de generation, la rédaction.
Cette architecture apporte trois bénéfices. Le modèle travaille sur le patrimoine documentaire réel de l'entreprise, qu'il n'a jamais vu pendant son entraînement. Il hallucine beaucoup moins (une hallucination étant une information inventée par le modèle et présentée avec le même aplomb qu'un fait avéré), car on lui fournit la matière première. Et chaque réponse peut être tracée jusqu'aux documents qui l'ont nourrie, ce qui permet à l'utilisateur de vérifier par lui-même.
Un RAG est donc une chaîne à deux maillons. Le premier, le retriever, est un moteur de recherche qui trouve les documents. Le second, le generator, est le modèle de langage qui rédige à partir de ce qu'on lui donne.
Le moteur de recherche fixe le plafond de tout le reste
Cette architecture en deux maillons a une conséquence lourde. Que se passe-t-il quand le retriever se trompe de documents ?
On pourrait espérer que le generator s'en aperçoive et s'abstienne. Il n'en est rien. Il rédige quand même, avec le même aplomb, à partir des mauvaises sources. L'utilisateur reçoit alors une réponse fluide, bien construite, apparemment sourcée… et fausse.
Quand un assistant RAG répond mal, le réflexe est d'incriminer le modèle et de vouloir en changer. Or dans la grande majorité des cas, le coupable est en amont : le bon document n'est simplement pas arrivé jusqu'au modèle. Ni le réglage du generator, ni le changement de fournisseur, ni l'amélioration du prompt (le texte de consigne envoyé au modèle) ne rattraperont un document qui n'a pas été retrouvé. La qualité du retriever constitue une limite que le reste de la chaîne ne dépassera jamais. C'est pour cela qu'on commence toujours par évaluer la recherche avant de toucher à la rédaction.
Comment fonctionne ce fameux retriever ?
Deux grandes familles de techniques existent, et notre mission a fini par combiner les deux.
- La première est la recherche vectorielle : on découpe le corpus en fragments de quelques centaines de mots, les chunks. Chaque fragment est converti en un vecteur de nombres, un embedding, qui capture son contenu sémantique : deux textes qui parlent de la même chose auront des vecteurs proches, même s'ils n'emploient pas les mêmes mots. Quand une question arrive, elle subit la même conversion, et le système remonte les fragments dont le vecteur est le plus proche du sien. Le nombre de fragments remontés est un paramètre de réglage appelé top-k : avec un top-k de 5, on prend les 5 plus proches. Cette approche convient bien pour retrouver un passage précis. Elle l'est beaucoup moins quand la réponse exige de recouper plusieurs documents.
- La seconde famille, le GraphRAG, comble la lacune décrite précédemment. Au lieu de traiter les fragments comme des îlots isolés, on construit un graphe de connaissances (une carte qui relie les entités du corpus entre elles pour montrer comment elles sont liées, par exemple : Paris → capitale de → France). Les questions transverses, celles dont la réponse est éparpillée, deviennent traitables en suivant les liens du graphe.
Avant d'optimiser quoi que ce soit, nous avons construit le banc d'essai
Revenons à notre assistant. La tentation, en arrivant sur une mission comme celle-là, est de se jeter sur les réglages : changer le prompt, ajuster le découpage, tester un autre modèle. Nous avons résisté : sans mesure, impossible de savoir si un changement améliore ou dégrade. On avancerait à l'aveugle. La première étape a donc été de construire l'instrument de mesure.
- Les questions, d'abord : avec les experts du domaine, nous avons constitué un jeu d'environ 140 questions métier représentatives de ce que les utilisateurs demandent réellement. Pas seulement les questions faciles : nous y avons mis les questions factuelles simples, celles dont la réponse est répartie sur plusieurs documents, et celles dont la réponse ne figure nulle part dans le corpus, parce qu'un assistant fiable doit aussi savoir dire qu'il ne sait pas, et qu'il faut bien des questions pour le vérifier.
- Les réponses de référence, ensuite : pour chaque question, une personne du métier a rédigé et validé la réponse considérée comme correcte, ce qu'on appelle la ground truth, la vérité terrain. C'est la référence à laquelle les réponses de l'assistant seront comparées.
- Les critères de notation, enfin. Quatre en l'occurrence : l'exactitude des faits avancés, la complétude par rapport à la réponse de référence, la faithfulness (la fidélité : la réponse ne contient rien qui ne figure pas dans les sources fournies) et l'answer relevancy (la pertinence : la réponse traite bien la question posée, pas une question voisine).
Restait à décider qui allait noter 140 réponses à chaque itération, car le faire à la main aurait été intenable. Nous avons croisé deux évaluateurs automatiques. Le premier est un framework d'évaluation standardisé, une bibliothèque logicielle qui calcule ces métriques de façon normalisée. Le second est un LLM-as-judge, littéralement « un modèle de langage en position de juge » : on demande à un second modèle, distinct de celui qui produit les réponses, de les noter en suivant une grille écrite.
« LLM-as-judge » peut sonner comme un tour de magie, alors que c'est l'exact équivalent d'un barème de correction de copies. Pour le critère de complétude, par exemple, la grille énumère les éléments attendus dans la réponse et fixe l'échelle : 0 si aucun n'est présent, 1 si une partie l'est, 2 si tous le sont, chaque niveau étant illustré d'un exemple. Plus le barème est explicite, moins le juge improvise.
Deux évaluateurs plutôt qu'un, parce que leurs désaccords sont une information. Quand le framework et le juge notent différemment la même réponse, c'est le signal qu'un cas est ambigu, et c'est celui-là que nous allions inspecter à la main.
Le banc était prêt. Nous avons lancé la première mesure sur l'assistant tel qu'il existait, un RAG standard sans adaptation particulière. Verdict : environ 1 réponse fiable sur 2. L'assistant que tout le monde utilisait au quotidien se trompait une fois sur deux. Ce chiffre a été utile précisément parce qu'il était brutal : il a transformé un vague doute en problème établi, avec l'adhésion de tous pour le traiter.
Le diagnostic passe par la décomposition : quel maillon a cassé ?
Un score global de 50 % dit qu'on a un problème. Il ne dit pas lequel. Est-ce le retriever qui rapporte les mauvais documents, ou le generator qui exploite mal les bons ? Les corrections ne sont pas du tout les mêmes dans les deux cas, et c'est là que la structure en chaîne du RAG devient un atout : on peut instrumenter chaque maillon séparément.
Côté retriever, deux métriques répondent à deux questions complémentaires.
- Context precision : demande si les fragments rapportés sont réellement pertinents, ou si le système noie le modèle sous du bruit.
- Context recall : demande si tout ce qui était nécessaire a bien été rapporté, ou si une partie de la réponse est restée dans le corpus.
Trois leviers permettent d'agir :
- Le découpage en fragments (diviser les documents du corpus en petits morceaux indexables séparément. La taille de ces fragments compte beaucoup : s'ils sont trop grands, ils apportent du bruit inutile ; s'ils sont trop petits, on risque de perdre des informations importantes),
- Le réglage du top-k (le nombre de fragments remontés) : quand le retriever cherche dans le corpus, il doit décider combien de fragments il transmet au modèle (le top-k c'est ce nombre) ; s'il est trop petit, on risque de manquer des informations utiles, et s'il est trop grand, on ajoute du bruit inutile.
- Le re-ranking (le ré-ordonnancement des fragments candidats avant transmission au modèle) : le retriever récupère d'abord un ensemble de fragments potentiellement utiles, puis un second système les réexamine et les classe à nouveau selon leur pertinence réelle, pour s'assurer que les meilleurs fragments arrivent en tête avant d'être transmis au modèle.
Côté generator, deux métriques symétriques :
- Faithfulness : demande si la réponse générée reste fidèle aux fragments transmis, ou si le modèle invente des éléments qui n'y figurent pas.
- Answer relevancy : demande si la réponse générée répond bien à la question posée, ou si elle s'en écarte tout en restant fidèle au contexte.
Trois leviers permettent d'agir :
- La formulation du prompt : (les instructions données au modèle sur la façon d'utiliser le contexte et de structurer sa réponse)
- La mise en forme du contexte transmis : (la manière dont les fragments récupérés sont présentés au modèle, par exemple leur ordre ou leur balisage)
- Le comportement de repli quand la recherche n'a rien donné de solide : (ce que le modèle doit faire lorsqu'aucun fragment pertinent n'a été trouvé, plutôt que d'inventer une réponse)
Étape 1 : en structurant le contexte, nous sommes montés à 7 sur 10, avec une mauvaise surprise à la clé
Les premières mesures détaillées ont montré que le generator recevait des passages corrects mais les exploitait mal. Nous avons donc commencé par là, sans toucher ni au modèle, ni à l'index documentaire (la base dans laquelle les fragments sont rangés pour être retrouvés rapidement).
Trois changements :
- Nous avons recadré le prompt système, la consigne permanente placée en tête de chaque requête, sur le vocabulaire du domaine, pour que le modèle interprète correctement les termes au lieu de leur donner leur sens courant.
- Nous avons mis en forme les passages récupérés, jusque-là concaténés en vrac, de façon homogène, chacun avec sa source et sa date.
- Nous avons imposé un format de réponse, incluant la citation systématique des sources.
Remesure sur le banc : environ 7 réponses fiables sur 10. Un bond appréciable, pour un effort modeste.
Mais le banc a aussi révélé quelque chose que nous n'avions pas anticipé : la latence (le délai entre la question et l'affichage de la réponse) s'était nettement dégradée.
En y regardant de plus près, c'était logique : notre orchestration plus rigoureuse alourdissait chaque requête. Voilà un arbitrage qualité contre réactivité dont nous n'aurions rien su sans mesure, et que nous aurions découvert en production, par les plaintes des utilisateurs.
Nous avons choisi de continuer, en gardant ce point sous surveillance. Bien nous en a pris, comme la suite l'a montré.
Étape 2 : le pipeline adaptatif qui a dépassé 9 sur 10, et réglé la latence par-dessus le marché
Restait le retriever, devenu le maillon limitant. En analysant les échecs restants, un motif est apparu : le système traitait toutes les questions de la même façon, avec le même effort de recherche, alors qu'elles n'avaient rien de comparable.
Une question factuelle simple était noyée sous des fragments inutiles ; une question transverse manquait de matière. La réponse à ce constat a été de rendre la récupération adaptative.
D'abord, une classification de la complexité. Avant toute recherche, la question est classée simple, intermédiaire ou complexe, et cette étiquette pilote tout ce qui suit.
Ensuite, un top-k dynamique. Le nombre de fragments récupérés s'ajuste à l'étiquette : peu de fragments pour une question simple, pour ne pas noyer le generator ; davantage pour une question complexe, dont la réponse est dispersée. Le compromis entre précision et couverture se règle ainsi question par question, au lieu d'être figé une fois pour toutes.
Puis un re-ranking hybride. Les fragments candidats sont réordonnés selon trois signaux pondérés : leur similarité avec la question, leur diversité (inutile de retenir dix fragments qui répètent la même chose) et leur position dans le document d'origine. Le contexte final est tronqué pour tenir dans la fenêtre de contexte du modèle (la quantité maximale de texte qu'il peut lire en une fois).
Enfin, un repli sur score faible. Si le meilleur score de recherche reste sous un seuil, le système ne tente pas de répondre : il indique qu'il n'a pas trouvé de matière suffisante.
C'est déjà un quality gate : un point de contrôle qui interrompt le traitement quand la qualité n'est pas au rendez-vous.
Le pipeline adapte son effort à la complexité de la question, recombine plusieurs signaux, et sait reconnaître quand il manque de matière.
Nouvelle mesure sur le banc : plus de 9 réponses fiables sur 10.
Et la bonne surprise, cette fois : la latence dégradée à l'étape 1 s'était résorbée. Avec le recul, l'explication est logique. En adaptant l'effort de recherche à chaque question au lieu de tout traiter au maximum, le pipeline dépensait moins là où c'était inutile. Il répondait plus vite et plus juste. Nous étions partis du principe que qualité et performance s'opposaient ; le banc d'essai nous a montré que ce n'est pas une fatalité.
Une question dont la réponse tenait dans deux documents
Suivons une question précise du référentiel, du début à la fin de la mission. Elle portait sur les effectifs de recherche de l'entreprise et le montant d'investissement associé. L'information existait bien dans le corpus, mais elle était répartie sur deux documents : le chiffre des effectifs dans l'un, le montant dans l'autre.
Au départ, l'assistant répondait « je ne dispose pas de cette information ». Une fois les maillons instrumentés, le diagnostic est devenu plus facile : la recherche vectorielle, avec son top-k trop étroit, ne rapportait qu'un seul des deux documents. Le generator, qui avait pour consigne de ne rien inventer, se retrouvait avec la moitié de la réponse et préférait renoncer. C'était le bon comportement de sa part : le problème était bien en amont.
Dans la configuration finale, la même question obtient une réponse complète et sourcée. Trois mécanismes se sont relayés :
- La classification a rangé la question parmi les complexes et donc élargi le top-k.
- Le graphe de connaissances a relié les deux documents.
- Le re-ranking a fait remonter les fragments porteurs des chiffres.
Le corpus, lui, n'avait pas changé. Toute la différence tenait au dispositif de recherche.
Ce que la mission nous a appris sur la mesure elle-même : le juge se trompe, et le référentiel aussi
Il y a un piège dans la démarche que nous venons de décrire, et nous sommes tombés dedans : faire une confiance aveugle à l'instrument de mesure.
Premier constat : le LLM-as-judge oriente sans mesurer, et ce n'est pas un instrument étalonné. Sa note varie selon la formulation de la consigne. Il a un biais documenté en faveur des réponses longues, qu'il note mieux que les concises à contenu égal. Et il ne rend pas exactement le même verdict d'un appel à l'autre sur une réponse identique. Rien de rédhibitoire, à condition de le savoir : c'est justement pour cela que nous croisions ses notes avec celles du framework, et que chaque désaccord partait en inspection manuelle.
Second constat, plus inattendu : le référentiel lui-même était partiellement faux. En dépouillant les désaccords entre les deux juges, nous avons découvert que plusieurs réponses parfaitement correctes de l'assistant étaient notées comme fausses, simplement parce que leur formulation s'écartait de celle de la ground truth. Autrement dit, notre système était meilleur que ce que notre banc d'essai affichait, et c'est l'étalon qu'il a fallu corriger. Un référentiel n'est donc pas un livrable qu'on fige à la recette : il se valide avec le métier, se corrige et s'enrichit au fil de l'usage. C'est un objet vivant.
Ce que vous pouvez emporter de cette mission, et ce que vous devez laisser
Si vous reteniez de cet article « il faut un top-k dynamique », vous auriez retenu la mauvaise chose. Les réglages précis ne se transposent pas : ils dépendent du corpus, des questions, du modèle.
Ce qui se transporte, c'est le protocole. Constituer un référentiel représentatif avec le métier. Écrire des critères explicites. Mesurer chaque configuration sur le même banc. Agir sur les leviers du maillon que la mesure a désigné, et pas un autre. Recommencer. Notre corpus parlait de réglementaire et de RSE ; le vôtre parlera peut-être de RH, de juridique ou de documentation technique. Le cadre est identique, seul le contenu du référentiel change.
Une dernière condition, si l'objectif est d'industrialiser : le banc d'essai ne se range pas après la recette. Chez notre client, il est devenu une suite de tests de non-régression (des tests qui vérifient qu'une modification n'a rien cassé de ce qui fonctionnait), exécutée automatiquement par la chaîne d'intégration continue à chaque évolution du corpus, du prompt ou du modèle. Car un RAG fiable à la livraison ne le reste pas tout seul : le corpus évolue, les questions des utilisateurs se déplacent, le fournisseur met à jour son modèle sans prévenir. Sans mesure rejouée en permanence, la dégradation reste invisible, et on retombe dans le problème de départ.
Continuer votre exploration
Découvrez d'autres articles du cluster ia-generative dans l'univers Intelligence Artificielle