{"id":154,"date":"2026-09-29T15:14:34","date_gmt":"2026-09-29T13:14:34","guid":{"rendered":"https:\/\/www.ranksignal.fr\/blog\/?p=154"},"modified":"2026-10-07T20:48:36","modified_gmt":"2026-10-07T18:48:36","slug":"comment-evaluer-la-qualite-d-un-rag","status":"publish","type":"post","link":"https:\/\/www.ranksignal.fr\/blog\/rag\/comment-evaluer-la-qualite-d-un-rag\/","title":{"rendered":"Comment \u00e9valuer un RAG : mesurer la recherche, puis la r\u00e9ponse"},"content":{"rendered":"<p>Tu as branch\u00e9 ton assistant sur tes documents. Il r\u00e9pond vite, avec aplomb, et sur les trois questions que tu as essay\u00e9es, il a m\u00eame eu raison. Pas de quoi dormir tranquille : un <a href=\"\/blog\/rag\/a-quoi-ressemble-un-systeme-rag\/\" title=\"RAG\">RAG<\/a> peut se tromper de deux fa\u00e7ons tr\u00e8s diff\u00e9rentes, et rien ne te dit laquelle tant que tu ne mesures pas.<\/p>\n<p>\u00c0 la fin de cet article, tu sauras poser le bon diagnostic : ton syst\u00e8me ne trouve pas la bonne information, ou bien il la trouve et la lit de travers. Et tu sauras avec quelles mesures, sur quel jeu de test, et avec quelles pr\u00e9cautions le v\u00e9rifier.<\/p>\n<h2>L&rsquo;essentiel en 30 secondes<\/h2>\n<ul>\n<li>Un RAG se joue \u00e0 deux \u00e9tages mesurables : la <strong>r\u00e9cup\u00e9ration<\/strong> (trouver les bons passages) et la <strong>g\u00e9n\u00e9ration<\/strong> (r\u00e9diger la r\u00e9ponse \u00e0 partir d&rsquo;eux). L&rsquo;indexation et l&rsquo;augmentation ne se mesurent qu&rsquo;indirectement.<\/li>\n<li>Trois relations \u00e0 surveiller : la question face au contexte r\u00e9cup\u00e9r\u00e9 (pertinence du contexte), le contexte face \u00e0 la r\u00e9ponse (fid\u00e9lit\u00e9), la r\u00e9ponse face \u00e0 la question (pertinence de la r\u00e9ponse).<\/li>\n<li>C\u00f4t\u00e9 r\u00e9cup\u00e9ration, on emprunte les m\u00e9triques de la recherche d&rsquo;information : pr\u00e9cision, pr\u00e9cision@k, rappel, F1, MRR, MAP, nDCG. C\u00f4t\u00e9 r\u00e9ponse, des frameworks comme RAGAS demandent \u00e0 un LLM de jouer le juge.<\/li>\n<li>Tout cela exige un jeu de test : des questions associ\u00e9es \u00e0 une r\u00e9ponse de r\u00e9f\u00e9rence (la <em>ground truth<\/em>), \u00e9crites \u00e0 la main ou g\u00e9n\u00e9r\u00e9es.<\/li>\n<li>Aucun score n&rsquo;est parfait : le juge peut \u00eatre biais\u00e9, les benchmarks vieillissent, et la latence comme le co\u00fbt comptent autant que l&rsquo;exactitude.<\/li>\n<\/ul>\n<h2>L&rsquo;intuition : deux endroits o\u00f9 \u00e7a peut casser<\/h2>\n<p>Le RAG le plus simple suit un chemin lin\u00e9aire, \u00ab r\u00e9cup\u00e9rer puis lire \u00bb : un <a href=\"\/blog\/rag\/qu-est-ce-qu-un-retriever\/\" title=\"retriever\">retriever<\/a> va chercher l&rsquo;information, un <a href=\"\/blog\/inference\/qu-est-ce-qu-un-llm\/\" title=\"LLM\">LLM<\/a> la lit pour \u00e9crire la r\u00e9ponse. Chaque \u00e9tape a ses faiblesses. \u00c0 la r\u00e9cup\u00e9ration, on peut ramener des passages hors sujet ou en manquer d&rsquo;utiles. \u00c0 la g\u00e9n\u00e9ration, ces d\u00e9fauts se paient en hallucinations.<\/p>\n<p>Une <a href=\"\/blog\/agentic\/eviter-hallucination-documents-recuperes\/\" title=\"hallucination\">hallucination<\/a> peut ainsi na\u00eetre de trois causes : le retriever n&rsquo;a pas r\u00e9cup\u00e9r\u00e9 tout le contexte pertinent (ou en a r\u00e9cup\u00e9r\u00e9 un qui ne l&rsquo;est pas), le LLM ignore le contexte fourni, ou il puise dans des \u00e9l\u00e9ments non pertinents du contexte au lieu de r\u00e9pondre \u00e0 la question.<\/p>\n<blockquote>\n<p><strong>\ud83d\udca1 Intuition<\/strong> Face \u00e0 une mauvaise r\u00e9ponse, la bonne question n&rsquo;est pas \u00ab est-elle fausse ? \u00bb mais \u00ab \u00e0 quel \u00e9tage a-t-elle d\u00e9raill\u00e9 ? \u00bb. V\u00e9rifier si le LLM r\u00e9pond bien <em>quand on lui donne le bon contexte<\/em> permet de s\u00e9parer ses capacit\u00e9s de raisonnement et de synth\u00e8se de celles de la r\u00e9cup\u00e9ration.<\/p>\n<\/blockquote>\n<p>Une figure r\u00e9sume ce qu&rsquo;il faut regarder : un triangle form\u00e9 par la question, le contexte r\u00e9cup\u00e9r\u00e9 et la r\u00e9ponse g\u00e9n\u00e9r\u00e9e. Chaque c\u00f4t\u00e9 est une m\u00e9trique.<\/p>\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6adef46bf01c0&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6adef46bf01c0\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1849\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch02_triade_evaluation-scaled.png\" alt=\"Triangle d'\u00e9valuation d'un RAG : la question est reli\u00e9e au contexte r\u00e9cup\u00e9r\u00e9 par la pertinence du contexte, \u00e0 la r\u00e9ponse g\u00e9n\u00e9r\u00e9e par la pertinence de la r\u00e9ponse, et le contexte est reli\u00e9 \u00e0 la r\u00e9ponse par la fid\u00e9lit\u00e9 (groundedness)\" class=\"wp-image-120\" srcset=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch02_triade_evaluation-scaled.png 2560w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch02_triade_evaluation-300x217.png 300w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch02_triade_evaluation-1024x739.png 1024w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch02_triade_evaluation-768x555.png 768w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch02_triade_evaluation-1536x1109.png 1536w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch02_triade_evaluation-2048x1479.png 2048w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Regarde le c\u00f4t\u00e9 du bas, entre contexte et r\u00e9ponse : c&rsquo;est la fid\u00e9lit\u00e9, celle qui te dit si le LLM s&rsquo;appuie vraiment sur ce qu&rsquo;on lui a fourni. Ce cadre est celui de la triade de m\u00e9triques RAG propos\u00e9e par TruEra.<\/figcaption><\/figure>\n\n\n<h3>O\u00f9 placer les mesures dans un vrai pipeline<\/h3>\n<p>Prenons un agent qui r\u00e9pond \u00e0 des questions sur une base de films, le fil rouge de cet article. Le pipeline commence par la question. Un LLM choisit l&rsquo;outil de r\u00e9cup\u00e9ration le plus adapt\u00e9 (recherche vectorielle, gabarit de requ\u00eate, g\u00e9n\u00e9ration de requ\u00eate \u00e0 la vol\u00e9e) : le choix lui-m\u00eame peut \u00eatre \u00e9valu\u00e9. L&rsquo;outil ram\u00e8ne un contexte, dont la pertinence est un autre point de mesure. Le LLM r\u00e9dige enfin la r\u00e9ponse, et le pipeline entier peut \u00eatre jug\u00e9 d&rsquo;un bloc.<\/p>\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6adef46bf0758&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6adef46bf0758\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"683\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b1_ch08_etapes_evaluation-scaled.png\" alt=\"Pipeline en quatre \u00e9tapes reli\u00e9es par des fl\u00e8ches : question, s\u00e9lection de l'outil, contexte r\u00e9cup\u00e9r\u00e9, r\u00e9ponse g\u00e9n\u00e9r\u00e9e\" class=\"wp-image-147\" srcset=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b1_ch08_etapes_evaluation-scaled.png 2560w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b1_ch08_etapes_evaluation-300x80.png 300w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b1_ch08_etapes_evaluation-1024x273.png 1024w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b1_ch08_etapes_evaluation-768x205.png 768w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b1_ch08_etapes_evaluation-1536x410.png 1536w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b1_ch08_etapes_evaluation-2048x546.png 2048w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Chaque fl\u00e8che de ce sch\u00e9ma est un endroit o\u00f9 tu peux poser un thermom\u00e8tre : s\u00e9lection de l&rsquo;outil, contexte r\u00e9cup\u00e9r\u00e9, r\u00e9ponse g\u00e9n\u00e9r\u00e9e, puis \u00e9valuation de bout en bout.<\/figcaption><\/figure>\n\n\n<h3>D\u00e9cider de ce que \u00ab r\u00e9ussir \u00bb veut dire<\/h3>\n<p>Avant de mesurer quoi que ce soit, il faut fixer des objectifs chiffr\u00e9s. Un \u00ab r\u00e9ponse rapide \u00bb vague devient \u00ab 90 % des requ\u00eates trait\u00e9es en moins de 2 secondes \u00bb, accompagn\u00e9 de m\u00e9triques de succ\u00e8s choisies d\u00e8s le d\u00e9part, comme le taux de requ\u00eates r\u00e9solues, la latence ou la pr\u00e9cision@5.<\/p>\n<h2>Sous le capot : les m\u00e9triques<\/h2>\n<h3>C\u00f4t\u00e9 r\u00e9cup\u00e9ration : a-t-il trouv\u00e9 les bons passages ?<\/h3>\n<p>La <strong>pr\u00e9cision<\/strong> r\u00e9pond \u00e0 \u00ab parmi les documents r\u00e9cup\u00e9r\u00e9s, combien \u00e9taient pertinents ? \u00bb. Le <strong>rappel<\/strong> r\u00e9pond \u00e0 l&rsquo;inverse : \u00ab parmi tous les documents pertinents, combien ont \u00e9t\u00e9 r\u00e9cup\u00e9r\u00e9s ? \u00bb. La pr\u00e9cision@k limite le calcul aux k premiers r\u00e9sultats, ce qui colle bien au RAG puisque seuls les tout premiers servent \u00e0 nourrir la r\u00e9ponse.<\/p>\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6adef46bf0c40&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6adef46bf0c40\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"2250\" height=\"1650\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_precision_rappel.png\" alt=\"Diagramme de Venn : les documents r\u00e9cup\u00e9r\u00e9s et les documents pertinents se recoupent, l'intersection \u00e9tant les vrais positifs ; pr\u00e9cision = vrais positifs \/ documents r\u00e9cup\u00e9r\u00e9s, rappel = vrais positifs \/ documents pertinents\" class=\"wp-image-148\" srcset=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_precision_rappel.png 2250w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_precision_rappel-300x220.png 300w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_precision_rappel-1024x751.png 1024w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_precision_rappel-768x563.png 768w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_precision_rappel-1536x1126.png 1536w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_precision_rappel-2048x1502.png 2048w\" sizes=\"auto, (max-width: 2250px) 100vw, 2250px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Sur ce sch\u00e9ma, l&rsquo;intersection des deux ensembles porte les vrais positifs : c&rsquo;est le num\u00e9rateur commun aux deux m\u00e9triques. Seul le d\u00e9nominateur change, et c&rsquo;est ce qui les fait se contredire. Un rappel parfait s&rsquo;obtient trivialement en r\u00e9cup\u00e9rant toute la base, ce qui montre qu&rsquo;il ne veut rien dire tout seul.<\/figcaption><\/figure>\n\n\n<p>Le <strong>score F1<\/strong> r\u00e9concilie les deux. C&rsquo;est leur moyenne harmonique : il p\u00e9nalise fortement la valeur faible, donc un F1 \u00e9lev\u00e9 exige pr\u00e9cision et rappel \u00e9lev\u00e9s ensemble.<\/p>\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6adef46bf10fa&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6adef46bf10fa\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"2250\" height=\"1500\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_f1_score.png\" alt=\"Trois courbes du F1-score en fonction de la pr\u00e9cision, pour un rappel fix\u00e9 \u00e0 0,9, 0,5 et 0,1 : la courbe \u00e0 rappel 0,1 plafonne autour de 0,18 m\u00eame quand la pr\u00e9cision atteint 1,0\" class=\"wp-image-149\" srcset=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_f1_score.png 2250w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_f1_score-300x200.png 300w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_f1_score-1024x683.png 1024w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_f1_score-768x512.png 768w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_f1_score-1536x1024.png 1536w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_f1_score-2048x1365.png 2048w\" sizes=\"auto, (max-width: 2250px) 100vw, 2250px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Suis la courbe la plus basse : avec un rappel de 0,1, le F1 plafonne autour de 0,18 m\u00eame avec une pr\u00e9cision parfaite. Le score reste toujours tir\u00e9 vers la plus faible des deux mesures.<\/figcaption><\/figure>\n\n\n<p>Ces m\u00e9triques ignorent l&rsquo;ordre des r\u00e9sultats. Trois autres en tiennent compte :<\/p>\n<ul>\n<li>le <strong>MRR<\/strong> (rang de r\u00e9ciprocit\u00e9 moyen) prend l&rsquo;inverse du rang du premier document pertinent, puis moyenne sur les requ\u00eates. Il dit \u00e0 quelle vitesse on trouve un bon r\u00e9sultat, mais ignore tout ce qui suit ;<\/li>\n<li>le <strong>MAP<\/strong> (pr\u00e9cision moyenne) moyenne la pr\u00e9cision calcul\u00e9e \u00e0 chaque rang o\u00f9 appara\u00eet un document pertinent. Il donne une mesure unique sensible au classement, au prix d&rsquo;un calcul plus lourd ;<\/li>\n<li>le <strong>nDCG<\/strong> donne un score plus \u00e9lev\u00e9 aux documents pertinents plac\u00e9s en t\u00eate, et accepte des degr\u00e9s de pertinence gradu\u00e9s. Il exige en contrepartie un score de pertinence pour chaque document, ce qui ajoute de la subjectivit\u00e9.<\/li>\n<\/ul>\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6adef46bf15a2&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6adef46bf15a2\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1122\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_mrr_map-scaled.png\" alt=\"Deux colonnes : MRR, moyenne des inverses du rang du premier r\u00e9sultat pertinent, avec un exemple \u00e0 deux requ\u00eates (1\/1 = 1,0 et 1\/3 = 0,33) ; MAP, pr\u00e9cision moyenne calcul\u00e9e \u00e0 chaque rang pertinent\" class=\"wp-image-150\" srcset=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_mrr_map-scaled.png 2560w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_mrr_map-300x131.png 300w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_mrr_map-1024x449.png 1024w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_mrr_map-768x336.png 768w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_mrr_map-1536x673.png 1536w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_mrr_map-2048x897.png 2048w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">\u00c0 gauche, l&rsquo;exemple chiffr\u00e9 du MRR : une requ\u00eate dont le premier bon r\u00e9sultat arrive au rang 1 vaut 1,0, une autre o\u00f9 il arrive au rang 3 vaut 0,33. Le MRR moyenne ces valeurs.<\/figcaption><\/figure>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6adef46bf1a48&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6adef46bf1a48\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"2400\" height=\"1440\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_ndcg.png\" alt=\"Barres comparant, sur cinq rangs, le gain cumul\u00e9 actualis\u00e9 du classement obtenu et celui du classement id\u00e9al ; le nDCG vaut ici environ 0,887\" class=\"wp-image-151\" srcset=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_ndcg.png 2400w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_ndcg-300x180.png 300w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_ndcg-1024x614.png 1024w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_ndcg-768x461.png 768w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_ndcg-1536x922.png 1536w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_ndcg-2048x1229.png 2048w\" sizes=\"auto, (max-width: 2400px) 100vw, 2400px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Ici, le classement obtenu s&rsquo;\u00e9carte du classement id\u00e9al surtout aux rangs 2 et 4, ce qui explique un nDCG d&rsquo;environ 0,887 plut\u00f4t que 1.<\/figcaption><\/figure>\n\n\n<blockquote>\n<p><strong>\ud83d\udccc \u00c0 retenir<\/strong> Ces chiffres se lisent en combinaison. Pr\u00e9cision faible avec fort rappel : tu r\u00e9cup\u00e8res trop de documents, sois plus s\u00e9lectif. Pr\u00e9cision faible et rappel faible : le probl\u00e8me est plus profond, du c\u00f4t\u00e9 de l&rsquo;indexation. MRR ou nDCG faible : suspecte l&rsquo;algorithme de classement du retriever.<\/p>\n<\/blockquote>\n<h3>C\u00f4t\u00e9 r\u00e9ponse : trois scores et un juge<\/h3>\n<p>Passons \u00e0 l&rsquo;\u00e9tage du dessus. Les trois relations de la triade deviennent trois scores, que le framework <a href=\"\/blog\/rag\/comment-utiliser-ragas\/\" title=\"RAGAs\">RAGAs<\/a> calcule \u00e0 l&rsquo;aide d&rsquo;un LLM :<\/p>\n<ul>\n<li>la <strong>pertinence du contexte<\/strong> : la proportion de phrases du contexte r\u00e9cup\u00e9r\u00e9 r\u00e9ellement utiles pour r\u00e9pondre \u00e0 la question ;<\/li>\n<li>la <strong>fid\u00e9lit\u00e9<\/strong> : on d\u00e9compose la r\u00e9ponse en affirmations \u00e9l\u00e9mentaires, puis on mesure la proportion de celles qu&rsquo;on retrouve dans le contexte. L&rsquo;inverse de la fid\u00e9lit\u00e9 est le taux d&rsquo;hallucination ;<\/li>\n<li>la <strong>pertinence de la r\u00e9ponse<\/strong> : on demande au LLM de fabriquer plusieurs questions \u00e0 partir de la r\u00e9ponse, puis on calcule la similarit\u00e9 cosinus moyenne avec la question d&rsquo;origine. Si la r\u00e9ponse traite bien la question, les questions reconstruites lui ressemblent.<\/li>\n<\/ul>\n<p>Une variante voisine mesure la <strong>couverture<\/strong> : la part des affirmations pertinentes du contexte effectivement reprises dans la r\u00e9ponse.<\/p>\n<p>Une autre pr\u00e9sentation de la m\u00eame d\u00e9marche d\u00e9coupe l&rsquo;\u00e9valuation avec des noms un peu diff\u00e9rents : <strong>rappel de contexte<\/strong> (l&rsquo;information n\u00e9cessaire a-t-elle \u00e9t\u00e9 retrouv\u00e9e ?), <strong>fid\u00e9lit\u00e9<\/strong> et <strong>exactitude<\/strong> de la r\u00e9ponse (est-elle conforme \u00e0 la v\u00e9rit\u00e9 de r\u00e9f\u00e9rence ?). C&rsquo;est la formulation qu&rsquo;on retrouve dans le code plus bas.<\/p>\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6adef46bf1ecd&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6adef46bf1ecd\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1240\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b1_ch08_metriques_ragas-scaled.png\" alt=\"Un bloc \u00ab contexte r\u00e9cup\u00e9r\u00e9 + r\u00e9ponse g\u00e9n\u00e9r\u00e9e \u00bb reli\u00e9 \u00e0 trois m\u00e9triques : rappel de contexte (information n\u00e9cessaire retrouv\u00e9e ?), fid\u00e9lit\u00e9 (r\u00e9ponse align\u00e9e sur le contexte ?) et exactitude (r\u00e9ponse conforme au vrai r\u00e9sultat ?)\" class=\"wp-image-152\" srcset=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b1_ch08_metriques_ragas-scaled.png 2560w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b1_ch08_metriques_ragas-300x145.png 300w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b1_ch08_metriques_ragas-1024x496.png 1024w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b1_ch08_metriques_ragas-768x372.png 768w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b1_ch08_metriques_ragas-1536x744.png 1536w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b1_ch08_metriques_ragas-2048x992.png 2048w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Les trois fl\u00e8ches partent du m\u00eame bloc : ce sont trois questions diff\u00e9rentes pos\u00e9es sur les m\u00eames donn\u00e9es. La fid\u00e9lit\u00e9, mise en orange sur le sch\u00e9ma, est celle qui traque l&rsquo;hallucination.<\/figcaption><\/figure>\n\n\n<p>Comment un LLM juge-t-il la fid\u00e9lit\u00e9 ? En deux temps : il d\u00e9compose d&rsquo;abord la r\u00e9ponse en affirmations atomiques, sans pronoms pour faciliter la v\u00e9rification. Il juge ensuite, pour chacune, si elle peut \u00eatre directement inf\u00e9r\u00e9e du contexte, avec un verdict binaire.<\/p>\n<p>L&rsquo;exactitude, elle, reprend cette d\u00e9composition puis classe chaque affirmation : vrai positif (dans la r\u00e9ponse et soutenue par la r\u00e9f\u00e9rence), faux positif (dans la r\u00e9ponse mais absente de la r\u00e9f\u00e9rence) ou faux n\u00e9gatif (dans la r\u00e9f\u00e9rence mais absente de la r\u00e9ponse), avec une justification \u00e0 chaque fois.<\/p>\n<p>Ces trois scores ne se valent pas et ne montent pas ensemble. Une forte pertinence du contexte am\u00e9liore g\u00e9n\u00e9ralement la fid\u00e9lit\u00e9, mais une forte fid\u00e9lit\u00e9 ne garantit pas une bonne pertinence de la r\u00e9ponse : un syst\u00e8me peut recopier fid\u00e8lement le contexte sans r\u00e9pondre directement \u00e0 la question.<\/p>\n<h3>Les aptitudes qu&rsquo;un score ne voit pas<\/h3>\n<p>Au-del\u00e0 de ces scores, un RAG doit poss\u00e9der quatre aptitudes :<\/p>\n<ul>\n<li>la <strong>robustesse au bruit<\/strong> : distinguer les documents qui parlent du sujet sans rien apporter des documents r\u00e9ellement utiles ;<\/li>\n<li>le <strong>rejet n\u00e9gatif<\/strong> : ne pas r\u00e9pondre quand la base ne contient rien de pertinent, car un LLM tend par nature \u00e0 toujours g\u00e9n\u00e9rer du texte ;<\/li>\n<li>l&rsquo;<strong>int\u00e9gration d&rsquo;information<\/strong> : composer une r\u00e9ponse compl\u00e8te \u00e0 partir de plusieurs documents ;<\/li>\n<li>la <strong>robustesse contrefactuelle<\/strong> : rejeter des inexactitudes connues pr\u00e9sentes dans la base elle-m\u00eame.<\/li>\n<\/ul>\n<p>La premi\u00e8re rel\u00e8ve surtout de la r\u00e9cup\u00e9ration, les trois autres de la g\u00e9n\u00e9ration.<\/p>\n<h2>Le jeu de test : la moiti\u00e9 du travail<\/h2>\n<p>Aucune de ces m\u00e9triques ne dit quoi que ce soit sans des exemples. Les donn\u00e9es de v\u00e9rit\u00e9 terrain (des exemples question, contexte, r\u00e9ponse pr\u00e9par\u00e9s \u00e0 l&rsquo;avance) jouent ici le r\u00f4le du jeu \u00e9tiquet\u00e9 d&rsquo;un apprentissage supervis\u00e9. Les fabriquer \u00e0 la main est fastidieux, et un LLM peut aider : \u00e0 partir des documents de la base, il produit des questions vari\u00e9es (simples, multi-contextes, conditionnelles, de raisonnement).<\/p>\n<p>C&rsquo;est exactement ce que fait RAGAs : un g\u00e9n\u00e9rateur de questions initiales, puis un module d&rsquo;\u00e9volution qui les complexifie, puis la g\u00e9n\u00e9ration des r\u00e9ponses.<\/p>\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;6adef46bf2359&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"6adef46bf2359\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"485\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_ragas_synthetic-scaled.png\" alt=\"Cinq \u00e9tapes en cha\u00eene : documents, g\u00e9n\u00e9rateur de questions germes, \u00e9volveur (multi-contexte, raisonnement), g\u00e9n\u00e9ration de r\u00e9ponses, jeu de test\" class=\"wp-image-153\" srcset=\"https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_ragas_synthetic-scaled.png 2560w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_ragas_synthetic-300x57.png 300w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_ragas_synthetic-1024x194.png 1024w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_ragas_synthetic-768x146.png 768w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_ragas_synthetic-1536x291.png 1536w, https:\/\/www.ranksignal.fr\/wp-content\/uploads\/2026\/09\/b2_ch05_ragas_synthetic-2048x388.png 2048w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">Lis le sch\u00e9ma de gauche \u00e0 droite : la base de connaissances entre d&rsquo;un c\u00f4t\u00e9, un jeu de test complet sort de l&rsquo;autre, sans annotation humaine extensive.<\/figcaption><\/figure>\n\n\n<p>Dans notre fil rouge, le jeu de test est construit \u00e0 la main et il est vari\u00e9 \u00e0 dessein. Chaque exemple associe une question \u00e0 une r\u00e9ponse de r\u00e9f\u00e9rence. Il doit mettre \u00e0 l&rsquo;\u00e9preuve chaque maillon : le choix du bon outil, le mappage des entit\u00e9s de la question vers la base, les sc\u00e9narios en plusieurs \u00e9tapes, les cas limites, et m\u00eame la conversation (une salutation, une question hors sujet).<\/p>\n<p>Une astuce \u00e9l\u00e9gante : plut\u00f4t qu&rsquo;une cha\u00eene fig\u00e9e comme r\u00e9ponse attendue, la r\u00e9f\u00e9rence est une requ\u00eate Cypher ex\u00e9cut\u00e9e sur la base de donn\u00e9es. Comme la v\u00e9rit\u00e9 est recalcul\u00e9e \u00e0 chaque test, le benchmark reste valide m\u00eame quand les donn\u00e9es \u00e9voluent, sans mise \u00e0 jour constante. Pour une salutation ou une question m\u00e9t\u00e9o hors sujet, une simple instruction <code>RETURN<\/code> suffit \u00e0 d\u00e9finir une r\u00e9ponse statique.<\/p>\n<p>Tu y glisses aussi des cas limites : des questions dans le domaine dont la r\u00e9ponse manque pourtant dans les donn\u00e9es (par exemple le film qui a remport\u00e9 le plus d&rsquo;Oscars, absent du jeu de donn\u00e9es de films). Le benchmark construit ici compte 17 exemples et sa composition d\u00e9pend enti\u00e8rement des fonctionnalit\u00e9s de l&rsquo;agent test\u00e9.<\/p>\n<h2>Le voir tourner<\/h2>\n<p>Deux fa\u00e7ons de faire tourner l&rsquo;\u00e9valuation. La premi\u00e8re g\u00e9n\u00e8re le jeu de test avec RAGAs. Elle installe la biblioth\u00e8que, configure un LLM et un mod\u00e8le d&#8217;embeddings, puis demande 20 questions \u00e0 partir des documents.<\/p>\n<pre><code>%pip install ragas==0.2.13\n\nfrom ragas.llms import LangchainLLMWrapper\nfrom ragas.embeddings import LangchainEmbeddingsWrapper\nfrom ragas.testset import TestsetGenerator\nfrom langchain_openai import ChatOpenAI, OpenAIEmbeddings\n\ngenerator_llm = LangchainLLMWrapper(ChatOpenAI(model=&quot;gpt-4o-mini&quot;))\ngenerator_embeddings = LangchainEmbeddingsWrapper(\n    OpenAIEmbeddings(model=&quot;text-embedding-3-small&quot;)\n)\ngenerator = TestsetGenerator(\n    llm=generator_llm,\n    embedding_model=generator_embeddings\n)\ntestset = generator.generate_with_langchain_docs(\n    html_data_transformed,\n    test_size=20,\n)\n<\/code><\/pre>\n<p>Ici <code>html_data_transformed<\/code> est la liste de documents d\u00e9j\u00e0 charg\u00e9s et nettoy\u00e9s par l&rsquo;\u00e9tape d&rsquo;indexation. Le r\u00e9sultat : 20 questions, chacune li\u00e9e au fragment dont elle est issue et \u00e0 sa r\u00e9ponse de r\u00e9f\u00e9rence. Il reste \u00e0 passer le pipeline sur chaque question, en gardant le contexte r\u00e9cup\u00e9r\u00e9 et la r\u00e9ponse g\u00e9n\u00e9r\u00e9e.<\/p>\n<p>La seconde fa\u00e7on part du jeu de test construit \u00e0 la main. Pour chaque ligne, on ex\u00e9cute la requ\u00eate Cypher de r\u00e9f\u00e9rence pour obtenir la v\u00e9rit\u00e9 terrain, on demande sa r\u00e9ponse \u00e0 l&rsquo;agent, et on note au passage la latence et le contexte r\u00e9cup\u00e9r\u00e9. La fonction <code>get_answer<\/code> est celle de l&rsquo;agent, <code>neo4j_driver<\/code> le connecteur vers la base, <code>test_data<\/code> le tableau des questions :<\/p>\n<pre><code>answers = []\nground_truths = []\nlatencies = []\ncontexts = []\nfor i, row in tqdm(test_data.iterrows(), total=len(test_data),\ndesc=&quot;Processing rows&quot;):\n    ground_truth, _, _ = neo4j_driver.execute_query(row[&quot;cypher&quot;])\n    ground_truths.append([str(el.data()) for el in ground_truth])\n    start = datetime.now()\n    try:\n        answer, context = get_answer(row[&quot;question&quot;])\n        context = [el['content'] for el in context]\n    except Exception:\n        answer, context = None, []\n    latencies.append((datetime.now() - start).total_seconds())\n    answers.append(answer)\n    contexts.append(context)\n\ntest_data['ground_truth'] = [str(el) for el in ground_truths]\ntest_data['answer'] = answers\ntest_data['latency'] = latencies\ntest_data['retrieved_contexts'] = contexts\n<\/code><\/pre>\n<p>Retiens deux d\u00e9tails : une exception ne plante pas le test, elle est enregistr\u00e9e comme une absence de r\u00e9ponse, et la latence est mesur\u00e9e pour chaque question, ce qui donnera un second axe d&rsquo;analyse.<\/p>\n<p>Reste \u00e0 lancer l&rsquo;\u00e9valuation proprement dite. Le cadre exige des valeurs non nulles : les r\u00e9ponses manquantes sont donc remplac\u00e9es par \u00ab I don&rsquo;t know \u00bb. Trois m\u00e9triques sont calcul\u00e9es : l&rsquo;exactitude de la r\u00e9ponse, le rappel de contexte et la fid\u00e9lit\u00e9.<\/p>\n<pre><code>dataset = Dataset.from_pandas(test_data.fillna(&quot;I don't know&quot;))\n\nresult = evaluate(\n    dataset,\n    metrics=[\n        answer_correctness,\n        context_recall,\n        faithfulness,\n    ],\n)\n<\/code><\/pre>\n<p>Avec un jeu de test g\u00e9n\u00e9r\u00e9 comme dans le premier extrait, on assemble d&rsquo;abord les r\u00e9sultats (question, r\u00e9ponse g\u00e9n\u00e9r\u00e9e, contexte r\u00e9cup\u00e9r\u00e9, r\u00e9ponse de r\u00e9f\u00e9rence) dans une liste <code>dataset_to_eval<\/code>. Puis on invoque cinq m\u00e9triques, avec un LLM \u00e9valuateur expos\u00e9 par LangChain. Tu remarques que cet extrait utilise des classes (<code>Faithfulness()<\/code>) l\u00e0 o\u00f9 le pr\u00e9c\u00e9dent importe des fonctions (<code>faithfulness<\/code>) : c&rsquo;est la m\u00eame id\u00e9e, \u00e9crite diff\u00e9remment.<\/p>\n<pre><code>from ragas import EvaluationDataset, evaluate\nfrom ragas.metrics import (\n    LLMContextRecall,\n    Faithfulness,\n    FactualCorrectness,\n    AnswerCorrectness,\n    ResponseRelevancy)\n\nevaluation_dataset = EvaluationDataset.from_list(dataset_to_eval)\nevaluator_llm = LangchainLLMWrapper(ChatOpenAI(model=&quot;gpt-4o-mini&quot;))\n\nresult = evaluate(\n    dataset=evaluation_dataset,\n    metrics=[LLMContextRecall(), Faithfulness(), AnswerCorrectness(),\n             ResponseRelevancy(), FactualCorrectness()],\n    llm=evaluator_llm)\n<\/code><\/pre>\n<p>Pas besoin d&rsquo;un framework pour mesurer la r\u00e9cup\u00e9ration seule. Voici une fonction d&rsquo;\u00e9valuation \u00e9crite pour tester la m\u00e9moire d&rsquo;un agent, mais qui s&rsquo;applique telle quelle \u00e0 n&rsquo;importe quel retriever : pour chaque requ\u00eate, y a-t-il au moins un \u00e9l\u00e9ment attendu parmi les k premiers r\u00e9sultats ?<\/p>\n<pre><code>def evaluate_memory_retrieval(\n    retrieve_fn: Any,\n    queries: List[str],\n    expected_results: List[List[Any]],\n    top_k: int = 1) -&gt; Dict[str, float]:\n    &quot;&quot;&quot;\n    Given a retrieval function `retrieve_fn(query, k)` that returns a list of\n    k memory items, evaluate over multiple queries.\n    Returns:\n      - `retrieval_accuracy@k`: fraction of queries for which at least one\n        expected item appears in the top-k.\n    &quot;&quot;&quot;\n    hits = 0\n    for query, expect in zip(queries, expected_results):\n        results = retrieve_fn(query, top_k)\n        # did we retrieve any expected item?\n        if set(results) &amp; set(expect):\n            hits += 1\n    accuracy = hits \/ len(queries) if queries else 1.0\n    return {f&quot;retrieval_accuracy@{top_k}&quot;: accuracy}\n<\/code><\/pre>\n<p>Le r\u00e9sultat est une fraction : sur combien de requ\u00eates la bonne information est-elle remont\u00e9e dans les k premiers ? C&rsquo;est une mesure de r\u00e9cup\u00e9ration pure, sans LLM juge.<\/p>\n<h2>Lire les r\u00e9sultats<\/h2>\n<p>Sur le jeu de 17 questions, le r\u00e9sum\u00e9 global affiche une exactitude de r\u00e9ponse de 0,7774, un rappel de contexte de 0,7941 et une fid\u00e9lit\u00e9 de 0,9657.<\/p>\n<p>Comment lire ces trois chiffres ensemble ? Avec une exactitude proche de 0,78, l&rsquo;agent r\u00e9pond correctement la plupart du temps mais se trompe encore dans pr\u00e8s d&rsquo;un quart des cas. Le rappel de 0,79 montre que la r\u00e9cup\u00e9ration fonctionne plut\u00f4t bien sans toujours ramener toute l&rsquo;information n\u00e9cessaire, ce qui p\u00e8se sur l&rsquo;exactitude. La fid\u00e9lit\u00e9, elle, est excellente : le mod\u00e8le invente rarement et reste fid\u00e8le au contexte.<\/p>\n<blockquote>\n<p><strong>\ud83d\udccc \u00c0 retenir<\/strong> Une fid\u00e9lit\u00e9 haute avec une exactitude et un rappel plus bas dit o\u00f9 investir : pas dans la r\u00e9daction, mais dans la r\u00e9cup\u00e9ration. Enrichir la couverture de r\u00e9cup\u00e9ration, affiner la reformulation des requ\u00eates, am\u00e9liorer le mappage d&rsquo;entit\u00e9s pour les questions ambigu\u00ebs.<\/p>\n<\/blockquote>\n<p>Les r\u00e9ponses individuelles apprennent autant que la moyenne. La latence est nettement plus faible pour les questions qui n&rsquo;ont pas besoin de la g\u00e9n\u00e9ration de requ\u00eate Cypher, puisqu&rsquo;on \u00e9vite un appel LLM suppl\u00e9mentaire. Certains scores paraissent incoh\u00e9rents (sur la simple salutation \u00ab Hello \u00bb), le juge \u00e9tant lui-m\u00eame un LLM. Enfin, une question ne trouve aucune r\u00e9ponse : \u00ab Who has the longest name among all actors ? \u00bb, faute d&rsquo;avoir g\u00e9n\u00e9r\u00e9 la bonne requ\u00eate. Le rem\u00e8de propos\u00e9 : ajouter un exemple few-shot pour guider cette g\u00e9n\u00e9ration ou cr\u00e9er un outil d\u00e9di\u00e9.<\/p>\n<h2>Pi\u00e8ges et limites<\/h2>\n<p><strong>Le juge n&rsquo;est pas neutre.<\/strong> L&rsquo;approche \u00ab LLM as a judge \u00bb d\u00e9pend directement de la qualit\u00e9 du LLM utilis\u00e9. En cas d&rsquo;auto-r\u00e9f\u00e9rence, quand le LLM juge et le LLM g\u00e9n\u00e9rateur sont les m\u00eames, l&rsquo;\u00e9valuation peut \u00eatre biais\u00e9e. Les rem\u00e8des : \u00e9chantillonner r\u00e9guli\u00e8rement les jugements et recourir \u00e0 plusieurs juges diff\u00e9rents du g\u00e9n\u00e9rateur.<\/p>\n<p><strong>Pas de standard, pas de score universel.<\/strong> Chaque framework calcule ses m\u00e9triques selon sa m\u00e9thodologie propre : il est recommand\u00e9 de comparer les r\u00e9sultats de plusieurs frameworks.<\/p>\n<p><strong>Le choix de l&rsquo;outil d&rsquo;\u00e9valuation est un arbitrage.<\/strong> ARES, d\u00e9velopp\u00e9 par des chercheurs de Stanford et Databricks, entra\u00eene un classifieur au lieu d&rsquo;utiliser des prompts heuristiques et fournit des intervalles de confiance. Il exige davantage de donn\u00e9es : des passages du domaine, un ensemble de validation d&rsquo;environ 150 annotations humaines et au moins cinq exemples few-shot. Il est plus robuste mais plus complexe \u00e0 mettre en \u0153uvre que RAGAs, qui privil\u00e9gie la rapidit\u00e9. TruLens, DeepEval ou RAGChecker existent aussi.<\/p>\n<p><strong>Un benchmark public ne remplace pas le tien.<\/strong> Les benchmarks sont statiques et ignorent l&rsquo;\u00e9volution des connaissances. Pour se comparer \u00e0 d&rsquo;autres syst\u00e8mes, on trouve BEIR (9 t\u00e2ches de recherche d&rsquo;information, 19 jeux de questions-r\u00e9ponses), RGB (les quatre aptitudes vues plus haut), Multi-hop RAG (2556 requ\u00eates dont les preuves sont r\u00e9parties sur deux \u00e0 quatre documents) ou CRAG (4409 paires question-r\u00e9ponse, huit types de questions, cinq domaines). Mieux vaut pourtant un benchmark adapt\u00e9 \u00e0 ton domaine qu&rsquo;une confiance aveugle dans un score g\u00e9n\u00e9rique.<\/p>\n<p><strong>Attention au surajustement de m\u00e9triques.<\/strong> R\u00e9gler un syst\u00e8me pour exceller sur une r\u00e9f\u00e9rence se fait parfois au d\u00e9triment de son utilit\u00e9 r\u00e9elle : optimiser un score unique peut favoriser des sorties formula\u00efques qui manquent l&rsquo;intention. Si les cas de test sont trop \u00e9troits, le syst\u00e8me semble bon hors ligne et \u00e9choue en production.<\/p>\n<p><strong>Le jeu de test doit vivre.<\/strong> \u00c0 chaque outil ou flux ajout\u00e9, on ajoute les cas de test correspondants. Le jeu devient une sp\u00e9cification vivante qui permet de d\u00e9tecter les r\u00e9gressions et de rep\u00e9rer les progr\u00e8s apparents pay\u00e9s par de nouvelles erreurs ailleurs. On l&rsquo;alimente en extrayant des exemples des journaux de production, en faisant g\u00e9n\u00e9rer des variantes par un LLM (relues par des humains) ou avec des techniques cibl\u00e9es comme le prompt adverse ou l&rsquo;\u00e9dition contrefactuelle.<\/p>\n<p><strong>L&rsquo;exactitude n&rsquo;est pas tout.<\/strong> La latence (le d\u00e9lai entre la requ\u00eate et la r\u00e9ponse), le d\u00e9bit, l&rsquo;utilisation des ressources et le co\u00fbt par requ\u00eate font partie de l&rsquo;\u00e9valuation. Latence et co\u00fbt m\u00e9ritent une attention particuli\u00e8re en RAG, qui ajoute la r\u00e9cup\u00e9ration au co\u00fbt d\u00e9j\u00e0 inh\u00e9rent au LLM. Il faut aussi regarder le biais et la toxicit\u00e9 des r\u00e9ponses.<\/p>\n<p><strong>Et l&rsquo;humain ?<\/strong> Les m\u00e9triques g\u00e9n\u00e9riques doivent \u00eatre compl\u00e9t\u00e9es par des crit\u00e8res propres \u00e0 ton cas d&rsquo;usage et par un retour humain (avis des utilisateurs, \u00e9valuation d&rsquo;experts).<\/p>\n<p>En production, l&rsquo;\u00e9valuation continue permet d&rsquo;identifier les types de requ\u00eates que le syst\u00e8me traite mal, et le retour qualitatif des utilisateurs la compl\u00e8te. On suit par exemple le taux de reformulation (les utilisateurs sont-ils compris du premier coup ?), le taux d&rsquo;abandon de t\u00e2che et les notes explicites de type pouce en haut ou en bas.<\/p>\n<h2>Aller plus loin<\/h2>\n<ul>\n<li><strong>Hallucination<\/strong> : une hallucination est une information incorrecte, absurde ou fabriqu\u00e9e. On la limite en ancrant les sorties dans des donn\u00e9es v\u00e9rifiables, mais la qualit\u00e9 des sources reste d\u00e9terminante, car des donn\u00e9es p\u00e9rim\u00e9es ou mal v\u00e9rifi\u00e9es la favorisent.<\/li>\n<li><strong><a href=\"\/blog\/rag\/qu-est-ce-qu-un-rag-naif\/\" title=\"RAG na\u00eff\">RAG na\u00eff<\/a> et <a href=\"\/blog\/rag\/qu-est-ce-qu-un-rag-avance\/\" title=\"RAG avanc\u00e9\">RAG avanc\u00e9<\/a><\/strong> : les faiblesses rep\u00e9r\u00e9es \u00e0 l&rsquo;\u00e9valuation (faible pr\u00e9cision et rappel \u00e0 la r\u00e9cup\u00e9ration, contexte d\u00e9cousu, hallucinations) sont exactement ce que corrigent les techniques avanc\u00e9es comme le re-classement ou la r\u00e9cup\u00e9ration hybride. On mesure d&rsquo;abord, on am\u00e9liore ensuite.<\/li>\n<li><strong>Latence<\/strong> : chaque \u00e9tape ajout\u00e9e au pipeline augmente le d\u00e9lai de r\u00e9ponse, et un syst\u00e8me modulaire suppl\u00e9mentaire peut alourdir la latence et le co\u00fbt d&rsquo;inf\u00e9rence. L&rsquo;\u00e9valuation doit donc peser gain de qualit\u00e9 et surco\u00fbt.<\/li>\n<\/ul>\n<h2>\u00c0 retenir<\/h2>\n<ul>\n<li>\u00c9valuer un RAG, c&rsquo;est d&rsquo;abord localiser l&rsquo;erreur : le retriever n&rsquo;a pas trouv\u00e9, ou le LLM a mal lu.<\/li>\n<li>Pour la recherche, regarde pr\u00e9cision@k et rappel, puis les m\u00e9triques sensibles \u00e0 l&rsquo;ordre (MRR, MAP, nDCG) ; pour la r\u00e9ponse, pertinence du contexte, fid\u00e9lit\u00e9 et pertinence de la r\u00e9ponse.<\/li>\n<li>Sans jeu de test de qualit\u00e9, aucune m\u00e9trique ne vaut rien : construis-le avec des cas vari\u00e9s, des cas limites, et fais-le grandir.<\/li>\n<li>Un score de fid\u00e9lit\u00e9 \u00e9lev\u00e9 rassure sur l&rsquo;invention, mais ne dit rien de la compl\u00e9tude de la r\u00e9cup\u00e9ration : croise toujours plusieurs scores.<\/li>\n<li>M\u00e9fie-toi du juge (un LLM), des benchmarks fig\u00e9s et des scores uniques ; ajoute humain, latence et co\u00fbt.<\/li>\n<\/ul>\n<h2>Questions fr\u00e9quentes<\/h2>\n<p><strong>Peut-on \u00e9valuer un RAG sans annoter soi-m\u00eame des centaines de questions ?<\/strong><br \/>\nOn peut g\u00e9n\u00e9rer un jeu de test synth\u00e9tique \u00e0 partir de la base de connaissances (questions simples, multi-contextes, conditionnelles, de raisonnement). Les \u00e9chantillons g\u00e9n\u00e9r\u00e9s sont ensuite relus et raffin\u00e9s par des humains avant d&rsquo;entrer dans le jeu de test.<\/p>\n<p><strong>Quel LLM utiliser comme juge ?<\/strong><br \/>\nIl est recommand\u00e9 d&rsquo;utiliser un LLM juge diff\u00e9rent du LLM de g\u00e9n\u00e9ration, pour \u00e9viter le biais d&rsquo;auto-r\u00e9f\u00e9rence, et d&rsquo;\u00e9chantillonner r\u00e9guli\u00e8rement ses jugements.<\/p>\n<p><strong>Une bonne fid\u00e9lit\u00e9 veut-elle dire que mon RAG est bon ?<\/strong><br \/>\nNon : la fid\u00e9lit\u00e9 mesure que la r\u00e9ponse colle au contexte, pas que le contexte soit le bon ni que la r\u00e9ponse traite la question. Dans notre exemple, une fid\u00e9lit\u00e9 de 0,97 cohabite avec un rappel de contexte de 0,79.<\/p>","protected":false},"excerpt":{"rendered":"<p>Un RAG peut se tromper en cherchant ou en r\u00e9pondant. Voici les m\u00e9triques, le jeu de test et l&rsquo;outil RAGAS pour savoir lequel des deux pose probl\u00e8me.<\/p>\n","protected":false},"author":1,"featured_media":269,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-154","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-rag"],"_links":{"self":[{"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/posts\/154","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/comments?post=154"}],"version-history":[{"count":3,"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/posts\/154\/revisions"}],"predecessor-version":[{"id":540,"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/posts\/154\/revisions\/540"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/media\/269"}],"wp:attachment":[{"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/media?parent=154"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/categories?post=154"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ranksignal.fr\/blog\/wp-json\/wp\/v2\/tags?post=154"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}