Aller au contenu principal

Exemples pratiques du JSON Mode

Mis à jour le 29 juillet 2026

Mettre le JSON Mode en pratique

Vous savez activer le JSON Mode : passons à des cas concrets. Trois scénarios reviennent constamment dans les projets réels, et chacun illustre une manière différente d’exploiter le mode. Le code est donné en Python, avec l’équivalent TypeScript là où la traduction n’est pas immédiate.

Extraire des entités d’un texte non structuré

L’extraction d’entités est le cas d’usage le plus fréquent, et le plus rentable : un email de prospection contient un contact complet, mais noyé dans une signature et une formule de politesse. La consigne clé de l’exemple suivant est la dernière ligne du system prompt — imposer null pour les informations absentes évite que le modèle invente un numéro de téléphone pour remplir le champ.

from mistralai import Mistral
import json

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

email_text = """
Bonjour,
Je suis Marie Dupont, directrice commerciale chez TechVision SAS.
Vous pouvez me joindre au 06 12 34 56 78 ou par email à [email protected].
Notre siège est au 42 rue de la Paix, 75002 Paris.
Cordialement,
Marie
"""

response = client.chat.complete(
    model="mistral-large-latest",
    messages=[
        {
            "role": "system",
            "content": """Extrais les informations de contact du texte fourni.
Retourne un JSON avec les clés : name, title, company, phone, email, address.
Si une information est absente, utilise null."""
        },
        {"role": "user", "content": email_text}
    ],
    response_format={"type": "json_object"},
    temperature=0
)

contact = json.loads(response.choices[0].message.content)
print(f"Nom : {contact['name']}")
print(f"Entreprise : {contact['company']}")
print(f"Téléphone : {contact['phone']}")

Sortie attendue :

{
  "name": "Marie Dupont",
  "title": "Directrice commerciale",
  "company": "TechVision SAS",
  "phone": "06 12 34 56 78",
  "email": "[email protected]",
  "address": "42 rue de la Paix, 75002 Paris"
}

Classifier des tickets de support

La classification demande autre chose : au lieu de laisser le modèle choisir ses valeurs, vous énumérez dans le prompt les valeurs autorisées de chaque champ. C’est ce qui rend le résultat comparable d’un ticket à l’autre et directement utilisable pour du routage. Notez le passage à mistral-small-latest — un tri de tickets ne justifie pas le modèle le plus puissant.

tickets = [
    "Mon paiement a été débité deux fois, j'exige un remboursement immédiat !",
    "Comment puis-je changer mon mot de passe ?",
    "Votre application plante à chaque fois que j'ouvre l'onglet paramètres.",
]

for ticket in tickets:
    response = client.chat.complete(
        model="mistral-small-latest",
        messages=[
            {
                "role": "system",
                "content": """Classifie le ticket de support.
Retourne un JSON avec :
- category: "billing", "account", "technical", "feature_request" ou "other"
- priority: "low", "medium", "high" ou "critical"
- sentiment: "positive", "neutral" ou "negative"
- summary: résumé en une phrase"""
            },
            {"role": "user", "content": ticket}
        ],
        response_format={"type": "json_object"},
        temperature=0
    )

    result = json.loads(response.choices[0].message.content)
    print(f"Catégorie: {result['category']} | Priorité: {result['priority']} | Sentiment: {result['sentiment']}")

Le même classifieur en TypeScript, où le ! après content rappelle que le SDK type ce champ comme potentiellement nul :

import Mistral from "@mistralai/mistralai";

const client = new Mistral({ apiKey: "votre-clé-api" });

const ticket = "Mon paiement a été débité deux fois !";

const response = await client.chat.complete({
  model: "mistral-small-latest",
  messages: [
    {
      role: "system",
      content: `Classifie le ticket de support.
Retourne un JSON avec : category, priority, sentiment, summary.`,
    },
    { role: "user", content: ticket },
  ],
  responseFormat: { type: "json_object" },
  temperature: 0,
});

const result = JSON.parse(response.choices[0].message.content!);
console.log(`Catégorie: ${result.category}`);
console.log(`Priorité: ${result.priority}`);

Convertir une description en fiche produit

Troisième registre : transformer du texte marketing en enregistrement prêt pour une base de données. L’exercice se corse parce que les types comptent — un prix doit arriver en nombre, une durée de livraison en deux entiers, la gratuité du port en booléen. D’où la précision des annotations dans le prompt.

texte_produit = """
Le MacBook Pro 16 pouces avec puce M4 Pro est disponible à partir de 2 799 €.
Il dispose de 24 Go de RAM unifiée, d'un SSD de 512 Go, et d'un écran Liquid Retina XDR.
Disponible en Noir Sidéral et Argent. Livraison gratuite sous 3-5 jours.
"""

response = client.chat.complete(
    model="mistral-large-latest",
    messages=[
        {
            "role": "system",
            "content": """Convertis la description produit en fiche structurée.
JSON avec : name, brand, price_eur (nombre), specs (objet avec ram_gb, storage_gb, screen),
colors (liste), delivery_days_min, delivery_days_max, free_shipping (booléen)."""
        },
        {"role": "user", "content": texte_produit}
    ],
    response_format={"type": "json_object"},
    temperature=0
)

produit = json.loads(response.choices[0].message.content)
print(json.dumps(produit, indent=2, ensure_ascii=False))

Résultat :

{
  "name": "MacBook Pro 16 pouces",
  "brand": "Apple",
  "price_eur": 2799,
  "specs": {
    "ram_gb": 24,
    "storage_gb": 512,
    "screen": "Liquid Retina XDR"
  },
  "colors": ["Noir Sidéral", "Argent"],
  "delivery_days_min": 3,
  "delivery_days_max": 5,
  "free_shipping": true
}

Observez que la marque, Apple, n’apparaît nulle part dans le texte source : le modèle l’a déduite du nom du produit. C’est une force pour l’enrichissement, et un risque à surveiller si vous exigez une extraction strictement littérale.

Traiter plusieurs éléments en un appel

Rien ne vous oblige à un appel par élément. En demandant au modèle une liste sous une clé unique, vous divisez le nombre de requêtes — et donc la latence cumulée — sur des tâches courtes comme l’analyse d’avis. Le score demandé ici va de -1.0 à 1.0, une convention utile pour agréger ensuite les résultats.

textes = [
    "Excellent produit, je recommande !",
    "Livraison en retard, produit abîmé.",
    "Correct pour le prix, rien d'exceptionnel."
]

response = client.chat.complete(
    model="mistral-small-latest",
    messages=[
        {
            "role": "system",
            "content": "Analyse le sentiment de chaque avis. Retourne un JSON avec une clé 'reviews' contenant une liste d'objets {text, sentiment, score}. Le score va de -1.0 (très négatif) à 1.0 (très positif)."
        },
        {"role": "user", "content": "\n---\n".join(textes)}
    ],
    response_format={"type": "json_object"},
    temperature=0
)

reviews = json.loads(response.choices[0].message.content)["reviews"]
for r in reviews:
    print(f"[{r['score']:+.1f}] {r['sentiment']}{r['text'][:40]}...")

Un détail commun à tous ces exemples mérite d’être souligné : temperature=0 y est systématique. Sur des tâches d’extraction et de classification, la créativité n’apporte rien et coûte la reproductibilité.

Points clés à retenir

  • Le JSON Mode excelle pour l’extraction, la classification et la conversion de données
  • Utilisez le system prompt pour définir la structure attendue et les types
  • temperature=0 assure des résultats reproductibles
  • Le traitement par lots en une seule requête est possible en demandant une liste JSON
  • Parsez toujours la réponse avec json.loads() / JSON.parse() avant d’accéder aux données