Sortie structurée des LLM : mode JSON, appels de fonctions et plus

AI Bot
Par AI Bot ·

Chargement du lecteur de synthèse vocale...
Sortie structurée des LLM avec mode JSON et appels de fonctions

Les LLM génèrent du texte. Votre application a besoin de structures de données. Le fossé entre ces deux réalités est le terrain fertile des bugs de production — JSON malformé, champs manquants, types incorrects et formatage incohérent qui casse votre interface à 2 heures du matin.

En 2026, chaque fournisseur majeur propose des capacités natives de sortie structurée qui garantissent la conformité au schéma au niveau du token. Si vous analysez encore les réponses des LLM avec des regex ou espérez que votre prompt engineering tiendra, ce guide vous montrera la bonne méthode.

Les trois niveaux de contrôle des sorties

Toutes les approches pour obtenir des données structurées ne se valent pas. Comprendre les compromis vous aide à choisir le bon outil.

Niveau 1 : Prompt Engineering

La méthode la plus simple — vous demandez au modèle de retourner du JSON dans votre prompt :

Retourne un objet JSON avec les champs : name (string), age (number), skills (array de strings).

Cela fonctionne 80 à 95 % du temps, mais sans garantie de types et avec des échecs silencieux. Le modèle peut retourner du JSON valide avec un nom de champ inattendu. Acceptable pour les prototypes, dangereux en production.

Niveau 2 : Appels de fonctions (Tool Use)

Les appels de fonctions vous permettent de définir des schémas typés que le modèle utilise pour structurer sa sortie :

const tools = [{
  type: "function",
  function: {
    name: "extract_contact",
    description: "Extraire les informations de contact du texte",
    parameters: {
      type: "object",
      properties: {
        name: { type: "string" },
        email: { type: "string", format: "email" },
        company: { type: "string" }
      },
      required: ["name", "email"]
    }
  }
}];

La fiabilité monte à 95–99 %. Le schéma agit comme un indice fort, mais le modèle peut parfois produire des valeurs qui ne correspondent pas au format attendu.

Niveau 3 : Sortie structurée native

Le standard de référence. Le décodage contraint utilise une machine à états finis pour masquer les tokens invalides au moment de la génération. Le modèle ne peut prédire que des tokens conformes au schéma à chaque étape.

import OpenAI from "openai";
import { z } from "zod";
import { zodResponseFormat } from "openai/helpers/zod";
 
const ContactSchema = z.object({
  name: z.string(),
  email: z.string().email(),
  company: z.string().optional(),
  role: z.enum(["developer", "designer", "manager", "other"]),
});
 
const client = new OpenAI();
 
const response = await client.beta.chat.completions.parse({
  model: "gpt-4o",
  messages: [
    { role: "user", content: "Extract contact: John Smith, john@acme.co, CTO at Acme Inc" }
  ],
  response_format: zodResponseFormat(ContactSchema, "contact"),
});
 
const contact = response.choices[0].message.parsed;
// TypeScript sait : contact.name est string, contact.role est "developer" | "designer" | ...

Conformité au schéma : 100 %. Voilà où les applications de production doivent se situer en 2026.

Comparaison des fournisseurs

Chaque fournisseur gère les sorties structurées différemment :

OpenAI offre le support natif le plus mature. Le paramètre response_format avec le type json_schema impose une conformité stricte. Les SDK Python et TypeScript intègrent directement Pydantic et Zod.

Anthropic (Claude) réalise les sorties structurées via le tool use. Vous définissez un outil avec un input_schema et Claude retourne des paramètres structurés :

import Anthropic from "@anthropic-ai/sdk";
import { zodTool } from "@anthropic-ai/sdk/helpers/zod";
import { z } from "zod";
 
const client = new Anthropic();
 
const ProductSchema = z.object({
  name: z.string(),
  price: z.number(),
  currency: z.enum(["USD", "EUR", "TND"]),
  inStock: z.boolean(),
});
 
const response = await client.messages.create({
  model: "claude-sonnet-4-6-20260320",
  max_tokens: 1024,
  tools: [
    zodTool({
      name: "extract_product",
      description: "Extraire les détails du produit",
      schema: ProductSchema,
    }),
  ],
  tool_choice: { type: "tool", name: "extract_product" },
  messages: [
    { role: "user", content: "Le nouveau casque coûte 89,99 EUR et est actuellement disponible" }
  ],
});

Google Gemini supporte les sorties structurées natives via response_schema dans la configuration API.

Le pattern Sandwich de validation

Même avec des sorties structurées natives garantissant du JSON valide, vous avez besoin de validation métier. Le pattern "sandwich de validation" superpose trois couches :

import { z } from "zod";
 
// Couche 1 : Le schéma définit la structure
const OrderSchema = z.object({
  productId: z.string().uuid(),
  quantity: z.number().int().positive(),
  unitPrice: z.number().positive(),
  total: z.number().positive(),
});
 
// Couche 2 : Raffinement de la logique métier
const ValidatedOrder = OrderSchema.refine(
  (order) => Math.abs(order.total - order.quantity * order.unitPrice) < 0.01,
  { message: "Le total doit être égal à quantité × prix unitaire" }
);
 
// Couche 3 : Vérification au niveau application
async function processOrder(raw: unknown) {
  const order = ValidatedOrder.parse(raw);
  const product = await db.products.find(order.productId);
  if (!product) throw new Error("Produit non trouvé");
  if (order.quantity > product.stockCount) throw new Error("Stock insuffisant");
  return order;
}

Le LLM garantit la forme. Zod valide les contraintes. Votre logique applicative vérifie contre la réalité. Ne faites confiance à aucune couche seule.

Quand utiliser quoi

Le choix entre sortie structurée, appels de fonctions et mode JSON dépend de votre cas :

Utilisez les sorties structurées natives pour extraire des données de texte, générer des réponses structurées pour votre interface, ou construire des pipelines de données.

Utilisez les appels de fonctions quand votre modèle doit interagir avec des systèmes externes, choisir entre plusieurs outils, ou opérer dans une boucle agentique.

Évitez le mode JSON seul. Il garantit une syntaxe JSON valide mais pas la conformité au schéma.

Bonnes pratiques de conception de schémas

Gardez des schémas focalisés. Incluez uniquement les champs que vous utilisez réellement. Les schémas plus grands augmentent la consommation de tokens.

Utilisez des noms de champs et descriptions parlants. Le modèle lit les noms de propriétés et descriptions pour comprendre quel contenu placer dans chaque champ.

Préférez les enums aux chaînes ouvertes. Quand un champ a un ensemble connu de valeurs, utilisez un enum :

// Faible : le modèle pourrait retourner "High", "HIGH", "haute priorité"
priority: z.string()
 
// Fort : garanti comme une de ces valeurs
priority: z.enum(["low", "medium", "high", "critical"])

Découpez les extractions complexes en appels plus petits. Un seul appel avec 20 champs est moins fiable et plus coûteux que deux appels de 10 champs chacun.

Exemple concret : extraction de données de factures

Un exemple complet qui extrait des données de factures depuis du texte non structuré — un besoin courant pour les systèmes de facturation électronique et l'automatisation métier :

import Anthropic from "@anthropic-ai/sdk";
import { zodTool } from "@anthropic-ai/sdk/helpers/zod";
import { z } from "zod";
 
const InvoiceSchema = z.object({
  invoiceNumber: z.string().describe("Numéro de facture ou de reçu"),
  vendor: z.string().describe("Entreprise ou personne ayant émis la facture"),
  date: z.string().describe("Date de la facture au format AAAA-MM-JJ"),
  lineItems: z.array(z.object({
    description: z.string(),
    quantity: z.number().positive(),
    unitPrice: z.number().positive(),
  })),
  subtotal: z.number(),
  taxRate: z.number().describe("Taux de taxe en pourcentage, ex. 19 pour 19 %"),
  taxAmount: z.number(),
  total: z.number(),
  currency: z.enum(["USD", "EUR", "TND", "SAR", "AED"]),
});
 
const client = new Anthropic();
 
async function extractInvoice(text: string) {
  const response = await client.messages.create({
    model: "claude-sonnet-4-6-20260320",
    max_tokens: 2048,
    tools: [
      zodTool({
        name: "extract_invoice",
        description: "Extraire les données structurées de la facture",
        schema: InvoiceSchema,
      }),
    ],
    tool_choice: { type: "tool", name: "extract_invoice" },
    messages: [{ role: "user", content: text }],
  });
 
  const toolBlock = response.content.find((b) => b.type === "tool_use");
  return InvoiceSchema.parse(toolBlock?.input);
}

Considérations de coût

Les sorties structurées ne sont pas gratuites. Les schémas complexes ajoutent des tokens à chaque requête. Gardez en tête :

  • Minimisez les champs optionnels. Chaque champ optionnel coûte des tokens même quand le modèle ne produit rien.
  • Mettez vos schémas en cache. Avec le prompt caching activé, les définitions de schémas sont mises en cache entre les requêtes, réduisant les coûts de 90 %. Consultez notre guide sur l'optimisation des coûts API IA.
  • Utilisez le modèle le moins cher qui fonctionne. Pour les tâches simples, les modèles plus petits comme Claude Haiku gèrent les sorties structurées avec la même fiabilité — à une fraction du coût.

Et ensuite

L'écosystème des sorties structurées évolue rapidement. Le streaming de sorties structurées — où des objets JSON partiels sont livrés au fur et à mesure de leur génération — est maintenant supporté et permet des interfaces qui affichent progressivement les données extraites.

Les sorties structurées multimodales, où les modèles extraient des données directement depuis des images, PDF et audio, mûrissent également. Combinées à l'automatisation métier par IA, ces capacités permettent de construire des pipelines de traitement de documents de bout en bout sans intervention humaine.

En résumé : si vous construisez des fonctionnalités IA en 2026, les sorties structurées ne sont pas optionnelles. Elles sont le socle qui permet à tout le reste — agents, automatisation, pipelines de données — de fonctionner réellement en production.


Vous voulez lire plus d'articles de blog? Découvrez notre dernier article sur Cloud AI-Natif : La Nouvelle Pile de Déploiement.

Discutez de votre projet avec nous

Nous sommes ici pour vous aider avec vos besoins en développement Web. Planifiez un appel pour discuter de votre projet et comment nous pouvons vous aider.

Trouvons les meilleures solutions pour vos besoins.