Domaines
D3 · Prompt Engineering and Structured Output
Le prompt comme conception de système, critères de réussite et barèmes, frontières XML, few-shot et thinking, prefilling, routes de sortie structurée (output_config.format vs tool-use-comme-schéma vs strict tools), conception de schémas, reprise sur validation, parsing défensif, pipelines d’extraction, et gestion des stop reasons.
Ce domaine vaut environ 12 des 60 items et correspond aux scénarios Structured Data Extraction et CI/CD. Il traite un prompt comme une conception de système, non une astuce textuelle : structure stable pour le caching, critères de réussite explicites, frontières de contenu claires et — surtout — obtenir du modèle une sortie fiable lisible par machine et la valider. La décision la plus testée est quelle route de sortie structurée utiliser, y compris la restriction de Fable 5.1 qui interdit le forçage du tool choice.
Objectifs d’apprentissage
À la fin de cette page, vous devriez savoir :
- Traiter un prompt comme un système versionné et modulaire avec un préfixe stable cachable et une séparation des rôles system/user.
- Écrire des critères de réussite et barèmes explicites et utiliser des balises XML comme frontières de contenu.
- Sélectionner de bons exemples few-shot et choisir entre chaîne de pensée et extended thinking.
- Utiliser le prefilling pour orienter la forme de la sortie.
- Choisir la bonne route de sortie structurée — schéma JSON
output_config.format, tool-use-comme-schéma, ou strict tools — y compris la règle Fable 5.1 de non-forçage du tool choice. - Concevoir des schémas (enums, required, nullable, descriptions) et bâtir une boucle de reprise sur validation avec retour d’erreur et parsing défensif.
- Construire des pipelines d’extraction pour des documents hétérogènes avec des métriques par type (anti-pattern 10) et gérer les stop reasons
refusaletmax_tokens. - Concevoir des prompts evaluator-optimizer et éviter l’auto-revue dans la même session (anti-pattern 9).
3.1 Le prompt comme conception de système
Un prompt de production est un artefact d’ingénierie dont les parties changent à des rythmes différents. Ordonnez-les pour que le contenu stable soit placé en premier et puisse être mis en cache.
[ system role ] stable: role, rules, output contract, tools ← cache_control here +[ user role ] variable: the specific task, the document, the question- Rôles system vs user. Placez les instructions durables, le contrat de sortie et les contraintes dans le prompt
system; placez la tâche spécifique et les données dans les toursuser. - Préfixe stable pour le caching. Les lectures de cache coûtent ~0,1× l’entrée de base ; placez le system prompt, les définitions d’outils et tout long document de référence en premier et marquez le dernier bloc stable avec
cache_control: {"type": "ephemeral"}. Préfixe cachable minimum ~1024 tokens (2048 sur Haiku). - Assemblage modulaire et versionnage. Construisez les prompts à partir de blocs composables (rôle, règles, schéma, exemples) et versionnez-les pour pouvoir évaluer et revenir en arrière. Traitez les changements de prompt comme des changements de code.
system = [ {"type": "text", "text": ROLE_AND_RULES}, # stable {"type": "text", "text": OUTPUT_CONTRACT}, # stable {"type": "text", "text": REFERENCE_DOC, "cache_control": {"type": "ephemeral"}}, # stable, cache boundary]messages = [{"role": "user", "content": task_specific_input}] # variableFable 5.1 est append-only
Sur Fable 5.1 vous ne devez pas éditer, réordonner ni supprimer les tours antérieurs (cela invalide les thinking blocks ultérieurs). Figez system et tools, placez les changements en cours de session dans des messages role: "system", et réduisez côté serveur via l’édition de contexte/la compaction. Concevez le préfixe stable une fois et n’y touchez plus. (Sonnet 5 n’autorise pas les messages system en cours de conversation.)
3.2 Critères de réussite et barèmes explicites
Des instructions vagues produisent une sortie vague. Énoncez à quoi ressemble le bon résultat — des critères mesurables et, pour les tâches jugées, un barème.
| Faible | Fort |
|---|---|
| « Résumez bien ceci. » | « Résumez en ≤150 mots, ouvrez par la décision, listez exactement 3 risques, citez la source de chaque chiffre. » |
| « Vérifiez le code. » | « Signalez chaque fonction dépourvue de validation d’entrée sous la forme {file, line, severity} ; severity ∈ high/medium/low. » |
Les barèmes pilotent aussi les boucles evaluator-optimizer (§3.10) et les evals : l’évaluateur note contre les mêmes critères explicites donnés au générateur.
3.3 Les balises XML comme frontières de contenu
Claude est entraîné à respecter les balises de style XML. Utilisez-les pour séparer les instructions des données et délimiter les régions de sortie — cela réduit le risque d’injection et rend le parsing déterministe.
<instructions>Extract the invoice total. Return only the value.</instructions><document>{ untrusted document text here }</document>Envelopper le contenu non fiable dans une balise clairement nommée améliore à la fois la précision et signale au modèle que le texte enclos est des données, non des instructions — une première ligne de défense contre l’injection de prompt indirecte.
3.4 Sélection des exemples few-shot
Les exemples few-shot enseignent le format et la gestion des cas limites. Sélectionnez-les délibérément :
- Représentatifs de la distribution réelle, y compris les cas difficiles/limites qui vous importent.
- Cohérents dans le format — le modèle imite la forme, donc toute incohérence se propage.
- Assez divers pour couvrir les classes, mais pas au point de gonfler le contexte (et le coût).
- Corrects — un mauvais exemple est pire qu’aucun.
Pour l’extraction, un exemple par type de document bat généralement dix exemples d’un seul type.
3.5 Chaîne de pensée vs extended thinking
| Technique | Ce dont il s’agit | À utiliser quand |
|---|---|---|
| Chaîne de pensée (par prompt) | Demander au modèle de raisonner pas à pas dans la sortie | Vous voulez un raisonnement visible à inspecter ou quand le thinking est désactivé |
| Extended thinking | Le modèle raisonne dans des thinking blocks dédiés avant de répondre (thinking: {"type": "adaptive"}) | Raisonnement difficile, problèmes multi-étapes, planification agentique |
Sur les modèles actuels le thinking est adaptive ; budget_tokens est retiré sur Fable 5.x / Opus 5 / Sonnet 5 (erreur 400) et seul Haiku 4.5 utilise encore budget_tokens. Les niveaux d’effort sont low | medium | high (default) | xhigh — utilisez xhigh pour le travail de codage/agentique le plus difficile sur Opus 5 / Fable 5.1. Sur Fable 5.1 le thinking est toujours actif.
Thinking blocks et repli
Les thinking blocks ne sont lisibles que par le modèle qui les produit ou un plus récent. Si vous repliez de Fable 5.1 vers un modèle plus ancien, les thinking blocks antérieurs sont silencieusement écartés — concevez pour cela dans la discussion sur le repli du Domaine 5.
3.6 Prefilling
Préremplissez le début du tour assistant pour contraindre la forme de la sortie — forcer du JSON, sauter le préambule, ou verrouiller un format.
messages = [ {"role": "user", "content": "Return the extracted fields."}, {"role": "assistant", "content": "{"}, # prefill: forces the model to continue JSON]Le prefilling est une orientation légère, non une garantie. Pour des garanties fortes utilisez les structured outputs ou les strict tools (ci-après). Note : le prefilling s’articule mal avec l’extended thinking sur les modèles où le thinking doit venir en premier — préférez-y les structured outputs.
3.7 Sortie structurée : les trois routes
C’est la table de décision à plus forte valeur du domaine.
| Route | Comment | Garantie | Idéal pour | Réserves |
|---|---|---|---|---|
output_config.format (structured outputs) | Passer un schéma JSON dans output_config.format | La sortie du modèle se conforme au schéma | Vous voulez un objet de réponse typé, sans sémantique d’outil | Capacité plus récente ; vérifiez le support du modèle |
| Tool-use-comme-schéma | Définir un outil dont l’input_schema est votre forme cible ; lire l’entrée de l’appel d’outil | Forte combinée à strict: true | Vous utilisez déjà des outils, ou voulez que le modèle « émette » un enregistrement | Historiquement associé à un tool_choice forcé — restreint sur Fable 5.1 |
Strict tools (strict: true) | Ajouter strict: true à un schéma d’outil | Impose le schéma sur l’entrée de l’outil | Arguments d’outil fiables / émission d’enregistrement | Préféré sur Fable 5.1 où forcer tool_choice est bloqué |
# Route 1: structured outputs via output_config.formatresp = client.messages.create( model="claude-opus-5", max_tokens=1024, messages=[{"role": "user", "content": f"<document>{doc}</document> Extract fields."}], output_config={"format": {"type": "json_schema", "schema": INVOICE_SCHEMA}},)# Route 3: strict tool as a schema (works on Fable 5.1 with tool_choice: auto)tools = [{ "name": "record_invoice", "description": "Record the extracted invoice fields.", "strict": True, "input_schema": INVOICE_SCHEMA,}]resp = client.messages.create( model="claude-fable-5-1", max_tokens=1024, tools=tools, tool_choice={"type": "auto"}, # NOT {"type":"tool"} or "any" on Fable 5.1 messages=[{"role": "user", "content": prompt}],)Fable 5.1 · pas de forçage du tool choice
Sur Claude Fable 5.1, tool_choice: "any" et le {"type": "tool", "name": …} forcé renvoient 400. Pour obtenir une sortie structurée sur Fable 5.1, utilisez l’une de ces options : tool_choice: "auto" plus une instruction d’appeler l’outil, des schémas d’outil strict: true, ou les structured outputs (output_config.format). C’est un distracteur favori : toute option qui force un outil sur Fable 5.1 est fausse.
Signal d’examen
« Garanti de correspondre à un schéma, sans besoin de sémantique d’outil » → structured outputs. « Utilise déjà des outils / veut que le modèle émette un enregistrement » → tool-use-comme-schéma avec strict: true. « Sur Fable 5.1 » → ne forcez jamais tool_choice ; utilisez auto + instruction, strict, ou structured outputs.
3.8 Conception de schémas
Un bon schéma est auto-documenté et contraignant.
{ "type": "object", "properties": { "invoice_number": { "type": "string", "description": "The vendor invoice ID as printed." }, "total": { "type": "number", "description": "Grand total in the invoice currency." }, "currency": { "type": "string", "enum": ["USD", "EUR", "GBP"] }, "due_date": { "type": ["string", "null"], "description": "ISO 8601 date, or null if absent." }, "line_items": { "type": "array", "items": { "type": "object" } } }, "required": ["invoice_number", "total", "currency"], "additionalProperties": false}enumcontraint un champ à des valeurs connues (empêche la dérive en texte libre).requiredforce la présence ; omettez-en les champs optionnels.- Nullable via
"type": ["string", "null"]— modélisez le cas « absent » explicitement plutôt que d’inviter une valeur hallucinée. descriptionsur chaque champ — le modèle les lit ; c’est le levier de précision le moins cher.additionalProperties: falsegarde la sortie serrée.
3.9 Boucle de reprise sur validation et parsing défensif
Même avec des schémas, validez et soyez prêt à réessayer avec un retour d’erreur spécifique.
import json, jsonschema
def extract_with_retry(client, prompt, schema, max_attempts=3): messages = [{"role": "user", "content": prompt}] for attempt in range(max_attempts): resp = client.messages.create( model="claude-opus-5", max_tokens=1024, messages=messages, output_config={"format": {"type": "json_schema", "schema": schema}}, ) if resp.stop_reason == "refusal": return {"status": "refused"} # ne pas réessayer aveuglément if resp.stop_reason == "max_tokens": raise OutputTruncated() # augmenter max_tokens et réessayer text = "".join(b.text for b in resp.content if b.type == "text") try: data = json.loads(text) # parsing défensif jsonschema.validate(data, schema) return {"status": "ok", "data": data} except (json.JSONDecodeError, jsonschema.ValidationError) as e: messages.append({"role": "assistant", "content": text}) messages.append({"role": "user", "content": f"That output failed validation: {e}. " f"Return only valid JSON matching the schema."}) return {"status": "failed_validation"}Points clés : renvoyez l’erreur spécifique pour que le modèle se corrige ; parsez défensivement (jamais eval) ; traitez refusal et max_tokens comme des issues distinctes, non des échecs de validation.
3.10 Pipelines d’extraction pour documents hétérogènes
Lorsque vous extrayez à partir de nombreux types de documents (factures, contrats, reçus), un unique chiffre de précision agrégé masque un type qui échoue lourdement.
Anti-pattern 10 · Des métriques agrégées masquant l’échec par type
Reporter « 94 % de précision d’extraction globale » peut masquer que les contrats sont à 60 % tandis que les factures sont à 99 %. Mesurez toujours par type de document (métriques par segment). L’évaluation correcte à l’examen découpe la métrique par type et barre sur le pire type.
┌─► classify type ─┬─► invoice schema ─► validate ─► metrics[invoice]Document ─► route ┤ ├─► contract schema ─► validate ─► metrics[contract] └─────────────────┴─► receipt schema ─► validate ─► metrics[receipt] per-type accuracy, not one aggregate numberConception : router par type → appliquer le schéma propre au type → valider → enregistrer les métriques par type. Reportez et alertez par type.
3.11 Gérer refusal et max_tokens
| stop_reason | Signification | Gestion correcte |
|---|---|---|
refusal | Le modèle a décliné (sécurité) | Arrêter ; ne pas « réessayer plus fort » ; escalader ou reformuler légitimement ; journaliser |
max_tokens | Sortie tronquée | Pas un achèvement ; augmenter max_tokens, ou découper la tâche, puis réessayer |
end_turn | Le modèle a terminé | Continuer |
tool_use | Veut un outil | Exécuter l’outil, continuer la boucle |
Traiter une sortie max_tokens comme un résultat complet et parsable est un piège de défaillance silencieuse.
3.12 Prompts evaluator-optimizer et indépendance
Pour une boucle générer-critiquer-raffiner, donnez à l’évaluateur le barème explicite et exécutez-le comme un contexte indépendant — une session vierge, idéalement un modèle différent. Réutiliser la conversation génératrice pour se noter elle-même conserve le biais de raisonnement qui a produit le défaut.
Anti-pattern 9 · Auto-revue dans la même session
« Demander au modèle, dans le même chat, si sa réponse est correcte » conserve le biais de contexte de raisonnement. Utilisez une session séparée / un modèle différent comme juge, notant contre le barème écrit. Cela s’applique aussi aux evals LLM-as-judge.
3.13 Patrons de conception de schémas pour les cas d’extraction difficiles
Au-delà des enums et des types nullable, plusieurs patrons de schéma décident si l’extraction est fiable sur des documents désordonnés.
| Patron | JSON Schema | Résout |
|---|---|---|
| Union discriminée | oneOf avec un champ discriminateur const | Un seul outil/endpoint gérant proprement plusieurs types de documents |
| Tableaux bornés | "maxItems": N sur line_items | Sortie emballée et troncature sur d’énormes tables |
| Chaînes formatées | "format": "date", "pattern": "^[A-Z]{3}$" | Dates/codes qui doivent correspondre à une forme |
| Confiance & provenance | enum confidence + champ source_span | Gating en aval et vérification humaine |
| « Non trouvé » explicite | nullable + un frère found: boolean | Distinguer « absent » de « manqué » |
{ "type": "object", "oneOf": [ { "properties": { "doc_type": { "const": "invoice" }, "total": { "type": "number" } }, "required": ["doc_type", "total"] }, { "properties": { "doc_type": { "const": "contract" }, "term_months": { "type": "integer" } }, "required": ["doc_type", "term_months"] } ]}Signal d’examen
« Le champ optionnel est parfois halluciné quand absent » → modélisez-le comme nullable avec un indicateur found explicite, non comme un simple optionnel que le modèle se sent poussé à remplir. « Un pipeline, plusieurs types de documents » → union discriminée, non un objet lâche unique.
3.14 Un harnais robuste de reprise sur validation (avec retour d’erreur de schéma)
La boucle correcte à l’examen traite refusal et max_tokens comme des issues distinctes, renvoie l’erreur de validation spécifique, et ne parse jamais de façon non sûre.
import json, jsonschemafrom jsonschema import Draft202012Validator
def extract(client, prompt, schema, model="claude-opus-5", max_attempts=3): messages = [{"role": "user", "content": prompt}] for attempt in range(max_attempts): resp = client.messages.create( model=model, max_tokens=2048, messages=messages, output_config={"format": {"type": "json_schema", "schema": schema}}, ) if resp.stop_reason == "refusal": return {"status": "refused"} # safety stop — do not bypass if resp.stop_reason == "max_tokens": return {"status": "truncated", "retry": "raise_limit_or_chunk"} # not complete text = "".join(b.text for b in resp.content if b.type == "text") try: data = json.loads(text) # never eval() errors = sorted(Draft202012Validator(schema).iter_errors(data), key=lambda e: e.path) if not errors: return {"status": "ok", "data": data} detail = "; ".join(f"{list(e.path)}: {e.message}" for e in errors[:5]) except json.JSONDecodeError as e: detail = f"invalid JSON at pos {e.pos}: {e.msg}" messages += [ {"role": "assistant", "content": text}, {"role": "user", "content": f"Validation failed: {detail}. " f"Return ONLY valid JSON matching the schema."}, ] return {"status": "failed_validation"}import Ajv from 'ajv';const ajv = new Ajv({ allErrors: true });
async function extract(client, prompt, schema, model = 'claude-opus-5', maxAttempts = 3) { const validate = ajv.compile(schema); const messages: any[] = [{ role: 'user', content: prompt }]; for (let i = 0; i < maxAttempts; i++) { const resp = await client.messages.create({ model, max_tokens: 2048, messages, output_config: { format: { type: 'json_schema', schema } }, }); if (resp.stop_reason === 'refusal') return { status: 'refused' }; if (resp.stop_reason === 'max_tokens') return { status: 'truncated' }; // not complete const text = resp.content.filter(b => b.type === 'text').map(b => b.text).join(''); try { const data = JSON.parse(text); // never eval / Function if (validate(data)) return { status: 'ok', data }; const detail = (validate.errors ?? []).slice(0, 5) .map(e => `${e.instancePath} ${e.message}`).join('; '); messages.push({ role: 'assistant', content: text }, { role: 'user', content: `Validation failed: ${detail}. Return ONLY valid JSON.` }); } catch (e) { messages.push({ role: 'assistant', content: text }, { role: 'user', content: `Invalid JSON: ${e}. Return ONLY valid JSON.` }); } } return { status: 'failed_validation' };}Ne faites jamais eval sur la sortie du modèle
Parser la sortie du modèle avec eval() (Python) ou Function/eval (JS) exécute du code arbitraire depuis une source non fiable. Utilisez toujours json.loads / JSON.parse derrière un validateur de schéma.
3.15 Calcul de coût et de tokens de la sortie structurée
La sortie structurée n’est pas exempte de coût en tokens, et la verbosité du schéma apparaît sur la facture. Un modèle rapide :
Prompt = system(1,500) + tools/schema(800) + document(6,000) = 8,300 input tokensOutput = ~400 tokens of JSON
On Opus 5 ($5/M in, $25/M out): input = 8,300 × $5 / 1e6 = $0.0415 output = 400 × $25 / 1e6 = $0.0100 per doc ≈ $0.0515
Cache the stable 2,300-token prefix (system + schema), read ≈ 0.1×: cached prefix = 2,300 × $0.5 / 1e6 = $0.00115 (vs $0.0115 uncached) → saves ≈ $0.0104 per doc; over 1M docs ≈ $10,400 saved.
Batch API (latency-tolerant) halves the remaining cost → ~$0.026/doc.| Levier | Effet | Quand c’est correct |
|---|---|---|
| Mettre en cache le préfixe schéma + system | Lectures ~10× moins chères sur la partie stable | Extraction répétée avec un schéma fixe |
| Batch API | 50 % de réduction, ≤24 h | Extraction en masse tolérante à la latence |
| Modèle moins cher (Haiku 4.5) | Prix par token plus bas | Schémas simples et bien contraints |
Schéma plus serré (maxItems, objets fermés) | Moins de tokens de sortie, moins de troncature | Grandes tables/postes de lignes |
Signal d’examen
« MOST cost-effective way to extract from a million documents overnight » combine la mise en cache du préfixe schéma/system stable avec le Batch API, et possiblement un modèle moins cher — non « utiliser un modèle plus gros » ni « appeler en temps réel à forte concurrence ».
Idées reçues fréquentes
| Idée reçue | Réalité | Pourquoi cela compte à l’examen |
|---|---|---|
| « Le prefilling garantit un JSON valide. » | Le prefill ne fait qu’orienter ; les structured outputs / strict tools garantissent le schéma. | Items de sélection de route. |
« Forcez tool_choice pour une sortie d’outil fiable. » | Sur Fable 5.1 forcer le tool choice est un 400 ; utilisez auto+instruction, strict, ou structured outputs. | Le distracteur caractéristique de Fable 5.1. |
« Une sortie max_tokens est juste un peu plus courte. » | Elle est tronquée ; la parser comme complète corrompt les données. | Piège de troncature silencieuse. |
| « Un refusal est une erreur de validation à réessayer. » | Le refusal est un arrêt de sécurité ; réessayer pour le contourner est faux. | Items de gestion de stop_reason. |
| « Un unique chiffre de précision agrégé suffit. » | L’agrégat masque un type de document défaillant ; découpez par type (#10). | Items d’évaluation. |
| « Le modèle peut noter sa propre réponse en session. » | L’auto-revue dans la même session hérite du biais (#9) ; utilisez un juge indépendant. | Items evaluator-optimizer / LLM-as-judge. |
« budget_tokens contrôle le thinking partout. » | Seul Haiku 4.5 utilise budget_tokens ; Opus/Sonnet/Fable utilisent l’adaptive thinking + effort. | Distracteur de faits sur les modèles. |
| « Mettre l’entrée variable en premier est acceptable. » | Le préfixe stable doit être en premier pour être cachable. | Items de caching. |
Étude de scénario — un pipeline d’extraction qui semble correct mais livre de mauvais contrats
Situation. Un pipeline extrait des champs de factures, contrats et reçus sur Fable 5.1 et écrit dans une base de données. Il reporte 96 % de précision globale, pourtant l’équipe juridique trouve sans cesse de mauvaises durées de contrat. Les ingénieurs forcent tool_choice sur un outil record et voient des 400 intermittents ; quand un gros contrat est traité, le JSON se termine parfois en milieu de tableau et le code écrit l’objet partiel. Une proposition est de « noter les sorties en demandant au modèle, dans le même chat, s’il est confiant ».
Trace de raisonnement d’expert.
-
Corriger d’abord les 400. Fable 5.1 interdit le
tool_choiceforcé. Basculez vers les structured outputs (output_config.format) ou un outilstrict: trueavectool_choice: "auto"plus une instruction. Rejetez « réessayer avec backoff » (un 400 est déterministe) et"any"(aussi bloqué). -
Corriger la troncature silencieuse. Un JSON se terminant en milieu de tableau avec
stop_reason == max_tokensest une troncature, non un résultat. Augmentezmax_tokens, ou découpez le contrat (ou bornezline_itemsavecmaxItems), puis réessayez. N’écrivez jamais l’objet partiel. -
Corriger la métrique. 96 % global masque un type défaillant (#10). Reportez la précision par type de document, alertez sur les contrats, et barrez la mise en production sur le pire type. Rejetez « échantillon plus grand » et « moyenner plus d’exécutions » — les deux agrègent encore.
-
Corriger la conception de l’évaluation. L’auto-confiance dans la même session est du #9 et relève aussi de la confiance auto-déclarée. Utilisez un juge indépendant (session vierge, idéalement un modèle différent) notant contre un barème écrit.
-
Durcir le schéma. Les contrats ont besoin d’une branche d’union discriminée avec
term_monthsen entier typé et d’un nullable + indicateur found pour les clauses optionnelles afin que l’absence ne soit pas hallucinée.
Décision correcte à l’examen : structured outputs / strict tools (non choix forcé), gestion de la troncature par augmentation/découpage, métriques par type barrant sur le pire type, un évaluateur indépendant, et un schéma en union discriminée. Chaque option rejetée est un piège nommé (choix forcé Fable, troncature silencieuse, masquage agrégé #10, même-session #9).
Pièges d’examen dans ce domaine
| Piège | Pourquoi c’est faux |
|---|---|
Forcer tool_choice: "any"/{"type":"tool"} sur Fable 5.1 | Renvoie 400 ; utilisez auto+instruction, strict, ou structured outputs |
| Mettre la tâche variable avant le system prompt stable | Casse le caching ; le contenu stable doit être en premier |
| Utiliser une métrique de précision agrégée unique entre types de documents | Masque l’échec par type (anti-pattern 10) |
Traiter une sortie max_tokens comme un résultat complet | Elle est tronquée ; augmentez la limite ou découpez |
Réessayer un refusal en reformulant pour contourner la sécurité | Les refusals sont des arrêts de sécurité, non des erreurs de validation |
| Noter une réponse dans la même session qui l’a produite | Biais d’auto-revue en même session (anti-pattern 9) |
Fixer budget_tokens sur Opus 5 / Sonnet 5 / Fable 5.1 | Retiré (400) ; seul Haiku 4.5 l’utilise |
| Se fier au prefilling comme garantie dure | Il oriente, ne garantit pas ; utilisez structured outputs/strict tools |
| Sauter les descriptions de champ dans le schéma | Les descriptions sont le levier de précision le moins cher |
| Éditer les tours antérieurs en cours de session sur Fable 5.1 | Invalide les thinking blocks ; le harnais doit être append-only |
Parser la sortie du modèle avec eval() | Exécute du code non fiable ; utilisez json.loads/JSON.parse derrière un validateur |
| Modéliser un champ optionnel comme un simple optionnel | Le modèle peut halluciner une valeur ; utilisez nullable + un indicateur found |
| Utiliser un objet lâche unique pour plusieurs types de documents | Utilisez une union discriminée (oneOf + const) |
| Laisser les tableaux de postes de lignes non bornés | Ajoutez maxItems pour empêcher la sortie emballée et la troncature |
| Temps réel à forte concurrence pour une extraction de masse nocturne | Utilisez le Batch API (50 % de réduction, ≤24 h) et mettez en cache le préfixe de schéma |
Questions d’entraînement
Q1 · Un pipeline sur Claude Fable 5.1 doit renvoyer des enregistrements qui correspondent à un schéma JSON. Un ingénieur met un tool_choice forcé sur l’outil record et obtient des erreurs 400. Quel est le correctif correct ? (Sélectionnez une réponse)
A. Réessayer avec un backoff exponentiel.
B. Utiliser tool_choice: 'auto' avec une instruction d’appeler l’outil, ou des outils strict: true, ou les structured outputs via output_config.format.
C. Basculer vers tool_choice: 'any'.
D. Baisser max_tokens.
Réponse : B. Fable 5.1 rejette le tool choice forcé (any et {type:"tool"} renvoient tous deux 400). Les routes supportées sont auto+instruction, strict tools, ou structured outputs. Le backoff (A) ne corrige pas un 400 ; any (C) est aussi bloqué ; max_tokens (D) est sans rapport.
Q2 · Une équipe reporte 94 % de précision d’extraction globale entre factures, contrats et reçus. Une partie prenante se plaint que les contrats sont fréquemment faux. Quel est le MEILLEUR changement d’évaluation ? (Sélectionnez une réponse)
A. Augmenter la taille d’échantillon globale. B. Reporter la précision par type de document et barrer sur le type le moins performant. C. Augmenter la température du modèle pour les contrats. D. Moyenner trois exécutions pour lisser la métrique.
Réponse : B. La précision agrégée masque un type défaillant (anti-pattern 10). Les métriques par type exposent et barrent sur le type faible. De plus grands échantillons (A) agrègent encore ; la température (C) ne corrige pas la précision ; moyenner (D) masque davantage le problème.
Q3 · Un prompt place le document utilisateur spécifique en premier et les longues règles système stables en dernier. La latence et le coût sont élevés faute de succès de cache. Quel est le correctif ? (Sélectionnez une réponse)
A. Raccourcir le document.
B. Placer le system prompt stable, les outils et le matériel de référence en premier avec cache_control sur le dernier bloc stable, et la tâche variable après.
C. Désactiver le caching.
D. Utiliser un modèle plus gros.
Réponse : B. Le caching exige le contenu stable en premier ; la tâche variable va en dernier. Raccourcir le document (A) n’active pas le caching, désactiver le caching (C) aggrave le coût, et la taille du modèle (D) est sans rapport.
Q4 · Une extraction renvoie un texte se terminant en milieu d’objet et `stop_reason` vaut `max_tokens`. Le code le parse en JSON et échoue. Quelle est la gestion correcte ? (Sélectionnez une réponse)
A. Traiter le JSON partiel comme le résultat.
B. Reconnaître max_tokens comme une troncature, augmenter la limite de tokens ou découper la tâche, puis réessayer — ne pas le parser comme complet.
C. Journaliser une erreur générique et renvoyer vide.
D. Demander au modèle dans le même chat s’il est sûr.
Réponse : B. max_tokens signifie une sortie tronquée, non un achèvement. Augmentez la limite ou découpez. Parser une sortie partielle (A) est un piège de défaillance silencieuse ; renvoyer vide (C) est l’anti-pattern 7 ; l’auto-vérification en même session (D) est sans rapport.
Q5 · Quels DEUX choix de conception de schéma améliorent le plus la fiabilité de l’extraction ? (Sélectionnez deux réponses)
A. Une description sur chaque champ.
B. Du texte libre pour les champs qui ont un ensemble fixe de valeurs.
C. Un enum pour le champ currency et des types nullable explicites pour les champs optionnels.
D. Omettre required entièrement.
E. Autoriser additionalProperties: true.
Réponse : A et C. Les descriptions guident le modèle et les enums/types nullable contraignent et modélisent l’absence explicitement. Le texte libre (B) invite la dérive, omettre required (D) perd les garanties de présence, et des propriétés additionnelles ouvertes (E) relâchent la sortie.
Q6 · Une boucle de reprise sur validation échoue sans cesse. Actuellement elle renvoie simplement le même prompt. Quel changement aide le plus le modèle à se corriger ? (Sélectionnez une réponse)
A. Augmenter seulement le nombre de réessais.
B. Renvoyer l’erreur de validation spécifique au modèle et lui demander de ne renvoyer que du JSON valide correspondant au schéma.
C. Basculer vers eval() pour parser la sortie.
D. Baisser max_tokens.
Réponse : B. Un retour d’erreur spécifique laisse le modèle corriger le problème exact. Plus de réessais aveugles (A) aident rarement, eval() (C) est dangereux, et baisser max_tokens (D) risque la troncature.
Q7 · Quand devriez-vous utiliser l’extended thinking plutôt que la chaîne de pensée par prompt ? (Sélectionnez une réponse)
A. Pour chaque requête, toujours.
B. Pour le raisonnement difficile multi-étapes ou la planification agentique, en utilisant thinking: {'type': 'adaptive'} sur les modèles actuels.
C. Jamais ; la chaîne de pensée est toujours meilleure.
D. Uniquement pour réduire le coût.
Réponse : B. L’extended thinking convient au raisonnement difficile, multi-étapes ou agentique. Il n’est pas nécessaire pour chaque requête (A), n’est pas universellement pire (C), et ne réduit pas le coût (D) — les thinking tokens ajoutent du coût.
Q8 · Une boucle evaluator-optimizer note la traduction dans la même conversation qui l’a produite et la qualité ne s’améliore pas. Quel est le défaut ? (Sélectionnez une réponse)
A. Le barème est trop détaillé. B. L’auto-revue dans la même session conserve le biais de raisonnement ; exécutez l’évaluateur comme un contexte indépendant, idéalement un modèle différent, contre le barème explicite. C. Le générateur a besoin d’une température plus élevée. D. Il y a trop peu de réessais.
Réponse : B. Anti-pattern 9. L’indépendance supprime le biais partagé. Un barème détaillé (A) est bon, la température (C) ne corrige pas le biais, et plus de réessais (D) répètent le juge biaisé.
Q9 · Un document contient du texte tiers non fiable qui ordonne au modèle d’ignorer sa tâche. Quelle pratique de conception de prompt réduit ce risque ? (Sélectionnez une réponse)
A. Concaténer le document directement dans les instructions.
B. Envelopper le contenu non fiable dans une balise XML clairement nommée (par ex. <document>…</document>) et instruire le modèle de le traiter comme des données, non des instructions.
C. Faire confiance au modèle pour le remarquer.
D. Régler la température à 0.
Réponse : B. Les frontières de contenu XML séparent les données des instructions et émoussent l’injection indirecte. La concaténation (A) invite l’injection, faire confiance au modèle (C) n’est pas un contrôle, et la température (D) est sans rapport.
Q10 · Sur Claude Sonnet 5, un harnais tente d’injecter un message system en cours de conversation. Qu’est-ce qui est vrai ? (Sélectionnez une réponse)
A. Sonnet 5 autorise les messages system en cours de conversation.
B. Sonnet 5 n’autorise pas les messages system en cours de conversation ; concevez le system prompt d’emblée.
C. Seul Fable 5.1 interdit cela.
D. Régler budget_tokens pour l’activer.
Réponse : B. Sonnet 5 n’autorise pas les messages system en cours de conversation, donc la conception doit figer le system prompt d’emblée. A est faux ; la contrainte append-only de Fable 5.1 est distincte (C) ; budget_tokens (D) est retiré sur Sonnet 5.
Q11 · Un pipeline a besoin d’un objet conforme au schéma garanti et n’utilise pas d’outils pour autre chose. Quelle route est la plus propre ? (Sélectionnez une réponse)
A. Préremplir le tour assistant avec { et espérer.
B. Structured outputs via output_config.format avec un schéma JSON.
C. Forcer tool_choice sur un outil factice sur Fable 5.1.
D. Parser de la prose en texte libre avec une regex.
Réponse : B. Les structured outputs donnent une garantie de schéma sans sémantique d’outil. Le prefill (A) ne fait qu’orienter, forcer le tool_choice sur Fable 5.1 (C) renvoie 400, et une regex sur de la prose (D) est fragile.
Q13 · Un pipeline d’extraction unique doit gérer factures, contrats et reçus, chacun avec des champs requis différents. Quel patron de schéma est le MEILLEUR ? (Sélectionnez une réponse)
A. Un objet lâche unique avec chaque champ possible optionnel.
B. Une union discriminée (oneOf avec un discriminateur const doc_type), pour que chaque branche impose ses propres champs requis.
C. Trois endpoints sans rapport et sans contrat partagé.
D. Un unique champ chaîne contenant du texte JSON brut.
Réponse : B. Une union discriminée impose proprement les exigences par type dans un seul schéma. A relâche tout et invite la dérive ; C perd un contrat partagé ; D abandonne entièrement les garanties de schéma.
Q14 · Un champ optionnel « renewal_clause » est fréquemment halluciné quand la clause est absente. Quel changement de schéma réduit le PLUS cela ? (Sélectionnez une réponse)
A. En faire une chaîne requise pour que le modèle le remplisse toujours.
B. Le modéliser comme nullable (type chaîne-ou-null) avec un frère renewal_found: boolean explicite, pour que l’absence soit représentée plutôt qu’inventée.
C. Supprimer le champ entièrement.
D. Augmenter la température pour que les réponses varient.
Réponse : B. Nullable plus un indicateur found explicite laisse le modèle représenter l’absence au lieu d’halluciner. Requis (A) force une valeur ; le supprimer (C) perd la donnée ; la température (D) aggrave la cohérence.
Q15 · Un million de documents doivent être extraits pendant la nuit le moins cher possible avec un schéma fixe. Quelle combinaison est la PLUS économique ? (Sélectionnez deux réponses)
A. Mettre en cache le préfixe stable system + schéma pour que les lectures coûtent ~0,1×. B. Utiliser la Message Batches API pour l’exécution de masse tolérante à la latence (50 % de réduction, ≤24 h). C. Appeler l’API temps réel à concurrence maximale. D. Utiliser Fable 5.1 à $10/$50 pour chaque document. E. Randomiser le prompt à chaque appel pour éviter les lectures périmées.
Réponse : A et B. La mise en cache du préfixe fixe et le Batch API réduisent ensemble fortement le coût pour un travail de masse tolérant à la latence. Le temps réel à forte concurrence (C) coûte plein tarif et risque les limites ; le modèle le plus cher (D) augmente le coût ; randomiser (E) détruit le préfixe cachable.
Q16 · Un développeur parse la sortie d’extraction avec `eval()` parce que « ça gère les virgules finales ». Quelle est la critique correcte ? (Sélectionnez une réponse)
A. C’est acceptable si le modèle est de confiance.
B. eval() exécute du code arbitraire non fiable venant du modèle ; parsez avec json.loads/JSON.parse derrière un validateur de schéma et renvoyez les erreurs de validation en cas d’échec.
C. Utiliser une regex au lieu de eval().
D. Baisser max_tokens pour que la sortie soit plus petite.
Réponse : B. La sortie du modèle est non fiable ; eval() est un risque d’exécution de code. Un parsing sûr plus la validation de schéma et le retour d’erreur est correct. Le modèle n’est jamais « de confiance » pour eval (A) ; une regex (C) est fragile ; max_tokens (D) est sans rapport.
Q17 · Le JSON extrait d’un gros contrat se termine en milieu de tableau avec `stop_reason` `max_tokens`, et le pipeline écrit l’objet partiel. Quelle est la gestion correcte ? (Sélectionnez une réponse)
A. Écrire l’objet partiel ; il est presque complet.
B. Traiter max_tokens comme une troncature : augmenter la limite ou découper le document (ou borner les tableaux avec maxItems), puis réessayer — ne jamais persister la sortie partielle.
C. Renvoyer un objet vide pour que le pipeline continue.
D. Demander au modèle dans la même session s’il a terminé.
Réponse : B. max_tokens est une troncature, non un achèvement. Persister le partiel (A) corrompt les données ; renvoyer vide (C) est une défaillance silencieuse (#7) ; l’auto-vérification en même session (D) ne traite pas la troncature.
Q18 · Sur Opus 5 un harnais agentique fixe `budget_tokens` pour le thinking et reçoit un 400. Qu’est-ce qui est vrai et quel est le correctif ? (Sélectionnez une réponse)
A. budget_tokens fonctionne sur Opus 5 ; réessayer le 400.
B. budget_tokens est réservé à Haiku 4.5 ; sur Opus 5 utilisez l’adaptive thinking avec un niveau d’effort (low|medium|high|xhigh), par ex. xhigh pour le travail le plus difficile.
C. Désactiver le thinking pour éviter l’erreur.
D. Basculer vers tool_choice: any pour activer les budgets.
Réponse : B. Seul Haiku 4.5 utilise budget_tokens ; Opus 5 utilise des niveaux d’effort. Le 400 est déterministe, non transitoire (A) ; désactiver le thinking (C) supprime un raisonnement nécessaire ; tool_choice (D) est sans rapport avec le contrôle du thinking.
Points clés à retenir
- Concevez les prompts comme des systèmes versionnés et modulaires : contenu stable en premier (rôle system, outils, docs) avec
cache_control; tâche variable en dernier. - Énoncez des critères de réussite et des barèmes explicites ; utilisez des balises XML pour séparer les données non fiables des instructions.
- Choisissez la sortie structurée délibérément :
output_config.formatpour les garanties de schéma, tool-use-comme-schéma/strictpour l’émission d’enregistrements ; ne forcez jamaistool_choicesur Fable 5.1. - Concevez les schémas avec enums, required, types nullable, descriptions, unions discriminées et tableaux bornés ; modélisez l’absence avec nullable + un indicateur found.
- Construisez une boucle de reprise sur validation qui renvoie l’erreur de schéma spécifique et parse sûrement (jamais
eval) ; traitezrefusaletmax_tokenscomme des issues distinctes. - Découpez les métriques d’extraction par type de document et barrez sur le pire ; ne faites jamais confiance à un unique chiffre agrégé.
- Contrôlez le raisonnement avec l’adaptive thinking +
effort(Opus/Sonnet/Fable) ; seul Haiku 4.5 utilisebudget_tokens. - Exécutez les évaluateurs comme des contextes indépendants ; sur Fable 5.1 gardez le harnais append-only et figez system/tools.
- Pour l’extraction de masse, mettez en cache le préfixe stable schéma/system et utilisez le Batch API (50 % de réduction) — les leviers de coût, non un modèle plus gros.
Dernière mise à jour le 18 sept. 2026