Structured Outputs
Les structured outputs transforment les réponses des modèles, passant de texte libre à du JSON strictement formaté. RouteAPI prend en charge deux modes de structured outputs : JSON mode (nécessite un JSON valide) et JSON Schema (garantit la conformité à un schéma spécifique).
1. Vue d’ensemble des Structured Outputs
Section intitulée « 1. Vue d’ensemble des Structured Outputs »Qu’est-ce que les Structured Outputs
Section intitulée « Qu’est-ce que les Structured Outputs »Les structured outputs sont un mécanisme permettant de contrôler le format des réponses des modèles. Contrairement aux conversations ordinaires où les modèles génèrent librement du texte, les structured outputs forcent le modèle à générer des données JSON selon le format que vous avez défini. Ceci est crucial pour les scénarios nécessitant un traitement programmatique des sorties du modèle (extraction de données, génération de formulaires, analyse de réponses API).
JSON mode vs JSON Schema
Section intitulée « JSON mode vs JSON Schema »RouteAPI propose deux modes de structured outputs :
| Comparaison | JSON mode | JSON Schema |
|---|---|---|
| Garantie | La sortie est un JSON valide | La sortie est conforme au schéma spécifié |
| Paramètre | response_format: { type: "json_object" } | response_format: { type: "json_schema", json_schema: {...} } |
| Définition du schéma | Non requise, mais le format doit être décrit dans le prompt | JSON Schema complet requis |
| Rigueur | Garantit uniquement l’analysabilité, pas la structure | Garantit que les champs, types et éléments requis correspondent exactement |
| Cas d’usage | Formats simples, le modèle peut comprendre la structure depuis le prompt | Structures imbriquées complexes, validation de type stricte nécessaire |
Explication simple : JSON mode garantit uniquement « peut être analysé avec succès par JSON.parse » mais ne se soucie pas des champs ; JSON Schema garantit non seulement la validité mais aussi que la structure, les noms de champs, les types et les éléments requis sont tous conformes à votre définition.
Cas d’usage
Section intitulée « Cas d’usage »| Scénario | Description | Mode recommandé |
|---|---|---|
| Extraction de données | Extraire des informations structurées de texte non structuré (nom, adresse, date) | JSON Schema |
| Génération de formulaires | Faire générer au modèle des valeurs initiales de formulaire ou des objets de configuration | JSON Schema |
| Analyse de réponses API | La sortie du modèle doit s’interfacer avec des API système en aval | JSON Schema |
| Paires clé-valeur simples | Besoin de quelques champs seulement, structure simple et claire | JSON mode |
| Tâches de classification | Sortie de valeurs enum fixes (ex : sentiment : positif/négatif/neutre) | JSON Schema + enum |
2. JSON Mode
Section intitulée « 2. JSON Mode »JSON mode est la méthode de structured output la plus simple : vous définissez response_format.type à "json_object" dans votre requête, et le modèle générera un JSON valide au lieu de texte brut.
Format de requête
Section intitulée « Format de requête »{ "model": "gpt-5.5", "messages": [ { "role": "system", "content": "You are a data extraction assistant. Extract name, age, and city fields from user input and return in JSON format." }, { "role": "user", "content": "My name is Li Ming, I'm 28 years old, and I live in Shanghai." } ], "response_format": { "type": "json_object" }}Points clés
Section intitulée « Points clés »-
Le format JSON doit être décrit dans le prompt : Le modèle ne sait pas quels champs vous voulez ; vous devez lui indiquer explicitement via le message système ou le message utilisateur quels champs générer et leurs types. Dans l’exemple ci-dessus,
"Extract name, age, and city fields from user input and return in JSON format"est la description du format. -
Ne garantit pas la conformité au schéma : Le modèle pourrait générer
{"name": "Li Ming", "age": 28, "city": "Shanghai"}, ou{"姓名": "Li Ming", "年龄": 28}, ou même{"person": {"name": "Li Ming"}}. Tant que c’est un JSON valide, c’est acceptable. -
Comment l’utiliser : Convient aux scénarios avec des formats simples, peu de champs, et où le modèle peut comprendre la structure depuis le langage naturel. Si une validation stricte des noms de champs ou des types est nécessaire, utilisez JSON Schema.
Exemple complet
Section intitulée « Exemple complet »Requête (curl) :
curl https://api.routeapi.ai/v1/chat/completions \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-5.5", "messages": [ { "role": "system", "content": "You are a data extraction assistant. Extract name, age, and city fields from user input and return in JSON format." }, { "role": "user", "content": "My name is Li Ming, I am 28 years old, and I live in Shanghai." } ], "response_format": { "type": "json_object" } }'Réponse :
{ "id": "chatcmpl_xxx", "object": "chat.completion", "created": 1730000000, "model": "gpt-5.5", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "{\"name\": \"Li Ming\", \"age\": 28, \"city\": \"Shanghai\"}" }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 58, "completion_tokens": 18, "total_tokens": 76 }}Notez que message.content est une chaîne JSON, vous devez l’analyser vous-même avec JSON.parse / json.loads.
3. JSON Schema (Structured Outputs)
Section intitulée « 3. JSON Schema (Structured Outputs) »Le mode JSON Schema vous permet de définir précisément la structure de sortie, et le modèle garantit que le JSON généré est entièrement conforme à votre définition de schéma.
Format de requête
Section intitulée « Format de requête »{ "model": "gpt-5.5", "messages": [ { "role": "user", "content": "My name is Li Ming, I'm 28 years old, and I live in Shanghai." } ], "response_format": { "type": "json_schema", "json_schema": { "name": "person_extraction", "strict": true, "schema": { "type": "object", "properties": { "name": { "type": "string", "description": "Name" }, "age": { "type": "integer", "description": "Age" }, "city": { "type": "string", "description": "City" } }, "required": ["name", "age", "city"], "additionalProperties": false } } }}Structure de response_format
Section intitulée « Structure de response_format »| Champ | Type | Requis | Description |
|---|---|---|---|
type | string | Oui | Fixé à "json_schema" |
json_schema.name | string | Oui | Nom du schéma pour identification, lettres, chiffres, underscores, tirets |
json_schema.strict | boolean | Non | Active le mode strict, défaut false |
json_schema.schema | object | Oui | Définition JSON Schema standard |
Mode strict vs Mode non-strict
Section intitulée « Mode strict vs Mode non-strict »| Mode | strict | Comportement |
|---|---|---|
| Mode strict | true | Le modèle doit générer exactement selon le schéma, noms de champs, types, éléments requis, additionalProperties tous strictement respectés |
| Mode non-strict | false | Le modèle essaie de se conformer au schéma, mais ne garantit pas une cohérence complète, peut omettre des champs ou en ajouter d’autres |
Recommandation : Utilisez strict: true en production ; c’est la valeur principale du mode JSON Schema. Le comportement du mode non-strict est similaire à JSON mode + description dans le prompt, l’intérêt est limité.
Spécification de définition de schéma
Section intitulée « Spécification de définition de schéma »Le champ schema suit la spécification standard JSON Schema (Draft 2020-12), champs courants :
| Champ | Description |
|---|---|
type | Type de données : "object", "array", "string", "number", "integer", "boolean", "null" |
properties | Définitions de champs pour les objets (utilisé quand type est "object") |
required | Tableau des noms de champs requis |
additionalProperties | Autorise ou non des champs supplémentaires non définis (recommandé false en mode strict) |
items | Schéma pour les éléments du tableau (utilisé quand type est "array") |
enum | Liste de valeurs enum, restreint la plage de valeurs |
description | Description du champ, aide le modèle à comprendre la sémantique |
4. Guide de définition de schéma
Section intitulée « 4. Guide de définition de schéma »Types de base
Section intitulée « Types de base »{ "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" }, "score": { "type": "number" }, "is_active": { "type": "boolean" }, "notes": { "type": ["string", "null"] } }}Descriptions de types :
"string": Chaîne de caractères"integer": Entier"number": Nombre (incluant entiers et décimaux)"boolean": Booléen"null": Valeur nulle["string", "null"]: Autorise chaîne ou null (champ optionnel)
Objets et tableaux
Section intitulée « Objets et tableaux »{ "type": "object", "properties": { "user": { "type": "object", "properties": { "name": { "type": "string" }, "email": { "type": "string" } }, "required": ["name"] }, "tags": { "type": "array", "items": { "type": "string" } }, "scores": { "type": "array", "items": { "type": "number" } } }}Champs requis
Section intitulée « Champs requis »{ "type": "object", "properties": { "name": { "type": "string" }, "age": { "type": "integer" }, "city": { "type": "string" } }, "required": ["name", "age"]}Le tableau required liste les champs qui doivent exister. Dans l’exemple ci-dessus, name et age sont requis, city est optionnel.
Valeurs enum
Section intitulée « Valeurs enum »{ "type": "object", "properties": { "sentiment": { "type": "string", "enum": ["positive", "negative", "neutral"], "description": "Sentiment classification result" }, "priority": { "type": "integer", "enum": [1, 2, 3], "description": "Priority: 1-low, 2-medium, 3-high" } }, "required": ["sentiment"]}enum restreint le champ aux seules valeurs de la liste ; le modèle ne générera pas d’autres valeurs.
Structures imbriquées
Section intitulée « Structures imbriquées »{ "type": "object", "properties": { "user": { "type": "object", "properties": { "name": { "type": "string" }, "address": { "type": "object", "properties": { "city": { "type": "string" }, "street": { "type": "string" } }, "required": ["city"] } }, "required": ["name", "address"] } }, "required": ["user"]}Les objets peuvent être imbriqués indéfiniment, mais une imbrication excessive peut affecter la qualité de génération et les performances du modèle.
Champs de description
Section intitulée « Champs de description »{ "type": "object", "properties": { "date": { "type": "string", "description": "Date, format YYYY-MM-DD" }, "amount": { "type": "number", "description": "Amount in CNY" } }}description n’est pas requis, mais fortement recommandé. Il aide le modèle à comprendre la sémantique du champ, les plages de valeurs et les conventions de format, améliorant significativement la précision de génération.
5. Exemples de schémas
Section intitulée « 5. Exemples de schémas »Extraction d’informations utilisateur
Section intitulée « Extraction d’informations utilisateur »Extraire les informations utilisateur depuis du texte non structuré :
{ "name": "user_info_extraction", "strict": true, "schema": { "type": "object", "properties": { "name": { "type": "string", "description": "User name" }, "age": { "type": "integer", "description": "Age" }, "email": { "type": ["string", "null"], "description": "Email address, null if not in text" }, "phone": { "type": ["string", "null"], "description": "Phone number, null if not in text" }, "city": { "type": "string", "description": "City" } }, "required": ["name", "age", "city"], "additionalProperties": false }}Génération de liste de produits
Section intitulée « Génération de liste de produits »Faire générer au modèle un tableau de produits :
{ "name": "product_list", "strict": true, "schema": { "type": "object", "properties": { "products": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string", "description": "Product name" }, "price": { "type": "number", "description": "Price in CNY" }, "category": { "type": "string", "enum": ["electronics", "clothing", "food", "other"], "description": "Product category" }, "in_stock": { "type": "boolean", "description": "Whether in stock" } }, "required": ["name", "price", "category", "in_stock"], "additionalProperties": false } }, "total_count": { "type": "integer", "description": "Total product count" } }, "required": ["products", "total_count"], "additionalProperties": false }}Objet imbriqué complexe
Section intitulée « Objet imbriqué complexe »Extraction d’informations de commande avec imbrication multi-niveaux :
{ "name": "order_extraction", "strict": true, "schema": { "type": "object", "properties": { "order_id": { "type": "string", "description": "Order ID" }, "customer": { "type": "object", "properties": { "name": { "type": "string" }, "phone": { "type": "string" }, "address": { "type": "object", "properties": { "province": { "type": "string" }, "city": { "type": "string" }, "street": { "type": "string" } }, "required": ["province", "city", "street"], "additionalProperties": false } }, "required": ["name", "phone", "address"], "additionalProperties": false }, "items": { "type": "array", "items": { "type": "object", "properties": { "product_name": { "type": "string" }, "quantity": { "type": "integer" }, "unit_price": { "type": "number" } }, "required": ["product_name", "quantity", "unit_price"], "additionalProperties": false } }, "total_amount": { "type": "number", "description": "Order total amount" } }, "required": ["order_id", "customer", "items", "total_amount"], "additionalProperties": false }}6. Support des modèles
Section intitulée « 6. Support des modèles »Modèles supportant JSON mode
Section intitulée « Modèles supportant JSON mode »La plupart des modèles mainstream agrégés par RouteAPI supportent JSON mode (response_format: { type: "json_object" }), incluant :
- Série OpenAI GPT (gpt-4o, gpt-4-turbo, gpt-3.5-turbo, etc.)
- Série Claude (claude-3.5-sonnet, claude-3-opus, claude-3-haiku, etc.)
- Série Gemini (gemini-2.0-flash, gemini-1.5-pro, etc.)
- Autres modèles supportant le format OpenAI
Modèles supportant JSON Schema
Section intitulée « Modèles supportant JSON Schema »JSON Schema (response_format: { type: "json_schema" }) nécessite des capacités de modèle plus élevées ; modèles actuellement supportés :
- OpenAI : séries gpt-4o, gpt-4-turbo (version 2024-08-06 et ultérieures)
- Claude : séries claude-3.5-sonnet, claude-3-opus
- Gemini : gemini-2.0-flash-exp, séries gemini-1.5-pro
- Autres : certains modèles de nouvelle génération
Comment confirmer : Interrogez les capacités du modèle via l’API Models avant d’appeler, vérifiez le champ supports_response_format.
Comparaison des capacités des modèles
Section intitulée « Comparaison des capacités des modèles »| Capacité | JSON mode | JSON Schema | Notes |
|---|---|---|---|
| Plage de support des modèles | Large (presque tous les modèles mainstream) | Limitée (modèles de nouvelle génération) | JSON mode a un support plus élevé |
| Complexité du schéma | N/A | Recommandé pas plus de 3 niveaux d’imbrication | Profondeur excessive affecte la qualité de génération |
| Nombre max de champs | N/A | Recommandé pas plus de 50 champs de niveau supérieur | Trop de champs affecte les performances |
| Garantie stricte | Garantit uniquement JSON valide | Garantit conformité au schéma | Conformité à 100% en mode strict |
| Performance | Rapide | Relativement plus lent | Validation du schéma a un coût supplémentaire |
| Consommation de tokens | Faible | Légèrement plus élevée | Définition du schéma occupe des tokens de prompt |
Limitations et notes
Section intitulée « Limitations et notes »-
Limite de taille de schéma : Une définition de schéma unique ne devrait pas dépasser 10KB ; des schémas excessivement larges peuvent être tronqués ou rejetés.
-
Limite de profondeur d’imbrication : Recommandé que les niveaux d’imbrication ne dépassent pas 3-4 niveaux ; une imbrication excessive réduit la qualité et la vitesse de génération du modèle.
-
Impact sur les performances : Le temps de réponse du mode JSON Schema est généralement 10%-30% plus lent que les requêtes régulières car le modèle doit valider la structure en temps réel pendant la génération.
-
Fonctionnalités de schéma non supportées : Certaines fonctionnalités avancées de JSON Schema (comme
$ref,allOf,anyOf,oneOf, regex) peuvent ne pas être supportées par tous les modèles. -
Sortie en streaming : Le mode JSON Schema supporte la sortie en streaming (
stream: true), maiscontentest retourné en fragments ; le JSON complet doit être concaténé avant analyse.
7. Exemples d’applications complets
Section intitulée « 7. Exemples d’applications complets »Exemple 1 : Extraire des informations structurées depuis du texte non structuré
Section intitulée « Exemple 1 : Extraire des informations structurées depuis du texte non structuré »Scénario : Extraire les informations client et la classification des problèmes depuis une conversation de service client.
curl :
curl https://api.routeapi.ai/v1/chat/completions \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-4o", "messages": [ { "role": "user", "content": "Customer Li Ming (phone 13800138000) reported that order ORD-2024-001 in Chaoyang District, Beijing has not been shipped and is quite urgent." } ], "response_format": { "type": "json_schema", "json_schema": { "name": "customer_inquiry", "strict": true, "schema": { "type": "object", "properties": { "customer_name": { "type": "string", "description": "Customer name" }, "phone": { "type": ["string", "null"], "description": "Customer phone" }, "location": { "type": ["string", "null"], "description": "Customer location" }, "order_id": { "type": ["string", "null"], "description": "Order ID" }, "issue_category": { "type": "string", "enum": ["delivery", "quality", "refund", "other"], "description": "Issue category: delivery-logistics, quality-quality, refund-refund, other-other" }, "urgency": { "type": "string", "enum": ["low", "medium", "high"], "description": "Urgency level" } }, "required": ["customer_name", "issue_category", "urgency"], "additionalProperties": false } } } }'Réponse :
{ "choices": [ { "message": { "role": "assistant", "content": "{\"customer_name\":\"Li Ming\",\"phone\":\"13800138000\",\"location\":\"Chaoyang District, Beijing\",\"order_id\":\"ORD-2024-001\",\"issue_category\":\"delivery\",\"urgency\":\"high\"}" }, "finish_reason": "stop" } ]}Python :
import osimport jsonfrom openai import OpenAI
client = OpenAI( api_key=os.environ["ROUTEAPI_KEY"], base_url="https://api.routeapi.ai/v1",)
response = client.chat.completions.create( model="gpt-4o", messages=[ { "role": "user", "content": "Customer Li Ming (phone 13800138000) reported that order ORD-2024-001 in Chaoyang District, Beijing has not been shipped and is quite urgent.", } ], response_format={ "type": "json_schema", "json_schema": { "name": "customer_inquiry", "strict": True, "schema": { "type": "object", "properties": { "customer_name": {"type": "string", "description": "Customer name"}, "phone": {"type": ["string", "null"], "description": "Customer phone"}, "location": {"type": ["string", "null"], "description": "Customer location"}, "order_id": {"type": ["string", "null"], "description": "Order ID"}, "issue_category": { "type": "string", "enum": ["delivery", "quality", "refund", "other"], "description": "Issue category", }, "urgency": { "type": "string", "enum": ["low", "medium", "high"], "description": "Urgency level", }, }, "required": ["customer_name", "issue_category", "urgency"], "additionalProperties": False, }, }, },)
data = json.loads(response.choices[0].message.content)print(f"Customer: {data['customer_name']}")print(f"Issue type: {data['issue_category']}")print(f"Urgency: {data['urgency']}")Node.js :
import OpenAI from 'openai';
const client = new OpenAI({ apiKey: process.env.ROUTEAPI_KEY, baseURL: 'https://api.routeapi.ai/v1',});
const response = await client.chat.completions.create({ model: 'gpt-4o', messages: [ { role: 'user', content: 'Customer Li Ming (phone 13800138000) reported that order ORD-2024-001 in Chaoyang District, Beijing has not been shipped and is quite urgent.', }, ], response_format: { type: 'json_schema', json_schema: { name: 'customer_inquiry', strict: true, schema: { type: 'object', properties: { customer_name: { type: 'string', description: 'Customer name' }, phone: { type: ['string', 'null'], description: 'Customer phone' }, location: { type: ['string', 'null'], description: 'Customer location' }, order_id: { type: ['string', 'null'], description: 'Order ID' }, issue_category: { type: 'string', enum: ['delivery', 'quality', 'refund', 'other'], description: 'Issue category', }, urgency: { type: 'string', enum: ['low', 'medium', 'high'], description: 'Urgency level', }, }, required: ['customer_name', 'issue_category', 'urgency'], additionalProperties: false, }, }, },});
const data = JSON.parse(response.choices[0].message.content);console.log(`Customer: ${data.customer_name}`);console.log(`Issue type: ${data.issue_category}`);console.log(`Urgency: ${data.urgency}`);Exemple 2 : Générer des données de formulaire
Section intitulée « Exemple 2 : Générer des données de formulaire »Scénario : Faire générer au modèle des valeurs initiales de formulaire basées sur une description en langage naturel.
Python :
response = client.chat.completions.create( model="gpt-4o", messages=[ { "role": "system", "content": "You are a form filling assistant. Generate form data based on user description.", }, { "role": "user", "content": "Create a new employee onboarding form: Zhang Wei, male, born in 1995, bachelor's degree, software engineer position, monthly salary 15000.", }, ], response_format={ "type": "json_schema", "json_schema": { "name": "employee_form", "strict": True, "schema": { "type": "object", "properties": { "name": {"type": "string"}, "gender": {"type": "string", "enum": ["male", "female"]}, "birth_year": {"type": "integer"}, "education": { "type": "string", "enum": ["high_school", "bachelor", "master", "phd"], }, "position": {"type": "string"}, "salary": {"type": "number", "description": "Monthly salary in CNY"}, }, "required": ["name", "gender", "birth_year", "education", "position", "salary"], "additionalProperties": False, }, }, },)
form_data = json.loads(response.choices[0].message.content)print(json.dumps(form_data, ensure_ascii=False, indent=2))Sortie :
{ "name": "Zhang Wei", "gender": "male", "birth_year": 1995, "education": "bachelor", "position": "Software Engineer", "salary": 15000}Exemple 3 : Analyse de réponse API
Section intitulée « Exemple 3 : Analyse de réponse API »Scénario : Faire extraire au modèle les informations clés depuis une réponse API tierce non structurée.
Node.js :
const apiResponse = `Order status: ShippedLogistics company: SF ExpressTracking number: SF1234567890Estimated delivery: January 20, 2024Current location: Beijing Distribution Center`;
const response = await client.chat.completions.create({ model: 'gpt-4o', messages: [ { role: 'user', content: `Extract structured data from the following logistics information:\n${apiResponse}`, }, ], response_format: { type: 'json_schema', json_schema: { name: 'logistics_info', strict: true, schema: { type: 'object', properties: { status: { type: 'string', enum: ['pending', 'shipped', 'in_transit', 'delivered'], }, carrier: { type: 'string', description: 'Logistics company' }, tracking_number: { type: 'string', description: 'Tracking number' }, estimated_delivery: { type: ['string', 'null'], description: 'Estimated delivery date, format YYYY-MM-DD', }, current_location: { type: ['string', 'null'], description: 'Current location' }, }, required: ['status', 'carrier', 'tracking_number'], additionalProperties: false, }, }, },});
const data = JSON.parse(response.choices[0].message.content);console.log(data);// Output: { status: 'shipped', carrier: 'SF Express', tracking_number: 'SF1234567890', estimated_delivery: '2024-01-20', current_location: 'Beijing Distribution Center' }8. Gestion des erreurs
Section intitulée « 8. Gestion des erreurs »Échec de validation du schéma
Section intitulée « Échec de validation du schéma »Si votre définition de schéma elle-même a des problèmes (erreurs de syntaxe, fonctionnalités non supportées), la requête retournera directement une erreur 400 :
{ "error": { "message": "Invalid JSON schema: ...", "type": "invalid_request_error", "param": "response_format.json_schema.schema", "code": "invalid_json_schema" }}Solution :
- Vérifiez si la syntaxe du schéma est conforme à la spécification JSON Schema
- Supprimez les fonctionnalités avancées non supportées (comme
$ref,allOf) - Simplifiez les structures excessivement imbriquées
Le modèle ne peut pas générer une sortie conforme au schéma
Section intitulée « Le modèle ne peut pas générer une sortie conforme au schéma »Dans de rares cas, le modèle peut être incapable de générer du contenu conforme au schéma (par exemple, l’entrée utilisateur est complètement en conflit avec les exigences du schéma) ; dans ce cas, une erreur sera retournée ou il reviendra à une sortie en texte brut. Exemple d’erreur :
{ "error": { "message": "Failed to generate valid output matching the provided schema after maximum retries.", "type": "model_error", "code": "schema_generation_failed" }}Solution :
- Vérifiez si le prompt est cohérent avec les exigences du schéma
- Simplifiez le schéma, supprimez les contraintes trop strictes
- Indiquez explicitement les exigences de sortie dans le prompt
- Pour les champs optionnels, utilisez le type
["string", "null"]au lieu de juste"string"
Stratégie de réessai
Section intitulée « Stratégie de réessai »Pour les échecs de génération occasionnels, vous pouvez implémenter un réessai automatique :
import time
def call_with_retry(client, **kwargs): max_retries = 3 for attempt in range(max_retries): try: response = client.chat.completions.create(**kwargs) content = response.choices[0].message.content data = json.loads(content) # Verify it can be parsed return data except (json.JSONDecodeError, Exception) as e: if attempt == max_retries - 1: raise time.sleep(2 ** attempt) # Exponential backoff9. Meilleures pratiques
Section intitulée « 9. Meilleures pratiques »Principes de conception de schéma
Section intitulée « Principes de conception de schéma »-
Commencer simple : Vérifiez d’abord la faisabilité avec JSON mode, puis passez à JSON Schema après avoir confirmé qu’une validation stricte est nécessaire.
-
Clarifier requis et optionnel : Mettez les champs requis dans le tableau
required, utilisez["type", "null"]pour les champs optionnels ou ne les mettez simplement pas dansrequired. -
Utiliser enum pour restreindre les énumérations : Pour les champs avec des valeurs limitées (statut, classification, priorité), listez-les explicitement avec
enum; cela peut grandement réduire les taux d’erreur. -
Ajouter description : Ajoutez
descriptionà chaque champ, expliquant la signification, le format, la plage de valeurs ; le modèle génère plus précisément en se basant sur cela. -
Définir additionalProperties: false : En mode strict, ajouter cela empêche le modèle de générer des champs supplémentaires non définis.
Éviter les schémas trop complexes
Section intitulée « Éviter les schémas trop complexes »| Problème | Description | Suggestion |
|---|---|---|
| Trop profondément imbriqué | Plus de 4 niveaux d’imbrication réduit la qualité de génération | Diviser en plusieurs objets plats, ou extraire en étapes avec des conversations multi-tours |
| Trop de champs | Un seul objet dépasse 50 champs | Grouper par logique métier, diviser en plusieurs sous-objets |
| Sur-contraint | Tous les champs sont requis, pas de flexibilité | Marquer uniquement les champs essentiels comme requis, autoriser null pour les autres champs |
| Pas de description | Le modèle ne comprend pas la sémantique des champs | Ajouter description à chaque champ, expliquer clairement |
Optimisation des performances
Section intitulée « Optimisation des performances »-
Réduire la taille du schéma : La définition du schéma occupe des tokens de prompt ; des schémas excessivement larges augmentent la latence et le coût.
-
Mettre en cache les définitions de schéma : Lorsque le même schéma est utilisé de manière répétée, définissez-le comme une constante dans le code pour éviter de le reconstruire à chaque requête.
-
Choisir le modèle approprié : Toutes les tâches n’ont pas besoin du modèle le plus puissant ; une extraction structurée simple peut utiliser gpt-3.5-turbo + JSON mode.
-
Traitement par lots : S’il y a plusieurs tâches similaires, concevez un schéma de tableau pour faire traiter plusieurs éléments de données au modèle en une fois.
Considérations de coût
Section intitulée « Considérations de coût »| Facteur | Impact | Suggestion d’optimisation |
|---|---|---|
| Taille du schéma | La définition du schéma occupe des tokens de prompt | Rationaliser la description, supprimer les champs redondants |
| Choix du modèle | JSON Schema nécessite généralement des modèles plus puissants | Utiliser JSON mode + modèle plus faible pour les tâches simples |
| Longueur de réponse | La sortie JSON est généralement plus longue que le texte (noms de clés, guillemets, crochets) | Raccourcir les noms de champs, utiliser des enums au lieu de longues chaînes |
| Nombre de réessais | Les réessais d’échec de génération doublent la facturation | Optimiser le schéma et le prompt pour réduire le taux d’échec |
Conseil pratique : Pour les scénarios d’appels à haute fréquence, testez d’abord avec JSON mode ; après avoir confirmé que le modèle peut générer de manière stable le format correct, passez à JSON Schema. JSON mode a généralement 10%-20% de consommation de tokens et de coût inférieure à JSON Schema.
Notes de compatibilité
Section intitulée « Notes de compatibilité »- Le support de JSON mode et JSON Schema dépend du modèle sélectionné ; veuillez interroger le champ
supports_response_formatvia l’API Models pour confirmer. response_formatest mutuellement exclusif avectools(appel d’outils) : la même requête ne peut pas utiliser à la fois structured outputs et appel d’outils.- Dans la sortie en streaming (
stream: true),contentest retourné en fragments et doit être entièrement concaténé avantJSON.parse. - Les paramètres optionnels explicitement passés
0oufalsesont traités comme définis explicitement par l’utilisateur et ne seront pas traités comme des omissions par défaut. - Enregistrez l’ID de requête, l’ID de modèle, le code d’état et l’utilisation des tokens de chaque requête pour le dépannage. Les détails de la structure d’erreur sont disponibles dans Errors and Debugging.