Aller au contenu principal

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 dans tool_calls
  • function.description : une phrase claire qui aide le modèle à choisir la bonne fonction
  • function.parameters : un objet JSON Schema décrivant les paramètres attendus
  • required : 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 enum quand 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, une description et des parameters typés
  • Les types supportés incluent string, integer, number, boolean, array et object
  • La liste required distingue les paramètres obligatoires des optionnels
  • Des descriptions précises avec des exemples améliorent significativement la précision du modèle