LECTURE · EN DIRECT v3.2.1 QC · CA EN
notes-terrain/tx-018 · publié 2026·05·14 · 11m de lecture · nombre de mots 1 847
--:--:-- UTC
QUEBEC · 46.81°N -71.21°W
racine / notes-terrain / tx · 018
tx · 018 RAG · evals 2026·05·14 11m de lecture 1 847 mots diff +2 401 / −188

Pourquoi votre pipeline RAG se dégrade en silence, et comment nous l'avons détecté à la semaine 3.

Un exemple illustratif d'un mode de défaillance contre lequel nous concevons : trois semaines après un déploiement propre, la satisfaction client chute de quatre points sans changement de modèle, de prompt, ni anomalie de trafic. La dérive est dans l'index, et elle change la façon dont ces systèmes devraient être mesurés.

JP
Jean Pierre Levac
Fondateur · Acceleratech

La plupart des écrits techniques sur la génération augmentée par récupération traitent le déploiement comme une destination. Vous avez livré, les evals ont passé, votre client est satisfait. Ce n'est pas à ça que ressemble la production. La production, c'est une dérive lente et souvent invisible à partir du jour où vous avez livré. Si vous ne surveillez pas le bon signal, vous ne le remarquerez qu'au moment où un client le fera.

Voici le déroulement d'un mode de défaillance contre lequel nous concevons : à quoi ressemble une dérive d'index trois semaines après une remise, comment elle apparaît dans les métriques, et les changements que cela a imposés à notre harnais d'evals standard pour que cette catégorie d'échec remonte au premier jour, pas à la troisième semaine.

↳ résumé La péremption de l'index est le tueur silencieux. La qualité d'un système RAG est bornée par la qualité de son retrieval, et la qualité du retrieval se dégrade à mesure que le corpus change sans être ré-embeddé. Nos evals standard ne mesuraient pas le recall sur un corpus frais. Ils mesuraient la qualité de génération contre des réponses de référence figées. Nous avons changé ça.

Le contexte

Prenons un déploiement représentatif : une stack de support client pour une fintech de taille moyenne, environ 8 000 employés, 1,2 million de chunks de documents de support, en anglais et en français, avec un pic de charge autour de 240 QPS. Sept agents dans le graphe d'orchestration (recherche, classificateur, planificateur, exécuteur, deux spécialistes et un nœud de garde-fou). Le retrieval était hybride (BM25 plus dense) contre un cluster Qdrant, avec un re-ranker par-dessus.

Au jour 0, nous avons exécuté le harnais d'evals complet : 412 questions sur 14 catégories, scorées contre des réponses de référence figées par un LLM-as-judge avec des vérifications humaines ponctuelles. La satisfaction client (CSAT) du pilote en direct suivait nos scores hors ligne à 1,5 point près. Tout le monde s'accordait à dire que ça fonctionnait.

taille du corpus
1,2M
chunks indexés au moment du déploiement
couverture evals
412
questions de référence sur 14 catégories
csat jour de déploiement
88,4%
pilote en direct, n=1 840 conversations

Le signal

Trois semaines plus tard, le tableau de bord analytique du client a signalé une baisse de CSAT de 88 à 84. Ça ressemblait d'abord à du bruit (un écart de 4 points sur 1 200 conversations reste dans un intervalle de confiance raisonnable), mais le chiffre du lendemain était 83. Le surlendemain, 82. Ce n'est plus du bruit. C'est une tendance.

fig · 01 / csat · t-21j → t+0 ● dérive détectée · jour 21
90 88 86 84 cible · 88 dérive · jour 21 index staleness j0 j7 j14 j21 j28 j35
fig · 01 csat quotidien, glissement 1 jour. Le système a suivi la cible à ±2 points jusqu'au jour 19, puis a commencé une baisse régulière. La pente corrèle presque exactement avec le rythme d'ajout de nouveaux documents de support au corpus source qui n'avaient pas encore été ré-embeddés.

Nous avons extrait les traces d'orchestration pour les conversations aux CSAT les plus bas des 48 dernières heures. Les agents n'étaient pas confus. Le planificateur avait choisi le bon chemin. L'exécuteur avait appelé les bons outils. Les générations étaient fluides, conformes à la marque, polies. Elles étaient aussi fausses : citant les mauvaises politiques, reprenant des tarifs obsolètes, ignorant une ligne de produits lancée au jour 14.

Dans chaque cas, l'échec était en amont. Le retriever ne remontait aucun chunk utile, alors le générateur hallucinait quelque chose de plausible à partir de ses priors. Les agents eux-mêmes allaient bien. C'est le corpus qui avait bougé.

Le système a suivi la cible pendant 19 jours. Au jour 20, l'index n'avait pas bougé, mais le monde, lui, l'avait fait.

Le diagnostic

L'équipe de support du client avait été discrètement héroïque. Dans les trois semaines suivant la remise, ils avaient ajouté 2 401 nouveaux documents de support, retiré 188 anciens, et réécrit la politique sur deux lignes de produits. Rien de tout cela n'avait été ré-embeddé. Rien de tout cela n'était dans l'index que le retriever interrogeait.

Notre pipeline avait un job d'ingestion. Il tournait simplement sur le mauvais calendrier. Nous avions configuré un ré-embedding nocturne pour les documents delta, mais la requête d'ingestion dépendait d'une colonne last_modified que le CMS du client ne mettait à jour qu'à la création, pas à la modification. Les nouveaux docs entraient. Les docs modifiés, non. Les docs retirés restaient dans l'index. Chaque jour, discrètement, l'index devenait un peu plus faux.

Ce que la métrique aurait dû détecter

Notre harnais d'evals mesurait la qualité de génération contre des réponses de référence figées. Si le retriever remontait de mauvais chunks, la génération était quand même scorée contre ce que nous attendions au jour 0. Le juge marquait volontiers une génération « bonne » si elle correspondait à la réponse attendue du jour 0, même quand cette réponse était devenue obsolète.

métriquejour 0jour 21jour 35signal
qualité de génération (juge)0,910,900,88stable ✓
recall retrieval @ k=100,870,710,58−0,29
fraîcheur chunks (âge moyen)4 j18 j29 j+25 j
taux de correspondance des citations0,940,740,61−0,33
csat en direct88,483,981,2−7,2

La métrique basée sur le juge a été la dernière à bouger. Le recall retrieval, la fraîcheur des chunks et le taux de correspondance des citations s'étaient tous effondrés des semaines plus tôt. Nous ne les surveillions simplement pas.

La correction

Le correctif était petit. Le changement culturel, lui, ne l'était pas. Nous avons réécrit trois choses.

  1. Déclencheur d'ingestion. Au lieu de faire confiance à une colonne CMS, nous calculons maintenant un hash de contenu sur chaque document chaque nuit et ré-embeddons tout chunk dont le hash a changé. Plus lent. Correct.
  2. Evals de retrieval. Le recall@k contre un ensemble de citations de référence tenu à l'écart est maintenant une métrique de premier plan, exécutée quotidiennement contre l'index en direct. Une dérive au-delà d'un seuil page l'astreinte.
  3. Jauge de fraîcheur des chunks. L'âge moyen des chunks cités est maintenant dans le tableau de bord aux côtés de la latence et du coût. Si l'index ne bouge pas alors que le corpus source bouge, quelque chose ne va pas.

Voici à quoi ressemble approximativement le harnais de recall. Il tourne en cron job sur le même compute qui gère l'index, prend environ 90 secondes sur notre taille de corpus typique, et écrit une ligne par exécution dans une petite table Postgres.

eval/retrieval_recall.py · 24 lines python · 3.11
from dataclasses import dataclass
from retriever import Retriever
from ground_truth import load_eval_set

@dataclass
class RecallResult:
    recall: float
    mean_age_days: float
    n_queries: int

def eval_recall(retriever: Retriever, k: int = 10) -> RecallResult:
    # held-out: ~600 (query, expected_chunk_ids) pairs
    eval_set = load_eval_set("recall_v3")

    hits, ages = 0, []
    for q, expected_ids in eval_set:
        retrieved = retriever.search(q, k=k)
        retrieved_ids = {c.id for c in retrieved}
        hits += len(retrieved_ids & expected_ids) / len(expected_ids)
        ages.extend(c.age_days for c in retrieved)

    return RecallResult(
        recall=hits / len(eval_set),
        mean_age_days=sum(ages) / len(ages),
        n_queries=len(eval_set),
    )

Deux jours après la réécriture, le recall retrieval était remonté au-dessus de 0,85, l'âge moyen des chunks était sous 6 jours, et le CSAT avait récupéré à 89. Dans un scénario comme celui-ci, les utilisateurs finaux ne voient jamais le diagnostic. Ils constatent seulement que le système s'améliore.

Ce qui va dans les evals, exactement

Nous avons maintenant standardisé cela. Chaque système agentique que nous livrons exécute au minimum ces cinq métriques chaque jour, et chacune a un seuil documenté et une page d'astreinte en cas de dépassement.

Rien de tout cela n'est exotique. Rien de tout cela ne nécessite des articles de recherche. Si la plupart des équipes ne les exécutent pas, ce n'est pas une question de capacité. C'est que le tableau de bord construit par l'équipe de déploiement au jour 0 ne montrait que la qualité de génération, et une fois le système « en production », personne n'est revenu vérifier le tableau de bord.

↳ conclusion · pour quiconque livre Les evals sont une surface produit. Traitez le tableau de bord comme vous traiteriez l'interface utilisateur : qui le consulte, à quelle fréquence, quelle action est prise quand un chiffre bouge. Un tableau de bord que personne ne lit est pire qu'aucun tableau de bord, parce qu'il donne une fausse impression qu'on remarquerait si quelque chose cassait.

Conclusions

Si vous opérez un système RAG en production, trois demandes :

  1. Mesurez le recall retrieval quotidiennement contre un ensemble de référence tenu à l'écart. La qualité de génération est en aval. Si vous ne surveillez que la génération, vous regardez un indicateur retardé d'un indicateur retardé.
  2. Calculez une jauge de fraîcheur des chunks et affichez-la à côté de la latence et du coût. Un système dont les chunks récupérés vieillissent chaque semaine est un système qui casse en silence.
  3. Ne faites pas confiance au last_modified de votre CMS. Calculez des hashes de contenu. Les cycles supplémentaires sont bon marché. La semaine de production dégradée, non.

La dérive silencieuse du retrieval sur ce qui ressemble à un déploiement stable est l'un des modes de défaillance les plus courants pour un système RAG qui semble sain. Faites tourner RAG en production assez longtemps et vous rencontrerez ce mode de défaillance. L'intérêt d'un exemple illustratif est de le reconnaître avant que votre CSAT ne le fasse.

Si vous souhaitez que nous examinions votre suite d'evals, le formulaire de contact est la voie la plus rapide. Nous offrons des revues gratuites de 30 minutes pour les systèmes en production.

· fin · tx 018 ·
JP
Jean Pierre Levac

Fondateur d'Acceleratech, le pôle de services en IA et automatisation des flux de travail du Groupe de Croissance Numérique JPL. Rédige et révise les notes de terrain publiées ici.

Rédigé et révisé par Jean Pierre Levac. Note de transparence →

Vous avez aimé / recevez le prochain.

Notes de terrain, postmortems et opinions tranchées sur ce qui fonctionne vraiment en production dans l'IA agentique. Aux deux semaines.

© 2026 Acceleratech · notes-terrain · v3.2.1 ← retour au fil Une Stratégie de croissance numérique par Groupe de Croissance Numérique JPL.