Apprenez à forcer l'API de l'IA à vous répondre exclusivement dans un format JSON strict et validé
Source: Dev.to
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 (Web ou Mobile), vous avez sûrement vu cette erreur dans vos logs serveur :
SyntaxError: Unexpected token 'V', "Voici le J"... is not valid JSONVous avez demandé à l’IA de renvoyer un objet JSON contenant le nom et l’âge d’un utilisateur, et elle a répondu :
« Voici le JSON que vous avez demandé :
json { "nom": "Paul", "age": 32 }
J’espère que cela vous aide ! »
Le backend a tenté de parser cette phrase avec JSON.parse() et a planté.
Un développeur ne peut pas se contenter d’une réponse correcte 95 % du temps ; il a besoin de déterminisme. Voici comment l’obtenir.
1. La limite du Prompting
Au départ, on ajoute des consignes en majuscules dans le prompt :
"TU DOIS RÉPONDRE UNIQUEMENT EN JSON. N'AJOUTE AUCUN TEXTE AVANT OU APRÈS."Cela fonctionne la plupart du temps, mais face à un edge case l’IA peut sortir de son rôle et expliquer pourquoi elle ne peut pas répondre, brisant ainsi votre code.
Le format de sortie ne doit pas être une simple consigne textuelle ; il doit être une contrainte technique au niveau de l’API.
2. Structured Outputs et Pydantic
Depuis mi‑2024, les grands fournisseurs (OpenAI, Anthropic, …) proposent les Structured Outputs.
Vous transmettez un schéma de données directement dans la requête API, et le moteur s’auto‑restreint pour ne générer que des caractères respectant ce schéma.
En Python, l’outil standard est Pydantic, une bibliothèque de validation de données.
3. Pratique : Le code qui ne crashe jamais
Oubliez les prompts anxiogènes. Voici un exemple complet qui extrait des informations d’un texte de manière 100 % déterministe avec l’API OpenAI. Enregistrez‑le dans app.py et lancez‑le avec uv run app.py (les dépendances seront installées à 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. Définir le 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. Appeler 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, # )
# Premium ? : False (Type: )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 aucun hobby n’est trouvé, elle renverra une liste vide [], mais la clé sera toujours présente. Votre code applicatif est donc à l’abri des plantages.
4. JSON Mode vs Structured Output
La documentation des API mentionne souvent un paramètre simple :
{"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}.
Il faut donc privilégier les Structured Outputs (via Pydantic, Zod en JavaScript, etc.) 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 : servez‑vous de 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.
Pour aller plus loin : comment garantir que votre extraction Pydantic reste fiable après une mise à jour du modèle ou une modification du prompt ? Le prochain article de la série abordera la sécurisation des déploiements avec le Test‑Driven Prompting (Evals).