Aller au contenu principal
Leçon 4 sur 12 · Structured Output — JSON et Schémas

Activer le JSON Mode

Leçon 4 sur 12 Mis à jour le 3 novembre 2026 Développeur
Sur cette page
  1. Principe du JSON Mode
  2. Activation en Python
  3. Activation en TypeScript
  4. L’instruction explicite n’est pas optionnelle
  5. Déplacer le format dans le system prompt
  6. Parsing de la réponse
  7. Points clés à retenir

Corrigé le 3 novembre 2026 : les exemples TypeScript importaient Mistral par défaut (import Mistral from …), alors que le SDK ne propose qu’un export nommé : import { Mistral } from "@mistralai/mistralai". Ils passaient aussi à JSON.parse un contenu typé string | ContentChunk[], et écrivaient la clé API en dur dans le code. Vérifié par compilation avec le SDK 3.5.0 et TypeScript 7.0.2. Source : SDK TypeScript Mistral.

Principe du JSON Mode

Le JSON Mode est le mécanisme le plus simple pour obtenir une sortie structurée de Mistral. En activant un seul paramètre, vous garantissez que la réponse du modèle sera un JSON valide. Pas de schéma à définir, pas de modèle de données à écrire : juste du JSON, syntaxiquement correct, à chaque appel.

Activation en Python

L’activation passe par le paramètre response_format de la méthode client.chat.complete(). Remarquez que le prompt décrit lui-même la structure attendue — nous verrons plus bas pourquoi ce n’est pas facultatif.

from mistralai.client import Mistral

client = Mistral(api_key="votre-clé-api")

response = client.chat.complete(
    model="mistral-large-latest",
    messages=[
        {
            "role": "user",
            "content": "Décris les 3 principaux avantages du cloud computing. Retourne le résultat en JSON avec une clé 'advantages' contenant une liste d'objets avec 'title' et 'description'."
        }
    ],
    response_format={"type": "json_object"}
)

print(response.choices[0].message.content)

La sortie sera un JSON valide, exploitable tel quel :

{
  "advantages": [
    {
      "title": "Scalabilité",
      "description": "Ajustement dynamique des ressources selon la demande."
    },
    {
      "title": "Réduction des coûts",
      "description": "Pas d'investissement en infrastructure physique."
    },
    {
      "title": "Accessibilité",
      "description": "Accès aux services depuis n'importe où."
    }
  ]
}

Activation en TypeScript

Le SDK TypeScript suit exactement la même logique, à la casse près : le paramètre s’écrit responseFormat en camelCase, et le parsing se fait avec JSON.parse(). Une précaution s’ajoute : le SDK type content comme string | ContentChunk[], si bien que JSON.parse n’accepte la valeur qu’après avoir vérifié qu’il s’agit bien d’une chaîne.

import { Mistral } from "@mistralai/mistralai";

const client = new Mistral({ apiKey: process.env.MISTRAL_API_KEY });

const response = await client.chat.complete({
  model: "mistral-large-latest",
  messages: [
    {
      role: "user",
      content: "Liste 3 frameworks JavaScript populaires en JSON avec 'name' et 'useCase'."
    }
  ],
  responseFormat: { type: "json_object" },
});

const contenu = response.choices[0]?.message?.content;
if (typeof contenu !== "string") {
  throw new Error("La réponse ne contient pas de texte JSON.");
}
const data = JSON.parse(contenu);
console.log(data);

L’instruction explicite n’est pas optionnelle

Voici le point que beaucoup de développeurs négligent, et qui explique la majorité des déceptions avec le JSON Mode : activer le paramètre ne suffit pas. Le mode garantit la syntaxe, pas le contenu. Vous devez instruire explicitement le modèle, dans le prompt, sur le format que vous attendez.

Comparez les deux appels suivants. Dans le premier, aucune indication de structure n’est donnée : le modèle produira bien du JSON, mais les clés, leur nom et leur imbrication varieront d’un appel à l’autre, et votre code en aval n’aura aucun point d’ancrage stable.

# Mauvaise pratique — pas d'instruction JSON dans le prompt
response = client.chat.complete(
    model="mistral-large-latest",
    messages=[
        {"role": "user", "content": "Quels sont les avantages du cloud ?"}
    ],
    response_format={"type": "json_object"}
)
# Le modèle produira du JSON, mais la structure sera imprévisible

Dans le second, un squelette de structure est inséré directement dans le prompt. Le modèle a désormais une cible à imiter, et la sortie devient prévisible d’un appel à l’autre.

# Bonne pratique — instruction claire dans le prompt
response = client.chat.complete(
    model="mistral-large-latest",
    messages=[
        {
            "role": "user",
            "content": """Quels sont les avantages du cloud computing ?

Retourne ta réponse en JSON avec la structure suivante :
{
  "topic": "string",
  "advantages": [
    {"title": "string", "description": "string"}
  ]
}"""
        }
    ],
    response_format={"type": "json_object"}
)

Inclure un exemple de structure dans votre prompt guide le modèle vers le format souhaité. Ce n’est pas une garantie absolue, contrairement aux Custom Structured Outputs, mais c’est largement suffisant dans la majorité des cas.

Déplacer le format dans le system prompt

Dès que le même traitement se répète sur des centaines d’entrées, laisser les instructions de format dans le message utilisateur devient ingérable : vous les recopiez à chaque appel, et elles se mélangent au contenu à traiter. Placez-les dans le system prompt.

response = client.chat.complete(
    model="mistral-large-latest",
    messages=[
        {
            "role": "system",
            "content": "Tu es un assistant d'extraction de données. Tu retournés TOUJOURS tes réponses en JSON avec les clés 'entities', 'confidence' et 'source'."
        },
        {
            "role": "user",
            "content": "Extrais les informations de ce texte : 'La société Acme Corp, fondée en 2019 à Lyon, emploie 250 personnes.'"
        }
    ],
    response_format={"type": "json_object"}
)

Cette séparation entre les instructions de format, portées par le rôle system, et le contenu à traiter, porté par le rôle user, rend votre code nettement plus maintenable : changer le format se fait à un seul endroit.

Parsing de la réponse

Un dernier réflexe à acquérir : la réponse du JSON Mode est toujours une string JSON dans message.content, jamais un objet. Le parsing vous incombe, dans les deux langages.

import json

raw = response.choices[0].message.content
data = json.loads(raw)

# Accéder aux données
for advantage in data["advantages"]:
    print(f"- {advantage['title']}: {advantage['description']}")
const contenu = response.choices[0]?.message?.content;
if (typeof contenu !== "string") {
  throw new Error("La réponse ne contient pas de texte JSON.");
}
const data = JSON.parse(contenu);

data.advantages.forEach((adv: any) => {
  console.log(`- ${adv.title}: ${adv.description}`);
});

Points clés à retenir

  • Le JSON Mode s’active avec response_format: {"type": "json_object"}
  • Utilisez client.chat.complete() (pas parse())
  • Instruisez toujours le modèle dans le prompt sur la structure JSON attendue
  • La réponse est une string JSON — parsez-la avec json.loads() ou JSON.parse()
  • Placez les instructions de format dans le system prompt pour les pipelines répétitifs