Module XII — qualité, évaluations et tests
Le module XII répond à une seule question — mon agent fait-il toujours ce qu’il faut ? — en notant les sorties candidates par rapport à des suites de référence versionnées et en émettant le résultat sous forme de preuve canonique, inter-modules. C’est un module de la couche Intelligence : il mesure, il n’exécute pas le sujet et n’agit pas sur l’infrastructure. Cette page est la référence de ce que fait aujourd’hui le module d’évaluations, et de ses limites honnêtes.
Ce qu’il mesure (et ce qu’il n’exécute jamais)
Section intitulée « Ce qu’il mesure (et ce qu’il n’exécute jamais) »XII est une couche de mesure, pas une couche d’exécution. Une sortie candidate lui parvient
déjà produite — depuis le bac à sable de test (module XVII), depuis la CI, en ligne dans la
requête, ou comme signal échantillonné d’une session réelle — et XII la note par rapport aux cas
d’une suite. Le seul modèle que XII invoque jamais est le juge (pour le scorer llm_judge) ;
il n’exécute jamais l’agent ou le modèle sujet lui-même. Produire des sorties est le rôle du bac à sable,
pas celui de XII.
L’ensemble des scorers est enfichable. Des primitives déterministes et pures couvrent les contrats
courants — exact, contains, not_contains, regex, json_valid, json_equal
et numeric_range. À leurs côtés se trouve un scorer llm_judge qui invoque un modèle
via le port Judge pour noter par rapport à un barème.
Suites, exécutions et l’artefact canonique
Section intitulée « Suites, exécutions et l’artefact canonique »Une suite est un jeu de données de référence versionné : elle contient ses cas, un scorer par
défaut, un seuil de réussite et un seuil de régression. Les cas sont en ajout seul et immuables par
version — corriger un cas génère un nouveau suite_version, jamais une édition en place, de sorte
que le jeu de données ayant produit n’importe quel verdict passé est toujours reconstructible.
Une exécution note chaque cas d’une suite, agrège un score et un pass_rate, et
persiste trois choses : une preuve par cas en ajout seul, un agrégat d’exécution mutable, et un
EvalResult central — l’artefact canonique (Suite, SubjectKind, SubjectID,
Score, Passed, OccurredAt, Metrics) que la conformité (XIII) et l’interface lisent
sans connaître les propres tables de XII. Les exécutions s’effectuent de façon synchrone ; le flux SSE d’une
exécution rejoue l’exécution persistée (trames par cas, puis un résumé), il n’actionne rien.
Une régression est une comparaison avec une exécution de référence.
Quand la baisse de score dépasse le regression_threshold de la suite et que l’intervalle
à 95 % de la différence de taux de réussite (Newcombe, différence d’intervalles de Wilson)
exclut zéro, l’exécution positionne regressed et écrit un Finding central
(Kind = eval_regression). Une baisse au-dessus du seuil dont l’intervalle contient zéro
est marquée inconclusive_noise, pas comme une régression ; la comparaison montre
l’intervalle et les deux dénominateurs, donc les petites suites lèvent moins de findings.
La référence automatique est la dernière
exécution terminée pour la même suite et le même sujet, et pour la même variante
lorsqu’il y en a une, hors exécutions marquées inconclusive_noise. Cette exécution peut utiliser une autre version de suite, un
autre modèle ou un autre scorer, et la comparaison ne dit pas lequel a changé. Après
un changement de version de suite, passez une référence explicite ou épinglez-en une
(POST /baselines). Le constat est émis au mieux sur le bus sous la forme
finding.reported pour que les modules de diffusion (santé/notifications) le
routent. Côté lecture, les tableaux de bord (scorecards) agrègent le taux de réussite, le score moyen et la tendance par
sujet et s’exportent en CSV/JSON.
Données minimales, par construction
Section intitulée « Données minimales, par construction »La sortie candidate n’est jamais persistée — quelle qu’en soit la source. Un résultat par cas ne stocke
qu’un hachage à sens unique du détail et un libellé écrêté et nettoyé pour l’interface ; l’expurgation est faite
par le handler avant le stockage, jamais supposée du store. Le moniteur note des
signaux comportementaux d’une session réelle — son état, le nombre de findings, la sévérité maximale et
les chiffres de jetons/coûts (tirés des signaux centraux Session, Finding et CostRecord)
— et jamais le texte de sortie brut, que la plateforme ne persiste pas du tout. Les
fixtures de référence sont la seule exception bornée : autorisées par l’opérateur, en opt-in, contenu
non-production, écrêté par le handler avant écriture pour qu’une suite puisse réellement être exécutée.
Calibration du juge, atténuation des biais et la barrière de régression CI
Section intitulée « Calibration du juge, atténuation des biais et la barrière de régression CI »Les verdicts du juge ne sont fiables qu’après avoir été mesurés. Un jeu de calibration étiqueté
par un humain (constitué avec la session guidée olivares evals label) alimente une
exécution de calibration qui mesure le juge par rapport à la référence humaine : pourcentage
d’accord avec son intervalle de Wilson à 95 %, le kappa de Cohen (l’accord seul n’est pas
défendable en cas de déséquilibre des classes), sensibilité/spécificité avec leurs dénominateurs, et
une corrélation de biais de verbosité. Le rapport est une preuve en ajout seul ; la cible —
accord ≥ 0,85 et un kappa défini ≥ 0,6 — peut être relevée par exécution mais jamais
abaissée. Un jeu dont les étiquettes humaines sont toutes en réussite ne peut mesurer l’accord
corrigé du hasard et ne certifie rien.
L’atténuation des biais est intégrée et mesurée : le prompt du juge force le raisonnement avant
le verdict (l’analyse est écartée à la volée — données minimales) et instruit de ne pas
récompenser la longueur ; le mode pairwise en opt-in de la comparaison A/B juge chaque cas partagé
deux fois avec l’ordre de présentation inversé, déclare un vainqueur uniquement lorsque les deux ordres
concordent, et rapporte le taux de position_consistency mesuré.
La barrière de régression (POST /gate, CLI evals gate) transforme tout cela en un
verdict CI bloquant : une régression par rapport à la référence, un taux de réussite inférieur au seuil de la suite, ou un
juge non calibré font échouer la barrière (sortie 1) ; un identifiant de juge manquant se dégrade
en un avertissement déclaré, jamais en une réussite silencieuse. La
graine de la barrière choisit les cas de l’échantillon ; elle ne rend pas un modèle
distant déterministe. Un succès du cache de verdicts, indexé par le contenu, l’épinglage
du modèle juge et la version du prompt, renvoie le verdict enregistré. Un échec, et toute
exécution llm_judge ordinaire hors de cette barrière, rappelle le juge distant et peut
différer. Le contrôle FinOps ne porte que sur cette barrière. Quand aucun budget FinOps
qui bloque ou limite ne s’applique aux appels au juge, la barrière autorise la dépense.
Quand le stockage des budgets ne peut pas être lu, la barrière refuse la dépense et
échoue avec budget_blocked. Un budget qui bloque ou limite arrête la dépense. La
seule échappatoire à une barrière échouée est le contournement gouverné — niveau admin, raison
écrite, audité — qui change le verdict effectif que la CI revérifie, jamais celui qui est
enregistré. Chaque taux rapporté est livré avec son dénominateur et son intervalle à 95 %, et la
comparaison de régression aussi. Voir
docs/EVAL-METHODOLOGY.md dans le dépôt pour la méthodologie complète et les sources.
Liens connexes
Section intitulée « Liens connexes »- Catalogue des modules — où se situe XII et la séparation Gouverner/Actionner.
- Référence du bus d’événements — l’événement
finding.reportedqu’une régression émet. - Vue d’ensemble de l’architecture — la couche Intelligence.
- Gouverner et approuver — agir sur un finding de régression.
- Honnêteté & limites — les jointures deny-closed à travers le produit.