Une sortie structurée IA est une réponse contrainte par un format destiné à être lu par un programme, souvent un objet JSON décrit par JSON Schema. Elle réduit les clés manquantes, les types incohérents et les réponses entourées de texte. Elle ne prouve pas que les valeurs sont vraies, que le document source autorise leur extraction ou que l’action suivante peut être exécutée.
La différence est décisive. Un modèle peut produire un objet parfaitement conforme avec une date inventée, une catégorie plausible mais fausse ou un identifiant appartenant au mauvais dossier. Si le système confond conformité de forme et validité métier, l’automatisation devient plus facile à parser, pas plus fiable.
Ce guide propose un contrat en quatre niveaux : syntaxe JSON, conformité au schéma, validité sémantique et autorisation de l’effet. Il montre comment dessiner un schéma minimal, représenter l’incertitude, versionner le contrat, traiter les sorties incomplètes et tester le pipeline avant toute écriture dans un autre système.
Réponse en bref
Pour fiabiliser une sortie structurée produite par une IA :
- définissez le résultat métier avant de choisir les champs ;
- distinguez sortie finale et paramètres d’appel d’un outil ;
- utilisez des types stricts, des valeurs énumérées et des champs requis ;
- fermez les objets aux propriétés inattendues lorsque le fournisseur le permet ;
- prévoyez explicitement
unknown,not_applicableou une valeur nulle lorsque l’information peut manquer ; - séparez la valeur extraite de sa preuve et de son statut de vérification ;
- validez localement la réponse, même si le fournisseur annonce une conformité au schéma ;
- appliquez ensuite les règles métier, les autorisations et les contrôles de source ;
- traitez refus, troncature et réponse vide comme des états distincts ;
- versionnez le schéma et testez les anciennes données avant une migration ;
- bornez les reprises et ne demandez pas au modèle de réparer indéfiniment sa propre sortie ;
- n’exécutez jamais une action sensible sur la seule base d’un JSON bien formé.
La règle à retenir est simple : un schéma contrôle la forme d’une proposition. Le code métier décide si cette proposition est recevable et ce qu’elle a le droit de déclencher.
Les quatre niveaux de validité
Un pipeline robuste ne possède pas un seul verdict valid. Il traverse quatre contrôles.
| Niveau | Question | Exemple d’échec |
|---|---|---|
| syntaxe | la réponse est-elle un document JSON analysable ? | virgule finale ou texte avant l’objet |
| schéma | les clés, types et valeurs admises sont-ils respectés ? | priority contient 9 au lieu d’une valeur prévue |
| sens | les valeurs sont-elles cohérentes avec la source et les règles métier ? | date antérieure au document présenté comme échéance future |
| autorisation | le système peut-il utiliser ce résultat pour l’effet demandé ? | création automatique d’une tâche sans approbation |
Le mode JSON historique traite surtout le premier niveau. Les fonctions de sorties structurées proposées par plusieurs fournisseurs ajoutent une contrainte de schéma, avec des sous-ensembles et des interfaces qui leur sont propres. Les deux derniers niveaux restent à la charge de l’application.
Partir de la décision, pas du format
Avant d’écrire { "type": "object" }, complétez cette phrase :
À partir de cette sortie, le système pourra préparer ______, mais il ne pourra pas ______ sans ______.
Exemple : « À partir de cette sortie, le système pourra préparer une liste de tâches, mais il ne pourra pas les affecter sans validation du responsable. »
Cette phrase détermine les champs réellement nécessaires. Une sortie destinée à afficher une fiche de lecture n’a pas besoin des mêmes garanties qu’une sortie transmise à une API. Si aucun composant ne consomme une propriété, retirez-la. Chaque champ supplémentaire agrandit le contrat, le coût de test et les possibilités d’erreur.
Définissez ensuite :
- l’entrée autorisée ;
- l’unité traitée ;
- les valeurs qui peuvent manquer ;
- les contradictions à signaler ;
- les preuves attendues ;
- l’effet maximal de la sortie ;
- le responsable du contrôle.
JSON valide, schéma respecté et fait exact
Ces trois objets sont du JSON valide :
{"priority":"high"}
{"priority":4}
{"priority":"urgentissime"}
Un schéma peut n’accepter que le premier. Cela ne prouve pas que la priorité élevée est justifiée. Le modèle a peut-être mal lu le texte, confondu l’auteur d’une demande avec son destinataire ou comblé une absence.
La conformité au schéma empêche une classe d’incidents techniques. Elle ne transforme pas une génération probabiliste en base de données de référence. Google le rappelle dans sa documentation : une sortie structurée peut être syntaxiquement conforme tout en contenant des valeurs sémantiquement incorrectes. Les documentations d’OpenAI et d’Anthropic prévoient également des états où la génération peut être refusée ou interrompue.
Le système doit donc conserver deux verdicts :
schema_status: valid | invalid | unavailable
business_status: accepted | review | rejected | unknown
Choisir la bonne granularité
Une sortie trop large mélange plusieurs décisions. Une sortie trop fine multiplie les appels et perd le contexte commun. Cherchez une unité que l’on peut vérifier avec une seule source et accepter sans dépendre d’un autre objet encore inconnu.
Pour un document, cette unité peut être une affirmation, une action ou une ligne de facture, pas le dossier entier. Pour une classification, elle peut être un message avec une seule catégorie principale et un motif contrôlable. Pour une interface, elle peut être une carte prête à afficher, mais pas une suite complète d’actions.
Fixez aussi des bornes : nombre maximal d’éléments, longueur d’un libellé et profondeur d’imbrication. Ces limites facilitent la revue, le coût et les tests. Si la réponse dépasse la borne, le pipeline doit paginer, segmenter ou arrêter. Il ne doit pas couper silencieusement l’objet puis traiter ce fragment comme un résultat complet.
Construire un schéma minimal
Prenons un exemple fictif : extraire des actions à partir d’un compte rendu autorisé. Le résultat ne crée aucune tâche. Il prépare une proposition à relire.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": false,
"properties": {
"document_id": {
"type": "string",
"description": "Identifiant fourni par l’application, jamais inventé."
},
"source_status": {
"type": "string",
"enum": ["sufficient", "ambiguous", "insufficient"]
},
"actions": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"label": {"type": "string"},
"owner": {"type": ["string", "null"]},
"due_date": {"type": ["string", "null"], "format": "date"},
"evidence": {"type": "string"},
"confidence": {
"type": "string",
"enum": ["explicit", "inferred", "unknown"]
}
},
"required": ["label", "owner", "due_date", "evidence", "confidence"]
}
}
},
"required": ["document_id", "source_status", "actions"]
}
Ce schéma apporte six décisions utiles :
- l’identifiant vient de l’application ;
- l’état de la source est visible ;
- une personne et une date peuvent manquer ;
- chaque action garde un passage de preuve ;
- l’inférence est distincte de l’information explicite ;
- aucune clé improvisée n’est admise.
Les fournisseurs ne prennent pas tous en charge l’intégralité de JSON Schema. La version exacte, les mots-clés acceptés et le comportement des SDK doivent être vérifiés dans la documentation de l’API réellement utilisée. Le schéma de domaine complet peut être plus strict que le sous-ensemble transmis au modèle.
Représenter l’absence sans la faire disparaître
Un champ obligatoire ne signifie pas que la valeur existe dans la source. Si vous imposez une chaîne non vide pour owner, le modèle peut être incité à remplir le vide avec un nom plausible.
Trois stratégies sont possibles :
- valeur nulle : l’information n’existe pas ou n’a pas été trouvée ;
- statut explicite :
unknown,ambiguousounot_applicable; - objet résultat : valeur, état et preuve dans une même structure.
Pour une donnée importante, préférez l’objet résultat :
{
"value": null,
"status": "not_found",
"evidence": null
}
L’absence devient ainsi une sortie valide que le programme sait traiter. Elle ne déclenche ni valeur par défaut trompeuse, ni boucle de réparation.
Séparer extraction et décision
Demander au même appel « extrais les informations, juge leur qualité et décide de l’action » produit un contrat difficile à tester. Séparez :
- extraction des éléments présents ;
- validation locale des types ;
- vérification de cohérence ;
- application des règles déterministes ;
- revue humaine si la règle l’exige ;
- effet dans le système cible.
Un modèle peut proposer une catégorie. Le code doit refuser une catégorie inconnue. Une règle métier peut exiger une preuve explicite pour une échéance. Une personne autorisée peut enfin approuver la création de la tâche.
Cette séparation évite de cacher une décision dans un champ apparemment technique.
Sortie structurée ou appel d’outil
Les deux utilisent souvent un schéma, mais leur rôle diffère.
| Mécanisme | Question traitée | Exemple |
|---|---|---|
| sortie structurée | sous quelle forme rendre le résultat final ? | afficher une fiche d’analyse |
| appel d’outil | quelle fonction demander au programme d’exécuter ? | rechercher un statut de commande |
Un appel d’outil ne donne pas au modèle l’autorisation réelle d’agir. Le serveur doit encore authentifier, autoriser et valider les paramètres. Une sortie structurée ne doit pas être déguisée en commande si son résultat est seulement informatif.
Les documentations actuelles d’OpenAI, Anthropic et Google utilisent des noms de paramètres et des périmètres différents. Certaines distinguent la forme de la réponse finale des arguments stricts d’un outil. Évitez donc une couche d’abstraction qui prétend que tous les contrats sont identiques. Conservez une interface métier commune, puis un adaptateur testé par fournisseur.
Valider localement après la génération
Le pipeline de traitement peut rester indépendant du fournisseur :
recevoir la réponse brute et son statut
↓
détecter refus, troncature ou absence
↓
parser le JSON
↓
valider avec le schéma métier local
↓
appliquer les invariants métier
↓
vérifier preuves et autorisations
↓
préparer ou exécuter l’effet permis
La validation locale est utile même lorsque le mode strict fonctionne. Elle protège les migrations, les changements d’adaptateur, les anciennes réponses et les contraintes que le sous-ensemble du fournisseur ne sait pas exprimer.
Les invariants métier peuvent inclure :
- l’identifiant appartient au dossier demandé ;
- une date de fin ne précède pas la date de début ;
- une devise appartient à la liste autorisée ;
- la somme des lignes correspond au total ;
- une décision sensible possède un statut de revue ;
- une preuve renvoie à la source fournie ;
- aucune propriété n’augmente les permissions.
Les sept états à distinguer
Ne ramenez pas toutes les erreurs à invalid_json.
| État | Signification | Suite possible |
|---|---|---|
completed_valid | schéma et règles locales acceptés | préparer l’étape suivante |
completed_review | forme correcte, sens incertain | revue humaine |
refused | le modèle refuse la demande | arrêter ou reformuler le besoin légitime |
truncated | limite ou interruption avant la fin | reprendre selon une règle bornée |
schema_invalid | structure reçue non conforme | journaliser, éventuellement un nouvel essai |
business_invalid | objet conforme mais impossible | rejeter sans demander une correction aveugle |
source_insufficient | la source ne permet pas de répondre | demander une donnée ou accepter l’absence |
Cette taxonomie améliore les métriques. Un taux élevé de source_insufficient demande de revoir les entrées. Un taux élevé de schema_invalid indique un problème d’adaptateur ou de compatibilité. Un taux élevé de business_invalid révèle un contrat mal conçu ou une tâche trop complexe.
Encadrer les reprises
Une boucle « renvoie du JSON valide » peut coûter cher et masquer la cause. Décidez avant le déploiement :
- quels états autorisent un nouvel appel ;
- combien de tentatives sont admises ;
- si la même entrée et la même version de schéma sont conservées ;
- quel délai sépare les appels ;
- à quel moment une personne intervient ;
- quel résultat est retourné après épuisement.
Une erreur métier déterministe ne mérite pas un retry. Si end_date précède start_date, le système peut demander une clarification ou rejeter. Refaire cinq fois la même demande ne crée pas une source plus complète.
Si la sortie prépare une action externe, la reprise doit aussi respecter le protocole d’idempotence du workflow. La validité du JSON ne protège pas contre un double effet.
Versionner le schéma
Ajoutez une version contrôlée par l’application, pas inventée par le modèle :
{
"schema_version": "action-extraction/1.2",
"payload": {}
}
Une évolution est compatible si les anciens consommateurs peuvent encore lire le résultat. Renommer une clé, rendre un champ obligatoire ou changer le sens d’une valeur demande une migration.
Avant de publier une nouvelle version :
- rejouez les cas de référence ;
- validez les anciennes réponses ;
- testez le nouvel adaptateur de chaque fournisseur ;
- comparez les décisions métier, pas seulement la conformité ;
- prévoyez le retour à la version précédente ;
- changez la documentation et les exemples ensemble.
Ne laissez pas le modèle choisir la version. L’application sait quel contrat elle a envoyé et doit l’attacher au journal.
Les quinze tests avant production
- la réponse contient exactement les champs attendus ;
- une propriété supplémentaire est refusée ;
- un champ requis absent produit un état distinct ;
- une chaîne à la place d’un entier est bloquée ;
- une valeur hors
enumest bloquée ; - une information absente reste nulle ou inconnue ;
- une date impossible est rejetée localement ;
- une contradiction entre deux champs est détectée ;
- une preuve inexistante empêche l’acceptation ;
- un refus du modèle n’est pas parsé comme un résultat ;
- une réponse tronquée n’est pas exécutée ;
- une entrée très longue respecte les limites prévues ;
- une nouvelle version de schéma ne casse pas les anciennes données ;
- deux appels identiques ne créent pas deux effets ;
- une sortie correcte mais non autorisée reste sans effet.
Construisez les cas à partir d’erreurs plausibles : champ manquant, ambiguïté, source contradictoire, mauvaise unité et identifiant voisin. Un jeu composé uniquement d’exemples parfaits mesure surtout la capacité du développeur à écrire des démonstrations.
Les métriques qui aident à corriger
Suivez par version de schéma et par adaptateur :
- taux de réponses complètes ;
- taux de conformité locale ;
- erreurs par propriété ;
- refus et interruptions ;
- valeurs inconnues ;
- rejets métier ;
- passages en revue humaine ;
- retries par cause ;
- temps jusqu’à un résultat utilisable ;
- erreurs découvertes après acceptation.
Le dernier indicateur est le plus important. Un pipeline peut afficher 100 % de JSON conformes et continuer à produire de mauvaises décisions.
Journalisez des statuts, versions, empreintes et références. N’enregistrez pas automatiquement le contenu brut, les secrets ou les données personnelles pour faciliter le diagnostic.
Limites
Les sorties structurées dépendent du modèle, de l’API, du SDK et du sous-ensemble de JSON Schema pris en charge au moment de l’appel. Les paramètres, modèles compatibles, limites de complexité et comportements de refus peuvent évoluer. Vérifiez la documentation du fournisseur et verrouillez les versions utilisées.
Un schéma ne contrôle ni l’exactitude d’un fait, ni la qualité d’une source, ni la légitimité d’un traitement, ni l’autorisation d’une action. Il ne remplace pas les tests métier, les contrôles d’accès, la minimisation des données, la supervision et la gestion des incidents.
Les exemples de ce guide sont pédagogiques. Ils doivent être adaptés au format réellement accepté par l’API choisie et validés avec une bibliothèque maintenue. Aucun code de démonstration ne doit être branché directement à une production ou à des données sensibles.
Enfin, une structure trop détaillée peut dégrader la maintenabilité et pousser le modèle à remplir des champs inutiles. Le meilleur schéma est le plus petit contrat qui permet une décision sûre et observable.
À propos de l’auteur
Je suis Ayoub Kahouadji, développeur Python, formateur et consultant IA. Je conçois des workflows où les propositions du modèle restent séparées des règles métier, des autorisations et des effets externes.
Prochaine étape
Choisissez une sortie aujourd’hui lue par votre code. Réduisez-la à cinq champs, ajoutez un état d’absence et une preuve, puis exécutez les tests 3, 8, 10 et 15. Pour cadrer l’intégration complète, consultez la page automatisation IA et Python.
Sources vérifiées
- Structured model outputs , consultée le 1 août 2026
- Structured outputs , consultée le 1 août 2026
- Structured outputs , consultée le 1 août 2026
- JSON Schema Draft 2020-12 , consultée le 1 août 2026
- RFC 8259, The JavaScript Object Notation Data Interchange Format , consultée le 1 août 2026