Structured Output : JSON garanti
Structured Output : JSON garanti
Le Structured Output est l’une des fonctionnalités les plus puissantes de la Responses API. Au lieu d’espérer que le modèle retourne du JSON valide, vous le garantissez en fournissant un schéma. Le modèle est contraint structurellement de respecter ce schéma.
Le problème sans Structured Output
from openai import OpenAI
client = OpenAI()
# Sans structure — le modèle peut retourner n'importe quel format
response = client.responses.create(
model="gpt-5.3",
input="Donnez-moi les infos sur Paris en JSON."
)
print(response.output_text)
# Résultat imprévisible :
# Parfois du JSON valide, parfois du texte avec du JSON,
# parfois un format inattendu...
Structured Output avec un schéma JSON
response = client.responses.create(
model="gpt-5.3",
input="Donnez-moi les informations sur Paris.",
text={
"format": {
"type": "json_schema",
"name": "ville_info",
"strict": True,
"schema": {
"type": "object",
"properties": {
"nom": {"type": "string"},
"pays": {"type": "string"},
"population": {"type": "integer"},
"langue_officielle": {"type": "string"},
"monuments": {
"type": "array",
"items": {"type": "string"}
}
},
"required": ["nom", "pays", "population", "langue_officielle", "monuments"],
"additionalProperties": False
}
}
}
)
import json
data = json.loads(response.output_text)
print(f"Ville : {data['nom']}")
print(f"Population : {data['population']:,}")
print(f"Monuments : {', '.join(data['monuments'])}")
# Résultat GARANTI en JSON valide :
# Ville : Paris
# Population : 2,161,000
# Monuments : Tour Eiffel, Louvre, Notre-Dame, Arc de Triomphe, Sacre-Coeur
Utiliser Pydantic pour les schémas
Pydantic simplifie la définition des schémas et la validation :
from pydantic import BaseModel
from typing import Optional
import json
class Produit(BaseModel):
nom: str
prix: float
categorie: str
en_stock: bool
description: Optional[str] = None
response = client.responses.create(
model="gpt-5.3",
input="Décrivez un ordinateur portable gaming haut de gamme.",
text={
"format": {
"type": "json_schema",
"name": "produit",
"strict": True,
"schema": Produit.model_json_schema()
}
}
)
# Parser et valider avec Pydantic
produit = Produit.model_validate_json(response.output_text)
print(f"Produit : {produit.nom}")
print(f"Prix : {produit.prix} EUR")
print(f"En stock : {'Oui' if produit.en_stock else 'Non'}")
# Résultat :
# Produit : ASUS ROG Strix G18
# Prix : 2499.99 EUR
# En stock : Oui
Schémas imbriqués
Vous pouvez créer des structures complexes :
from pydantic import BaseModel
class Adresse(BaseModel):
rue: str
ville: str
code_postal: str
pays: str
class Contact(BaseModel):
nom: str
prenom: str
email: str
telephone: str
adresse: Adresse
class Entreprise(BaseModel):
nom: str
secteur: str
employes: int
contacts: list[Contact]
response = client.responses.create(
model="gpt-5.3",
input="Générez une fiche entreprise fictive dans le secteur tech "
"avec 2 contacts.",
text={
"format": {
"type": "json_schema",
"name": "entreprise",
"strict": True,
"schema": Entreprise.model_json_schema()
}
}
)
entreprise = Entreprise.model_validate_json(response.output_text)
print(f"Entreprise : {entreprise.nom} ({entreprise.secteur})")
for c in entreprise.contacts:
print(f" - {c.prenom} {c.nom} : {c.email}")
Cas d’usage courants
Extraction de données depuis du texte
class Evenement(BaseModel):
titre: str
date: str
lieu: str
participants: int
texte = """
La conférence PyCon France 2026 se tiendra les 15 et 16 novembre
au Palais des Congrès de Lyon. Plus de 800 développeurs Python
sont attendus pour cette édition.
"""
response = client.responses.create(
model="gpt-5.3",
input=f"Extrayez les informations de cet événement :\n{texte}",
text={
"format": {
"type": "json_schema",
"name": "evenement",
"strict": True,
"schema": Evenement.model_json_schema()
}
}
)
evt = Evenement.model_validate_json(response.output_text)
print(f"{evt.titre} - {evt.date} a {evt.lieu} ({evt.participants} participants)")
# Résultat : PyCon France 2026 - 15-16 novembre 2026 a Lyon (800 participants)
Classification avec enum
from enum import Enum
class Sentiment(str, Enum):
positif = "positif"
negatif = "negatif"
neutre = "neutre"
class Analyse(BaseModel):
sentiment: Sentiment
confiance: float
mots_cles: list[str]
response = client.responses.create(
model="gpt-5.3",
input="Analysez ce commentaire : 'Super service, livraison rapide !'",
text={
"format": {
"type": "json_schema",
"name": "analyse_sentiment",
"strict": True,
"schema": Analyse.model_json_schema()
}
}
)
analyse = Analyse.model_validate_json(response.output_text)
print(f"Sentiment : {analyse.sentiment.value} ({analyse.confiance:.0%})")
# Résultat : Sentiment : positif (95%)
Règles importantes pour les schémas strict
Quand strict: True, certaines contraintes s’appliquent :
- Toutes les propriétés doivent être dans
required additionalPropertiesdoit êtreFalse- Les types supportés :
string,number,integer,boolean,array,object,null - Pas de
oneOf,anyOfavec des types mixtes - Utilisez
Optional[str]qui se traduit par{"anyOf": [{"type": "string"}, {"type": "null"}]}
Points clés à retenir
- Le Structured Output garantit que la réponse respecte votre schéma JSON
- Utilisez
text={"format": {"type": "json_schema", ...}}dans la Responses API - Pydantic est l’outil idéal pour définir et valider les schémas
- Activez
strict: Truepour la conformité garantie du schéma - Idéal pour l’extraction de données, la classification et la génération structurée