Function Calling
Le Function Calling, dans le cadre de Tool Calling, permet aux modèles Mistral de se connecter à des outils locaux externes. En intégrant les modèles Mistral à des outils externes tels que des fonctions définies par l'utilisateur ou des API, vous pouvez créer des applications adaptées à des cas d'usage spécifiques et à des problématiques pratiques. Dans ce guide, par exemple, nous avons écrit deux fonctions pour suivre le statut de paiement et la date de paiement. Nous pouvons utiliser ces deux outils pour répondre à des requêtes liées aux paiements.
Avant de continuer, nous vous recommandons de lire la documentation Chat Completions pour en savoir plus sur l'API chat completions et comment l'utiliser avant de poursuivre.
Avant de commencer
Modèles disponibles
Actuellement, parmi les modèles compatibles avec le function calling, nous avons la liste non exhaustive suivante :
| Modèles généraux | Modèles spécialisés | Modèles de raisonnement |
|---|---|---|
| Mistral Large 3 - mistral-large-latest | Devstral 2.0 - devstral-latest | Magistral Medium 1.2 - magistral-medium-latest |
| Mistral Medium 3.1 - mistral-medium-latest | Devstral Small 2 - devstral-small-latest | Magistral Small 1.2 - magistral-small-latest |
| Mistral Small 3.2 - mistral-small-latest | Voxtral Small - voxtral-small-latest | |
| Mistral Small Creative - labs-mistral-small-creative | Codestral - codestral-latest | |
| Ministral 3 14B - ministral-14b-latest | ||
| Ministral 3 8B - ministral-8b-latest | ||
| Ministral 3 3B - ministral-3b-latest |
Pour des informations exhaustives sur tous nos modèles, consultez la page Modèles.
Cinq étapes
En résumé, le function calling comporte cinq étapes principales :
- 1. Développeur : Spécifier les fonctions/outils et un prompt système (optionnel)
- 2. Utilisateur : Interroger le modèle doté des nouvelles fonctions/outils
- 3. Modèle : Génère les arguments de fonction si applicable et si nécessaire
- 4. Développeur : Exécute la fonction correspondante pour obtenir les résultats de l'outil
- 5. Modèle : Génère une réponse basée sur les résultats de l'outil
En général, une conversation avec function calling se présente toujours ainsi :
| Type de séquence | Flux de rôles |
|---|---|
| Sans appel de fonction | system* → user → assistant → user → ... |
| Avec appel de fonction | system* → user → assistant appel fonction 1 → tool résultat 1 → assistant → user → ... |
| Appels de fonction successifs | system* → user → assistant af.1 → tool r.1 → assistant af.2 → tool r.2→ assistant → user → ... |
| Appels de fonction parallèles | system* → user → assistant af.1, af.2 → tool r.1 → tool r.2 → assistant → user → ... |
| *optionnel |
Dans ce guide, nous allons parcourir un exemple simple de function calling pour illustrer le fonctionnement du function calling avec les modèles Mistral en cinq étapes.

Avant de commencer, supposons que nous ayons un dataframe contenant des transactions de paiement. Lorsque les utilisateurs posent des questions sur ce dataframe, ils peuvent utiliser certains outils pour répondre à des questions sur ces données. Ceci est juste un exemple pour émuler une base de données externe à laquelle le LLM ne peut pas accéder directement.
import pandas as pd
# Assuming we have the following data
data = {
'transaction_id': ['T1001', 'T1002', 'T1003', 'T1004', 'T1005'],
'customer_id': ['C001', 'C002', 'C003', 'C002', 'C001'],
'payment_amount': [125.50, 89.99, 120.00, 54.30, 210.20],
'payment_date': ['2021-10-05', '2021-10-06', '2021-10-07', '2021-10-05', '2021-10-08'],
'payment_status': ['Paid', 'Unpaid', 'Paid', 'Paid', 'Pending']
}
# Create DataFrame
df = pd.DataFrame(data)Étape 1. Développeur
Fonctions et définitions système

Les développeurs peuvent définir tous les outils nécessaires à leurs cas d'usage. Souvent, nous pouvons disposer de plusieurs outils. Pour cet exemple, considérons que nous avons deux fonctions comme nos deux outils :
retrieve_payment_status: pour récupérer le statut de paiement à partir d'un ID de transaction.retrieve_payment_date: pour récupérer la date de paiement à partir d'un ID de transaction.
def retrieve_payment_status(transaction_id: str) -> str:
"Get payment status of a transaction"
if transaction_id in df.transaction_id.values:
return json.dumps({'status': df[df.transaction_id == transaction_id].payment_status.item()})
return json.dumps({'error': 'transaction id not found.'})
def retrieve_payment_date(transaction_id: str) -> str:
"Get payment date of a transaction"
if transaction_id in df.transaction_id.values:
return json.dumps({'date': df[df.transaction_id == transaction_id].payment_date.item()})
return json.dumps({'error': 'transaction id not found.'})Pour faciliter l'utilisation, nous allons organiser les deux fonctions dans un dictionnaire où les clés représentent les noms des fonctions, et les valeurs sont les fonctions elles-mêmes. Cela nous permet d'appeler dynamiquement chaque fonction en fonction de son nom.
names_to_functions = {
'retrieve_payment_status': retrieve_payment_status,
'retrieve_payment_date': retrieve_payment_date,
}Lors de la configuration d'un modèle capable d'appels de fonctions et de workflows agentiques, il est recommandé de fournir du contexte et des instructions personnalisées sous le rôle system. Vous pouvez le faire en ajoutant un message system à l'historique de conversation.
Pour cet exemple, nous allons définir un prompt système très simple pour guider le modèle sur la façon d'utiliser les outils fournis.
messages = [
{
"role": "system",
"content": "You are a helpful assistant. You can use the following tools to help answer the user's questions related to payment transactions."
}
]Pour que les modèles comprennent ces fonctions, nous devons décrire les spécifications des fonctions avec un schéma JSON. Plus précisément, nous devons décrire le type, le nom de la fonction, la description de la fonction, les paramètres de la fonction et le paramètre requis pour la fonction. Comme nous avons deux fonctions ici, listons deux spécifications de fonctions dans une liste.
tools = [
{
"type": "function",
"function": {
"name": "retrieve_payment_status",
"description": "Get payment status of a transaction",
"parameters": {
"type": "object",
"properties": {
"transaction_id": {
"type": "string",
"description": "The transaction id.",
}
},
"required": ["transaction_id"],
},
},
},
{
"type": "function",
"function": {
"name": "retrieve_payment_date",
"description": "Get payment date of a transaction",
"parameters": {
"type": "object",
"properties": {
"transaction_id": {
"type": "string",
"description": "The transaction id.",
}
},
"required": ["transaction_id"],
},
},
}
]
# Note: You can specify multiple parameters for each function in the `properties` object.Étape 2. Utilisateur
Interroger le modèle

Avec nos fonctions et instructions prêtes, supposons qu'un utilisateur pose la question suivante : « Quel est le statut de ma transaction T1001 ? » Un LLM autonome ne pourrait pas répondre à cette question, car il doit interroger le backend de la logique métier pour accéder aux données nécessaires. Mais avec les appels de fonctions, nous pouvons utiliser les outils que nous avons définis pour répondre en conséquence.
messages.append({"role": "user", "content": "What's the status of my transaction T1001?"})La question précédente attend du modèle qu'il utilise la fonction retrieve_payment_status pour obtenir le statut de paiement de la transaction T1001.
Étape 3. Modèle
Générer les arguments de fonction

Comment les modèles sont-ils informés de ces fonctions et savent-ils quelle fonction utiliser ? Nous fournissons à la fois la requête utilisateur et les spécifications des outils aux modèles. L'objectif de cette étape n'est pas que le modèle Mistral exécute directement la fonction. Il s'agit de :
- Déterminer la fonction appropriée à utiliser.
- Identifier s'il manque des informations essentielles pour une fonction.
- Générer les arguments nécessaires pour la fonction choisie.
Les développeurs peuvent utiliser tool_choice pour spécifier comment les outils sont utilisés :
- "auto" : mode par défaut. Le modèle décide s'il utilise l'outil ou non.
- "any" : force l'utilisation d'un outil.
- "none" : empêche l'utilisation d'outils.
Et parallel_tool_calls pour spécifier si l'appel d'outils parallèles est autorisé.
- true : mode par défaut. Le modèle décide s'il utilise des appels d'outils parallèles ou non.
- false : force le modèle à utiliser un appel d'outil unique.
Avec tous nos outils, le système et la requête prêts, nous pouvons appeler le modèle pour soit répondre, soit utiliser les outils, en générant les arguments nécessaires pour la fonction choisie.
import os
from mistralai.client import Mistral
api_key = os.environ["MISTRAL_API_KEY"]
model = "mistral-large-latest"
client = Mistral(api_key=api_key)
response = client.chat.complete(
model = model, # The model we want to use
messages = messages, # The message history, in this example we have a system (optional) + user query.
tools = tools, # The tools specifications
tool_choice = "any",
parallel_tool_calls = False,
)Le modèle a fourni un appel d'outil en réponse, consultez la sortie brute pour plus d'informations :
[
{
"function": {
"name": "retrieve_payment_status",
"arguments": "{\"transaction_id\": \"T1001\"}"
},
"id": "D681PevKs",
"type": "function"
}
]Ajoutons le message de réponse à l'historique de la liste messages pour poursuivre la conversation.
messages.append(response.choices[0].message)Ici, nous avons obtenu la réponse incluant tool_calls avec le nom de fonction choisi retrieve_payment_status et les arguments pour cette fonction, l'étape suivante consiste à exécuter la fonction.
Étape 4. Développeur
Exécuter les fonctions

Comment exécuter la fonction ? Actuellement, il incombe au développeur d'exécuter ces fonctions et l'exécution des fonctions relève de la responsabilité de l'utilisateur/développeur. Nous avons également introduit certains outils exécutés côté serveur pour nos API Agents et Conversations, consultez Outils.
Pour l'exécuter, nous extrayons quelques informations de fonction utiles de la réponse du modèle, notamment function_name et function_params. Il est clair ici que notre modèle a choisi d'utiliser retrieve_payment_status avec le paramètre transaction_id défini sur T1001.
import json
tool_call = response.choices[0].message.tool_calls[0]
function_name = tool_call.function.name # The function name to call
function_params = json.loads(tool_call.function.arguments) # The function arguments
print("\nfunction_name: ", function_name, "\nfunction_params: ", function_params)Nous exécutons ensuite la fonction correspondante et nous obtenons la sortie de fonction '{"status": "Paid"}'.
function_result = names_to_functions[function_name](**function_params)
print(function_result)Étape 5. Modèle
Générer la réponse de suivi

Nous pouvons désormais fournir la sortie des outils/fonctions à notre modèle, qui peut en retour produire une réponse finale personnalisée pour l'utilisateur spécifique (ou dans certains cas, un autre appel d'outil).
messages.append({
"role":"tool",
"name":function_name,
"content":function_result,
"tool_call_id":tool_call.id
})
response = client.chat.complete(
model = model,
messages = messages
)
response.choices[0].message.contentNotre modèle a généré avec succès une réponse en utilisant la sortie de l'outil, fournissant la réponse finale :
- « Le statut de votre transaction avec l'ID T1001 est Payé. Puis-je vous aider pour autre chose ? »
Un modèle est autorisé à faire suivre un appel d'outil par un autre appel d'outil. Pour gérer ces scénarios, vous devez appeler récursivement le modèle avec le nouvel appel d'outil jusqu'à ce qu'il génère une réponse finale.
Exemple complet
Vous trouverez ci-dessous un exemple complet des étapes ci-dessus en boucle pour simuler une session de chat, gérant de manière interactive des appels d'outils successifs et/ou parallèles.
# Imports
import pandas as pd
import os
from mistralai.client import Mistral
import json
# Example Dataset to query from
data = {
'transaction_id': ['T1001', 'T1002', 'T1003', 'T1004', 'T1005'],
'customer_id': ['C001', 'C002', 'C003', 'C002', 'C001'],
'payment_amount': [125.50, 89.99, 120.00, 54.30, 210.20],
'payment_date': ['2021-10-05', '2021-10-06', '2021-10-07', '2021-10-05', '2021-10-08'],
'payment_status': ['Paid', 'Unpaid', 'Paid', 'Paid', 'Pending']
}
df = pd.DataFrame(data)
# Functions to be used as tools
def retrieve_payment_status(transaction_id: str) -> str:
"Get payment status of a transaction"
if transaction_id in df.transaction_id.values:
return json.dumps({'status': df[df.transaction_id == transaction_id].payment_status.item()})
return json.dumps({'error': 'transaction id not found.'})
def retrieve_payment_date(transaction_id: str) -> str:
"Get payment date of a transaction"
if transaction_id in df.transaction_id.values:
return json.dumps({'date': df[df.transaction_id == transaction_id].payment_date.item()})
return json.dumps({'error': 'transaction id not found.'})
# Map function names to the functions
names_to_functions = {
'retrieve_payment_status': retrieve_payment_status,
'retrieve_payment_date': retrieve_payment_date,
}
# Define the system prompt
messages = [
{
"role": "system",
"content": "You are a helpful assistant. You can use the following tools to help answer the user's questions related to payment transactions."
}
]
# Define the tools specifications
tools = [
{
"type": "function",
"function": {
"name": "retrieve_payment_status",
"description": "Get payment status of a transaction",
"parameters": {
"type": "object",
"properties": {
"transaction_id": {
"type": "string",
"description": "The transaction id.",
}
},
"required": ["transaction_id"],
},
},
},
{
"type": "function",
"function": {
"name": "retrieve_payment_date",
"description": "Get payment date of a transaction",
"parameters": {
"type": "object",
"properties": {
"transaction_id": {
"type": "string",
"description": "The transaction id.",
}
},
"required": ["transaction_id"],
},
},
}
]
# Note: You can specify multiple parameters for each function in the `properties` object.
# Initialize the client and model
api_key = os.environ["MISTRAL_API_KEY"]
model = "mistral-large-latest"
client = Mistral(api_key=api_key)
temperature = 0.1
top_p = 0.9
# Chat loop
while True:
# The user query, example: "What's the status of my transaction T1001? After receiving the answer, provide the current status of T1001. Afte that, look for the next one between T1002 if previous status was 'Paid' and T1003 if previous status was 'Unpaid'."
user_query = input("User: ")
if not user_query:
break
messages.append({"role": "user", "content": user_query})
# Call the model
response = client.chat.complete(
model = model,
messages = messages,
tools = tools,
temperature = temperature,
top_p = top_p
)
# Add the response message to the messages list
messages.append(response.choices[0].message)
# Retrieve the function name and arguments if any, interactively until the model returns a final answer
while response.choices[0].message.tool_calls:
# Print content in case we have interleaved tool calls and text content
if response.choices[0].message.content:
print("Assistant:", response.choices[0].message.content)
# Handle each tool call
for tool_call in response.choices[0].message.tool_calls:
function_name = tool_call.function.name # The function name to call
function_params = json.loads(tool_call.function.arguments) # The function arguments
function_result = names_to_functions[function_name](**function_params) # The function result
# Print the function call
print(f"Tool {tool_call.id}:", f"{function_name}({function_params}) -> {function_result}")
# Add the function result to the messages list and call model
messages.append({
"role":"tool",
"name":function_name,
"content":function_result,
"tool_call_id":tool_call.id
})
response = client.chat.complete(
model = model,
messages = messages,
tools = tools,
temperature = temperature,
top_p = top_p
)
# Add the new response message to the messages list
messages.append(response.choices[0].message)
# Print the final answer
print("Assistant:", response.choices[0].message.content)Pour aller plus loin
Si vous vous intéressez aux appels de fonction et souhaitez explorer les solutions intégrées, MCP et d'autres cas d'usage agentiques, nous vous invitons à consulter la documentation Agents ici.