Structured Output : Forcez l'IA à parler JSON
Si vous avez déjà essayé d'intégrer une réponse d'IA directement dans une application classique (Web ou Mobile), vous avez obligatoirement rencontré cette erreur dans vos logs serveur :
SyntaxError: Unexpected token 'V', "Voici le J"... is not valid JSON
Que s'est-il passé ? Vous avez demandé à l'IA de vous renvoyer un objet JSON contenant le nom et l'âge d'un utilisateur. Et l'IA, dans son élan de politesse infinie, a répondu :
"Voici le JSON que vous avez demandé :
json { "nom": "Paul", "age": 32 }
J'espère que cela vous aide !"
Votre backend a tenté de parser cette phrase avec JSON.parse(). Et votre backend a crashé.
Un développeur ne prie pas pour que l'API réponde correctement 95% du temps. Un développeur veut du déterminisme. Voici comment l'obtenir.
1. La limite du "Prompting"
Au début, tout le monde essaie de régler ce problème avec du texte. On ajoute des phrases en majuscules dans le prompt :
"TU DOIS RÉPONDRE UNIQUEMENT EN JSON. N'AJOUTE AUCUN TEXTE AVANT OU APRÈS."
Ça fonctionne... la plupart du temps. Mais le jour où l'IA rencontre un cas limite (edge case), elle "sortira de son personnage" pour vous expliquer pourquoi elle ne peut pas le faire, brisant ainsi votre code.
Le format de sortie ne doit pas être une consigne textuelle. Cela doit être une contrainte technique au niveau de l'API.
2. Structured Outputs et Pydantic
Depuis mi-2024, les grands fournisseurs (OpenAI & Anthropic par exemple) ont introduit une fonctionnalité pour les développeurs : les Structured Outputs.
L'idée est de passer un Schéma de données directement dans la requête API, et le moteur d'inférence s'auto-restreindra mathématiquement pour ne générer que des caractères qui respectent ce schéma.
Pour faire cela proprement en Python, l'industrie standard est d'utiliser Pydantic, une librairie de validation de données.
3. Pratique : Le code qui ne crashe jamais
Oubliez les prompts angoissés. Voici comment on extrait des données d'un texte de manière 100% déterministe avec l'API OpenAI. Sauvegardez ce fichier dans app.py et lancez-le avec uv run app.py (l'outil téléchargera les dépendances à la volée).
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "openai",
# "pydantic",
# ]
# ///
import os
from pydantic import BaseModel
from openai import OpenAI
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key="sk-...",
)
# 1. On définit notre contrat de données (Le Schéma)
class ProfilUtilisateur(BaseModel):
nom: str
age: int
tags_hobbies: list[str]
est_premium: bool
texte_brut = "Hier j'ai discuté avec Marc, il vient d'avoir 28 ans. Il adore le tennis et la lecture, mais il refuse toujours de payer l'abonnement pro."
# 2. On appelle l'API en forçant le format de réponse
response = client.beta.chat.completions.parse(
model="qwen/qwen3-4b:free",
messages=[
{"role": "system", "content": "Extrait les informations du profil utilisateur."},
{"role": "user", "content": texte_brut}
],
response_format=ProfilUtilisateur, # <-- La magie opère ici
)
# 3. L'objet retourné est DÉJÀ typé et validé !
profil = response.choices[0].message.parsed
print(f"Nom extrait : {profil.nom} (Type: {type(profil.nom)})")
print(f"Premium ? : {profil.est_premium} (Type: {type(profil.est_premium)})")
# Output garanti :
# Nom extrait : Marc (Type: <class 'str'>)
# Premium ? : False (Type: <class 'bool'>)
Avec response_format, l'IA est physiquement incapable de générer du texte autour du JSON, ou d'oublier la clé tags_hobbies. Si elle ne trouve pas de hobbies, elle renverra une liste vide [], mais la clé sera là. Votre code applicatif est sauf.
4. JSON Mode vs Structured Output
Attention à la confusion dans la documentation des APIs.
Il existe souvent un paramètre simple appelé response_format={"type": "json_object"} (le JSON Mode). Ce mode garantit que la réponse sera un JSON valide, mais il ne garantit pas la présence de vos clés ! L'IA pourrait renvoyer {"utilisateur": "Marc", "annees": 28} au lieu de {"nom": "Marc", "age": 28}.
Utilisez toujours les Structured Outputs (via Pydantic ou Zod en JS) qui imposent le nom et le type exact de chaque variable.
L'essentiel en 3 points
✅ Ne suppliez pas : Un prompt en majuscules "ONLY JSON" n'est pas une garantie technique, c'est un vœu pieux.
✅ Imposez le schéma : Utilisez les Structured Outputs de l'API pour contraindre mathématiquement la réponse de l'IA.
✅ Typage fort : Utilisez Pydantic (Python) ou Zod (JavaScript) pour lier directement la réponse de l'IA à vos modèles de données internes.
Et après ?
Félicitations, vous savez maintenant appeler une IA proprement, gérer sa mémoire, réduire ses coûts, et typer sa réponse en JSON.
Mais si demain OpenAI met à jour son modèle, ou si vous modifiez une virgule de votre prompt système, comment être certain que votre extraction Pydantic fonctionne toujours aussi bien sur vos 1000 cas de test ? Dans le dernier article de cette série, nous allons voir comment sécuriser vos déploiements avec le Test-Driven Prompting (Evals).
Top comments (0)