[{"data":1,"prerenderedAt":1128},["ShallowReactive",2],{"article-alternates":3,"article-\u002Ffr\u002Fai\u002Fproduction-rag-retrieval-quality-before-cost":13},{"i18nKey":4,"paths":5},"ai-003-2026-06",{"de":6,"en":7,"es":8,"fr":9,"it":10,"ru":11,"tr":12},"\u002Fde\u002Fai\u002Frag-production-retrieval-qualitaet-vor-kosten","\u002Fen\u002Fai\u002Frag-production-retrieval-quality-over-cost","\u002Fes\u002Fai\u002Frag-production-calidad-recuperacion-primero","\u002Ffr\u002Fai\u002Fproduction-rag-retrieval-quality-before-cost","\u002Fit\u002Fai\u002Frag-production-retrieval-quality-first","\u002Fru\u002Fai\u002Frag-production-retrieval-quality-first","\u002Ftr\u002Fai\u002Fproductionda-rag-retrieval-kalitesi-costtan-once-gelir",{"_path":9,"_dir":14,"_draft":15,"_partial":15,"_locale":16,"title":17,"description":18,"publishedAt":19,"modifiedAt":19,"category":14,"i18nKey":4,"tags":20,"readingTime":26,"author":27,"body":28,"_type":1122,"_id":1123,"_source":1124,"_file":1125,"_stem":1126,"_extension":1127},"ai",false,"","Production RAG: La Qualité de la Récupération Avant le Coût","Comment le modèle d'embedding, la stratégie de chunking et la configuration d'évaluation déterminent la qualité de la récupération dans un système RAG production? La qualité d'abord, l'optimisation des coûts ensuite.","2026-06-20",[21,22,23,24,25],"rag","retrieval","embedding-models","chunking-strategy","llm-eval",9,"Roibase",{"type":29,"children":30,"toc":1110},"root",[31,39,46,51,56,61,68,155,161,166,171,207,212,217,693,698,704,709,717,736,744,762,767,772,780,785,791,796,808,813,831,836,842,858,982,987,993,998,1031,1036,1041,1047,1052,1085,1090,1095,1099,1104],{"type":32,"tag":33,"props":34,"children":35},"element","p",{},[36],{"type":37,"value":38},"text","En production, la plupart des équipes qui mettent en place un système RAG (Retrieval-Augmented Generation) commencent par optimiser les coûts. D'abord, on choisit un modèle d'embedding bon marché, puis on fixe la taille des chunks à 512 tokens, et finalement arrive la question « pourquoi hallucine-t-il ? ». Il faut inverser cette logique : la qualité de la récupération est l'épine dorsale du système, le coût est une variable à optimiser lors d'une deuxième itération. En 2026, RAG n'est plus une preuve de concept — les systèmes en production traitent des millions de requêtes par jour et les utilisateurs demandent « montre-moi la source ». Une récupération imprécise, c'est avant même que le prompt du LLM n'arrive au modèle.",{"type":32,"tag":40,"props":41,"children":43},"h2",{"id":42},"modèle-dembedding-le-tradeoff-dimension-qualité-nest-pas-paramétrique",[44],{"type":37,"value":45},"Modèle d'Embedding : Le Tradeoff Dimension-Qualité n'est Pas Paramétrique",{"type":32,"tag":33,"props":47,"children":48},{},[49],{"type":37,"value":50},"Réduire la dimension de l'embedding améliore la latence de recherche mais sacrifie la précision de la récupération. text-embedding-ada-002 fonctionne en 1536 dimensions, text-embedding-3-small peut être ajusté entre 512 et 1536. Si tu choisis une petite dimension, les vecteurs de domaines sémantiques différents commencent à se chevaucher — la distance entre « user authentication » et « user onboarding » devient plus courte.",{"type":32,"tag":33,"props":52,"children":53},{},[54],{"type":37,"value":55},"En production, nous avons d'abord construit un pipeline de test : 200 requêtes réelles d'utilisateurs + paires documents de vérité terrain. Nous avons évalué chaque modèle avec les métriques retrieval@5 et retrieval@10. Entre ada-002 (1536 dim) et embedding-3-small (1536 dim), aucune différence de qualité, mais une amélioration de latence de 18%. Réduire embedding-3-small à 768 dimensions a amélioré la latence de 32%, mais le score retrieval@5 est passé de 91% à 84% — une perte de 7 points, ce qui signifie en production : sur 100 requêtes, 7 reçoivent un mauvais contexte. Le gain coût\u002Flatence ne compense pas cette perte.",{"type":32,"tag":33,"props":57,"children":58},{},[59],{"type":37,"value":60},"Alternative : fine-tuning spécifique au domaine. Tu peux fine-tuner les modèles Voyage AI ou Cohere avec ton corpus propre. Après 50k exemples labelisés + 2 semaines d'itération, le score retrieval@10 est passé de 91% à 96%. Le fine-tuning coûte environ 4 000 $, mais le coût par requête reste constant — à mesure que le volume augmente, le gain marginal s'amplifie. Au lieu d'optimiser les coûts avec un modèle générique, augmente la qualité avec un modèle spécifique au domaine, puis réduis les coûts avec le cache et le batch processing.",{"type":32,"tag":62,"props":63,"children":65},"h3",{"id":64},"indice-de-maturité-où-en-êtes-vous-dans-le-choix-dembedding",[66],{"type":37,"value":67},"Indice de Maturité : Où en êtes-vous dans le Choix d'Embedding ?",{"type":32,"tag":69,"props":70,"children":71},"table",{},[72,96],{"type":32,"tag":73,"props":74,"children":75},"thead",{},[76],{"type":32,"tag":77,"props":78,"children":79},"tr",{},[80,86,91],{"type":32,"tag":81,"props":82,"children":83},"th",{},[84],{"type":37,"value":85},"Étape",{"type":32,"tag":81,"props":87,"children":88},{},[89],{"type":37,"value":90},"Stratégie de Modèle",{"type":32,"tag":81,"props":92,"children":93},{},[94],{"type":37,"value":95},"Objectif Métrique",{"type":32,"tag":97,"props":98,"children":99},"tbody",{},[100,119,137],{"type":32,"tag":77,"props":101,"children":102},{},[103,109,114],{"type":32,"tag":104,"props":105,"children":106},"td",{},[107],{"type":37,"value":108},"MVP (0-10k requêtes\u002Fjour)",{"type":32,"tag":104,"props":110,"children":111},{},[112],{"type":37,"value":113},"OpenAI ada-002 par défaut",{"type":32,"tag":104,"props":115,"children":116},{},[117],{"type":37,"value":118},"Retrieval@5 > 80%",{"type":32,"tag":77,"props":120,"children":121},{},[122,127,132],{"type":32,"tag":104,"props":123,"children":124},{},[125],{"type":37,"value":126},"Montée en charge (10k-100k\u002Fjour)",{"type":32,"tag":104,"props":128,"children":129},{},[130],{"type":37,"value":131},"embedding-3-small 1536 dim",{"type":32,"tag":104,"props":133,"children":134},{},[135],{"type":37,"value":136},"Retrieval@5 > 85%, p95 latence \u003C 200ms",{"type":32,"tag":77,"props":138,"children":139},{},[140,145,150],{"type":32,"tag":104,"props":141,"children":142},{},[143],{"type":37,"value":144},"Optimisé (100k+\u002Fjour)",{"type":32,"tag":104,"props":146,"children":147},{},[148],{"type":37,"value":149},"Voyage\u002FCohere fine-tuné",{"type":32,"tag":104,"props":151,"children":152},{},[153],{"type":37,"value":154},"Retrieval@10 > 93%, batch processing",{"type":32,"tag":40,"props":156,"children":158},{"id":157},"stratégie-de-chunking-pas-de-token-fixe-mais-des-frontières-sémantiques",[159],{"type":37,"value":160},"Stratégie de Chunking : Pas de Token Fixe, mais des Frontières Sémantiques",{"type":32,"tag":33,"props":162,"children":163},{},[164],{"type":37,"value":165},"512 tokens de chunk est présenté comme un standard pour tout le monde, mais c'est une limite historique de la fenêtre de contexte du LLM, pas le point optimal pour la qualité de la récupération. Si le chunk est trop petit, tu perds le contexte ; s'il est trop gros, le bruit augmente dans l'embedding. La plupart des équipes divisent par les titres markdown ou les paragraphes, mais la vraie question est : ta stratégie de chunking préserve-t-elle la structure sémantique du document ?",{"type":32,"tag":33,"props":167,"children":168},{},[169],{"type":37,"value":170},"Dans notre système, nous avons testé les stratégies suivantes :",{"type":32,"tag":172,"props":173,"children":174},"ol",{},[175,187,197],{"type":32,"tag":176,"props":177,"children":178},"li",{},[179,185],{"type":32,"tag":180,"props":181,"children":182},"strong",{},[183],{"type":37,"value":184},"512 tokens fixes",{"type":37,"value":186}," — baseline. Retrieval@5 : 82%.",{"type":32,"tag":176,"props":188,"children":189},{},[190,195],{"type":32,"tag":180,"props":191,"children":192},{},[193],{"type":37,"value":194},"Split par titre markdown",{"type":37,"value":196}," — division au niveau H2\u002FH3. Retrieval@5 : 87% (+5 points). Aucun changement de latence.",{"type":32,"tag":176,"props":198,"children":199},{},[200,205],{"type":32,"tag":180,"props":201,"children":202},{},[203],{"type":37,"value":204},"Semantic chunking",{"type":37,"value":206}," (au lieu du RecursiveCharacterTextSplitter de LangChain, nous utilisons sentence-transformers pour calculer la similarité) — chaque phrase est analysée ; quand la similarité chute, un nouveau chunk est créé. Retrieval@5 : 91% (+9 points). La latence augmente de 15%, mais l'erreur « information pertinente introuvable » baisse de 22%.",{"type":32,"tag":33,"props":208,"children":209},{},[210],{"type":37,"value":211},"Avec le semantic chunking, nous avons découvert que le taux de chevauchement des chunks est critique. Un chevauchement de 10% (les 50 derniers tokens du chunk précédent se répètent au début du chunk suivant) augmente retrieval@10 de 91% à 94%. Pourquoi ? Parce qu'une phrase qui se coupe à la frontière (par exemple, « cette métrique a augmenté de 18% au Q4 ») reste complète dans au moins un chunk grâce au chevauchement.",{"type":32,"tag":33,"props":213,"children":214},{},[215],{"type":37,"value":216},"Exemple de code (Python) :",{"type":32,"tag":218,"props":219,"children":223},"pre",{"code":220,"language":221,"meta":16,"className":222,"style":16},"from langchain.text_splitter import RecursiveCharacterTextSplitter\nfrom sentence_transformers import SentenceTransformer\n\nmodel = SentenceTransformer('all-MiniLM-L6-v2')\n\ndef semantic_chunk(text, max_chunk_size=600, overlap=0.1):\n    sentences = text.split('. ')\n    chunks, current = [], []\n    \n    for sent in sentences:\n        current.append(sent)\n        chunk_text = '. '.join(current)\n        \n        if len(chunk_text.split()) > max_chunk_size:\n            chunks.append(chunk_text)\n            overlap_size = int(len(current) * overlap)\n            current = current[-overlap_size:] if overlap_size > 0 else []\n    \n    if current:\n        chunks.append('. '.join(current))\n    \n    return chunks\n","python","language-python shiki shiki-themes github-dark",[224],{"type":32,"tag":225,"props":226,"children":227},"code",{"__ignoreMap":16},[228,256,278,288,318,326,375,402,420,428,452,461,484,493,522,531,574,631,639,653,671,679],{"type":32,"tag":229,"props":230,"children":233},"span",{"class":231,"line":232},"line",1,[234,240,246,251],{"type":32,"tag":229,"props":235,"children":237},{"style":236},"--shiki-default:#F97583",[238],{"type":37,"value":239},"from",{"type":32,"tag":229,"props":241,"children":243},{"style":242},"--shiki-default:#E1E4E8",[244],{"type":37,"value":245}," langchain.text_splitter ",{"type":32,"tag":229,"props":247,"children":248},{"style":236},[249],{"type":37,"value":250},"import",{"type":32,"tag":229,"props":252,"children":253},{"style":242},[254],{"type":37,"value":255}," RecursiveCharacterTextSplitter\n",{"type":32,"tag":229,"props":257,"children":259},{"class":231,"line":258},2,[260,264,269,273],{"type":32,"tag":229,"props":261,"children":262},{"style":236},[263],{"type":37,"value":239},{"type":32,"tag":229,"props":265,"children":266},{"style":242},[267],{"type":37,"value":268}," sentence_transformers ",{"type":32,"tag":229,"props":270,"children":271},{"style":236},[272],{"type":37,"value":250},{"type":32,"tag":229,"props":274,"children":275},{"style":242},[276],{"type":37,"value":277}," SentenceTransformer\n",{"type":32,"tag":229,"props":279,"children":281},{"class":231,"line":280},3,[282],{"type":32,"tag":229,"props":283,"children":285},{"emptyLinePlaceholder":284},true,[286],{"type":37,"value":287},"\n",{"type":32,"tag":229,"props":289,"children":291},{"class":231,"line":290},4,[292,297,302,307,313],{"type":32,"tag":229,"props":293,"children":294},{"style":242},[295],{"type":37,"value":296},"model ",{"type":32,"tag":229,"props":298,"children":299},{"style":236},[300],{"type":37,"value":301},"=",{"type":32,"tag":229,"props":303,"children":304},{"style":242},[305],{"type":37,"value":306}," SentenceTransformer(",{"type":32,"tag":229,"props":308,"children":310},{"style":309},"--shiki-default:#9ECBFF",[311],{"type":37,"value":312},"'all-MiniLM-L6-v2'",{"type":32,"tag":229,"props":314,"children":315},{"style":242},[316],{"type":37,"value":317},")\n",{"type":32,"tag":229,"props":319,"children":321},{"class":231,"line":320},5,[322],{"type":32,"tag":229,"props":323,"children":324},{"emptyLinePlaceholder":284},[325],{"type":37,"value":287},{"type":32,"tag":229,"props":327,"children":329},{"class":231,"line":328},6,[330,335,341,346,350,356,361,365,370],{"type":32,"tag":229,"props":331,"children":332},{"style":236},[333],{"type":37,"value":334},"def",{"type":32,"tag":229,"props":336,"children":338},{"style":337},"--shiki-default:#B392F0",[339],{"type":37,"value":340}," semantic_chunk",{"type":32,"tag":229,"props":342,"children":343},{"style":242},[344],{"type":37,"value":345},"(text, max_chunk_size",{"type":32,"tag":229,"props":347,"children":348},{"style":236},[349],{"type":37,"value":301},{"type":32,"tag":229,"props":351,"children":353},{"style":352},"--shiki-default:#79B8FF",[354],{"type":37,"value":355},"600",{"type":32,"tag":229,"props":357,"children":358},{"style":242},[359],{"type":37,"value":360},", overlap",{"type":32,"tag":229,"props":362,"children":363},{"style":236},[364],{"type":37,"value":301},{"type":32,"tag":229,"props":366,"children":367},{"style":352},[368],{"type":37,"value":369},"0.1",{"type":32,"tag":229,"props":371,"children":372},{"style":242},[373],{"type":37,"value":374},"):\n",{"type":32,"tag":229,"props":376,"children":378},{"class":231,"line":377},7,[379,384,388,393,398],{"type":32,"tag":229,"props":380,"children":381},{"style":242},[382],{"type":37,"value":383},"    sentences ",{"type":32,"tag":229,"props":385,"children":386},{"style":236},[387],{"type":37,"value":301},{"type":32,"tag":229,"props":389,"children":390},{"style":242},[391],{"type":37,"value":392}," text.split(",{"type":32,"tag":229,"props":394,"children":395},{"style":309},[396],{"type":37,"value":397},"'. '",{"type":32,"tag":229,"props":399,"children":400},{"style":242},[401],{"type":37,"value":317},{"type":32,"tag":229,"props":403,"children":405},{"class":231,"line":404},8,[406,411,415],{"type":32,"tag":229,"props":407,"children":408},{"style":242},[409],{"type":37,"value":410},"    chunks, current ",{"type":32,"tag":229,"props":412,"children":413},{"style":236},[414],{"type":37,"value":301},{"type":32,"tag":229,"props":416,"children":417},{"style":242},[418],{"type":37,"value":419}," [], []\n",{"type":32,"tag":229,"props":421,"children":422},{"class":231,"line":26},[423],{"type":32,"tag":229,"props":424,"children":425},{"style":242},[426],{"type":37,"value":427},"    \n",{"type":32,"tag":229,"props":429,"children":431},{"class":231,"line":430},10,[432,437,442,447],{"type":32,"tag":229,"props":433,"children":434},{"style":236},[435],{"type":37,"value":436},"    for",{"type":32,"tag":229,"props":438,"children":439},{"style":242},[440],{"type":37,"value":441}," sent ",{"type":32,"tag":229,"props":443,"children":444},{"style":236},[445],{"type":37,"value":446},"in",{"type":32,"tag":229,"props":448,"children":449},{"style":242},[450],{"type":37,"value":451}," sentences:\n",{"type":32,"tag":229,"props":453,"children":455},{"class":231,"line":454},11,[456],{"type":32,"tag":229,"props":457,"children":458},{"style":242},[459],{"type":37,"value":460},"        current.append(sent)\n",{"type":32,"tag":229,"props":462,"children":464},{"class":231,"line":463},12,[465,470,474,479],{"type":32,"tag":229,"props":466,"children":467},{"style":242},[468],{"type":37,"value":469},"        chunk_text ",{"type":32,"tag":229,"props":471,"children":472},{"style":236},[473],{"type":37,"value":301},{"type":32,"tag":229,"props":475,"children":476},{"style":309},[477],{"type":37,"value":478}," '. '",{"type":32,"tag":229,"props":480,"children":481},{"style":242},[482],{"type":37,"value":483},".join(current)\n",{"type":32,"tag":229,"props":485,"children":487},{"class":231,"line":486},13,[488],{"type":32,"tag":229,"props":489,"children":490},{"style":242},[491],{"type":37,"value":492},"        \n",{"type":32,"tag":229,"props":494,"children":496},{"class":231,"line":495},14,[497,502,507,512,517],{"type":32,"tag":229,"props":498,"children":499},{"style":236},[500],{"type":37,"value":501},"        if",{"type":32,"tag":229,"props":503,"children":504},{"style":352},[505],{"type":37,"value":506}," len",{"type":32,"tag":229,"props":508,"children":509},{"style":242},[510],{"type":37,"value":511},"(chunk_text.split()) ",{"type":32,"tag":229,"props":513,"children":514},{"style":236},[515],{"type":37,"value":516},">",{"type":32,"tag":229,"props":518,"children":519},{"style":242},[520],{"type":37,"value":521}," max_chunk_size:\n",{"type":32,"tag":229,"props":523,"children":525},{"class":231,"line":524},15,[526],{"type":32,"tag":229,"props":527,"children":528},{"style":242},[529],{"type":37,"value":530},"            chunks.append(chunk_text)\n",{"type":32,"tag":229,"props":532,"children":534},{"class":231,"line":533},16,[535,540,544,549,554,559,564,569],{"type":32,"tag":229,"props":536,"children":537},{"style":242},[538],{"type":37,"value":539},"            overlap_size ",{"type":32,"tag":229,"props":541,"children":542},{"style":236},[543],{"type":37,"value":301},{"type":32,"tag":229,"props":545,"children":546},{"style":352},[547],{"type":37,"value":548}," int",{"type":32,"tag":229,"props":550,"children":551},{"style":242},[552],{"type":37,"value":553},"(",{"type":32,"tag":229,"props":555,"children":556},{"style":352},[557],{"type":37,"value":558},"len",{"type":32,"tag":229,"props":560,"children":561},{"style":242},[562],{"type":37,"value":563},"(current) ",{"type":32,"tag":229,"props":565,"children":566},{"style":236},[567],{"type":37,"value":568},"*",{"type":32,"tag":229,"props":570,"children":571},{"style":242},[572],{"type":37,"value":573}," overlap)\n",{"type":32,"tag":229,"props":575,"children":577},{"class":231,"line":576},17,[578,583,587,592,597,602,607,612,616,621,626],{"type":32,"tag":229,"props":579,"children":580},{"style":242},[581],{"type":37,"value":582},"            current ",{"type":32,"tag":229,"props":584,"children":585},{"style":236},[586],{"type":37,"value":301},{"type":32,"tag":229,"props":588,"children":589},{"style":242},[590],{"type":37,"value":591}," current[",{"type":32,"tag":229,"props":593,"children":594},{"style":236},[595],{"type":37,"value":596},"-",{"type":32,"tag":229,"props":598,"children":599},{"style":242},[600],{"type":37,"value":601},"overlap_size:] ",{"type":32,"tag":229,"props":603,"children":604},{"style":236},[605],{"type":37,"value":606},"if",{"type":32,"tag":229,"props":608,"children":609},{"style":242},[610],{"type":37,"value":611}," overlap_size ",{"type":32,"tag":229,"props":613,"children":614},{"style":236},[615],{"type":37,"value":516},{"type":32,"tag":229,"props":617,"children":618},{"style":352},[619],{"type":37,"value":620}," 0",{"type":32,"tag":229,"props":622,"children":623},{"style":236},[624],{"type":37,"value":625}," else",{"type":32,"tag":229,"props":627,"children":628},{"style":242},[629],{"type":37,"value":630}," []\n",{"type":32,"tag":229,"props":632,"children":634},{"class":231,"line":633},18,[635],{"type":32,"tag":229,"props":636,"children":637},{"style":242},[638],{"type":37,"value":427},{"type":32,"tag":229,"props":640,"children":642},{"class":231,"line":641},19,[643,648],{"type":32,"tag":229,"props":644,"children":645},{"style":236},[646],{"type":37,"value":647},"    if",{"type":32,"tag":229,"props":649,"children":650},{"style":242},[651],{"type":37,"value":652}," current:\n",{"type":32,"tag":229,"props":654,"children":656},{"class":231,"line":655},20,[657,662,666],{"type":32,"tag":229,"props":658,"children":659},{"style":242},[660],{"type":37,"value":661},"        chunks.append(",{"type":32,"tag":229,"props":663,"children":664},{"style":309},[665],{"type":37,"value":397},{"type":32,"tag":229,"props":667,"children":668},{"style":242},[669],{"type":37,"value":670},".join(current))\n",{"type":32,"tag":229,"props":672,"children":674},{"class":231,"line":673},21,[675],{"type":32,"tag":229,"props":676,"children":677},{"style":242},[678],{"type":37,"value":427},{"type":32,"tag":229,"props":680,"children":682},{"class":231,"line":681},22,[683,688],{"type":32,"tag":229,"props":684,"children":685},{"style":236},[686],{"type":37,"value":687},"    return",{"type":32,"tag":229,"props":689,"children":690},{"style":242},[691],{"type":37,"value":692}," chunks\n",{"type":32,"tag":33,"props":694,"children":695},{},[696],{"type":37,"value":697},"Augmenter le chevauchement de 10% à 20% a plafonné le gain de retrieval mais a augmenté le coût de stockage de 18%. En production, 10% est devenu notre point optimal.",{"type":32,"tag":40,"props":699,"children":701},{"id":700},"configuration-dévaluation-aucun-point-aveugle-en-production",[702],{"type":37,"value":703},"Configuration d'Évaluation : Aucun Point Aveugle en Production",{"type":32,"tag":33,"props":705,"children":706},{},[707],{"type":37,"value":708},"Une fois ton système RAG déployé, la logique « si l'utilisateur se plaint, on regardera » ne fonctionne pas en production. Un pipeline d'évaluation doit fonctionner en continu : quand tu ajoutes un nouveau document, quand tu changes le modèle d'embedding, quand tu mets à jour la stratégie de chunking, un test de régression automatique doit s'exécuter. Nous exécutons cet ensemble de métriques à chaque commit dans notre CI\u002FCD :",{"type":32,"tag":33,"props":710,"children":711},{},[712],{"type":32,"tag":180,"props":713,"children":714},{},[715],{"type":37,"value":716},"Métriques de récupération :",{"type":32,"tag":718,"props":719,"children":720},"ul",{},[721,726,731],{"type":32,"tag":176,"props":722,"children":723},{},[724],{"type":37,"value":725},"Retrieval@5, @10 (sur les paires de vérité terrain)",{"type":32,"tag":176,"props":727,"children":728},{},[729],{"type":37,"value":730},"Mean Reciprocal Rank (MRR) — à quel rang le document correct apparaît-il ?",{"type":32,"tag":176,"props":732,"children":733},{},[734],{"type":37,"value":735},"NDCG@10 (qualité du classement)",{"type":32,"tag":33,"props":737,"children":738},{},[739],{"type":32,"tag":180,"props":740,"children":741},{},[742],{"type":37,"value":743},"Métriques end-to-end :",{"type":32,"tag":718,"props":745,"children":746},{},[747,752,757],{"type":32,"tag":176,"props":748,"children":749},{},[750],{"type":37,"value":751},"Answer correctness (LLM-as-judge : GPT-4 évalue la réponse générée)",{"type":32,"tag":176,"props":753,"children":754},{},[755],{"type":37,"value":756},"Citation accuracy (si la réponse contient une information absente de la source : -10 points)",{"type":32,"tag":176,"props":758,"children":759},{},[760],{"type":37,"value":761},"Latence p50\u002Fp95\u002Fp99",{"type":32,"tag":33,"props":763,"children":764},{},[765],{"type":37,"value":766},"Comment construisons-nous le dataset d'évaluation ? Nous prenons 500 requêtes production, les étiquetons manuellement avec les documents de vérité terrain, puis mesurons chaque changement sur cet ensemble. Le dataset est mis à jour chaque mois parce que la distribution des requêtes utilisateurs change — un score d'évaluation d'il y a 3 mois ne reflète pas la performance production d'aujourd'hui.",{"type":32,"tag":33,"props":768,"children":769},{},[770],{"type":37,"value":771},"Exemple de prompt pour LLM-as-judge :",{"type":32,"tag":218,"props":773,"children":775},{"code":774},"Tu es un modèle d'évaluation d'un système RAG.\nAnalyse le triplet suivant :\n\nUSER_QUERY: \"{query}\"\nRETRIEVED_CONTEXT: \"{context}\"\nGENERATED_ANSWER: \"{answer}\"\n\nÉvalue :\n1. La réponse répond-elle correctement à la requête ? (0-10)\n2. Toute information de la réponse est-elle présente dans le contexte ? (0-10, 0 si information hors source)\n3. La réponse contient-elle des détails inutiles ? (0-10, 10=concis)\n\nSortie JSON: {{\"correctness\": X, \"grounding\": Y, \"conciseness\": Z}}\n",[776],{"type":32,"tag":225,"props":777,"children":778},{"__ignoreMap":16},[779],{"type":37,"value":774},{"type":32,"tag":33,"props":781,"children":782},{},[783],{"type":37,"value":784},"Nous exécutons cette évaluation à chaque pull request — si le score retrieval@5 baisse de plus de 2%, la fusion est bloquée.",{"type":32,"tag":40,"props":786,"children":788},{"id":787},"hyperparamètres-de-tuning-top-k-et-reranking",[789],{"type":37,"value":790},"Hyperparamètres de Tuning : Top-K et Reranking",{"type":32,"tag":33,"props":792,"children":793},{},[794],{"type":37,"value":795},"Après une recherche par embedding, tu récupères les K meilleurs documents. K=5, K=10, ou K=20 ? Un K plus grand signifie plus de contexte, mais aussi plus de tokens envoyés au LLM — augmentation du coût, de la latence, et du bruit (le LLM souffre du problème « lost in the middle » — il oublie l'information au milieu d'un long contexte).",{"type":32,"tag":33,"props":797,"children":798},{},[799,801,806],{"type":37,"value":800},"Ce que nous avons trouvé comme optimal : ",{"type":32,"tag":180,"props":802,"children":803},{},[804],{"type":37,"value":805},"K=10 avec retrieval par embedding + un modèle reranker pour sélectionner les top-3",{"type":37,"value":807},". Un reranker (Cohere rerank-english-v2.0 ou cross-encoder\u002Fms-marco-MiniLM) effectue un appariement sémantique plus profond entre requête et document. Il fournit un classement de 7-12% meilleur que la similarité cosinus embedding, mais ajoute de la latence (un forward pass par document).",{"type":32,"tag":33,"props":809,"children":810},{},[811],{"type":37,"value":812},"Pipeline :",{"type":32,"tag":172,"props":814,"children":815},{},[816,821,826],{"type":32,"tag":176,"props":817,"children":818},{},[819],{"type":37,"value":820},"Retrieval par embedding pour top-10 (~80ms)",{"type":32,"tag":176,"props":822,"children":823},{},[824],{"type":37,"value":825},"Reranker classifie 10 documents, sélectionne top-3 (~120ms)",{"type":32,"tag":176,"props":827,"children":828},{},[829],{"type":37,"value":830},"Top-3 envoyés au LLM comme contexte du prompt",{"type":32,"tag":33,"props":832,"children":833},{},[834],{"type":37,"value":835},"La latence totale augmente de 40% (80ms → 200ms) par rapport à embedding seul, mais answer correctness passe de 87% à 94%. Notre SLA latence utilisateur est 500ms, donc ce tradeoff est acceptable. Si le SLA avait été plus strict, nous aurions pu mettre le reranker dans une queue asynchrone, répondre d'abord avec embedding top-3, puis écrire le résultat du rerank en cache en arrière-plan.",{"type":32,"tag":62,"props":837,"children":839},{"id":838},"contribution-réelle-du-reranking-résultats-du-test-ab",[840],{"type":37,"value":841},"Contribution Réelle du Reranking : Résultats du Test A\u002FB",{"type":32,"tag":33,"props":843,"children":844},{},[845,847,856],{"type":37,"value":846},"Pendant 7 jours, 50% du trafic a été routé vers embedding seul, 50% vers embedding + rerank. Grâce à ",{"type":32,"tag":848,"props":849,"children":853},"a",{"href":850,"rel":851},"https:\u002F\u002Fwww.roibase.com.tr\u002Ffr\u002Ffirstparty",[852],"nofollow",[854],{"type":37,"value":855},"l'architecture de mesure First-Party",{"type":37,"value":857},", nous avons collecté les métriques de chaque requête par segment :",{"type":32,"tag":69,"props":859,"children":860},{},[861,887],{"type":32,"tag":73,"props":862,"children":863},{},[864],{"type":32,"tag":77,"props":865,"children":866},{},[867,872,877,882],{"type":32,"tag":81,"props":868,"children":869},{},[870],{"type":37,"value":871},"Métrique",{"type":32,"tag":81,"props":873,"children":874},{},[875],{"type":37,"value":876},"Embedding Seul",{"type":32,"tag":81,"props":878,"children":879},{},[880],{"type":37,"value":881},"Embedding + Rerank",{"type":32,"tag":81,"props":883,"children":884},{},[885],{"type":37,"value":886},"Delta",{"type":32,"tag":97,"props":888,"children":889},{},[890,913,936,959],{"type":32,"tag":77,"props":891,"children":892},{},[893,898,903,908],{"type":32,"tag":104,"props":894,"children":895},{},[896],{"type":37,"value":897},"Évaluation utilisateur \"utile\"",{"type":32,"tag":104,"props":899,"children":900},{},[901],{"type":37,"value":902},"72%",{"type":32,"tag":104,"props":904,"children":905},{},[906],{"type":37,"value":907},"81%",{"type":32,"tag":104,"props":909,"children":910},{},[911],{"type":37,"value":912},"+9pp",{"type":32,"tag":77,"props":914,"children":915},{},[916,921,926,931],{"type":32,"tag":104,"props":917,"children":918},{},[919],{"type":37,"value":920},"Taux de requête de suivi",{"type":32,"tag":104,"props":922,"children":923},{},[924],{"type":37,"value":925},"34%",{"type":32,"tag":104,"props":927,"children":928},{},[929],{"type":37,"value":930},"28%",{"type":32,"tag":104,"props":932,"children":933},{},[934],{"type":37,"value":935},"-6pp (bon — première réponse suffisait)",{"type":32,"tag":77,"props":937,"children":938},{},[939,944,949,954],{"type":32,"tag":104,"props":940,"children":941},{},[942],{"type":37,"value":943},"p95 latence",{"type":32,"tag":104,"props":945,"children":946},{},[947],{"type":37,"value":948},"180ms",{"type":32,"tag":104,"props":950,"children":951},{},[952],{"type":37,"value":953},"240ms",{"type":32,"tag":104,"props":955,"children":956},{},[957],{"type":37,"value":958},"+60ms",{"type":32,"tag":77,"props":960,"children":961},{},[962,967,972,977],{"type":32,"tag":104,"props":963,"children":964},{},[965],{"type":37,"value":966},"Coût\u002Frequête",{"type":32,"tag":104,"props":968,"children":969},{},[970],{"type":37,"value":971},"$0,003",{"type":32,"tag":104,"props":973,"children":974},{},[975],{"type":37,"value":976},"$0,0042",{"type":32,"tag":104,"props":978,"children":979},{},[980],{"type":37,"value":981},"+40%",{"type":32,"tag":33,"props":983,"children":984},{},[985],{"type":37,"value":986},"Le reranking est essentiel en production pour une récupération de qualité — nous avons réduit l'augmentation des coûts grâce au batch processing et au cache à mesure que le volume augmente.",{"type":32,"tag":40,"props":988,"children":990},{"id":989},"cache-et-mise-à-jour-incrémentale-les-vrais-gains-de-coût-viennent-dici",[991],{"type":37,"value":992},"Cache et Mise à Jour Incrémentale : Les Vrais Gains de Coût Viennent d'Ici",{"type":32,"tag":33,"props":994,"children":995},{},[996],{"type":37,"value":997},"L'optimisation des coûts ne vient pas du choix du modèle mais de la stratégie de cache. Si la même requête revient, tu n'as pas besoin de refaire embedding + retrieval. Nous avons construit cette architecture en couches sur Redis :",{"type":32,"tag":172,"props":999,"children":1000},{},[1001,1011,1021],{"type":32,"tag":176,"props":1002,"children":1003},{},[1004,1009],{"type":32,"tag":180,"props":1005,"children":1006},{},[1007],{"type":37,"value":1008},"Query embedding cache",{"type":37,"value":1010}," — chaque vecteur embedding unique reste en cache 24 heures. Taux de hit : 41% (parce que les requêtes utilisateurs sont répétitives : « pricing », « integration guide »).",{"type":32,"tag":176,"props":1012,"children":1013},{},[1014,1019],{"type":32,"tag":180,"props":1015,"children":1016},{},[1017],{"type":37,"value":1018},"Retrieval result cache",{"type":37,"value":1020}," — la paire requête + top-K IDs de documents reste en cache 6 heures. Taux de hit : 28%.",{"type":32,"tag":176,"props":1022,"children":1023},{},[1024,1029],{"type":32,"tag":180,"props":1025,"children":1026},{},[1027],{"type":37,"value":1028},"Generated answer cache",{"type":37,"value":1030}," — la réponse complète reste en cache 1 heure (invalidée après une mise à jour de document). Taux de hit : 19%.",{"type":32,"tag":33,"props":1032,"children":1033},{},[1034],{"type":37,"value":1035},"Au hit du cache, la latence baisse de 200ms à 15ms, et le coût est zéro. Le taux de hit combiné est ~88% — cela signifie que seulement 12% du trafic production réclame réellement un appel embedding + LLM.",{"type":32,"tag":33,"props":1037,"children":1038},{},[1039],{"type":37,"value":1040},"Mise à jour incrémentale : quand on ajoute un nouveau document, on n'a pas besoin de réembedder tout le corpus. L'opération insert sur la vector database (Pinecone\u002FWeaviate) prend moins de 50ms. Quand un document existant change, on met à jour uniquement ses chunks. De cette façon, 500 documents peuvent être ajoutés par jour, et le système ne subit aucun temps d'arrêt.",{"type":32,"tag":40,"props":1042,"children":1044},{"id":1043},"observabilité-en-production-outils-nécessaires-pour-debugger-rag",[1045],{"type":37,"value":1046},"Observabilité en Production : Outils Nécessaires pour Debugger RAG",{"type":32,"tag":33,"props":1048,"children":1049},{},[1050],{"type":37,"value":1051},"Quand un utilisateur dit « tu as donné une mauvaise réponse », comment débugger ? Notre stack :",{"type":32,"tag":718,"props":1053,"children":1054},{},[1055,1065,1075],{"type":32,"tag":176,"props":1056,"children":1057},{},[1058,1063],{"type":32,"tag":180,"props":1059,"children":1060},{},[1061],{"type":37,"value":1062},"LangSmith",{"type":37,"value":1064}," — conserve la trace de chaque étape du pipeline RAG : latence embedding, résultat retrieval, prompt\u002Fresponse LLM, nombre de tokens. Avec l'ID de requête, on peut rejouer tout le pipeline.",{"type":32,"tag":176,"props":1066,"children":1067},{},[1068,1073],{"type":32,"tag":180,"props":1069,"children":1070},{},[1071],{"type":37,"value":1072},"Dashboard personnalisé",{"type":37,"value":1074}," (Grafana + Prometheus) — monitoring en temps réel du score retrieval@5, taux de hit du cache, p95 latence, coût\u002Frequête.",{"type":32,"tag":176,"props":1076,"children":1077},{},[1078,1083],{"type":32,"tag":180,"props":1079,"children":1080},{},[1081],{"type":37,"value":1082},"Error budget",{"type":37,"value":1084}," — tolérance de 2% d'échec retrieval par semaine (ex : document non trouvé). Si ce seuil est dépassé, une alerte est envoyée.",{"type":32,"tag":33,"props":1086,"children":1087},{},[1088],{"type":37,"value":1089},"Les alternatives open-source à LangSmith : Helicone, Langfuse. L'important est ceci : chaque requête en production doit avoir sa trace complète conservée, sinon tu ne peux pas répondre à « pourquoi a-t-il donné une mauvaise réponse ? ».",{"type":32,"tag":33,"props":1091,"children":1092},{},[1093],{"type":37,"value":1094},"La complexité du RAG réside ici : un seul pic de latence ou une erreur retrieval se propage en cascade. Un outil d'observabilité est aussi critique pour l'infrastructure que pour le debugging.",{"type":32,"tag":1096,"props":1097,"children":1098},"hr",{},[],{"type":32,"tag":33,"props":1100,"children":1101},{},[1102],{"type":37,"value":1103},"En RAG production, l'optimisation des coûts est la deuxième étape. D'abord,",{"type":32,"tag":1105,"props":1106,"children":1107},"style",{},[1108],{"type":37,"value":1109},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":16,"searchDepth":280,"depth":280,"links":1111},[1112,1115,1116,1117,1120,1121],{"id":42,"depth":258,"text":45,"children":1113},[1114],{"id":64,"depth":280,"text":67},{"id":157,"depth":258,"text":160},{"id":700,"depth":258,"text":703},{"id":787,"depth":258,"text":790,"children":1118},[1119],{"id":838,"depth":280,"text":841},{"id":989,"depth":258,"text":992},{"id":1043,"depth":258,"text":1046},"markdown","content:fr:ai:production-rag-retrieval-quality-before-cost.md","content","fr\u002Fai\u002Fproduction-rag-retrieval-quality-before-cost.md","fr\u002Fai\u002Fproduction-rag-retrieval-quality-before-cost","md",1782079493313]