Comparaison structurée des sorties parmi les fournisseurs d'LLM populaires - OpenAI, Gemini, Anthropic, Mistral et AWS Bedrock
Les API légèrement différentes nécessitent une approche spécifique.
Voici une comparaison côte à côte du support de sortie structurée (obtenir un JSON fiable) auprès des fournisseurs d’LLM populaires, ainsi que des exemples minimalistes en Python
Nous avons déjà vu comment demander une sortie structurée à l’LLM hébergé sur Ollama. Ici, nous examinons comment demander la même chose auprès d’autres fournisseurs.
TL;DR matrice
Fournisseur | Mode JSON natif | Contrainte de schéma JSON | Knob typique | Notes |
---|---|---|---|---|
OpenAI | Oui | Oui (premier plan) | response_format={"type":"json_schema", ...} |
Fonctionne via l’API des Réponses ou les Complétions de Chat ; peut également faire des appels de fonction. |
Google Gemini | Oui | Oui (premier plan) | response_schema= + response_mime_type="application/json" |
Retourne strictement du JSON validé lorsqu’un schéma est défini. |
Anthropic (Claude) | Indirect | Oui (via Utilisation d’outils avec un schéma JSON) | tools=[{input_schema=...}] + tool_choice |
Force le modèle à « appeler » votre outil défini par le schéma ; produit des arguments conformes au schéma. |
Mistral | Oui | Partiel (seulement JSON ; aucun schéma côté serveur) | response_format={"type":"json_object"} |
Assure le JSON, mais vous validez contre votre schéma côté client. |
AWS Bedrock (plateforme) | Varie selon le modèle | Oui (via le schéma d’outil/Converse) | toolConfig.tools[].toolSpec.inputSchema |
L’API Converse de Bedrock valide l’entrée de l’outil contre un schéma JSON. |
Sortie structurée des LLM - Informations générales
La sortie structurée des LLM désigne la capacité des grands modèles de langage (LLMs) à générer des réponses qui respectent strictement un format ou une structure prédéfini, plutôt que de produire un texte libre. Cette sortie structurée peut être au format JSON, XML, tableaux ou modèles, rendant les données lisible par machine, cohérentes et facilement parsables par des logiciels pour être utilisées dans diverses applications.
Contrairement aux sorties traditionnelles des LLM, qui génèrent généralement du texte libre et naturel, les sorties structurées imposent un schéma ou un format, comme des objets JSON avec des clés et types de valeur définis, ou des classes spécifiques dans la sortie (par exemple, des réponses à choix multiples, des classes de sentiment ou des formats de lignes de base de données). Cette approche améliore la fiabilité, réduit les erreurs et les hallucinations, et simplifie l’intégration dans des systèmes tels que les bases de données, les API ou les workflows.
La génération de sorties structurées dans les LLM implique souvent des techniques telles que :
- La spécification d’instructions détaillées pour guider le modèle à produire une sortie dans le format souhaité.
- L’utilisation d’outils de validation et de parsing comme Pydantic en Python pour s’assurer que la sortie correspond au schéma.
- Parfois, l’imposition de contraintes de décodage basées sur la grammaire ou des machines à états finis pour assurer la conformité au format au niveau des tokens.
Les avantages des sorties structurées des LLM incluent :
- La lisibilité par machine et l’intégration facile.
- La réduction de la variabilité et des erreurs.
- Une meilleure prévisibilité et vérifiabilité pour les tâches nécessitant des formats de données cohérents.
Les défis incluent la conception d’efficaces schémas, la gestion de données complexes imbriquées, et les limites potentielles en matière de raisonnement par rapport à la génération de texte libre.
En général, la sortie structurée permet aux LLM d’être plus utiles dans les applications nécessitant des données précises et formatées plutôt que uniquement du texte lisible par l’homme.
Exemples de sortie structurée en Python
Tous les extraits extraient l’événement sous forme de JSON : {title, date, location}
. Remplacez les clés/modèles selon vos besoins.
1) OpenAI — Schéma JSON (strict)
from openai import OpenAI
import json
client = OpenAI()
schema = {
"name": "Event",
"schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"date": {"type": "string", "description": "YYYY-MM-DD"},
"location": {"type": "string"}
},
"required": ["title", "date", "location"],
"additionalProperties": False
},
"strict": True
}
resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "user", "content": "Extraire l’événement à partir de : 'PyData Sydney est le 2025-11-03 à Darling Harbour.'"}
],
response_format={"type": "json_schema", "json_schema": schema},
)
data = json.loads(resp.choices[0].message.content)
print(data)
La fonction Sorties Structurées d’OpenAI impose ce schéma côté serveur.
2) Google Gemini — schéma de réponse + MIME JSON
import google.generativeai as genai
from google.genai import types
# Configurez avec votre clé API
# genai.configure(api_key="your-api-key")
schema = types.Schema(
type=types.Type.OBJECT,
properties={
"title": types.Schema(type=types.Type.STRING),
"date": types.Schema(type=types.Type.STRING),
"location": types.Schema(type=types.Type.STRING),
},
required=["title", "date", "location"],
additional_properties=False,
)
resp = genai.generate_content(
model="gemini-2.0-flash",
contents="Extraire l’événement à partir de : 'PyData Sydney est le 2025-11-03 à Darling Harbour.'",
generation_config=genai.GenerationConfig(
response_mime_type="application/json",
response_schema=schema,
),
)
print(resp.text) # déjà du JSON valide selon le schéma
Gemini retournera du JSON strict qui correspond à response_schema
.
3) Anthropic (Claude) — Utilisation d’outils avec schéma JSON
from anthropic import Anthropic
import json
client = Anthropic()
tool = {
"name": "extract_event",
"description": "Retourner les détails de l’événement.",
"input_schema": {
"type": "object",
"properties": {
"title": {"type": "string"},
"date": {"type": "string"},
"location": {"type": "string"}
},
"required": ["title", "date", "location"],
"additionalProperties": False
}
}
msg = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=256,
tools=[tool],
tool_choice={"type": "tool", "name": "extract_event"}, # forcer le schéma
messages=[{"role": "user", "content":
"Extraire l’événement à partir de : 'PyData Sydney est le 2025-11-03 à Darling Harbour.'"}],
)
# Claude "appellera" l’outil ; récupérez les arguments (qui correspondent à votre schéma)
tool_use = next(b for b in msg.content if b.type == "tool_use")
print(json.dumps(tool_use.input, indent=2))
Claude n’a pas de commutateur de mode JSON générique ; au lieu de cela, l’utilisation d’outils avec un input_schema
vous donne des arguments validés et conformes au schéma (et vous pouvez forcer son utilisation).
4) Mistral — mode JSON (validation côté client)
from mistralai import Mistral
import json
client = Mistral()
resp = client.chat.complete(
model="mistral-large-latest",
messages=[{"role":"user","content":
"Retourner un JSON avec les clés title, date (YYYY-MM-DD), location pour : "
"'PyData Sydney est le 2025-11-03 à Darling Harbour.'"}],
response_format={"type": "json_object"} # garantit un JSON valide
)
data = json.loads(resp.choices[0].message.content)
print(data)
# Astuce : valider `data` contre votre schéma Pydantic/JSON localement.
Le json_object
de Mistral impose la forme JSON (pas votre schéma exact) — valider côté client.
5) AWS Bedrock — schéma d’outil de l’API Converse (indépendant du modèle)
import boto3, json
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
model_id = "anthropic.claude-3-5-sonnet-20240620-v1:0"
tools = [{
"toolSpec": {
"name": "extract_event",
"inputSchema": {
"json": {
"type": "object",
"properties": {
"title": {"type": "string"},
"date": {"type": "string"},
"location": {"type": "string"}
},
"required": ["title","date","location"],
"additionalProperties": False
}
}
}
}]
resp = bedrock.converse(
modelId=model_id,
toolConfig={"tools": tools},
toolChoice={"tool": {"name": "extract_event"}}, # forcer le schéma
messages=[{"role":"user","content":[{"text":
"Extraire l’événement à partir de : 'PyData Sydney est le 2025-11-03 à Darling Harbour.'"}]}],
)
# Récupérer le contenu de l’outil
tool_use = next(
c["toolUse"] for c in resp["output"]["message"]["content"] if "toolUse" in c
)
print(json.dumps(tool_use["input"], indent=2))
Bedrock valide l’entrée de l’outil contre votre schéma JSON et de nombreux modèles hébergés (par exemple, Claude) le supportent via Converse.
Connaissances pratiques et validation
- Si vous souhaitez les garanties serveur les plus fortes : Sorties structurées d’OpenAI ou schéma de réponse de Gemini.
- Si vous utilisez déjà Claude/Bedrock : définissez un Outil avec un schéma JSON et forcez son utilisation ; lisez les arguments de l’outil comme votre objet typé.
- Si vous utilisez Mistral : activez
json_object
et validez localement (par exemple, avec Pydantic).
Modèle de validation (fonctionne pour tous)
from pydantic import BaseModel, ValidationError
class Event(BaseModel):
title: str
date: str
location: str
try:
event = Event.model_validate(data) # `data` depuis tout fournisseur
except ValidationError as e:
# gérer / réessayer / demander au modèle de corriger avec e.errors()
print(e)
Liens utiles
- https://platform.openai.com/docs/guides/structured-outputs
- https://ai.google.dev/gemini-api/docs/structured-output
- https://docs.mistral.ai/capabilities/structured-output/json_mode/
- https://aws.amazon.com/blogs/machine-learning/structured-data-response-with-amazon-bedrock-prompt-engineering-and-tool-use
- https://github.com/aws-samples/anthropic-on-aws/blob/main/complex-schema-tool-use/README.md
- https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages.html
- Comment demander une sortie structurée à l’LLM hébergé sur Ollama
- Feuille de triche Python
- AWS SAM + AWS SQS + Python PowerTools
- Comparaison de performances d’AWS Lambda : JavaScript vs Python vs Golang