Points clés
JSON-mode au niveau API arrête la syntaxe JSON malformée, pas les défaillances de conformité du schéma. Du JSON valide peut manquer de champs, utiliser les mauvais types et contenir des valeurs enum invalides qui échouent toutes à la validation en aval.
Intégrer le schéma dans le prompt est le fondement. Un template JSON structuré directement dans le prompt montre au modèle les noms de champs, la profondeur d'imbrication et les types par la structure, pas la prose.
Un exemple de sortie valide augmente la fiabilité de 5–10 points. Le modèle voit à quoi ressemble une sortie réussie et suit mieux.
Les instructions au niveau du champ pour le type, format et traitement null sont critiques. «Champ enum» est ambigu; «status (exactement l'un de: 'active', 'inactive', 'pending' — pas d'abréviations)» ne l'est pas.
95% de taux de réussite sur un ensemble de test de 20 cas est le gate de production. Sous 95%, les défaillances en production surviennent assez souvent pour exiger un loop de correction qui double le coût et la latence.
Le Design du Prompt Détermine la Fiabilité de la Sortie Structurée
Les APIs JSON-mode (OpenAI response_format, Anthropic tool_use, Google Gemini responseMimeType) imposent du JSON analysable, mais ne font rien pour la conformité du schéma — champs requis présents, types de données corrects, valeurs enum valides. Ces erreurs surviennent malgré l'enforcement au niveau API et exigent des contrôles de design de prompt.
🔍 JSON-mode ne suffit pas
JSON-mode imposé par API empêche les sorties non analysables (espaces dans JSON, guillemets non échappés). Il n'empêche pas la conformité du schéma: un modèle avec JSON-mode activé peut toujours retourner du JSON valide avec champs manquants, mauvais type et valeurs invalides. La conformité du schéma est un problème de prompt, pas un problème d'API.
🔍 Testez d'abord avec schéma dans le prompt seul
Les modèles sans JSON-mode imposé par API (APIs anciennes, LLMs locaux) atteignent 80–85% de fiabilité avec schéma seul dans le prompt. Cela établit la baseline et montre où les 15–20 points restants ajoutent utilement.
Intégrer le Schéma Directement dans le Prompt
Montrer le schéma comme un template JSON directement dans le prompt est la technique de plus haute valeur. Les prompts qui décrivent le schéma seulement en prose («une liste de champs») sont ambigus. Le modèle ne voit pas clairement les noms de champs, la profondeur d'imbrication ou le type et devine.
🔍 Distribuer les objets imbriqués sur plusieurs lignes
Presser les structures imbriquées sur une ligne rend difficile pour les modèles de voir la profondeur. Les templates multi-lignes avec indentation sont beaucoup plus faciles à suivre.
🔍 Montrer explicitement null et les arrays vides
Utilisez le template pour montrer à quoi null ressemble (pas «nil», pas «N/A», juste null) et à quoi un array vide ressemble ([] pas null). Si ce n'est pas dans votre template, ces choses se font mal.
❌ Ambigu — pas de structure
Retournez une liste de données client.
✅ Template de schéma avec types montrés par la structure
Retournez les données client dans ce format JSON exact: { "customer_id": "string", "name": "string", "email": "string", "purchases": ["item1", "item2"], "total_spent": 0.00, "is_premium": true } Incluez tous les champs. Jamais null.
Montrer au Modèle un Exemple de Sortie Valide
Un exemple de sortie augmente la fiabilité de 5–10 points et coûte peu de tokens. Le modèle voit un motif de sortie réussi et suit mieux, particulièrement pour les champs avec types ambigus (une liste de dates est-elle un array ou séparé par virgules?) ou valeurs enum (est-ce 'ACTIVE' ou 'active'?).
🔍 Un exemple suffit pour la plupart des cas
Deux ou plus d'exemples aident seulement quand vos types de données varient significativement selon les conditions d'entrée. Pour la plupart des tâches, un second exemple double le coût des tokens sans bénéfice de fiabilité.
🔍 Choisir un exemple pour les cas limites, pas juste happy path
Un exemple avec tous les champs remplis est moins utile qu'un avec un champ optionnel vide montrant null, ou un array avec un seul élément. Cela montre au modèle comment gérer les cas limites.
❌ Pas d'exemples — le modèle devine sur enum
Retournez les détails client en JSON. Champs: customer_id, status. Input: {{ data }}
✅ L'exemple montre format, type, orthographe de valeur enum
Retournez les détails client en JSON. Champs: customer_id (string), status (enum: 'active', 'inactive', 'pending'). Exemple: {"customer_id": "CUST-12345", "status": "active"} Input: {{ data }}
Instructions au Niveau du Champ, pas Seulement un Schéma
Les instructions au niveau du champ pour type, format, valeurs permises et traitement null élèvent la fiabilité de 90% à 95%+. Ces instructions sont la couche finale qui élimine l'ambiguïté.
| Type de champ | Erreur courante | Instruction de champ qui la prévient |
|---|---|---|
| Integer vs. Float | Le modèle retourne float quand integer est attendu | "score (integer — pas de décimales, ex. 4 pas 4.0)" |
| Énumération (5+ valeurs) | Le modèle invente des valeurs pas sur la liste | Toutes les valeurs listées: «Utilisez seulement les valeurs de la liste. Pas d'abréviations.» |
| Champ nullable | Le modèle retourne "" au lieu de null | "Retournez null si la valeur est inconnue. Retournez "" seulement si le champ est connu vide." |
| String de date | Le modèle utilise différents formats | "date_created (ISO 8601: '2026-05-15')" |
| Array | Le modèle retourne null pour array vide | "Toujours retourner un array, même si vide. [] pas null." |
🔍 Les instructions doivent être spécifiques et testables
Une instruction de champ comme «bonne qualité» n'est pas testable. «Exactement ISO 8601 ou erreur» l'est. Les instructions testables soutiennent l'automatisation des tests plus tard.
🔍 Utiliser regex ou exemples pour les formats
Pour les champs date, téléphone ou format, donnez un regex ou 2–3 exemples, pas seulement de la prose: «format: /^\d{3}-\d{3}-\d{4}$/ (ex. 555-123-4567)»
Choisir JSON, YAML ou CSV selon la Tâche et l'Imposition
La plupart des tâches de sortie structurée nécessitent JSON. YAML et CSV sont plus rapides à écrire pour les humains, mais les modèles y sont moins fiables sans imposition au niveau API. JSON avec API-mode a le sol de fiabilité le plus élevé.
| Format | Sol sans API | Sol avec API | Meilleur pour |
|---|---|---|---|
| JSON | 80–85% | 95%+ | Structures imbriquées, APIs, logging |
| YAML | 70–75% | 85–90% | Lisible humain, pas d'imbrication |
| CSV | 65–70% | 80–85% | Tableaux plats, capture de données batch |
| XML | 75–80% | 90–95% | Systèmes legacy qui en ont besoin |
🔍 JSON est le choix par défaut
Utilisez JSON si vous avez des structures imbriquées ou pouvez utiliser imposition au niveau API. Cela donne le sol de fiabilité le plus élevé.
🔍 Tester CSV pour structures tabulaires plates
CSV est plus rapide pour les données tabulaires simples (une ligne = un enregistrement) et moins cher en tokens. Si vous avez seulement 3–5 colonnes, testez CSV avec schéma; si l'imbrication apparaît, basculer à JSON.
Laisser le Modèle Corriger sa Propre Sortie Malformée
Quand un prompt de sortie structurée échoue, envoyez un prompt de correction contenant l'instruction originale, la sortie malformée et l'erreur de validation spécifique. Les modèles récupèrent une sortie valide de leur propre réponse malformée dans 60–75% des cas sans réécriture de prompt.
Un prompt de correction a trois parties requises: (1) une réaffirmation de ce que la sortie doit ressembler (le schéma ou format), (2) la sortie malformée exactement comme le modèle l'a retournée, (3) l'erreur de validation spécifique — «le champ requis 'invoice_id' manque», «amount est une string, attendu float». Cette structure en trois parties donne au modèle assez de contexte pour corriger le problème spécifique plutôt que de générer une réponse différente avec des erreurs différentes.
🔍 Si correction échoue deux fois, corriger le prompt de base
Si le prompt de correction ne produit pas une sortie valide à la deuxième tentative, le problème est dans le prompt de base, pas les données d'input. Arrêter la réitération et diagnostiquer le motif d'échec: quel champ échoue, sous quelles conditions d'input. Ajouter une instruction de champ ou changement de schéma pour prévenir l'échec à la source.
⚠️ Les prompts de correction ajoutent latence et coût
Chaque prompt de correction double le coût API et la latence pour cet appel. Utiliser les prompts de correction seulement pour les échecs de cas limites (<10% des sorties). Si votre prompt échoue plus de 10% du temps, corriger le prompt de base plutôt que de construire un loop de correction en production.
❌ Retry vague — pas de contexte d'erreur
Vous avez retourné une sortie invalide. Essayez à nouveau et retournez du JSON valide. {{original_prompt}}
✅ Prompt de correction avec schéma, sortie et erreurs spécifiques
Votre réponse précédente a échoué la validation. Corriger seulement les erreurs listées ci-dessous et retourner du JSON corrigé. Schéma attendu: { "invoice_id": "string", "amount": 0.00, "status": "string" } Votre réponse précédente: { "invoice_id": null, "amount": "150.00", "status": "PAID" } Erreurs de validation: - invoice_id est null mais doit être un champ string requis — l'extraire de l'input - amount est un string ("150.00") mais doit être un float (150.00) - status doit être minuscule: utilisez 'paid', pas 'PAID' Retourner seulement l'objet JSON corrigé.
Modèles de Prompt pour les Tableaux, Énumérations et Champs Nullables
Les arrays, énumérations et champs nullable sont les trois sources courantes d'erreurs de sortie structurée que schéma seul n'empêche pas. Chacun nécessite un motif d'instruction spécifique dans le prompt.
| Type de données | Erreur courante | Motif de prompt qui l'empêche |
|---|---|---|
| Array (0 éléments) | Le modèle retourne null au lieu de [] | "Retournez un array vide [] s'il n'y a pas d'éléments. Ne retournez jamais null pour les champs array." |
| Array (1+ éléments) | Le modèle retourne objet seul au lieu d'array avec un élément | "Toujours retourner un array, même avec un seul élément. Éléments uniques doivent être enrobés: {...}" |
| Énumération (2–5 valeurs) | Le modèle abrège ou invente des valeurs similaires | "status: exactement l'un de: 'active', 'inactive', 'pending' — pas d'abréviations ou variantes" |
| Énumération (6+ valeurs) | Le modèle invente des valeurs pas sur la liste | Lister toutes les valeurs dans une liste numérotée, puis: «Utilisez seulement les valeurs de la liste ci-dessus. Pas d'abréviations ou combinaisons.» |
| Champ nullable | Le modèle retourne "" au lieu de null, ou omet le champ | "Retournez null si la valeur est inconnue. Retournez "" seulement si le champ est connu vide. Toujours inclure le champ — ne l'omettez pas." |
| Integer vs float | Le modèle retourne float si integer attendu, ou string pour les deux | "score (integer — pas de décimales, ex. 4 pas 4.0)" ou "price (float — exactement 2 décimales, ex. 12.99 pas 13)" |
| Objet imbriqué | Le modèle aplatit l'objet imbriqué en clés plates (ex. "address.city" au lieu de {"address": {"city": ...}}) | Montrer la structure imbriquée complète dans le template de schéma avec indentation propre. La description en prose seule d'imbrication s'aplatit souvent. |
⚠️ null vs. undefined vs. omis
JSON n'a pas de valeur undefined, mais les modèles se comportent parfois comme si — omettant un champ entièrement quand ils pensent que la valeur est inconnue, plutôt que de retourner null. Si du code en aval utilise des vérifications hasOwnProperty(), un champ omis est différent d'un champ null. Ajoutez: «Toujours inclure chaque champ du schéma, même si la valeur est null.»
🔍 Les énumérations imbriquées ont besoin d'extra-spécificité
Les énumérations dans les objets imbriqués sont plus susceptibles à des fautes de frappe ou abréviations que les énumérations de top-level. Si vous avez une énumération dans un objet imbriqué, répétez l'instruction près de là où le champ apparaît dans le template de schéma, pas seulement dans une section générale de règles de champ.
Mesurer la Fiabilité de la Sortie Structurée
Ciblez 95%+ de taux de réussite sur un ensemble de test de 20 cas avant de déployer un prompt de sortie structurée en production. Sous 95%, les défaillances surviennent assez souvent pour exiger un loop de correction — qui ajoute latence et double le coût API pour chaque appel échoué.
Mesurez la fiabilité au niveau du champ, pas seulement au total. Un prompt à 95% de taux global mais 60% sur un champ enum est un prompt avec un mode d'défaillance de production connu. La mesure au niveau du champ vous dit exactement quelle instruction ajouter ou renforcer.
- 1Définir les critères de réussite/échec pour chaque champ du schéma. Pour chaque champ: type est correct, champ requis est présent, valeur enum est sur la liste permise, format de date correspond au motif requis. Écrivez-les comme des vérifications programmatiques — pas d'inspection visuelle. Cette étape produit votre oracle de test.
- 2Construire un ensemble de test de 20 cas. Dix happy-path (typiques, bien formées), cinq cas limites (champs optionnels manquants, texte long, valeurs inhabituelles, contenu multilingue), cinq adversariaux (instructions intégrées dans les valeurs de champs, dates extrêmes, types ambigus). Utilisez des inputs réalistes de votre domaine réel.
- 3Exécuter à la température 0 et enregistrer réussite/échec par champ. Exécutez les 20 cas à la température 0 pour des résultats déterministes et répétables. Enregistrez si chaque champ réussit ou échoue dans chaque test — pas seulement le résultat global. Les motifs d'échec au niveau du champ identifient quelle instruction manque.
- 4Corriger le champ avec le taux de réussite le plus faible et retester. Ajouter ou renforcer une instruction de champ: type, format, traitement null ou valeurs enum. Réexécuter les 20 cas. Une instruction unique ciblée élève typiquement le taux global de 5–15 points. Répétez jusqu'à atteindre 95% ou plus.
- 5Valider le prompt sur un second modèle. Exécuter l'ensemble complet de 20 cas sur un second modèle avec le même prompt. Un prompt à 95%+ sur GPT-4o mais 70% sur Claude 4.6 Sonnet est dépendant du modèle. Soit ajouter des instructions assez explicites pour réussir sur les deux, soit documenter quel modèle le prompt est validé pour et ne pas changer sans retesting.
🔍 Exécuter les tests à la température 0
Exécuter les ensembles de test de sortie structurée à la température 0 pour obtenir des résultats déterministes et répétables. Un prompt qui passe à la température 0 est fiable par design — pas lucky. Seulement augmenter la température après que le prompt passe 95%+ déterministement, puis retester l'ensemble à la nouvelle température pour confirmer que la fiabilité tient.
🔍 Utiliser PromptQuorum pour comparaison multi-modèle
PromptQuorum exécute votre ensemble de test de 20 cas sur GPT-4o, Claude 4.6 Sonnet et Gemini 2.5 Pro simultanément et affiche les taux de réussite par champ côte à côte. Cela identifie les défaillances dépendantes du modèle en un run au lieu de trois.
5 Erreurs Courantes des Prompts de Sortie Structurée
Les cinq erreurs courantes du prompting de sortie structurée produisent toutes le même symptôme — défaillances intermittentes ou systématiques — mais exigent des correctifs différents. Diagnostiquer quelle erreur vous avez avant d'ajouter des instructions économise du temps.
❌ Décrire le schéma en prose au lieu de l'intégrer
Why it hurts: Les descriptions en prose sont ambiguës — «une liste d'éléments» pourrait être un array, une string séparé par virgules ou une liste numérotée; «le total» pourrait être string ou float
Fix: Intégrer le schéma attendu comme template JSON directement dans le prompt. Le template montre noms de champs, profondeur d'imbrication et types de valeurs par la structure plutôt que la description en prose.
❌ Ne pas spécifier comment gérer les valeurs manquantes ou inconnues
Why it hurts: Les modèles inventent des valeurs plausibles pour champs inconnus plutôt que de retourner null — dates deviennent «unknown», montants deviennent 0, IDs manquantes deviennent «N/A» — rien ne passe la validation de type
Fix: Ajouter un traitement explicit null pour chaque champ nullable: «Retournez null si la valeur ne peut pas être déterminée de l'input. Ne devinez ou n'inventez pas de valeurs. Ne retournez pas de string vide.»
❌ Tester seulement contre le modèle sur lequel vous avez développé le prompt
Why it hurts: La fiabilité de sortie structurée varie significativement entre les modèles — un prompt à 95% sur GPT-4o peut échouer à 70% sur Claude 4.6 Sonnet à cause du suivi d'instruction différent sur les contraintes de schéma
Fix: Exécuter chaque prompt de sortie structurée contre au minimum 2 modèles avant de le traiter comme agnostique au modèle. Utiliser PromptQuorum ou des appels API directs pour tester les prompts sur les modèles en une étape.
❌ Réessayer une sortie échouée avec le même prompt
Why it hurts: Un prompt échouant réessayé à la température 0 produit la même erreur à chaque fois. À température plus élevée, il produit une sortie variée mais toujours échouée — erreurs différentes, cause racine identique
Fix: Utiliser un prompt de correction avec l'erreur de validation spécifique et la sortie malformée, ou diagnostiquer le motif d'échec (quel champ, quel type d'input) et ajouter une instruction de champ ciblée au prompt de base.
❌ Traiter JSON-mode comme une solution complète de sortie structurée
Why it hurts: JSON-mode empêche la sortie non analysable mais pas les défaillances de conformité du schéma — un modèle avec JSON-mode peut toujours retourner du JSON valide avec champs manquants, mauvais types et valeurs enum invalides, tous échouant à la validation en aval
Fix: Toujours inclure schéma-dans-le-prompt et instructions de champ même quand utilisant JSON-mode imposé par API. Voir Sortie Structurée et JSON-mode pour configuration API — ce guide couvre le complément au niveau prompt.
Lectures Supplémentaires
- Sortie Structurée et JSON-mode: Quand et Comment l'Utiliser — Configuration JSON-mode au niveau API pour GPT-4o, Claude et Gemini avec tableau de conformité du modèle
- Meilleurs Outils pour Sortie Structurée (2026) — Instructor, Outlines, Pydantic AI et LangChain comparés pour workflows d'extraction structurée
- Comment Contrôler la Sortie: Format, Température et Décodage Contraint — Mécanique de décodage contraint, température et top-p pour tâches structurées, séquences d'arrêt
- Comment Évaluer la Qualité du Prompt: Métriques, Tests et Checklist — Construction d'ensemble de test de 20 cas, scoring réussite/échec binaire et rubriques LLM-as-judge
- Comment Tester les Prompts sur les Modèles — Exécution du même prompt sur GPT-4o, Claude 4.6 Sonnet et Gemini 2.5 Pro pour trouver les défaillances dépendantes du modèle
- Zero-Shot vs. Few-Shot Prompting — Quand ajouter des exemples à un prompt et combien en inclure pour différents types de tâches
Sources
- Documentation OpenAI Structured Outputs — Spécification technique pour response_format et JSON-mode dans l'API OpenAI
- Documentation Anthropic tool use — Comment le paramètre tool_use de Claude impose la sortie structurée au niveau API
- Documentation Google Gemini GenerationConfig — Configuration responseMimeType de Gemini pour sortie JSON native
- Benchmark BAML: compromis de précision de sortie structurée — Preuve sur les différences de fiabilité entre génération contraint et sans contrainte sur les modèles
- Framework de Gestion des Risques AI du NIST — Principes de gouvernance pour la validation des sorties AI dans les systèmes de production