Utiliser client.chat.parse()
La méthode parse() : le coeur des Custom Structured Outputs
La méthode client.chat.parse() est l’équivalent structuré de client.chat.complete(). Au lieu de retourner du texte libre ou du JSON brut, elle retourne directement un objet typé correspondant à votre modèle Pydantic.
Différence entre complete() et parse()
# JSON Mode — complete() retourne du texte JSON
response = client.chat.complete(
model="mistral-large-latest",
messages=messages,
response_format={"type": "json_object"}
)
raw_json: str = response.choices[0].message.content
data = json.loads(raw_json) # Parsing manuel
# Custom — parse() retourne un objet typé
response = client.chat.parse(
model="mistral-large-latest",
messages=messages,
response_format=MonSchema
)
obj: MonSchema = response.choices[0].message.parsed # Objet Pydantic
raw_json: str = response.choices[0].message.content # JSON brut aussi disponible
La différence clé : parse() vous donne accès à .parsed, un objet Pydantic directement exploitable avec l’autocomplétion de votre IDE et la validation de types.
Exemple complet en Python
from mistralai import Mistral
from pydantic import BaseModel, Field
from typing import Optional
# 1. Définir le schéma
class BookInfo(BaseModel):
title: str = Field(description="Titre du livre")
authors: list[str] = Field(description="Liste des auteurs")
year: Optional[int] = Field(default=None, description="Année de publication")
genre: str = Field(description="Genre littéraire principal")
summary: str = Field(description="Résumé en 2-3 phrases")
# 2. Créer le client
client = Mistral(api_key="votre-clé-api")
# 3. Appeler parse()
response = client.chat.parse(
model="mistral-large-latest",
messages=[
{
"role": "system",
"content": "Tu es un bibliothécaire expert. Extrais les informations du livre mentionné."
},
{
"role": "user",
"content": "J'ai adoré '1984' de George Orwell. C'est un roman dystopique publié en 1949 qui décrit une société totalitaire sous surveillance permanente."
}
],
temperature=0
)
# 4. Utiliser l'objet parsé
book = response.choices[0].message.parsed
print(f"Titre : {book.title}")
print(f"Auteurs : {', '.join(book.authors)}")
print(f"Année : {book.year}")
print(f"Genre : {book.genre}")
print(f"Résumé : {book.summary}")
# 5. Le JSON brut est aussi disponible
raw = response.choices[0].message.content
print(f"\nJSON brut : {raw}")
Le system prompt auto-prepended
Quand vous utilisez parse(), Mistral ajoute automatiquement un préfixe au system prompt :
Your output should be an instance of a JSON object following this schema: { ... }
Ce préfixe contient le schéma JSON généré à partir de votre modèle Pydantic. Vous n’avez pas besoin de décrire le format dans votre prompt — le SDK le fait pour vous.
Cependant, ajouter des instructions contextuelles dans le system prompt reste recommandé :
response = client.chat.parse(
model="mistral-large-latest",
messages=[
{
"role": "system",
# Pas besoin de décrire le format JSON — c'est automatique
# Concentrez-vous sur le CONTEXTE et la QUALITÉ
"content": """Tu es un analyste financier expert.
Sois précis dans les montants et les pourcentages.
Si une donnée n'est pas disponible dans le texte, utilise null."""
},
{"role": "user", "content": texte_rapport}
],
response_format=RapportFinancier
)
Accéder aux données : parsed vs content
La réponse de parse() offre deux accès aux données :
.parsed — l’objet typé
book = response.choices[0].message.parsed
# Accès typé avec autocomplétion IDE
print(book.title) # str
print(book.authors) # list[str]
print(book.year) # Optional[int]
# Itération sur les listes
for author in book.authors:
print(f" - {author}")
# Conversion en dictionnaire
book_dict = book.model_dump()
# Sérialisation JSON
book_json = book.model_dump_json(indent=2)
.content — le JSON brut
raw = response.choices[0].message.content
# C'est une string JSON, utile pour :
# - Le logging
# - Le stockage en base de données
# - L'envoi à une autre API
import json
data = json.loads(raw)
Gestion des erreurs
Même avec parse(), des erreurs peuvent survenir. Voici un pattern robuste :
from mistralai import Mistral
from mistralai.models import SDKError
from pydantic import ValidationError
client = Mistral(api_key="votre-clé-api")
def extract_structured(text: str, schema, max_retries: int = 2):
"""Extraction structurée avec gestion d'erreurs."""
for attempt in range(max_retries + 1):
try:
response = client.chat.parse(
model="mistral-large-latest",
messages=[
{"role": "system", "content": "Extrais les informations demandées."},
{"role": "user", "content": text}
],
response_format=schema,
temperature=0,
max_tokens=1024
)
parsed = response.choices[0].message.parsed
if parsed is None:
raise ValueError("Parsed est None — réponse peut-être tronquée")
return parsed
except SDKError as e:
print(f"Erreur API (tentative {attempt + 1}) : {e}")
if attempt == max_retries:
raise
except ValidationError as e:
print(f"Erreur de validation (tentative {attempt + 1}) : {e}")
if attempt == max_retries:
raise
# Utilisation
try:
book = extract_structured("'Le Petit Prince' de Saint-Exupéry, 1943", BookInfo)
print(f"Extrait : {book.title} par {', '.join(book.authors)}")
except Exception as e:
print(f"Échec définitif : {e}")
Vérifier finish_reason
Comme avec complete(), vérifiez que la réponse est complète :
response = client.chat.parse(
model="mistral-large-latest",
messages=messages,
response_format=MonSchema,
max_tokens=256
)
if response.choices[0].finish_reason != "stop":
print(f"Attention : finish_reason = {response.choices[0].finish_reason}")
# "length" = réponse tronquée, augmentez max_tokens
Points clés à retenir
client.chat.parse()remplaceclient.chat.complete()pour les Custom Structured Outputs.parsedretourne un objet Pydantic typé,.contentretourne le JSON brut- Le schéma est automatiquement ajouté au system prompt — inutile de décrire le format
- Vérifiez toujours
finish_reasonet gérez les erreursSDKErroretValidationError - Utilisez
model_dump()pour convertir l’objet parsé en dictionnaire Python