AI Cert Prep
Saisissez un mot-clé pour rechercher dans la documentation.

Domaines

D8 · Eval, Testing and Debugging

Identifier les erreurs de la couche d’intégration vs de la sortie du modèle, récupération, analyse de traces, journalisation des request ID, reproductibilité, bases de l’éval, tests de régression en CI et métriques par segment.

Ce domaine représente environ 1 item sur 53, mais il relie les autres entre eux. Il vérifie que vous savez distinguer une défaillance de la couche d’intégration d’une défaillance de la sortie du modèle, reproduire et tracer les problèmes, et évaluer la qualité sans vous tromper vous-même. Le thème : mesurez par segment, reproduisez de manière déterministe, et jugez la sortie dans une session séparée.

Objectifs d’apprentissage

À la fin de cette page, vous devriez être capable de :

  1. Distinguer les erreurs de la couche d’intégration de celles de la sortie du modèle et choisir la récupération.
  2. Faire de l’analyse de traces et journaliser les request ID.
  3. Reproduire les problèmes avec un modèle épinglé et temperature: 0 là où c’est approprié.
  4. Appliquer les bases de l’éval : jeu de référence, rubrique, LLM-as-judge dans une session séparée.
  5. Ajouter des tests de régression en CI et utiliser des métriques par segment.

8.1 Integration-layer vs model-output errors

La première question dans tout incident : quelle couche a échoué ? Les erreurs de la couche d’intégration vivent dans la tuyauterie (auth, transport, forme de requête, limites de débit, parsing). Les erreurs de sortie du modèle vivent dans ce que Claude a produit (hallucination, dérive de format, refus, troncature). Les retries et timeouts corrigent les premières ; les changements de prompt/contexte/éval corrigent les secondes. Appliquer le mauvais correctif à la mauvaise couche est le distracteur classique.

Error taxonomy

LayerErrorDiagnostic signalRecovery
IntégrationAuth401 authentication / 403 permissionVérifier la clé d’API, l’org, les scopes ; ne pas réessayer aveuglément
IntégrationSchéma / mauvaise requête400 invalid_request (p. ex. tool_choice:"any" sur Fable 5.1)Corriger la forme de requête ; utiliser auto + strict:true / sorties structurées
IntégrationTimeoutTimeout client, aucune réponseRégler des timeouts sains ; réessayer avec backoff ; envisager le streaming
IntégrationLimite de débit429 rate_limit, en-tête retry-afterBackoff exponentiel + jitter ; respecter retry-after ; batch/file
IntégrationParsingErreur de décodage JSON sur le corps de réponseValider/réparer ; demander des sorties structurées ; validation-retry
Sortie du modèleHallucinationAffirmation fluide sans ancrage dans les entréesAncrage, citations, RAG, validation ; vérifier les affirmations
Sortie du modèleDérive de formatSortie presque valide mais hors schémaSchéma d’outil strict:true / sorties structurées ; validation-retry
Sortie du modèleRefusstop_reason: "refusal"Reformuler une requête légitime ; ajuster le prompt système ; escalader
Sortie du modèleTroncaturestop_reason: "max_tokens"Augmenter max_tokens ; découper la tâche ; streamer et continuer

Signal d’examen

Demandez d’abord quelle couche. Un 429, un timeout, ou une erreur de décodage JSON relève de l’intégration — corrigez avec backoff, timeouts, ou changements de requête/schéma. Une hallucination, une sortie hors schéma, ou un refus relève de la sortie du modèle — corrigez avec des changements de prompt/contexte/modèle et de la validation. Le stop_reason et le code de statut HTTP vous disent quelle couche.


8.2 Trace analysis walkthrough

Journalisez le request-id et un ID de corrélation pour chaque appel, plus model, stop_reason, usage et la latence. Pour les agents, journalisez la séquence d’outils. Les traces vous permettent de localiser où une exécution multi-étapes a mal tourné et donnent au support Anthropic une prise.

python
resp = client.messages.create(model=MODEL, max_tokens=512, messages=msgs)
log.info("claude_call", extra={
"request_id": resp._request_id, "model": resp.model,
"stop_reason": resp.stop_reason, "in": resp.usage.input_tokens,
"out": resp.usage.output_tokens})

Lire une trace d’un agent bloqué :

text
corr_id=abc-123
step 1 request_id=req_01A stop_reason=tool_use tools=[search_orders] in=1,240 out=180
step 2 request_id=req_01B stop_reason=tool_use tools=[get_order(id=9981)] in=1,910 out=95
step 3 request_id=req_01C stop_reason=tool_use tools=[get_order(id=9981)] in=2,600 out=95 ← repeat
step 4 request_id=req_01D stop_reason=tool_use tools=[get_order(id=9981)] in=3,290 out=95 ← loop
...
step N request_id=req_01Z stop_reason=max_tokens in=9,900 out=512 ← truncated

Diagnostic : la boucle répète le même appel d’outil et les tokens d’entrée grimpent à chaque tour — le harnais ne renvoie pas le résultat de l’outil, ou la terminaison est pilotée par autre chose que stop_reason. C’est les anti-patterns nº 1/nº 2 (terminaison en langage naturel et plafonds d’itérations) plutôt qu’un défaut du modèle. Le max_tokens à la fin est un symptôme en aval, pas la cause. Corrigez la boucle : après chaque tool_use, ajoutez le résultat de l’outil et continuez jusqu’à ce que stop_reason soit end_turn.


8.3 Reproducibility

Pour reproduire un problème de sortie du modèle, contrôlez chaque variable possible :

  1. Épinglez le snapshot de modèle exact — pas un alias flottant.
  2. Réglez temperature: 0 là où c’est approprié pour minimiser la variance.
  3. Figez le prompt système et les outils et rejouez les mêmes messages dans l’ordre.
python
resp = client.messages.create(
model="claude-sonnet-5", # snapshot épinglé
temperature=0, # minimiser la variance
max_tokens=512,
system=FROZEN_SYSTEM_PROMPT,
tools=FROZEN_TOOLS,
messages=RECORDED_MESSAGES, # rejeu exact
)

Le non-déterminisme signifie que la sortie n’est toujours pas identique octet par octet, mais l’épinglage + temperature: 0 + un prompt figé rendent les problèmes bien plus reproductibles et les comparaisons équitables. Note : les harnais Fable 5.x / Opus 5 / Sonnet 5 doivent être append-only — éditer ou réordonner des tours antérieurs invalide les blocs de thinking ultérieurs, donc rejouez en ajoutant, jamais en réécrivant l’historique.


8.4 Eval basics and an eval harness

ElementWhat it is
Jeu de référenceEntrées curées avec des sorties connues-bonnes
Correspondance exactePour les sorties déterministes (labels, extractions)
RubriqueCritères de notation explicites pour la sortie ouverte
LLM-as-judgeUn modèle/une session différent note la sortie par rapport à la rubrique

Auto-revue en même session

Ne faites jamais noter au modèle sa propre sortie dans la même session — il conserve le biais de raisonnement qui l’a produite (anti-pattern nº 9). Utilisez une session séparée et idéalement un modèle différent comme juge.

Un harnais minimal combinant correspondance exacte et un LLM-as-judge dans un appel séparé :

python
import json
from anthropic import Anthropic
client = Anthropic()
GEN_MODEL = "claude-sonnet-5" # système sous test
JUDGE_MODEL = "claude-opus-5" # modèle différent, appel séparé
def generate(case):
r = client.messages.create(
model=GEN_MODEL, temperature=0, max_tokens=512,
system="Extract the invoice total as JSON: {'total_cents': int}.",
messages=[{"role": "user", "content": case["input"]}],
)
return r.content[0].text
def exact_match(pred, expected):
try:
return json.loads(pred).get("total_cents") == expected["total_cents"]
except json.JSONDecodeError:
return False # un échec de parsing compte comme un raté, jamais passé silencieusement
RUBRIC = (
"Score 1 if the answer is faithful to the source and correctly formatted, "
"else 0. Return JSON: {'score': 0 or 1, 'reason': str}."
)
def llm_judge(case, pred):
# Session/modèle séparé — aucun contexte partagé avec le générateur.
r = client.messages.create(
model=JUDGE_MODEL, temperature=0, max_tokens=256,
system=RUBRIC,
messages=[{"role": "user",
"content": f"SOURCE:\n{case['input']}\n\nANSWER:\n{pred}"}],
)
return json.loads(r.content[0].text)
def run(golden):
results = []
for case in golden:
pred = generate(case)
results.append({
"id": case["id"], "segment": case["segment"],
"exact": exact_match(pred, case["expected"]),
"judge": llm_judge(case, pred)["score"],
})
return results

8.5 Regression tests in CI

Exécutez le jeu de référence en CI à chaque changement de prompt/modèle/config et faites échouer le build en cas de régression. Épinglez le modèle et temperature: 0 pour des comparaisons stables.

yaml
name: eval-regression
on:
pull_request:
paths: ["prompts/**", "src/**", "evals/**"]
jobs:
eval:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install anthropic
- name: Run golden-set eval
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: python evals/run.py --golden evals/golden.jsonl --min-score 0.95
# run.py sort avec un code non nul si le score global OU un score par segment tombe sous le seuil

8.6 Per-segment metrics

Rapportez les métriques par segment (par type de document, par langue, par intention). La précision agrégée masque les défaillances par segment (anti-pattern nº 10) — le piège d’éval le plus courant à l’examen.

SegmentCasesAccuracyVerdict
Overall (aggregate)1 00092 %Semble correct — trompeur
invoices60098 %Sain
receipts30095 %Sain
handwritten10061 %Le vrai problème, caché par l’agrégat

Les 92 % agrégés passent un contrôle naïf, pourtant les formulaires manuscrits échouent 4 fois sur 10. Contrôlez la CI sur le pire segment, pas la moyenne, et décomposez toujours les métriques avant de livrer.


8.7 Choosing the right eval method for the output type

Toutes les sorties ne se notent pas de la même façon. Choisir la mauvaise méthode de notation est un piège d’examen subtil.

Output typeBest scoring methodWhy
Labels / classificationsCorrespondance exacte (accuracy, F1 par classe)Vérité de terrain déterministe
Extraction structuréeCorrespondance au niveau champ par rapport au JSON attenduCrédit partiel et diagnostic par champ
Prose ouverteRubrique + LLM-as-judge (session séparée)Aucune chaîne unique correcte
Qualité comparativePaire A/B (laquelle des deux est meilleure)Humains/juges comparent plus fiablement qu’un score absolu
Récupération/ancrageContrôles de citation/fidélitéAttrape les affirmations non ancrées
python
# Paire A/B : demander à un juge séparé quelle réponse est meilleure, en randomisant l'ordre pour éviter le biais de position.
import random
def pairwise(judge_client, question, ans_a, ans_b):
first, second = ("A", ans_a, "B", ans_b) if random.random() < 0.5 else ("B", ans_b, "A", ans_a)
label1, text1, label2, text2 = first
r = judge_client.messages.create(
model="claude-opus-5", max_tokens=128, temperature=0,
system="Reply with the label of the better answer: 'A' or 'B'. JSON: {'winner': 'A'|'B'}.",
messages=[{"role": "user",
"content": f"Q:{question}\n\n{label1}:\n{text1}\n\n{label2}:\n{text2}"}])
import json
return json.loads("".join(b.text for b in r.content if b.type == "text"))["winner"]

Signal d’examen

« Labels déterministes » → correspondance exacte. « Qualité ouverte » → rubrique + LLM-as-judge dans une session séparée. « Quelle version est meilleure » → paire A/B. « Ancrage » → citation/fidélité. Associez la méthode au type de sortie.


8.8 Debugging decision tree: which layer, which fix

Un flux de triage rapide transforme un vague « c’est cassé » en un correctif ciblé. Le statut HTTP et le stop_reason sont vos deux premiers signaux.

text
Failure observed
│
├─ HTTP 4xx/5xx? ──► INTEGRATION layer
│ ├─ 429 / 500 / 529 ──► transient: backoff + jitter, honour retry-after
│ ├─ 400 invalid_request ──► fix request shape (e.g. forced tool on Fable 5.1)
│ ├─ 401 / 403 ──► auth/permissions: fix key/org/scopes (do NOT retry)
│ └─ timeout / JSON decode ──► timeouts/streaming; schema + validation-retry
│
└─ HTTP 200 but bad answer? ──► MODEL-OUTPUT layer
├─ stop_reason == max_tokens ──► truncation: continue / raise cap / chunk
├─ stop_reason == refusal ──► safety decline: reframe / policy path
├─ off-schema-but-close ──► strict/structured outputs + validation-retry
└─ confident but wrong ──► grounding: docs-first, citations, RAG, claim validation
SymptomLayerWrong fix (distractor)Right fix
429 sous chargeIntégrationRéécrire le promptBackoff + retry-after ; batch/file
400 sur outil forcé (Fable 5.1)IntégrationRéessayer avec backoffauto/sorties structurées
JSON tronqué, max_tokensSortie du modèleFaire tourner la clé d’APIAugmenter le plafond / continuer / découper
Valeur fabriquéeSortie du modèleAugmenter temperatureAncrage + validation des affirmations

Signal d’examen

Lisez d’abord le code de statut et le stop_reason. Un 429/timeout/erreur JSON relève de l’intégration ; une hallucination/hors schéma/refus relève de la sortie du modèle. Appliquer un correctif d’intégration à un problème de sortie du modèle (ou vice-versa) est le distracteur classique.


8.9 Common misconceptions

MisconceptionRealityWhy it matters on the exam
Toute défaillance peut être réessayéeSeules les erreurs d’intégration transitoires (429/5xx/529) sont réessayablesCorrectif de mauvaise couche
Un 400 pourrait être transitoireIl est déterministe ; corrigez la requêteDistingue les couches
La précision agrégée suffitElle masque les défaillances par segment (anti-pattern nº 10)Le principal piège d’éval
L’auto-revue en même session est efficaceLe juge hérite du biais du générateur (anti-pattern nº 9)Piège de conception du juge
temperature: 0 donne des octets reproductiblesIl réduit la variance ; épinglez aussi le snapshotNuance de reproductibilité
Une fin max_tokens est la cause racine d’une boucleC’est un symptôme en aval ; corrigez la gestion de la boucle/stop_reasonPiège de lecture de trace
Une sortie vide signifie « aucun résultat »Ce peut être une erreur supprimée silencieusement (anti-pattern nº 7)Piège d’échec silencieux
La correspondance exacte convient à toute sortieLa sortie ouverte nécessite une rubrique/un juge LLM ; les comparaisons nécessitent une paireSélection de la méthode d’éval

8.10 Scenario walkthrough: an eval that lied

Scénario. Un service de classification de documents rapporte 93 % de précision sur son jeu de référence et passe la CI, pourtant les incidents de production impliquent sans cesse des formulaires manuscrits et des documents non anglophones. L’investigation révèle : (1) la CI ne contrôle que la précision agrégée ; (2) l’éval faisait noter par le modèle générateur ses propres justifications ouvertes dans la même session ; (3) un 400 invalid_request intermittent en production est réessayé avec backoff exponentiel et ne réussit jamais ; et (4) un helper renvoie une liste vide quand un appel lève une exception, ce que l’appelant traite comme « aucune correspondance ». Corrigez l’éval et le débogage.

Trace de raisonnement d’expert.

  1. Cassez l’agrégat. 93 % global cache que les segments manuscrits et non anglophones échouent gravement (anti-pattern nº 10). Rapportez des métriques par segment (par type de document et langue) et contrôlez la CI sur le pire segment, pas la moyenne.
  2. Corrigez le juge. L’auto-notation en même session (anti-pattern nº 9) tamponne le générateur. Passez à un LLM-as-judge dans une session séparée, idéalement un modèle différent, par rapport à une rubrique explicite ; pour les justifications ouvertes, envisagez une paire A/B avec ordre randomisé.
  3. Corrigez le triage du 400. Un 400 invalid_request est une erreur d’intégration/schéma et déterministe — réessayer avec backoff boucle indéfiniment. Lisez l’erreur : probablement un paramètre interdit (p. ex. tool_choice forcé sur Fable 5.1). Corrigez la forme de requête (auto/sorties structurées) ; ne réessayez pas.
  4. Corrigez la suppression silencieuse. Renvoyer une liste vide sur exception (anti-pattern nº 7) rapporte l’échec comme un succès. Propagez l’erreur avec un contexte de diagnostic, ou échouez bruyamment ; ne laissez jamais un vide-comme-succès s’écouler en aval.
  5. Rendez-le reproductible. Épinglez le snapshot de modèle et réglez temperature: 0 pour l’éval ; journalisez request_id, stop_reason, usage et la latence pour que les incidents soient traçables.
  6. Rejetez les alternatives tentantes. « Monter le seuil agrégé à 95 % » — masque toujours les défaillances par segment. « Réessayer le 400 plus agressivement » — erreur déterministe. « Faire confiance au résultat vide comme aucune correspondance » — suppression silencieuse. « Faire re-noter par le même modèle pour économiser » — réintroduit le biais.

Décision correcte. Métriques par segment avec contrôle CI sur le pire segment ; un juge LLM en session séparée/modèle différent (paire A/B pour l’ouvert) ; corriger le 400 à la couche de requête (pas de backoff) ; remonter bruyamment l’erreur supprimée ; snapshot épinglé + temperature: 0 et journaliser les request ID pour la traçabilité.


Pièges de l’examen dans ce domaine

PiègePourquoi c’est faux
Réessayer une erreur de sortie du modèle comme une erreur réseauMauvaise couche ; corrigez le prompt/l’éval, pas le backoff
Traiter une erreur de schéma 400 comme transitoireElle est déterministe ; corrigez la forme de requête, ne réessayez pas
Auto-revue en même sessionAnti-pattern nº 9 ; utilisez une session/un modèle de juge séparé
Ne rapporter que la précision agrégéeAnti-pattern nº 10 ; masque les défaillances par segment
Ne pas journaliser les request IDAucune prise de trace pour le débogage/support
Reproduire avec une température aléatoire et un modèle non épingléNon reproductible ; épinglez snapshot + température 0
Traiter une sortie vide comme un succèsSuppression silencieuse (anti-pattern nº 7)
Aucune suite de régression en CILes changements de prompt/modèle régressent silencieusement
Juger avec le même modèle dans le même contexteBiais ; utilisez une session/un modèle différent
Lire la troncature max_tokens comme la cause racine d’une boucleC’est un symptôme en aval ; corrigez la gestion de la boucle/stop_reason
Monter le seuil agrégé au lieu de contrôler par segmentMasque toujours le segment défaillant ; contrôlez sur le pire segment
Utiliser la correspondance exacte pour une sortie ouverteUtilisez une rubrique + LLM-as-judge (session séparée) ; paire A/B pour les comparaisons
Ne pas lire le code de statut et le stop_reason avant de choisir un correctifIls vous disent la couche ; le correctif de mauvaise couche est le distracteur classique
Ignorer le biais de position dans le jugement par paireRandomisez l’ordre A/B pour que le juge ne soit pas influencé par la position
Traiter un 400 déterministe comme instable et réessayerCorrigez la forme de requête ; le backoff bouclera indéfiniment

Questions d’entraînement

Q1 · Un service échoue par intermittence avec des erreurs de décodage JSON et des 429, et séparément extrait parfois le mauvais total de facture. Comment l’équipe devrait-elle trier ? (Sélectionnez une réponse)

A. Traiter les deux comme des problèmes de modèle et réécrire le prompt. B. Séparer les couches : corriger les 429 avec backoff et les erreurs JSON avec validation-retry (intégration) ; corriger la mauvaise extraction avec du prompt/context engineering et de la validation (sortie du modèle). C. Traiter les deux comme des problèmes réseau et ajouter des retries. D. Augmenter max_tokens pour les deux.

Réponse : B. Les défaillances sont dans des couches différentes et nécessitent des correctifs différents. Les réécritures de prompt généralisées (A) ignorent les erreurs d’intégration ; les retries (C) ne font rien pour la mauvaise extraction ; augmenter max_tokens (D) ne traite ni un 429 ni une mauvaise valeur.

Q2 · Un modèle obtient 91 % global à l’éval, mais un incident de production implique des formulaires manuscrits. Quelle pratique d’éval aurait fait remonter cela, et comment la sortie devrait-elle être jugée ? (Sélectionnez deux réponses)

A. Rapporter des métriques par segment (par type de document) au lieu du seul agrégat. B. Faire noter par la même session sa propre sortie. C. Utiliser un LLM-as-judge dans une session/un modèle séparé par rapport à une rubrique. D. Ne suivre que la précision globale. E. Sauter les évals en CI.

Réponse : A et C. Les métriques par segment exposent l’échec des formulaires manuscrits (anti-pattern nº 10), et un juge en session séparée évite le biais d’auto-revue (anti-pattern nº 9). L’agrégat seul (D), la notation en même session (B) et l’absence de CI (E) sont les anti-patterns.

Q3 · Chaque requête à Claude Fable 5.1 renvoie `400 invalid_request` ; le code règle `tool_choice: {'type':'any'}`. De quelle couche s’agit-il et quel est le correctif ? (Sélectionnez une réponse)

A. Erreur de sortie du modèle ; réécrire le prompt pour être plus clair. B. Erreur d’intégration/schéma ; Fable 5.1 rejette any/{type:tool} forcé, donc utilisez auto avec une instruction, strict:true, ou les sorties structurées. C. Erreur de limite de débit ; ajouter un backoff exponentiel. D. Erreur transitoire ; réessayer avec jitter.

Réponse : B. Un 400 sur un paramètre interdit est une erreur d’intégration/schéma déterministe propre à la restriction de choix d’outil de Fable 5.1 ; le correctif est de changer la requête. Il ne s’agit pas de la qualité du prompt (A) ; ce n’est pas un 429 (C) ; et réessayer un 400 déterministe (D) échouera toujours à nouveau.

Q4 · Une trace montre un agent appelant le même outil avec une entrée identique à chaque étape, avec des tokens d’entrée qui grimpent à chaque tour, se terminant par `stop_reason: max_tokens`. Quelle est la cause racine ? (Sélectionnez une réponse)

A. Le modèle a manqué de tokens de sortie ; augmenter max_tokens. B. Le harnais ne renvoie pas le résultat de l’outil et/ou la terminaison n’est pas pilotée par stop_reason ; corrigez la boucle pour ajouter les résultats et s’arrêter sur end_turn. C. Limitation de débit ; ajouter un backoff. D. Une hallucination ; ajouter des citations.

Réponse : B. Répéter le même appel avec un contexte croissant est un défaut de contrôle de boucle (anti-patterns nº 1/nº 2). Le max_tokens final est un symptôme en aval, pas la cause (A). Ce n’est pas un problème de transport (C) ni d’ancrage (D).

Q5 · Une réponse revient avec `stop_reason: 'max_tokens'` et le JSON est coupé au milieu d’un objet. Quelle couche, et quelles sont DEUX récupérations valides ? (Sélectionnez deux réponses)

A. Troncature de sortie du modèle ; augmenter max_tokens pour l’appel. B. Découper la tâche ou streamer et continuer la génération. C. C’est une erreur d’auth ; faire tourner la clé d’API. D. Renvoyer silencieusement le JSON partiel comme un succès. E. Réessayer inchangé avec backoff.

Réponse : A et B. max_tokens signifie que la sortie a été tronquée ; augmenter la limite ou découper/streamer le travail la récupère. Ce n’est pas de l’auth (C) ; renvoyer une sortie partielle comme un succès est une suppression silencieuse, anti-pattern nº 7 (D) ; réessayer inchangé (E) tronque à nouveau.

Q6 · Pour reproduire de manière fiable un bug de sortie du modèle, quelle combinaison l’équipe devrait-elle utiliser ? (Sélectionnez une réponse)

A. Le dernier alias de modèle flottant, température 1, prompt paraphrasé. B. Snapshot de modèle épinglé, temperature: 0, prompt système et outils figés, rejeu exact des messages. C. N’importe quel modèle, tant que le prompt est similaire. D. Un modèle différent à chaque exécution pour lisser le bruit.

Réponse : B. Contrôler le snapshot de modèle, la température, le prompt, les outils, et l’historique des messages maximise la répétabilité. Les alias flottants et une température non nulle (A), les prompts lâches (C), et varier le modèle (D) injectent tous de la variance qui défait la reproduction.

Q7 · Un pipeline d’éval fait noter par le modèle générateur ses propres réponses dans la même conversation. Qu’est-ce qui ne va pas, et quel est le correctif ? (Sélectionnez une réponse)

A. Rien ; l’auto-notation est efficace. B. L’auto-revue en même session conserve le biais de raisonnement qui a produit la réponse ; exécutez un LLM-as-judge dans une session séparée, idéalement un modèle différent. C. Utiliser la correspondance exacte pour tout à la place. D. Ne noter que l’agrégat.

Réponse : B. L’auto-revue en même session (anti-pattern nº 9) est biaisée car le juge partage le contexte du générateur. Un juge en session séparée, modèle différent supprime ce biais. La correspondance exacte (C) ne convient pas à une sortie ouverte ; la notation agrégée seule (D) est un anti-pattern différent.

Q8 · Quels artefacts devraient être journalisés pour chaque appel à Claude afin de permettre l’analyse de traces ? (Sélectionnez deux réponses)

A. request_id et un ID de corrélation. B. Le mot de passe de l’utilisateur. C. model, stop_reason, les tokens usage, la latence, et (pour les agents) la séquence d’outils. D. Rien, pour économiser le stockage. E. Seulement le texte de la réponse finale.

Réponse : A et C. Les IDs de requête/corrélation plus le modèle, le stop reason, l’usage de tokens, la latence, et la séquence d’outils donnent une prise de trace complète pour le débogage et le support. Journaliser des secrets (B) est une violation de sécurité ; ne rien journaliser (D) ou seulement la réponse (E) vous rend aveugle pendant les incidents.

Q9 · Un job CI exécute le jeu de référence mais ne fait échouer le build que si la précision agrégée baisse. Une régression par segment sur les « documents juridiques » part en production. Que devrait faire la CI à la place ? (Sélectionnez une réponse)

A. Continuer à contrôler sur l’agrégat ; c’est plus simple. B. Contrôler sur le pire segment ainsi que sur l’agrégat, en échouant si un segment tombe sous son seuil. C. Retirer l’éval de la CI. D. N’exécuter les évals que mensuellement.

Réponse : B. Contrôler sur des seuils par segment attrape les défaillances qu’un agrégat cache (anti-pattern nº 10). Le contrôle agrégat-seulement (A) est exactement ce qui a laissé passer la régression ; retirer (C) ou ralentir (D) les évals empire la situation.

Q10 · Une fonction renvoie une liste vide quand l’appel à Claude lève une exception, et l’appelant traite le vide comme « aucun résultat trouvé ». De quel anti-pattern s’agit-il et comment est-il corrigé ? (Sélectionnez une réponse)

A. Métriques agrégées ; ajouter un rapport par segment. B. Suppression silencieuse des erreurs (anti-pattern nº 7) ; remonter l’erreur avec un contexte de diagnostic au lieu de renvoyer un vide-comme-succès. C. Auto-revue en même session ; utiliser un juge séparé. D. Plafond d’itérations ; piloter depuis stop_reason.

Réponse : B. Renvoyer un vide sur échec masque les erreurs et rapporte l’échec comme un succès — suppression silencieuse (anti-pattern nº 7). Le correctif est de propager l’erreur avec du contexte. Les autres options nomment des anti-patterns sans rapport.

Q11 · La sortie est presque du JSON valide mais émet occasionnellement un champ supplémentaire en fin, absent du schéma. Quelle couche, et quel est le correctif le plus robuste ? (Sélectionnez une réponse)

A. Timeout d’intégration ; ajouter des retries. B. Dérive de format de sortie du modèle ; imposer le schéma avec strict: true sur l’outil ou les sorties structurées, plus une validation-retry. C. Limite de débit ; ajouter un backoff. D. Erreur d’auth ; faire tourner la clé.

Réponse : B. Une sortie hors schéma-mais-proche est une dérive de format, un problème de sortie du modèle ; strict:true/les sorties structurées plus la validation-retry imposent le schéma. Ce n’est pas un timeout (A), une limite de débit (C), ou un problème d’auth (D).

Q12 · Une équipe veut empêcher les changements de prompt et de modèle de dégrader silencieusement la qualité. Quelle pratique est essentielle ? (Sélectionnez une réponse)

A. Des vérifications ponctuelles manuelles quand quelqu’un s’en souvient. B. Une suite de régression sur un jeu de référence exécutée automatiquement en CI à chaque changement de prompt/modèle/config, avec des seuils par segment qui font échouer le build. C. Faire confiance à la confiance auto-déclarée du modèle. D. Ne mesurer que la latence.

Réponse : B. La régression CI automatisée sur un jeu de référence avec contrôle par segment est la discipline qui attrape les chutes de qualité silencieuses. Les vérifications manuelles ad hoc (A) ne sont pas fiables ; la confiance auto-déclarée (C) est un anti-pattern ; la latence (D) ne mesure pas la qualité.

Q13 · Une éval note des justifications ouvertes. Quelle méthode de notation est appropriée, et laquelle ne l’est pas ? (Sélectionnez une réponse)

A. Correspondance exacte de chaîne par rapport à une réponse de référence unique. B. Une rubrique avec un LLM-as-judge dans une session séparée (et une paire A/B pour les comparaisons), pas la correspondance exacte. C. La précision agrégée uniquement. D. Le générateur se notant lui-même pour la vitesse.

Réponse : B. La sortie ouverte n’a pas de chaîne unique correcte, donc utilisez une rubrique + un juge en session séparée, avec une paire A/B pour les comparaisons. La correspondance exacte (A) convient aux labels déterministes, pas à la prose ; l’agrégat seul (C) masque les segments ; l’auto-notation (D) est l’anti-pattern nº 9.

Q14 · Un appel de production renvoie par intermittence `400 invalid_request` et est réessayé avec backoff exponentiel, sans jamais réussir. Quel est le triage correct ? (Sélectionnez une réponse)

A. Ajouter plus de retries avec un backoff plus long. B. Reconnaître qu’un 400 est une erreur d’intégration/schéma déterministe (p. ex. un paramètre interdit comme tool_choice forcé sur Fable 5.1) ; corriger la forme de requête plutôt que de réessayer. C. Le traiter comme une hallucination du modèle et réécrire le prompt. D. Faire tourner la clé d’API.

Réponse : B. Un 400 ne réussira jamais au retry ; lisez-le et corrigez la requête. Plus de backoff (A) boucle indéfiniment ; ce n’est pas un problème de sortie du modèle (C) ; la rotation d’auth (D) traite les 401/403, pas un 400.

Q15 · Une trace montre un agent répétant le même appel d’outil avec des tokens d’entrée croissants, se terminant par `stop_reason: max_tokens`. Quelle est la cause racine ? (Sélectionnez une réponse)

A. Le modèle a manqué de tokens de sortie ; augmenter max_tokens. B. Un défaut de contrôle de boucle : le harnais ne renvoie pas le résultat de l’outil et/ou la terminaison n’est pas pilotée par stop_reason ; corrigez la boucle. Le max_tokens final est un symptôme en aval. C. Limitation de débit ; ajouter un backoff. D. Une hallucination ; ajouter des citations.

Réponse : B. Répéter le même appel avec un contexte croissant est un problème de contrôle de boucle (anti-patterns nº 1/nº 2) ; la fin max_tokens est un symptôme, pas la cause (A). Ce n’est pas du transport (C) ni de l’ancrage (D).

Q16 · Une éval CI ne contrôle que sur la précision agrégée (93 %), et une régression sur les formulaires manuscrits part. Quels DEUX changements corrigent le processus d’éval ? (Sélectionnez deux réponses)

A. Rapporter et contrôler sur des métriques par segment (par type de document), en échouant si un segment tombe sous son seuil. B. Utiliser un LLM-as-judge dans une session/un modèle séparé par rapport à une rubrique pour les parties ouvertes. C. Monter le seuil agrégé à 96 %. D. Faire noter par la même session sa propre sortie. E. N’exécuter les évals que mensuellement.

Réponse : A et B. Le contrôle par segment fait remonter l’échec caché (anti-pattern nº 10) et un juge en session séparée évite le biais d’auto-revue (anti-pattern nº 9). Un agrégat plus élevé (C) masque toujours les segments ; l’auto-notation (D) est le nº 9 ; les évals mensuelles (E) ralentissent la détection.

Q17 · Un helper renvoie une liste vide quand l’appel à Claude lève une exception, et l’appelant traite le vide comme « aucune correspondance ». De quel anti-pattern s’agit-il et quel est le correctif ? (Sélectionnez une réponse)

A. Métriques agrégées ; ajouter un rapport par segment. B. Suppression silencieuse des erreurs (anti-pattern nº 7) ; propager l’erreur avec un contexte de diagnostic au lieu de renvoyer un vide-comme-succès. C. Auto-revue en même session ; utiliser un juge séparé. D. Plafond d’itérations ; piloter depuis stop_reason.

Réponse : B. Renvoyer un vide sur échec rapporte l’échec comme un succès — suppression silencieuse (anti-pattern nº 7). Remontez l’erreur avec du contexte. Les autres nomment des anti-patterns sans rapport.

Q18 · En comparant deux versions de prompt avec un juge LLM, les résultats s’inversent selon la réponse affichée en premier. Quel est le problème et le correctif ? (Sélectionnez une réponse)

A. Le modèle juge est cassé ; changer de modèle. B. Biais de position dans le jugement par paire ; randomisez l’ordre A/B (et éventuellement moyennez les deux ordres) pour que la position ne décide pas du gagnant. C. La température est trop basse ; l’augmenter. D. Utiliser la correspondance exacte à la place.

Réponse : B. Les juges par paire peuvent être influencés par la position de la réponse ; randomiser l’ordre (ou noter les deux ordres) supprime le biais. Ce n’est pas un modèle cassé (A) ; la température (C) n’est pas la cause ; la correspondance exacte (D) ne convient pas à une comparaison ouverte.

À retenir

  • Triez par couche : les erreurs d’intégration (429/5xx/timeouts/JSON/rôles) reçoivent des retries et des correctifs de requête ; les erreurs de sortie du modèle reçoivent des changements de prompt/contexte/modèle et de la validation.
  • Journalisez les request ID, le modèle, stop_reason, usage et la latence pour l’analyse de traces.
  • Reproduisez avec un snapshot épinglé et temperature: 0, en acceptant le non-déterminisme résiduel.
  • Évaluez avec un jeu de référence et une rubrique ; utilisez le LLM-as-judge dans une session séparée (jamais d’auto-revue en même session).
  • Exécutez des tests de régression en CI et rapportez des métriques par segment – les agrégats cachent les défaillances qui comptent.
  • Associez la méthode d’éval à la sortie : correspondance exacte pour les labels, correspondance au niveau champ pour l’extraction, rubrique + juge LLM en session séparée pour la prose, paire A/B (avec ordre randomisé) pour les comparaisons.
  • Triez avec le code de statut et le stop_reason d’abord : 429/timeout/JSON = intégration ; hallucination/hors schéma/refus = sortie du modèle — le correctif de mauvaise couche est le distracteur classique.
  • Contrôlez la CI sur le pire segment, pas l’agrégat ; monter le seuil agrégé masque toujours un segment défaillant.
  • Un 400 déterministe ne réussit jamais au retry — corrigez la forme de requête (p. ex. le choix d’outil forcé sur Fable 5.1) plutôt que d’ajouter un backoff.

Dernière mise à jour le 18 sept. 2026