Aller au contenu

Traduction automatique

Cet article a été traduit automatiquement depuis la version originale en anglais.

Évaluer les agents IA en production : des traces aux suites de test

Une réponse de chatbot est une ligne. L’exécution d’un agent est un arbre.

Cette différence casse beaucoup d’habitudes d’évaluation. La réponse finale peut sembler correcte alors que l’agent a ignoré un outil requis, relancé 17 fois le même appel, mal interprété le résultat d’un outil ou suivi un chemin qui serait interdit en production. Si vous ne notez que la réponse, vous manquez l’endroit où le système a réellement échoué.

TL;DR : les evals d’agents ont besoin de trois couches : métriques de résultat, métriques de trajectoire et métriques de composant. Construisez autour de cette boucle : trace -> label -> cluster -> déduplication -> jeu de données versionné -> garde CI -> monitoring en ligne. Utilisez des vérifications déterministes pour l’ordre des outils, les arguments, les boucles et les invariants. N’utilisez des juges LLM que là où la vérification dépend de l’interprétation, structurez ces juges avec Schema-Guided Reasoning (SGR), et calibrez-les sur des labels humains avant de leur faire confiance.


Pourquoi les evals d’agents sont différentes

Les evals LLM traditionnelles notent généralement une seule paire entrée-sortie : pertinence, fidélité, exactitude, sécurité, parfois style. Les agents ajoutent la planification, les appels d’outils, les retries et les vérifications de terminaison, et chaque étape crée un nouveau point de défaillance.

Prenez un agent de remboursement. La transcription peut bien se terminer alors que la trace est erronée :

lookup_order -> issue_refund -> final_answer

L’eval de sortie passe. Une eval de trajectoire devrait échouer parce que verify_identity n’a jamais été exécuté avant issue_refund. Pour les agents qui utilisent des outils, les evals centrées uniquement sur la réponse sont des smoke tests : elles détectent les pannes totales et ratent tout le reste.

Il y a un second problème : les erreurs se composent. Si un workflow en 20 étapes est fiable à 95 % à chaque étape, son taux de réussite de bout en bout tombe quand même autour de 36 % :

\[ 0.95^{20} \approx 0.36 \]

L’agent peut donc sembler solide dans des vérifications isolées et pourtant échouer sur la majorité des exécutions complètes. La rupture se situe généralement au milieu, et la trouver demande une visibilité au niveau des composants, pas un autre regard sur la réponse.

Une ligne contre un arbre : là où se cachent les échecs des agents

Deux équipes de recherche ont mis des chiffres sur ce phénomène.

tau-bench est un benchmark où un agent gère des tâches de service client dans l’aérien et le retail : il parle à un utilisateur simulé, appelle des API et doit respecter la politique métier pendant tout le parcours. La notation ignore la transcription. Une fois la conversation terminée, le benchmark vérifie si la base de données a atteint l’état objectif annoté ; ainsi, une exécution polie et crédible qui a laissé les mauvaises lignes en base échoue quand même. Avec cette méthode de notation, même GPT-4o a réussi moins de la moitié des tâches. L’article a aussi introduit pass^k : exécuter la même tâche k fois et ne compter comme réussite que si l’agent réussit les k exécutions. Des scores retail qui semblaient acceptables sur une seule tentative sont tombés sous les 25 % à k = 8. Même agent, même tâche, huit exécutions, résultats souvent différents. Cette incohérence reste invisible si votre eval n’exécute chaque cas qu’une seule fois.

MAST pose une autre question : non pas à quelle fréquence les agents échouent, mais pourquoi. Les auteurs ont annoté plus de 1 600 traces d’exécution issues de 7 frameworks multi-agents populaires et ont classé les échecs en 14 modes récurrents. Presque aucun n’est de type « le modèle a donné une mauvaise réponse ». Ce sont des choses comme des définitions de rôle vagues (conception système), un agent qui ignore ce qu’un autre agent lui a dit (désalignement inter-agents), ou une déclaration de succès sans vérification du résultat (absence de vérification). La plupart des échecs vivent dans le harness : les prompts, la logique d’orchestration, les vérifications manquantes. Un meilleur modèle de base réduit ces chiffres, mais ne peut pas corriger une étape de vérification qui n’a jamais été construite. C’est pourquoi il faut évaluer le harness, pas seulement le modèle qu’il contient.


Le gap d’adoption

La plupart des équipes ont déjà la matière première pour de meilleures evals. Elles ont des traces. Elles ne les ont simplement pas encore transformées en tests.

L’enquête State of Agent Engineering de LangChain est le meilleur instantané public de ce décalage. Elle indique que 57,3 % des répondants ont déjà des agents en production, 89 % ont une forme d’observabilité, 52,4 % exécutent des evals offline et 37,3 % des evals online. Et lorsqu’on leur demande ce qui bloque la production, 32 % citent la qualité, devant la latence à 20 %. La chose que mesurent les evals est précisément celle sur laquelle les équipes bloquent.

Cela laisse les équipes dans un état intermédiaire inconfortable : elles peuvent inspecter une mauvaise exécution après coup, puis quand même livrer deux fois le même échec.

Une règle corrige cela : chaque échec de production diagnostiqué doit laisser derrière lui une trace, un label, une ligne de jeu de données et un scorer. Si cela peut se reproduire, cela appartient à la suite de régression.


Choisir les métriques selon le mode d’échec

La bonne métrique dépend du mode d’échec, pas du framework. La séparation utile a trois niveaux :

  1. Les evals de résultat répondent à la question de savoir si la tâche a réussi.
  2. Les evals de trajectoire répondent à la question de savoir si le chemin était valide, efficace et conforme à la politique.
  3. Les evals de composant répondent à la question de savoir quel outil, retriever, sous-agent ou étape de décision a cassé.

Trois niveaux d’évaluation d’agent et leurs métriques

Chaque niveau peut s’exécuter offline (cas fixes et rejouables avant release) ou online (traces de production échantillonnées après la réponse) ; la section sur les garde-fous couvre cette séparation en détail plus bas. Version courte : les evals offline peuvent exiger des goldens, tandis que les evals online doivent privilégier les invariants, les distributions et les vérifications asynchrones qui restent hors du chemin de requête.

Question Famille de métriques Contrat offline / online Déterministe ou juge ? Point d’attention
L’agent a-t-il appelé les bons outils ? Exactitude des outils : correspondance exacte, en ordre, ou dans n’importe quel ordre Goldens exacts offline ; invariants d’outils requis et anomalies online Déterministe La correspondance exacte pénalise des chemins alternatifs valides
Les a-t-il appelés avec les bonnes entrées ? Exactitude des arguments, validation de schéma, correspondance des paramètres Arguments attendus offline ; vérifications de schéma, plage et politique online Les deux Bon outil avec mauvais arguments reste une panne
A-t-il gaspillé des étapes ? Efficacité en nombre d’étapes, nombre de retries, détection de boucles, coût et latence Budgets d’étapes et de boucles offline ; dérive de coût et de latence online Majoritairement déterministe Un taux élevé de réussite peut masquer une dérive coûteuse
La tâche a-t-elle réellement réussi ? Réalisation de tâche, notation du résultat, diff d’état final Simulateur ou état golden offline ; état final, signal utilisateur ou juge asynchrone online Juge ou vérification d’état Notez l’état de l’environnement quand c’est possible
A-t-il conservé le contexte sur plusieurs tours ? Fidélité multi-tour, respect du rôle, complétude de conversation Cas scénarisés longue portée offline ; sessions longues échantillonnées online Juge Les tests mono-tour ne disent rien sur le tour 14
S’est-il arrêté au bon moment ? Exactitude de terminaison, succès prématuré, travail sans fin Tests de scénario offline ; boucles, timeouts et faux succès monitorés online Les deux « Done » peut être un état halluciné
A-t-il correctement interprété les résultats des outils ? Compréhension du résultat d’outil, vérifications d’état en aval Sorties d’outils adversariales offline ; vérifications d’état aval et revue échantillonnée online Les deux L’outil peut être correct alors que l’agent le lit mal

Commencez par les métriques déterministes. Elles sont peu coûteuses, rapides et ne dérivent pas.

Exactitude des appels d’outils

L’exactitude des outils compare les outils appelés aux outils attendus. Choisissez le niveau de stricteté délibérément :

  • Correspondance exacte : la séquence doit correspondre exactement. À utiliser quand l’ordre relève de la politique, par exemple lookup_order -> verify_identity -> issue_refund.
  • Correspondance en ordre : les outils requis doivent apparaître dans le bon ordre relatif, mais des appels supplémentaires inoffensifs sont autorisés.
  • Correspondance dans n’importe quel ordre : les outils requis doivent apparaître, mais l’ordre peut varier.

Un petit scorer local suffit pour démarrer :

def tool_correctness(called: list[str], expected: list[str], mode: str = "in_order") -> float:
    if not expected:
        return 1.0
    if mode == "exact":
        return float(called == expected)
    if mode == "any_order":
        return len(set(expected) & set(called)) / len(set(expected))

    rows = [[0] * (len(expected) + 1) for _ in range(len(called) + 1)]
    for i, tool in enumerate(called):
        for j, wanted in enumerate(expected):
            if tool == wanted:
                rows[i + 1][j + 1] = rows[i][j] + 1
            else:
                rows[i + 1][j + 1] = max(rows[i][j + 1], rows[i + 1][j])
    return rows[-1][-1] / len(expected)


called = ["lookup_order", "check_refund_policy", "issue_refund"]
expected = ["lookup_order", "verify_identity", "issue_refund"]

print(round(tool_correctness(called, expected, "exact"), 3))     # 0.0
print(round(tool_correctness(called, expected, "in_order"), 3))  # 0.667

La métrique Tool Correctness de DeepEval expose les mêmes leviers via should_consider_ordering et should_exact_match.

Exactitude des arguments

Appeler le bon outil avec les mauvais arguments est souvent pire qu’appeler le mauvais outil, parce que la trace semble normale.

Pour les cas simples, validez le schéma JSON et les valeurs exactes. Pour les cas sémantiques, stockez les arguments attendus et notez les écarts :

{
    "trace_id": "tr_2417",
    "input": "Reschedule order A-100 for next Friday.",
    "expected_tools": ["lookup_order", "reschedule_delivery"],
    "expected_arguments": {
        "reschedule_delivery": {
            "order_id": "A-100",
            "date": "2026-06-19"
        }
    }
}

Une métrique sur le nom de l’outil ne peut pas détecter 2026-06-17 quand la politique exige 2026-06-19. Le jeu de données doit aussi stocker les arguments.

Efficacité, boucles et impasses

Le chemin compte même quand la destination est atteinte. Un agent qui termine la tâche après cinq appels d’outils redondants signale toujours un problème de planification et coûte plus cher à exécuter.

Signaux peu coûteux à mettre en place en premier :

  • Taux d’appels redondants : appels d’outils identiques avec arguments identiques répétés plus de deux fois.
  • Anomalies de forme de trace : pics soudains de profondeur, de nombre d’appels d’outils, de nombre de tokens, de latence ou de coût.
  • Convergence de chemin : proximité de l’exécution avec le plus court chemin valide connu pour la tâche.
  • Exactitude de terminaison : si l’agent s’est arrêté trop tôt, a continué à travailler après le succès, ou a déclaré un succès sans changement d’état requis.

Exécutez ces vérifications avant un juge dès que possible. Un détecteur de boucle tient en quelques lignes sur la trace. Il n’a pas besoin d’un modèle.

Réalisation de tâche et notation du résultat

De bout en bout, la question est : « l’utilisateur a-t-il obtenu ce qu’il demandait ? »

Deux patterns fonctionnent le mieux :

  • Notation de réalisation de tâche sans référence : extraire l’objectif depuis l’entrée et juger si la trace plus la réponse finale l’ont atteint. Cela fonctionne online parce que le trafic de production a rarement des sorties golden.
  • Notation par état de l’environnement : comparer les lignes finales de base de données, fichiers, tickets, réservations ou enregistrements à un état objectif annoté. C’est plus robuste qu’une comparaison de transcription, car les agents peuvent trouver des chemins valides que vous n’aviez pas explicités.

La seconde option est meilleure quand vous pouvez la construire. L’état final est le contrat. La transcription n’est qu’une preuve.


Le flywheel trace-to-eval

Ne commencez pas par brainstormer votre jeu d’eval. Exploitez les échecs de production.

Le flywheel trace-to-eval

La boucle :

  1. Capturer la trace complète.
  2. Labelliser ce qui a échoué.
  3. Regrouper les échecs similaires.
  4. Garder un golden représentatif par cluster.
  5. Versionner le jeu de données.
  6. L’exécuter en CI.
  7. Continuer à scorer des traces de production échantillonnées online.

Exploiter les échecs avec l’analyse d’erreurs

Hamel Husain et Shreya Shankar enseignent un workflow d’analyse d’erreurs exactement pour cette étape ; le field guide de Hamel le détaille. Les deux premières étapes empruntent leurs noms à la recherche qualitative, mais la méthode est simple : lisez les traces, prenez des notes, nommez les motifs.

  1. Open coding : lire 30 à 50 traces réelles et écrire des notes libres sur ce qui a mal tourné.
  2. Axial coding : regrouper ces notes en 5 ou 6 catégories d’échec nommées.
  3. Labelliser l’ensemble selon cette taxonomie.
  4. Construire des métriques pour les plus gros buckets.

Ne commencez pas avec des labels comme reasoning_issue ou tool_problem. Ils sont trop vagues pour être testés. Utilisez des labels comme missing_identity_verification, date_argument_mismatch, retried_same_tool_after_429 ou stopped_before_database_update. Un label aussi précis indique exactement ce que le test de régression doit vérifier.

Dédupliquer avant de promouvoir

La boucle d’exploitation des traces a un piège : ajouter toutes les mauvaises traces pour toujours. Cela crée un jeu de données volumineux, coûteux et étroit. Il passe sur des quasi-doublons de mars tout en manquant la nouvelle forme du même bug en juin.

Regroupez d’abord. Promouvez un golden représentatif par cluster. Stockez les IDs de traces associées dans les métadonnées pour qu’un reviewer puisse inspecter plus tard les preuves en production.

Si un cluster d’échec réapparaît après un correctif, le cas de régression n’a pas généralisé. Re-clustérisez et élargissez le golden au lieu d’ajouter 15 exemples ponctuels.

Versionner le jeu de données

Versionnez les jeux de données comme vous versionnez les prompts et le code. À chaque changement significatif (modèle, prompt, schéma d’outil, prompt du juge ou comportement de l’application), vous devez pouvoir exécuter la même version de jeu de données avant et après.

La garde CI doit épingler :

  • version du jeu de données
  • version de l’application
  • version du prompt
  • modèle du juge
  • prompt du juge
  • version du code d’évaluation

Si l’un de ces éléments change, votre comparaison avant/après devient brouillée. Un fichier goldens-v3.json dans git suffit à petite échelle. Les snapshots natifs aux outils dans Langfuse, Phoenix, Braintrust ou LangSmith aident quand le jeu de données devient collaboratif.

Garder la CI

Une métrique en échec doit devenir un build en échec, sinon la suite d’eval n’est qu’un dashboard que personne ne lit.

Le test doit relancer l’agent courant contre l’entrée golden. Il ne doit pas simplement rejouer l’ancienne trace en échec :

@pytest.mark.parametrize("golden", GOLDENS, ids=[item["id"] for item in GOLDENS])
def test_agent_regression(golden: dict) -> None:
    answer, fresh_trace = run_agent_and_capture_trace(golden["input"])

    refired = set(flag_failures(fresh_trace)) & set(golden["failure_modes"])
    assert not refired, f"failure mode regressed: {sorted(refired)}"

    assert tool_correctness(
        called=[call["name"] for call in fresh_trace["tool_calls"]],
        expected=golden["expected_tools"],
        mode=golden.get("tool_match", "in_order"),
    ) >= golden.get("tool_threshold", 1.0)

Cette distinction est facile à manquer. Le rôle du jeu de données est de détecter que la prochaine version de l’agent répète un ancien échec, pas d’archiver l’échec lui-même.


Calibrer le juge avant de lui faire confiance

Le paradigme LLM-as-judge aide. Il est aussi très facile de s’illusionner avec.

L’idée a des antécédents solides. G-Eval a montré qu’un juge qui suit explicitement une rubrique étape par étape suit mieux les notes humaines que les anciennes métriques automatiques qu’il remplaçait. MT-Bench a montré que GPT-4 s’aligne avec les préférences humaines à peu près aussi souvent que les humains s’alignent entre eux, ce qui a popularisé l’usage de juges LLM. Puis sont arrivées les réserves : les juges favorisent la réponse qui apparaît en premier dans un prompt pairwise, notent plus haut les réponses plus longues, préfèrent les sorties de leur propre famille de modèles, et changent quand le prompt ou la version du modèle change. JudgeBench a testé des juges sur des paires de réponses où l’une est objectivement fausse et a trouvé que même de bons juges restent proches d’une précision de pile ou face sur les cas difficiles.

Traitez le juge comme un instrument de mesure.

Quand un juge est nécessaire, rendez le verdict structuré. Schema-Guided Reasoning (SGR) est le pattern par défaut ici : définissez le chemin de raisonnement du juge comme un schéma Pydantic, exécutez-le via Structured Outputs ou constrained decoding, et forcez le modèle à émettre des champs comme evidence, passed_criteria, failed_criteria, failure_mode et score.

Cela ne rend pas magiquement le juge correct. En revanche, cela rend la mesure plus reproductible. Le juge doit suivre les mêmes étapes de rubrique prédéfinies, dans le même ordre de champs, à chaque exécution et sur tout modèle compatible. Un reviewer peut inspecter des champs nommés au lieu de parser un paragraphe. La CI peut faire un diff sur un objet JSON stable. Le calibrage devient plus simple parce que la rubrique n’est plus enterrée dans du texte libre.

Cela change aussi la courbe de coût. Quand la topologie du raisonnement est explicite et la sortie contrainte, des modèles moins chers deviennent souvent suffisants pour la notation de routine. Réservez le juge plus grand aux désaccords, aux cas à haut risque ou aux runs de calibrage au lieu de le payer sur chaque trace.

Boucle de calibrage du juge

Biais Ce qui se passe Mitigation
Position Les prompts pairwise favorisent un slot Inverser l’ordre et moyenner les deux permutations
Verbosité Les réponses plus longues sont mieux notées même si la qualité ne change pas Pénaliser la verbosité non étayée dans la rubrique
Auto-préférence Un juge favorise sa propre famille de modèles Utiliser une autre famille de modèles ou un jury
Sycophancy Le juge crédite des affirmations non vérifiées Exiger des preuves de la trace dans le verdict
Dérive de calibrage Une mise à jour de modèle ou de prompt fait dériver les scores Épingler modèle et prompt du juge ; recalibrer à chaque changement

Checklist d’hygiène par défaut pour les juges :

  1. Préférez un binaire pass/fail quand c’est possible. Les échelles en cinq points invitent à une fausse précision.
  2. Annotez manuellement 30 à 50 trajectoires avant d’écrire la rubrique finale.
  3. Mesurez l’accord juge-humain avec le kappa de Cohen ou simplement TPR/TNR.
  4. Décomposez les critères grossiers. « L’agent a-t-il vérifié l’identité avant l’appel à l’outil de remboursement ? » vaut mieux que « La trajectoire était-elle bonne ? »
  5. Émettez le verdict via un schéma SGR avec preuves, critères échoués, mode d’échec et score.
  6. Utilisez si possible un juge d’une famille de modèles différente de celle du générateur.
  7. Randomisez l’ordre pairwise et moyennez dans les deux sens.
  8. Épinglez le modèle du juge, le prompt, le jeu de données, le schéma et la version de l’application.
  9. Recalibrez après des changements de modèle, prompt, outil, politique ou schéma.

Pour des scores à forts enjeux, utilisez un petit jury plutôt qu’un seul gros juge. PoLL a testé exactement cette configuration : un panel de petits juges issus de familles de modèles disjointes, dont les verdicts sont agrégés en un score unique. Sur six jeux de données, le panel suivait mieux les jugements humains qu’un juge GPT-4 unique, évitait le biais d’auto-préférence qu’un juge solitaire porte envers les sorties de sa propre famille, et coûtait plus de sept fois moins cher. Gardez une revue humaine pour les décisions qui affectent l’argent, l’accès, la sécurité ou la conformité.

Si un juge s’aligne avec les humains à 0,55 de kappa sur votre tâche, ne l’utilisez pas pour bloquer des déploiements. Utilisez-le pour trier des files de revue. S’il se situe près de 0,75 et que le coût d’un échec est modéré, une garde CI devient bien plus défendable.


Les evals online ne sont pas des garde-fous

On les confond souvent parce que les deux produisent des scores. Mais ils se situent à des endroits différents.

Garde-fous versus evals online

Les garde-fous s’exécutent inline. Ils sont rapides, déterministes et visibles par l’utilisateur. Un garde-fou peut bloquer un appel d’outil, expurger des PII, rejeter une prompt injection ou forcer un retry avant que la réponse quitte votre système. Un faux positif est un bug de production.

Les evals offline s’exécutent avant la release. Elles sont reproductibles. Elles mettent sous garde les prompts, modèles, outils, retrievers et politiques contre un jeu de données fixe.

Les evals online s’exécutent après la réponse, généralement sur un trafic échantillonné. Elles peuvent utiliser des juges LLM plus lents parce qu’elles ne sont pas sur le chemin de latence. Leur rôle est de détecter la dérive, trouver de nouveaux clusters d’échec et alimenter le prochain jeu de données offline.

Un mauvais placement fait mal dans les deux cas :

  • Un juge dans le chemin de requête ajoute de la latence et une nouvelle source d’instabilité.
  • Un garde-fou relégué à une notation asynchrone laisse des violations de politique atteindre les utilisateurs.

Pour les systèmes à fort volume, scorez un petit échantillon avec un juge plus fort et un échantillon plus large avec des classifieurs moins chers. Déclenchez des alertes sur les clusters et les bornes de confiance, pas sur une estimation ponctuelle bruitée.


Choix d’outillage

Aucun outil ne couvre à lui seul toute la boucle. La plupart des stacks sérieuses utilisent deux briques : un stockage de traces et un runner CI/eval.

Tool Meilleur usage Intégration CI Hébergement autonome Compromis
DeepEval Evals natives Pytest pour agents et LLM Solide : deepeval test run s’intègre bien en CI La bibliothèque cœur est locale/open source Les appels au juge et les fonctions cloud peuvent ajouter du coût
Inspect AI Évaluations de sécurité, frontier et sandboxées CLI et API Python Entièrement local/open source Ce n’est pas une plateforme de traces de production
Phoenix Tracing OTel/OpenInference plus evals Scripts personnalisés Option self-host solide L’alerting managé vit dans la couche commerciale
Langfuse Stockage de traces, jeux de données, versions de prompts Expériences et gardes personnalisées Option self-host solide Les métriques d’eval sont moins batteries-included que DeepEval
LangSmith Tracing et evals LangChain/LangGraph pytest, Vitest, workflows GitHub Self-host enterprise Closed source ; surveillez les tarifs par siège et volume de traces
Braintrust Boucle produit pilotée par eval et revue de PR Flux managé de régression PR très solide Enterprise/hybride Le volume de spans, les données traitées et le nombre de scores peuvent s’accumuler
Promptfoo Tests de prompts et suites de red team GitHub, GitLab, Jenkins, CircleCI Cœur local/open source Excellent runner pre-release, pas un hub de traces

Les remarques sur les compromis décrivent d’où vient le coût, pas son niveau. Les pages de pricing bougent, et les fournisseurs ne comptent pas la même chose : traces, observations, spans, scores, utilisateurs, rétention ou données traitées. Revérifiez la tarification en direct avant de vous engager.

Raccourcis de décision :

  • Besoin d’un tracing self-host avec portabilité OTel : commencez avec Phoenix ou Langfuse.
  • Besoin d’une garde CI code-first : commencez avec DeepEval.
  • Déjà engagé sur LangGraph : LangSmith est pratique.
  • Besoin d’une revue de régression PR managée : Braintrust est difficile à battre.
  • Les cas sécurité et red team dominent : Promptfoo est l’outil le plus ciblé.
  • Recherche en sécurité ou benchmark contrôlé : Inspect AI est le meilleur choix.

Le choix de l’outil est secondaire. Si les échecs de production ne deviennent pas des cas de test, vous payez surtout du stockage de traces.


Une checklist de déploiement pratique

Avant que l’implémentation devienne sophistiquée, construisez le pipeline de preuves. La première question n’est pas « quelle métrique devons-nous optimiser ? » mais « d’où viendront les exemples ? »

  1. Collectez d’abord les exécutions historiques. Si l’agent existe déjà, récupérez les traces, tickets de support, rapports de bug, sessions avec vote négatif, transcriptions de QA manuelle et notes de dogfooding avant de modifier l’implémentation. Si l’agent n’existe pas encore, logguez chaque prototype et chaque exécution de test manuel dès le premier jour.

  2. Instrumentez la forme de la trace. Capturez les messages, appels d’outils, arguments, sorties d’outils, erreurs, nombres de tokens, latence, coût, feedback utilisateur, version de l’application, version du prompt, version du modèle, version du schéma d’outil et état final de l’environnement. Utilisez les conventions OpenTelemetry GenAI ou des spans de style OpenInference si vous voulez de la portabilité. Utilisez Langfuse, LangSmith, Phoenix ou Braintrust si vous voulez immédiatement une UI de traces et un workflow de jeu de données.

  3. Transformez les vrais échecs en cas de départ. Lisez les traces avant de les résumer avec un modèle. Pour chaque échec utile, stockez l’entrée, l’ID de trace source, l’état attendu, les invariants d’outils attendus, le mode d’échec, la sévérité et une note de reviewer. Langfuse peut relier les éléments du jeu de données aux traces de production ; LangSmith peut créer des jeux de données à partir d’exécutions tracées. Conservez le lien source pour que le cas reste auditable.

  4. S’il n’y a pas d’historique, générez des cas cold-start. Demandez à un LLM de rédiger des tâches à partir des exigences produit, politiques, schémas d’outils, machines à états et macros de support. Générez à la fois des happy paths et des cas « ne devrait pas arriver » : mauvaises permissions, vérifications d’identité manquantes, résultats d’outils obsolètes, dates ambiguës, retries après rate limits, et sorties d’outils qui contredisent la demande utilisateur.

  5. Ne faites pas confiance aux cas synthétiques avant une revue humaine. Les exemples synthétiques sont utiles pour la couverture, pas pour la vérité. Marquez-les avec source: synthetic, exigez qu’un reviewer approuve le résultat attendu, exécutez si possible un chemin de référence connu comme bon, et évitez d’utiliser la même famille de modèles pour générer le cas et juger le résultat.

  6. Construisez un petit jeu de données équilibré. Incluez des succès, des échecs, des refus, des cas limites, des cas à long horizon, des cas sensibles à la politique et des chemins alternatifs valides. Ne faites pas du golden « l’ancienne transcription exacte ». Le golden doit encoder le résultat requis, les invariants autorisés et le mode d’échec.

  7. Ajoutez d’abord des vérifications déterministes. L’ordre requis des outils quand l’ordre relève de la politique, les arguments requis, la validation de schéma, les diffs d’état final, les limites de boucle, les plafonds de tokens et de latence, et les invariants spécifiques à la tâche doivent s’exécuter avant tout juge.

  8. Ajoutez un juge structuré en SGR. Utilisez-le uniquement pour la partie qui demande de l’interprétation. Calibrez-le sur des labels humains. S’il ne sépare pas correctement bons et mauvais exemples sur le jeu de calibrage, corrigez la rubrique avant de le brancher dans la CI.

  9. Câblez la boucle. Exécutez la petite suite offline en CI, exécutez la suite plus large avant release, scorez un trafic de production échantillonné online, puis promouvez les clusters d’échec online récurrents dans le jeu de données offline.

Votre première suite d’eval sera imparfaite pour des raisons banales. Livrez-la quand même. Une suite que vous exécutez chaque jour est plus facile à corriger qu’un design doc parfait qui ne bloque jamais une mauvaise PR.


Points clés à retenir

  1. Les evals d’agents sont des evals de traces. La réponse finale n’est qu’un nœud de l’exécution.
  2. Le choix d’outil, l’exactitude des arguments, la détection de boucles, la réalisation de tâche et la fidélité multi-tour doivent appartenir à des métriques séparées.
  3. Le flywheel de production est : trace -> label -> cluster -> déduplication -> jeu de données -> garde CI -> score online.
  4. Commencez par le déterministe. Les vérifications d’outils, d’arguments, d’état et les détecteurs de boucle sont moins chers et plus stables que les juges.
  5. Les juges LLM ont besoin de structure et de calibrage. Utilisez SGR pour des verdicts reproductibles et inspectables, puis épinglez le modèle du juge, le prompt, le schéma, la version du jeu de données, la version de l’application et l’échantillon de labels humains.
  6. Les evals offline gardent les cas connus avant la release. Les evals online exploitent des traces de production échantillonnées après la réponse. Les garde-fous bloquent les comportements non sûrs inline.
  7. La plupart des équipes ont besoin d’un stockage de traces et d’un runner CI. Choisissez des outils simples qui transforment rapidement les échecs de production en tests de régression.

Références