Structured outputs et JSON schema : la méthode fiable pour intégrer un LLM dans un workflow métier

Combien de pipelines LLM se cassent chaque semaine en production parce qu’un modèle a répondu « Voici le JSON demandé : » suivi d’un backtick manquant, d’une virgule en trop ou d’un commentaire en français au milieu de l’objet attendu ? Pendant des années, les équipes ont colmaté ce problème avec des parseurs tolérants, du prompt engineering défensif et des couches de retry. Les structured outputs, désormais exposés nativement par les principaux fournisseurs d’API (OpenAI, Anthropic, Google, Mistral) via la contrainte sur un JSON schema, règlent définitivement cette classe de bugs. En 2026, intégrer un LLM dans un workflow métier critique sans utiliser cette capacité est un choix architectural difficile à défendre. Fine-tuning d'embeddings : adapter un modèle de retrieval à votre domaine métier

À retenir en 30 secondes : les structured outputs forcent la sortie du LLM à respecter un JSON schema fourni par l’appelant. La contrainte est appliquée au niveau de la génération (constrained decoding) et non en post-traitement : le modèle ne peut produire que des tokens compatibles avec le schéma à chaque étape. Le résultat est garanti valide — pas de parseur à écrire, pas de retry sur erreur de format, pas de hallucination de champs manquants.

Comment fonctionne le constrained decoding sous le capot

À chaque étape de génération, un LLM produit une distribution de probabilités sur l’ensemble du vocabulaire (typiquement 100 000 à 200 000 tokens). Le décodeur sélectionne ensuite le token suivant selon cette distribution (greedy, top-k, nucleus, etc.). Le constrained decoding intervient à cette étape en masquant à zéro les probabilités des tokens incompatibles avec la grammaire du JSON schema à l’instant t. Si l’état courant du JSON exige par exemple l’ouverture d’un objet, seuls les tokens correspondant à « { » et aux espaces sont autorisés. Si une clé « email » est attendue, seuls les tokens formant une chaîne encadrée par des guillemets sont valides.

Cette contrainte est appliquée via un automate à états finis dérivé du schéma, ce qui garantit la conformité syntaxique à chaque pas. Les enums, les patterns regex, les types imbriqués et les tableaux fermés sont tous supportés. En revanche, les contraintes sémantiques (par exemple « email valide ») restent du ressort du modèle lui-même : le format est garanti, pas la véracité du contenu. Ce principe se marie naturellement avec le function calling classique dans les LLMs, qui est en pratique un cas particulier de structured output : le modèle produit un objet JSON décrivant l’appel de fonction à exécuter.

Trois patterns d’intégration en workflow métier

Pattern 1 : extraction d’informations à partir d’un document. Un contrat, une facture, un email : le LLM reçoit le document brut et un schéma d’extraction (champs attendus, types, cardinalités), et renvoie un objet strictement conforme. Les équipes qui pratiquent ce pattern obtiennent typiquement un taux de validité à 100 % (versus 85 à 95 % en prompt libre), ce qui change radicalement l’architecture downstream : plus besoin de couche de validation ni de retry. Prompt Engineering : guide complet

Pattern 2 : routage de requêtes utilisateur vers une API métier. Le LLM traduit une demande en langage naturel en appel structuré d’un service interne. Le schéma décrit les paramètres acceptés, les énumérations possibles pour chaque champ, et les contraintes de cardinalité. Le résultat est directement exécutable, sans couche d’adaptation.

Pattern 3 : génération de contenu structuré (fiche produit, résumé exécutif à sections fixes, rapport d’audit). Chaque section devient un champ typé du schéma, et le LLM produit l’ensemble en un seul appel. Ce pattern se combine très bien avec le système de guardrails en production pour valider sémantiquement chaque champ avant diffusion.

Concevoir un bon JSON schema : les règles pratiques

Le schéma transporte à la fois la contrainte syntaxique et une partie de l’intention métier. Trois règles pratiques émergent de nos retours d’expérience. Premièrement, décrire chaque champ via la propriété description : le LLM utilise ces descriptions pour comprendre la sémantique attendue, elles sont au moins aussi importantes que les types eux-mêmes. Deuxièmement, préférer les enums aux chaînes libres quand les valeurs possibles sont bornées : la contrainte devient absolue et élimine les variations orthographiques. Troisièmement, marquer les champs optionnels explicitement plutôt que de laisser le modèle deviner : certains fournisseurs exigent par défaut que tous les champs du schéma soient présents dans la sortie, ce qui peut forcer des hallucinations si le document source ne contient pas l’information.

Pydantic et génération automatique de schémas en Python

L’intégration la plus propre en Python passe par Pydantic : vous définissez un modèle Pydantic qui représente la sortie attendue, et vous laissez la bibliothèque générer le JSON schema à partir des annotations de type. Côté SDK, OpenAI, Anthropic et Mistral acceptent directement un modèle Pydantic en argument. Cette approche élimine la duplication entre la définition du schéma et la définition du type côté application, et garantit que le code consommateur manipule des objets fortement typés plutôt que des dicts anonymes. Combinée à la validation Pydantic en sortie, elle fournit une double protection : syntaxique (via la contrainte de génération) et sémantique (via les validators Pydantic).

Pour aller plus loin sur les mécaniques d’évaluation et de robustesse qui accompagnent cette discipline, consultez notre guide d’évaluation de la qualité d’un LLM avant déploiement, ainsi que la documentation officielle d’OpenAI sur les structured outputs.

Les limites à connaître avant de généraliser

Les structured outputs ont deux coûts qu’il faut peser. Premièrement, un surcoût d’inférence : la contrainte via automate ajoute quelques pourcents de latence (généralement 5 à 15 %), et certains fournisseurs facturent légèrement plus cher les requêtes avec schéma. Deuxièmement, un risque de dégradation qualitative dans les cas où le schéma est mal calibré : forcer un champ obligatoire que le document source ne contient pas pousse le modèle à inventer une valeur plausible — c’est une hallucination structurée, parfois plus difficile à détecter qu’une hallucination libre. Marquer correctement les champs optionnels, prévoir une valeur sentinel (« unknown ») pour l’absence d’information, et évaluer rigoureusement la cohérence sémantique de chaque champ restent indispensables. Caching sémantique pour LLMs : réduire latence et coûts d'inférence sans sacrifier la pertinence

Mon point de vue d’expert

Je conseille systématiquement aux équipes françaises que j’accompagne d’adopter les structured outputs dès que le résultat du LLM est consommé par un autre système (base de données, API aval, workflow BPM). La règle est simple : si vous écrivez du code qui parse la sortie du LLM, vous auriez dû utiliser un schéma. Vous gagnerez en robustesse, en vitesse d’intégration, et vous rendrez votre pipeline testable de manière déterministe. En revanche, pour les sorties destinées à un humain (rédaction, synthèse, dialogue), le texte libre reste préférable — la contrainte structurée dégrade souvent la qualité conversationnelle. Le discernement entre les deux cas d’usage est l’une des compétences architecturales clés d’une équipe LLM mature.

FAQ : structured outputs et JSON schema

Structured outputs et function calling, quelle différence ?
Le function calling est un cas particulier de structured output : le modèle produit un objet JSON décrivant un appel de fonction (nom + paramètres). Les structured outputs généralisent cette capacité à n’importe quelle structure de données définie par un JSON schema. En pratique, les deux mécanismes partagent la même implémentation sous le capot (contrainte sur le décodage) chez la plupart des fournisseurs.
La qualité des réponses est-elle dégradée par la contrainte ?
Dans les cas où le schéma est bien calibré sur la tâche, la qualité est équivalente voire supérieure (le modèle n’a plus à gérer la mise en forme). Dans les cas où le schéma impose des champs incohérents avec la demande, la qualité peut chuter car le modèle est forcé de produire une valeur même en l’absence d’information. La clé est de concevoir le schéma en pensant aux cas de nullité réels.
Tous les modèles supportent-ils les structured outputs ?
Les principaux fournisseurs cloud (OpenAI, Anthropic, Google, Mistral) les proposent nativement depuis 2024-2025. Côté open source, vLLM, llama.cpp et SGLang supportent les mêmes contraintes via des bibliothèques comme Outlines ou LMFE. Pour les modèles plus anciens, un fallback via prompt engineering + validateur strict reste nécessaire, mais avec une fiabilité moindre.
Peut-on imposer des contraintes sémantiques en plus du format ?
Le schéma garantit la conformité syntaxique (types, champs obligatoires, enums, regex). La conformité sémantique (par exemple cohérence métier entre deux champs, plausibilité d’une valeur) reste du ressort de la validation applicative. L’approche recommandée est de combiner structured outputs côté LLM et validators Pydantic ou JSON schema custom côté application, pour obtenir une double protection.