Appeler l'API avec les Tools
Envoyer les tools à l’API Mistral
Vous avez défini vos fonctions et leurs spécifications JSON. Maintenant, il faut envoyer tout cela à l’API Mistral et comprendre ce que le modèle retourne. C’est l’étape 2-3 du processus : le modèle reçoit la requête utilisateur avec les outils et génère un appel de fonction.
La première requête
import os
import json
from mistralai import Mistral
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
# Les outils définis dans la leçon précédente
tools = [
{
"type": "function",
"function": {
"name": "retrieve_payment_status",
"description": "Récupère le statut d'un paiement à partir de l'identifiant de transaction.",
"parameters": {
"type": "object",
"properties": {
"transaction_id": {
"type": "string",
"description": "Identifiant unique de la transaction (ex: T1001)"
}
},
"required": ["transaction_id"]
}
}
}
]
# Message de l'utilisateur
messages = [
{"role": "user", "content": "Quel est le statut du paiement T1001 ?"}
]
# Appel à l'API avec les tools
response = client.chat.complete(
model="mistral-large-latest",
messages=messages,
tools=tools
)
Comprendre la réponse du modèle
La réponse du modèle contient un objet message qui peut avoir deux formes :
Cas 1 — Le modèle répond directement (pas besoin de fonction) :
# response.choices[0].message.content contient la réponse texte
# response.choices[0].message.tool_calls est None
print(response.choices[0].message.content)
# → "Bonjour ! Comment puis-je vous aider ?"
Cas 2 — Le modèle veut appeler une fonction :
# response.choices[0].message.content est None ou vide
# response.choices[0].message.tool_calls contient les appels
message = response.choices[0].message
if message.tool_calls:
for tool_call in message.tool_calls:
print(f"Fonction : {tool_call.function.name}")
print(f"Arguments : {tool_call.function.arguments}")
print(f"ID : {tool_call.id}")
Sortie typique :
Fonction : retrieve_payment_status
Arguments : {"transaction_id": "T1001"}
ID : call_abc123xyz
Parser la réponse et extraire les tool_calls
Voici le code complet pour extraire proprement les informations d’un tool_call :
message = response.choices[0].message
if message.tool_calls and len(message.tool_calls) > 0:
tool_call = message.tool_calls[0]
# Extraire le nom de la fonction
function_name = tool_call.function.name
# Parser les arguments JSON en dictionnaire Python
function_params = json.loads(tool_call.function.arguments)
# Récupérer l'identifiant unique de l'appel
tool_call_id = tool_call.id
print(f"Le modèle veut appeler : {function_name}")
print(f"Avec les paramètres : {function_params}")
print(f"ID de l'appel : {tool_call_id}")
else:
# Le modèle a répondu directement
print(f"Réponse : {message.content}")
Le tool_call_id est crucial — vous devrez le renvoyer avec le résultat pour que le modèle puisse associer le résultat au bon appel de fonction.
Quand le modèle demande des informations manquantes
Si l’utilisateur ne fournit pas assez d’informations, le modèle peut choisir de ne pas appeler de fonction et de poser une question clarificatrice :
messages = [
{"role": "user", "content": "Quel est le statut de mon paiement ?"}
]
response = client.chat.complete(
model="mistral-large-latest",
messages=messages,
tools=tools
)
message = response.choices[0].message
print(message.content)
# → "J'ai besoin de l'identifiant de transaction pour vérifier le statut.
# Pourriez-vous me fournir le numéro de transaction ?"
C’est un comportement souhaitable : le modèle sait que transaction_id est requis et demande l’information plutôt que d’inventer un identifiant.
Gestion du message système
Un message système permet de donner du contexte au modèle et de guider son comportement :
messages = [
{
"role": "system",
"content": "Vous êtes un assistant de suivi de paiements. "
"Répondez en français. "
"Utilisez les outils disponibles pour répondre aux questions "
"sur les transactions. Si l'utilisateur ne fournit pas "
"l'identifiant de transaction, demandez-le poliment."
},
{
"role": "user",
"content": "Quel est le statut du paiement T1001 ?"
}
]
Le message système est recommandé pour :
- Définir le ton et la langue de l’assistant
- Préciser quand utiliser les fonctions
- Donner des instructions spécifiques sur la gestion des erreurs
Code complet de l’étape 2-3
Voici le code complet et réutilisable pour envoyer une requête avec des tools :
import os
import json
from mistralai import Mistral
def call_mistral_with_tools(
messages: list,
tools: list,
model: str = "mistral-large-latest",
tool_choice: str = "auto"
) -> dict:
"""Envoie une requête à Mistral avec des tools et retourne la réponse parsée."""
client = Mistral(api_key=os.environ["MISTRAL_API_KEY"])
response = client.chat.complete(
model=model,
messages=messages,
tools=tools,
tool_choice=tool_choice
)
message = response.choices[0].message
if message.tool_calls and len(message.tool_calls) > 0:
return {
"type": "tool_call",
"message": message,
"tool_calls": [
{
"id": tc.id,
"function_name": tc.function.name,
"arguments": json.loads(tc.function.arguments)
}
for tc in message.tool_calls
]
}
return {
"type": "text",
"message": message,
"content": message.content
}
Points clés à retenir
- Envoyez les
toolset lesmessagesàclient.chat.complete()pour activer le function calling - Vérifiez toujours si
message.tool_callsexiste avant d’essayer de parser - Le
tool_call_idest obligatoire pour renvoyer le résultat au modèle - Les arguments sont une chaîne JSON qu’il faut parser avec
json.loads() - Le modèle peut choisir de répondre directement s’il n’a pas besoin de fonction ou s’il manque des informations