Lección 8 — Décider et automatiser

Construire ou adopter

8 min de lectura

Este contenido aún no está traducido. Se muestra la versión original.

Construire ou adopter

Vous avez maintenant 1 100 lignes de Python à maintenir. Un architecte qui reprend le projet demandera, à juste titre, pourquoi ne pas avoir pris promptfoo ou Inspect. La réponse « on voulait comprendre » vaut pour une formation, pas pour un dépôt de production. Cette leçon tranche : ce que les outils existants font mieux, ce qu'ils ne font pas, et quand le code de ce projet doit céder la place.

Le mécanisme : les cinq fonctions d'un harness

Tout outil d'évaluation assemble les mêmes briques. La décision se prend brique par brique, pas en bloc.

flowchart LR
  D["1. jeu de données versionné"] --> X["2. exécution, cache, budget"]
  X --> S["3. scorers, juge calibré"]
  S --> C["4. comparaison statistique"]
  C --> G["5. porte en CI, rapport"]
  PF["promptfoo"] -.-> X & S & G
  IN["Inspect"] -.-> X & S
  ADK["ADK eval"] -.-> S
  ML["MLflow genai.evaluate"] -.-> S & D
  DE["DeepEval"] -.-> S & G

La mise en œuvre : six outils, lus sur leur documentation

Constats établis sur la documentation de chaque outil consultée le 2026-10-16 ; les versions évoluent vite, vérifiez avant de choisir.

OutilCe qu'il fait mieux que ce projetCe qu'il ne fait pas iciChoisissez-le si
promptfooconfiguration YAML de matrices prompt × modèle, vue comparative interactive, assertions prêtes (equals, regex, is-json, similar, llm-rubric, g-eval), Action GitHub, tests d'attaque (red team)outil Node.js ; pas d'intervalle de confiance apparié ni de non-infériorité ; la calibration d'un juge contre des annotations est à faire soi-mêmevotre besoin est surtout « comparer des prompts et des modèles côte à côte », avec une équipe à l'aise en YAML
Inspect (UK AISI)Task = jeu + solver + scorer, agents et outils, bac à sable Docker ou Kubernetes pour le code non fiable, visionneuse de journaux, plus de 200 évaluations prêtes ; les scorers rapportent moyenne et erreur standardpas de porte de qualité ni de comparaison A/B appariée prêtes à l'emploivous évaluez des agents qui exécutent du code, ou vous voulez des benchmarks reproductibles
OpenAI Evalsregistre historique d'évaluations, et désormais configuration directe dans le tableau de bord OpenAIcentré sur les modèles OpenAI ; le dépôt renvoie vers le service hébergévotre application tourne sur OpenAI et vous acceptez un service hébergé
DeepEvalmétriques prêtes (G-Eval, pertinence, fidélité au contexte, hallucination), cas de test au format pytest (deepeval test run), plateforme Confident AI en optionmétriques surtout fondées sur un LLM-juge, sans calibration contre vos annotations ; pas de statistique de comparaisonvotre équipe pense en tests pytest et veut des métriques RAG prêtes
ADK evalnatif pour un agent ADK : adk eval, intégration pytest, interface web ; critères tool_trajectory_avg_score, response_match_score (ROUGE-1), final_response_match_v2, hallucinations_v1, safety_v1trajectoire en correspondance exacte par défaut ; limité aux agents ADKvotre agent est construit avec ADK : commencez par là
MLflow genai.evaluatejuges intégrés (Correctness, Guidelines…) et @scorer maison, suivi des exécutions, jeux d'évaluation et traces dans un serveur MLflowpas de porte ni d'IC apparié ; demande un serveur de suivivous avez déjà MLflow pour le ML classique et voulez un seul endroit pour tout

Deux briques de ce projet n'apparaissent prêtes à l'emploi dans aucun des six : la comparaison appariée avec IC bootstrap et non-infériorité (leçon 3.1), et la calibration du juge par kappa qui conditionne son pouvoir de blocage (leçon 2.3). Les deux tiennent en moins de 150 lignes (stats.py, compare.py) et se greffent sur n'importe quel outil qui exporte des scores par cas.

Le chemin de migration recommandé

Le format pivot de ce projet est results.jsonl : un cas par ligne, un score par métrique. Tout outil qui exporte ses résultats par cas peut alimenter evalh compare. Pour un agent ADK, par exemple, écrivez un adaptateur qui convertit le résultat de adk eval en results.jsonl + summary.json, et gardez la porte de ce projet. Vous adoptez l'outil pour l'exécution et les scorers, vous gardez la décision.

adaptateur (esquisse)
rows = [{"id": c["eval_id"], "status": "ok", "output": {}, "tags": [],
         "scores": {m: {"value": float(v >= seuil), "detail": ""} for m, v in c["metriques"].items()}}
        for c in cas_exportes]

Votre équipe construit un agent avec ADK et doit choisir un outil d'évaluation. Elle veut une porte en CI qui bloque une baisse de qualité des trajectoires. Quelle architecture recommandez-vous ?

Ce qui casse en production

  • Adopter un outil pour sa vue, pas pour sa décision. Une matrice colorée de 30 cas × 2 modèles donne l'impression de comparer. Sans IC apparié, l'équipe tranche sur des moyennes, ce que la leçon 3.1 a montré trompeur deux jours de suite.
  • Métriques prêtes jamais calibrées. « Faithfulness 0,87 » sorti d'une bibliothèque est un LLM-juge comme un autre : même biais, même besoin de kappa sur vos annotations.
  • Plateforme hébergée et données. Envoyer des tickets clients à un service d'évaluation tiers, c'est un sous-traitant de plus au sens du RGPD. Vérifiez où partent les jeux de données et les sorties avant de brancher la CI.
  • Harness maison abandonné. Le risque inverse : 1 100 lignes que personne ne maintient. Ce code est volontairement petit et sans dépendance lourde (numpy, jsonschema, pyyaml) ; s'il dépasse 3 000 lignes, c'est que vous réécrivez un des outils ci-dessus.

Une équipe adopte une bibliothèque de métriques prêtes. Sa métrique « hallucination » vaut 0,12 sur le modèle actuel, et l'équipe veut bloquer toute PR au-dessus de 0,15. Que faites-vous avant d'activer ce seuil ?

La règle de décision

Construisez quand votre décision dépend d'une statistique que les outils ne donnent pas, ou quand l'évaluation doit vivre dans votre dépôt sans service tiers. Adoptez quand la valeur est dans l'exécution : agents ADK (ADK eval), code non fiable en bac à sable (Inspect), matrices de prompts (promptfoo), suivi centralisé (MLflow). Dans les deux cas, gardez trois choses sous votre contrôle : le jeu de données versionné, la calibration du juge et la règle de la porte. Surveillez le temps passé à maintenir le harness : au-delà d'une journée par mois, réévaluez ce choix.

Pratique

Exercice. Votre entreprise utilise déjà MLflow. Le responsable de la plateforme propose de remplacer evalh par mlflow.genai.evaluate. Listez ce que vous gagnez, ce que vous perdez, et ce que vous gardez de ce projet.

Voir la solution

Gains : suivi centralisé des exécutions et des traces, juges intégrés, interface partagée avec les équipes de data science, pas de code d'exécution à maintenir.

Pertes : le cache disque par clé de contenu (à vérifier dans la version utilisée), le budget en USD par exécution, la porte de non-infériorité, la calibration qui neutralise un juge non fiable.

À garder : stats.py et compare.py appliqués aux résultats par cas exportés depuis MLflow (un adaptateur vers results.jsonl), le jeu de données et son manifeste dans Git, calibration_juge.jsonl et la commande calibrate, appliquée au juge MLflow choisi. Le workflow de CI change d'étapes d'exécution, pas d'étape de porte.

  • Je décompose un outil d'évaluation en cinq briques et je choisis brique par brique.
  • Je sais ce que promptfoo, Inspect, OpenAI Evals, DeepEval, ADK eval et MLflow font mieux que ce projet.
  • Je garde le jeu de données, la calibration et la règle de porte sous mon contrôle, quel que soit l'outil.
  • J'écris un adaptateur vers results.jsonl pour réutiliser la comparaison appariée.