Définir des Fonctions avec JSON Schema
Le contrat entre votre code et le modèle
Pour que le modèle Mistral puisse appeler vos fonctions, il doit savoir ce qui existe et comment l’utiliser. C’est le rôle du JSON Schema : un format standardisé qui décrit chaque fonction — son nom, ce qu’elle fait, quels paramètres elle attend et lesquels sont obligatoires.
Le modèle ne voit jamais votre code Python. Il ne voit que cette spécification. Plus votre schéma est précis et bien documenté, plus le modèle génèrera des arguments corrects.
Anatomie d’une spécification de tool
Chaque outil envoyé à l’API Mistral a cette structure :
tool = {
"type": "function",
"function": {
"name": "nom_de_la_fonction",
"description": "Description claire de ce que fait la fonction",
"parameters": {
"type": "object",
"properties": {
"param1": {
"type": "string",
"description": "Description du paramètre"
},
"param2": {
"type": "integer",
"description": "Description du paramètre"
}
},
"required": ["param1"]
}
}
}
Décortiquons chaque champ :
type: toujours"function"(d’autres types pourront exister dans le futur)function.name: le nom exact de votre fonction Python — c’est ce que le modèle retournera danstool_callsfunction.description: une phrase claire qui aide le modèle à choisir la bonne fonctionfunction.parameters: un objet JSON Schema décrivant les paramètres attendusrequired: la liste des paramètres obligatoires
Les types JSON Schema supportés
Les types que vous pouvez utiliser dans les paramètres :
# String — texte libre ou contraint
{"type": "string", "description": "Identifiant de transaction"}
# String avec enum — valeurs limitées
{"type": "string", "enum": ["asc", "desc"], "description": "Ordre de tri"}
# Integer — nombre entier
{"type": "integer", "description": "Nombre de résultats à retourner"}
# Number — nombre décimal
{"type": "number", "description": "Montant en euros"}
# Boolean — vrai/faux
{"type": "boolean", "description": "Inclure les transactions annulées"}
# Array — liste de valeurs
{
"type": "array",
"items": {"type": "string"},
"description": "Liste des identifiants de transaction"
}
# Object — objet imbriqué
{
"type": "object",
"properties": {
"city": {"type": "string"},
"country": {"type": "string"}
},
"description": "Adresse de livraison"
}
Exemple complet : deux fonctions complémentaires
Voici un exemple réaliste avec deux fonctions liées aux paiements, inspiré de la documentation officielle Mistral :
tools = [
{
"type": "function",
"function": {
"name": "retrieve_payment_status",
"description": "Récupère le statut d'un paiement (payé, en attente, échoué) "
"à partir de l'identifiant de transaction.",
"parameters": {
"type": "object",
"properties": {
"transaction_id": {
"type": "string",
"description": "L'identifiant unique de la transaction (ex: T1001)"
}
},
"required": ["transaction_id"]
}
}
},
{
"type": "function",
"function": {
"name": "retrieve_payment_date",
"description": "Récupère la date à laquelle un paiement a été effectué "
"à partir de l'identifiant de transaction.",
"parameters": {
"type": "object",
"properties": {
"transaction_id": {
"type": "string",
"description": "L'identifiant unique de la transaction (ex: T1001)"
}
},
"required": ["transaction_id"]
}
}
}
]
Remarquez que les deux fonctions ont le même paramètre (transaction_id) mais des descriptions différentes. Le modèle utilisera la description de la fonction pour déterminer laquelle appeler selon la question de l’utilisateur.
Paramètres requis vs optionnels
La distinction entre paramètres requis et optionnels est cruciale :
{
"type": "function",
"function": {
"name": "search_transactions",
"description": "Recherche des transactions selon différents critères",
"parameters": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": ["payé", "en_attente", "échoué"],
"description": "Filtrer par statut de paiement"
},
"date_from": {
"type": "string",
"description": "Date de début au format YYYY-MM-DD"
},
"date_to": {
"type": "string",
"description": "Date de fin au format YYYY-MM-DD"
},
"min_amount": {
"type": "number",
"description": "Montant minimum en euros"
}
},
"required": ["status"]
}
}
}
Ici, seul status est requis. Les autres paramètres sont optionnels — le modèle ne les inclura que si l’utilisateur les mentionne. Si l’utilisateur dit « Montre-moi les paiements échoués », le modèle générera {"status": "échoué"}. S’il dit « Montre-moi les paiements échoués de mars 2026 », le modèle ajoutera les dates.
Bonnes pratiques pour les descriptions
La qualité des descriptions impacte directement la précision du modèle :
# Mauvais — trop vague
{"description": "Récupère des données"}
# Bon — précis et contextuel
{"description": "Récupère le statut d'un paiement (payé, en attente, échoué) "
"à partir de l'identifiant de transaction unique"}
# Mauvais — pas de description pour le paramètre
{"transaction_id": {"type": "string"}}
# Bon — description avec exemple
{"transaction_id": {
"type": "string",
"description": "Identifiant unique de la transaction (format: T suivi de 4 chiffres, ex: T1001)"
}}
Pensez à inclure :
- Ce que fait la fonction en une phrase
- Le format attendu pour chaque paramètre
- Un exemple quand le format n’est pas évident
- Les valeurs possibles via
enumquand elles sont limitées
Points clés à retenir
- Le JSON Schema est le contrat entre votre code et le modèle — il décrit vos fonctions sans exposer le code
- Chaque tool a un
name, unedescriptionet desparameterstypés - Les types supportés incluent
string,integer,number,boolean,arrayetobject - La liste
requireddistingue les paramètres obligatoires des optionnels - Des descriptions précises avec des exemples améliorent significativement la précision du modèle