JSON mode et schema enforcement
JSON mode et schema enforcement
Le Structured Output d’OpenAI garantit que la réponse du modèle est un JSON valide conforme à un schéma que vous définissez. Fini le parsing fragile avec des regex ou les erreurs de format — le modèle est contraint au niveau de la génération elle-même.
JSON mode vs Structured Output
OpenAI propose deux niveaux de contrainte :
- JSON mode : garantit un JSON valide, mais sans contrainte de structure
- Structured Output : garantit un JSON conforme à un JSON Schema spécifique
from openai import OpenAI
client = OpenAI()
# JSON mode simple (JSON valide, structure libre)
response = client.responses.create(
model="gpt-5.3",
instructions="Réponds toujours en JSON.",
input="Liste 3 langages de programmation avec leur année de création.",
text={"format": {"type": "json_object"}}
)
import json
data = json.loads(response.output_text)
print(data)
Structured Output avec JSON Schema
C’est la fonctionnalité la plus puissante. Vous définissez un schéma JSON, et l’API garantit que la sortie le respecte :
response = client.responses.create(
model="gpt-5.3",
input="Analyse le sentiment de : 'Le produit est excellent "
"mais la livraison était catastrophique.'",
text={
"format": {
"type": "json_schema",
"name": "sentiment_analysis",
"schema": {
"type": "object",
"properties": {
"sentiment": {
"type": "string",
"enum": ["positif", "negatif", "mixte", "neutre"]
},
"score": {
"type": "number",
"description": "Score de -1.0 (très négatif) à 1.0 (très positif)"
},
"aspects": {
"type": "array",
"items": {
"type": "object",
"properties": {
"aspect": {"type": "string"},
"sentiment": {
"type": "string",
"enum": ["positif", "negatif", "neutre"]
}
},
"required": ["aspect", "sentiment"],
"additionalProperties": False
}
},
"resume": {"type": "string"}
},
"required": ["sentiment", "score", "aspects", "resume"],
"additionalProperties": False
},
"strict": True
}
}
)
result = json.loads(response.output_text)
# Garanti : result a exactement les champs définis
print(f"Sentiment : {result['sentiment']}")
print(f"Score : {result['score']}")
for aspect in result["aspects"]:
print(f" - {aspect['aspect']}: {aspect['sentiment']}")
Règles du Structured Output strict
Le mode strict: true impose des contraintes sur le schéma :
- Tous les champs doivent être dans
required additionalPropertiesdoit êtrefalsesur chaque objet- Les types supportés :
string,number,integer,boolean,array,object,null - Les
enumsont supportés pour contraindre les valeurs - Pas de
patternni deminLength/maxLength(la validation fine se fait côté client)
Helper pour construire les schémas
def structured_query(prompt: str, schema: dict,
schema_name: str = "response",
model: str = "gpt-5.3",
system: str = "") -> dict:
"""Wrapper pour les requêtes Structured Output."""
response = client.responses.create(
model=model,
instructions=system or "Réponds en JSON selon le schéma fourni.",
input=prompt,
text={
"format": {
"type": "json_schema",
"name": schema_name,
"schema": schema,
"strict": True
}
},
temperature=0.1
)
return json.loads(response.output_text)
Exemple : extraction de données structurées
invoice_schema = {
"type": "object",
"properties": {
"numero_facture": {"type": "string"},
"date": {"type": "string"},
"fournisseur": {
"type": "object",
"properties": {
"nom": {"type": "string"},
"siret": {"type": "string"},
"adresse": {"type": "string"}
},
"required": ["nom", "siret", "adresse"],
"additionalProperties": False
},
"lignes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"description": {"type": "string"},
"quantite": {"type": "integer"},
"prix_unitaire_ht": {"type": "number"},
"tva_pourcent": {"type": "number"}
},
"required": ["description", "quantite",
"prix_unitaire_ht", "tva_pourcent"],
"additionalProperties": False
}
},
"total_ht": {"type": "number"},
"total_ttc": {"type": "number"}
},
"required": ["numero_facture", "date", "fournisseur",
"lignes", "total_ht", "total_ttc"],
"additionalProperties": False
}
facture_text = """
Facture N° 2026-0042
Date : 15/03/2026
Fournisseur : TechServ SARL, SIRET 123 456 789 00012
12 rue de la Paix, 75002 Paris
- Développement API REST x1 : 3500.00 EUR HT (TVA 20%)
- Hébergement cloud (3 mois) x1 : 450.00 EUR HT (TVA 20%)
- Support technique x10h : 150.00 EUR HT/h (TVA 20%)
Total HT : 5450.00 EUR
Total TTC : 6540.00 EUR
"""
result = structured_query(
facture_text,
invoice_schema,
schema_name="invoice",
system="Extrais les données de cette facture."
)
Mise en pratique
- Définissez un schéma JSON pour extraire les informations clés d’un CV (nom, expériences, compétences, formation)
- Testez avec 3 CV différents en texte brut
- Vérifiez que la sortie respecte systématiquement le schéma
- Comparez avec une extraction sans Structured Output
Points clés à retenir
- Le Structured Output garantit un JSON conforme au schéma au niveau de la génération
- Utilisez
strict: truepour la conformité maximale - Tous les champs doivent être
requiredavecadditionalProperties: false - Idéal pour l’extraction de données, la classification, les pipelines de traitement
- La validation fine (longueur, pattern) se fait côté client après réception