AI Endpoints - Appel de fonctions
Découvrez comment utiliser l'appel de fonctions avec OVHcloud AI Endpoints
Introduction
AI Endpoints est une plateforme serverless proposée par OVHcloud qui offre un accès simplifié à une sélection de modèles d'IA pré-entraînés, mondialement reconnus. La plateforme est conçue pour être simple, sécurisée et intuitive, ce qui en fait une solution idéale pour les développeurs souhaitant enrichir leurs applications avec des capacités d'IA sans expertise poussée en IA ni préoccupations sur la confidentialité des données.
L'appel de fonctions (Function Calling), aussi appelé tool calling, est une fonctionnalité qui permet à un grand modèle de langage (LLM) de déclencher des fonctions définies par l'utilisateur (aussi appelées outils/tools). Ces outils sont définis par le développeur et implémentent des comportements spécifiques tels qu'appeler une API, récupérer des données ou effectuer des calculs, ce qui étend les capacités du LLM.
Le LLM identifie quel(s) outil(s) appeler et les arguments à utiliser. Cette fonctionnalité peut par exemple être utilisée pour développer des assistants ou des agents.
Objectif
Cette documentation présente un aperçu de l'utilisation de l'appel de fonctions avec les modèles d'IA proposés sur AI Endpoints.
Les exemples fournis dans ce guide utilisent le modèle Mistral-Nemo-Instruct-2407.
Consultez notre Catalogue pour découvrir quels modèles sont compatibles avec l'appel de fonctions.
Prérequis
Nous utilisons Python pour les exemples fournis dans ce guide.
Assurez-vous d'avoir un environnement Python configuré, et installez le client openai.
Aperçu de l'appel de fonctions
Le fonctionnement de l'appel de fonctions est décrit ci-dessous :
- Définir les outils : indiquer au modèle quels outils il peut utiliser, avec un schéma JSON pour chaque outil.
- Appeler le modèle avec les outils : transmettre les outils avec vos messages système et utilisateur au modèle, qui générera éventuellement des appels d'outils.
- Traiter les appels d'outils : pour chaque appel d'outil renvoyé par le modèle, exécuter l'implémentation réelle de l'outil dans votre code.
- Appeler le modèle avec les réponses des outils : envoyer une nouvelle requête au modèle, avec la conversation mise à jour avec les résultats des appels d'outils.
- Réponse finale : traiter la réponse finale générée, qui prend en compte les résultats des outils.
Ce schéma illustre le fonctionnement :

Exemple : un assistant de suivi du temps
Pour illustrer l'utilisation de l'appel de fonctions et introduire progressivement les notions importantes liées à cette fonctionnalité, nous allons développer, étape par étape, un assistant de suivi du temps (time-tracking assistant).
L'assistant sera capable de :
- enregistrer le temps passé sur une tâche
- générer un rapport de temps
Chaque tâche possède un nom, une catégorie et une durée totale en minutes. Les catégories forment une liste fixe de chaînes de caractères, par exemple « Code » ou « Meetings ». Un rapport de temps peut être généré pour une catégorie de tâche donnée.
L'utilisateur pourra interagir avec l'assistant pour enregistrer du temps et obtenir des informations sur la répartition du temps passé.
Définir les outils
Notre assistant de suivi du temps utilisera deux outils :
-
log_work : enregistre le temps passé sur une tâche. Prend le nom de la tâche, la catégorie, la durée et l'unité (minutes ou heures).
Par exemple, pour enregistrer 2 heures passées sur la rédaction de documentation, vous appelleriez log_work("User guide", "Documentation", 2, "hours")
-
time_report : récupère des données JSON sur toutes les tâches d'une catégorie donnée, et la durée totale dans une unité de temps donnée (minutes ou heures).
Par exemple, pour obtenir la répartition du temps passé sur des tâches de code, en heures, vous appelleriez time_report("Code", "hours")
Pour que le modèle utilise ces outils, nous devons d'abord les déclarer à l'aide de schémas JSON, dans une liste tools que nous transmettrons à l'API Chat Completion.
Voici comment les outils peuvent être déclarés en Python :
# TOOLS DECLARATION (JSON SCHEMA)
# Possible Categories (we'll reuse this later)
CATEGORIES = ["Code", "Meetings", "Documentation", "Other"]
# Define the tool specification
TOOLS = [
{
"type": "function",
"function": {
"name": "log_work",
"description": "Logs a work session for a specific task by providing a start and end datetime.",
"parameters": {
"type": "object",
"properties": {
"task_name": {
"type": "string",
"description": "The name of the task to log work for."
},
"task_category": {
"type": "string",
"enum": CATEGORIES,
"description": "The category of the task to log work for."
},
"duration": {
"type": "number",
"description": "The duration to log work for."
},
"unit": {
"type": "string",
"enum": ["minutes", "hours"],
"description": "The time unit to log work in."
}
},
"required": ["task_name", "task_category", "duration", "unit"]
}
}
},
{
"type": "function",
"function": {
"name": "time_report",
"description": "Output a JSON with the breakdown of time spent by each task of a given category, returned in a given time unit.",
"parameters": {
"type": "object",
"properties": {
"category": {
"type": "string",
"description": "The name of the category to get the report for."
},
"unit": {
"type": "string",
"enum": ["minutes", "hours"],
"description": "The time unit to return the result in."
}
},
"required": ["category", "unit"]
}
}
}
]
Générer des appels d'outils
Nos outils étant prêts, nous pouvons maintenant essayer d'appeler le modèle et voir s'il comprend notre définition des outils. Nous utilisons le SDK Python OpenAI pour appeler la route ``/v1/chat/completionsde l'endpoint, en transmettant la définition des outils dans le paramètretools`.
Envoyons un simple message utilisateur : log 1 hour team meeting et voyons ce que répond le modèle.
Info
Pour obtenir une clé d'accès API pour un accès authentifié, suivez les instructions données dans le guide AI Endpoints - Premiers pas. Sinon, vous serez soumis à une limitation de débit (rate limiting).
import os
from openai import OpenAI
MODEL_NAME = "Mistral-Nemo-Instruct-2407"
API_KEY = os.environ.get("OVH_AI_ENDPOINTS_ACCESS_TOKEN")
# Initialize the OpenAI client
client = OpenAI(
base_url="https://oai.endpoints.kepler.ai.cloud.ovh.net/v1",
api_key=API_KEY
)
messages = [
{"role": "user", "content": "log 1 hour team meeting"}
]
response = client.chat.completions.create(
model=MODEL_NAME,
messages=messages,
tools=TOOLS,
tool_choice="auto",
temperature=0.15
)
# Add the assistant response to the conversation
assistant_response = response.choices[0].message
messages.append(assistant_response)
print(assistant_response.to_json())
Output:
{
"role": "assistant",
"tool_calls": [
{
"id": "wuvyeH6fR",
"function": {
"arguments": "{\"task_name\": \"team meeting\", \"task_category\": \"Meetings\", \"duration\": 1, \"unit\": \"hours\"}",
"name": "log_work"
},
"type": "function"
}
]
}
Nous constatons, en observant le message assistant généré, que le modèle a correctement identifié qu'il devait appeler l'outil log_work.
La liste tool_calls contient les appels d'outils générés par le modèle en réponse à notre message utilisateur.
Les champs name et arguments précisent quel outil appeler et quels paramètres transmettre à la fonction.
L'id est un identifiant unique pour cet appel d'outil, dont nous aurons besoin plus tard.
Cette liste peut contenir plusieurs appels d'outils.
En interne, le modèle a reconnu que l'intention de l'utilisateur était liée à l'ensemble des outils fournis, et a généré une séquence de tokens spécifiques qui ont été post-traités pour créer un objet d'appel d'outil.
Nous ajoutons ce message à la conversation afin que le modèle ait connaissance de cet appel d'outil lors des tours suivants de notre conversation multi-tours.
Traiter les appels d'outils
Maintenant que nous avons vu que le modèle est capable de générer des appels d'outils, nous devons coder l'implémentation Python des outils, afin de pouvoir traiter les appels d'outils générés par le LLM et commencer à enregistrer le temps !
Chaque tâche est stockée dans un dictionnaire, avec le nom comme clé, et les catégories forment une liste fixe.
Nous définissons les deux fonctions, log_work et time_report, dans le code Python ci-dessous :
# TOOLS IMPLEMENTATION
import json
from dataclasses import dataclass
# We store tasks by their names
TASKS_BY_NAME = {}
# A task has a name, category, and total duration in minutes
# When we log a new work entry for a task, we add to this total duration
@dataclass
class Task:
name: str
category: str
duration_minutes: float = 0.0
def add_entry(self, duration:float, unit:str):
self.duration_minutes += to_minutes(duration, unit)
def __str__(self):
return json.dumps({"name": self.name, "category": self.category, "total_duration": self.duration_minutes})
# TOOL 1 : log a work entry (task name, category, duration and unit = minutes or hours)
def log_work(task_name: str, task_category: str, duration: float, unit: str):
# we create a new task if the name doesn't exist yet
if task_name in TASKS_BY_NAME:
status = "updated"
else:
status = "created"
TASKS_BY_NAME[task_name] = Task(task_name, task_category)
task = TASKS_BY_NAME.get(task_name)
task.add_entry(duration=duration, unit=unit)
# the tool returns the data for the created or updated task, so that the model can use this information if needed
return {"task": task.name, "task_category": task.category, "total_duration": convert(task.duration_minutes, unit), "status": status}
# TOOL 2 : get JSON data about a tasks in a given category, and total duration (category, unit = minutes or hours)
def time_report(category: str, unit: str):
data = [{"name":t.name, "total_duration":convert(t.duration_minutes, unit)} for t in TASKS_BY_NAME.values() if t.category == category]
data.append({"total_duration_for_category": sum([x["total_duration"] for x in data])})
return data
# Utilities function: convert to and from minutes and hours
def convert(duration_min: float, unit: str) -> float:
if unit == "minutes":
return duration_min
elif unit == "hours":
return duration_min / 60
else:
raise ValueError("Invalid unit. Must be 'minutes', or 'hours'.")
def to_minutes(duration: float, unit: str) -> float:
if unit == "minutes":
return duration
elif unit == "hours":
return duration * 60
else:
raise ValueError("Invalid unit. Must be 'minutes', or 'hours'.")
Voyons maintenant comment nous pouvons traiter les appels d'outils générés par le modèle :
# this map allows us to know which Python function for a given tool
FUNCTION_MAP = {
"log_work": log_work,
"time_report": time_report
}
# if there are tool calls in the assistant-generated response
if assistant_response.tool_calls:
print(f"<\t{len(assistant_response.tool_calls)} tool(s) to call")
# we can have several tool calls
for tool_call in assistant_response.tool_calls:
# The tool name should be associated with a Python function
if tool_call.function.name in FUNCTION_MAP.keys():
# the arguments provided by the model should be a valid JSON (in production code, this should be checked)
function_args = json.loads(tool_call.function.arguments)
print(f">\t\tExecute tool {tool_call.function.name} with arguments {function_args}")
# execute the tool
function_response = FUNCTION_MAP[tool_call.function.name](**function_args)
print(function_response)
Output:
< 1 tool(s) to call
> Execute tool log_work with arguments {'task_name': 'team meeting', 'task_category': 'Meetings', 'duration': 1, 'unit': 'hours'}
{'task': 'team meeting', 'task_category': 'Meetings', 'total_duration': 1.0}
Nous constatons que nous avons créé avec succès une tâche appelée « team meeting », dans la catégorie « Meetings », avec une durée totale de 1 heure.
Envoyer les résultats des appels d'outils et obtenir la réponse finale
Maintenant que nous avons exécuté nos appels d'outils, nous devons renvoyer le résultat au modèle afin qu'il puisse générer une nouvelle réponse en tenant compte de cette nouvelle information, par exemple pour informer l'utilisateur que la tâche a bien été créée ou pour fournir le rapport horaire.
Il ne nous reste plus qu'à ajouter les résultats des outils sous forme de nouveaux messages tool dans la conversation ; nous allons donc mettre à jour notre code :
if assistant_response.tool_calls:
print(f"<\t{len(assistant_response.tool_calls)} tool(s) to call")
# we can have several tool calls
for tool_call in assistant_response.tool_calls:
# The tool name should be associated with a Python function
if tool_call.function.name in FUNCTION_MAP.keys():
# the arguments provided by the model should be a valid JSON (in production code, this should be checked)
function_args = json.loads(tool_call.function.arguments)
print(f">\t\tExecute tool {tool_call.function.name} with arguments {function_args}")
# execute the tool
function_response = FUNCTION_MAP[tool_call.function.name](**function_args)
# Add tool call result to the conversation
tool_call_result = {
"role": "tool",
"name": tool_call.function.name,
"content": json.dumps(function_response),
"tool_call_id": tool_call.id
}
messages.append(tool_call_result)
print(f">\t\tAdd tool call result to conversation:\n{tool_call_result}")
Nous appelons ensuite le modèle avec la conversation mise à jour :
print(f">\tCall assistant with tool results")
response = client.chat.completions.create(
model=MODEL_NAME,
messages=messages,
)
print(f"<\t\tAssistant final answer:\n{response.choices[0].message.content}")
Output:
< 1 tool(s) to call
> Execute tool log_work with arguments {'task_name': 'team meeting', 'task_category': 'Meetings', 'duration': 1, 'unit': 'hours'}
> Add tool call result to conversation:
{'role': 'tool', 'name': 'log_work', 'content': '{"task": "team meeting", "task_category": "Meetings", "total_duration": 1.0, "status": "created"}', 'tool_call_id': 'v1X1sJP9b'}
> Call assistant with tool results
< Assistant final answer:
Following is the details of 1 hour team meeting:
- Task: Team Meeting
- Duration: 1.0 hours
- Status: Created
L'assistant a généré une réponse confirmant la création de la tâche.
Ajouter un system prompt
Pour rendre notre assistant plus robuste et plus performant, il peut être utile d'ajouter un system prompt qui :
- explique ce qui est attendu du modèle.
- fournit au modèle des informations utiles, comme les tâches et catégories actuellement existantes.
SYSTEM_PROMPT = \
"""
You are a helpful and precise time-tracking assistant.
You use tools to log work and generate time reports.
# Possible categories: {{categories}}
# Existing tasks: {{tasks}}
"""
def format_system_prompt():
return SYSTEM_PROMPT \
.replace("{{tasks}}", json.dumps([str(t) for t in TASKS_BY_NAME.values()])) \
.replace("{{categories}}", json.dumps(CATEGORIES))
messages = [
{"role": "system", "content": format_system_prompt()},
{"role": "user", "content": "log 1 hour team meeting"}
]
Avec ce system prompt, le modèle pourra utiliser les données sur les tâches et catégories existantes pour générer ses réponses.
Assembler le tout
Nous pouvons maintenant combiner toutes les notions vues jusqu'ici pour créer une méthode query qui va :
- appeler le modèle avec le system prompt formaté et le message utilisateur
- traiter les appels d'outils
- appeler le modèle une seconde fois avec les résultats des outils
- produire la réponse finale
def query(user_prompt: str):
print(f"> Querying assistant with user prompt: {user_prompt}")
messages = [
{"role": "system", "content": format_system_prompt()},
{"role": "user", "content": user_prompt}
]
response = client.chat.completions.create(
model=MODEL_NAME,
messages=messages,
tools=TOOLS,
tool_choice="auto",
temperature=0.15
)
# Add the assistant response to the conversation
assistant_response = response.choices[0].message
messages.append(assistant_response)
# Process the tool calls
if assistant_response.tool_calls:
print(f"<\t{len(assistant_response.tool_calls)} tool(s) to call")
for tool_call in assistant_response.tool_calls:
# Execute the function
if tool_call.function.name in FUNCTION_MAP.keys():
function_args = json.loads(tool_call.function.arguments)
print(f">\t\tExecute tool {tool_call.function.name} with arguments {function_args}")
function_response = FUNCTION_MAP[tool_call.function.name](**function_args)
# Add results to the conversation
tool_call_result = {
"role": "tool",
"name": tool_call.function.name,
"content": json.dumps(function_response),
"tool_call_id": tool_call.id
}
messages.append(tool_call_result)
print(f">\t\tAdd tool call result to conversation:\n{tool_call_result}")
else:
print("<\tNO TOOL CALLS")
print(f">\tCall assistant with tool results")
response = client.chat.completions.create(
model=MODEL_NAME,
messages=messages,
)
print(f"<\t\tAssistant final answer:\n{response.choices[0].message.content}")
print("\n---\n")
Essayons notre assistant sur quelques exemples !
query("Spent 2 hours coding on Feature A")
query("Feature B: 3h")
query("Team meeting 1h")
# this query is more complex
# as it requires the model to generate 2 tool calls (one log_work for each feature),
# and to reuse the task "Feature B" instead of creating a new one
query("log 2 hours on feat B and 3 hours on feature C")
query("time spent in meetings?")
query("total time on coding")
query("on which task did I spent most hours coding?")
Output:
> Querying assistant with user prompt: Spent 2 hours coding on Feature A
< 1 tool(s) to call
> Execute tool log_work with arguments {'duration': 2, 'task_category': 'Code', 'task_name': 'Feature A', 'unit': 'hours'}
> Add tool call result to conversation:
{'role': 'tool', 'name': 'log_work', 'content': '{"task": "Feature A", "task_category": "Code", "total_duration": 2.0, "status": "created"}', 'tool_call_id': 'iGcC6qbte'}
> Call assistant with tool results
< Assistant final answer:
Logged time for Code
Feature A 2 hours, 0 minutes
============================
---
> Querying assistant with user prompt: Feature B: 3h
< 1 tool(s) to call
> Execute tool log_work with arguments {'task_name': 'Feature B', 'task_category': 'Code', 'duration': 3, 'unit': 'hours'}
> Add tool call result to conversation:
{'role': 'tool', 'name': 'log_work', 'content': '{"task": "Feature B", "task_category": "Code", "total_duration": 3.0, "status": "created"}', 'tool_call_id': 'd30xAKNT1'}
> Call assistant with tool results
< Assistant final answer:
- Your work log has been created. Here are the details:
- Task: Feature B
- Category: Code
- Duration: 3 hours
- Status: Created
---
> Querying assistant with user prompt: Team meeting 1h
< 1 tool(s) to call
> Execute tool log_work with arguments {'task_name': 'Team meeting', 'task_category': 'Meetings', 'duration': 60, 'unit': 'minutes'}
> Add tool call result to conversation:
{'role': 'tool', 'name': 'log_work', 'content': '{"task": "Team meeting", "task_category": "Meetings", "total_duration": 60.0, "status": "created"}', 'tool_call_id': 'EV3D7LdPE'}
> Call assistant with tool results
< Assistant final answer:
The task "Team meeting" has been created successfully.
---
> Querying assistant with user prompt: log 2 hours on feat B and 3 hours on feature C
< 2 tool(s) to call
> Execute tool log_work with arguments {'task_name': 'Feature B', 'task_category': 'Code', 'duration': 2, 'unit': 'hours'}
> Add tool call result to conversation:
{'role': 'tool', 'name': 'log_work', 'content': '{"task": "Feature B", "task_category": "Code", "total_duration": 5.0, "status": "updated"}', 'tool_call_id': 'frrThsgJ5'}
> Execute tool log_work with arguments {'task_name': 'Feature C', 'task_category': 'Code', 'duration': 3, 'unit': 'hours'}
> Add tool call result to conversation:
{'role': 'tool', 'name': 'log_work', 'content': '{"task": "Feature C", "task_category": "Code", "total_duration": 3.0, "status": "created"}', 'tool_call_id': 'K4aTPhdBp'}
> Call assistant with tool results
< Assistant final answer:
Great! Feature B's total working hours have been updated to 5 hours. Feature C's working time has been recorded as 3 hours.
---
> Querying assistant with user prompt: time spent in meetings?
< 1 tool(s) to call
> Execute tool time_report with arguments {'category': 'Meetings', 'unit': 'minutes'}
> Add tool call result to conversation:
{'role': 'tool', 'name': 'time_report', 'content': '[{"name": "Team meeting", "total_duration": 60.0}, {"total_duration_for_category": 60.0}]', 'tool_call_id': '1G8uk1bPH'}
> Call assistant with tool results
< Assistant final answer:
Here's the time spent in meetings:
- **Team meeting**: 60 minutes
---
> Querying assistant with user prompt: total time on coding
< 1 tool(s) to call
> Execute tool time_report with arguments {'category': 'Code', 'unit': 'hours'}
> Add tool call result to conversation:
{'role': 'tool', 'name': 'time_report', 'content': '[{"name": "Feature A", "total_duration": 2.0}, {"name": "Feature B", "total_duration": 5.0}, {"name": "Feature C", "total_duration": 3.0}, {"total_duration_for_category": 10.0}]', 'tool_call_id': '50bmrsPII'}
> Call assistant with tool results
< Assistant final answer:
Here's the breakdown of your coding time:
- Feature A: 2 hours
- Feature B: 5 hours
- Feature C: 3 hours
- **Total**: 10 hours
---
> Querying assistant with user prompt: on which task did I spent most hours coding?
< 1 tool(s) to call
> Execute tool time_report with arguments {'category': 'Code', 'unit': 'hours'}
> Add tool call result to conversation:
{'role': 'tool', 'name': 'time_report', 'content': '[{"name": "Feature A", "total_duration": 2.0}, {"name": "Feature B", "total_duration": 5.0}, {"name": "Feature C", "total_duration": 3.0}, {"total_duration_for_category": 10.0}]', 'tool_call_id': 'uFDF7rS0H'}
> Call assistant with tool results
< Assistant final answer:
Based on the tracking data, the task on which you spent the most hours coding is:
- **Feature B**: 5 hours
- The total coding time across all tasks is 10 hours.
Mission accomplie !
Astuces et bonnes pratiques
Cette section contient des astuces supplémentaires qui peuvent améliorer la performance des requêtes d'appel de fonctions.
Choix de l'outil
Vous avez remarqué que nous avons utilisé le mode auto dans notre tutoriel.
Voici les valeurs disponibles pour ce paramètre et leur impact sur la sortie.
Streaming
Vous pouvez utiliser l'appel de fonctions en mode streaming en réglant stream sur true dans votre requête.
Voici deux exemples cURL montrant comment effectuer une telle requête, avec le modèle LLaMa 3.3 70B :
- L'un utilisant un accès anonyme, soumis à des limitations de débit.
- L'autre utilisant l'authentification par token AI Endpoints, qui évite la limitation de débit.
Info
Pour obtenir un token d'accès API pour un accès authentifié, suivez les instructions données dans le guide AI Endpoints - Premiers pas.
curl -X 'POST' \
'https://oai.endpoints.kepler.ai.cloud.ovh.net/v1/chat/completions' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"max_tokens": 100,
"messages": [
{
"content": "What is the current weather in Paris?",
"role": "user"
}
],
"model": "Meta-Llama-3_3-70B-Instruct",
"seed": null,
"stream": true,
"temperature": 0.1,
"tool_choice": "auto",
"tools": [
{
"function": {
"description": "Get the current weather in a given location",
"name": "get_current_weather",
"parameters": {
"properties": {
"country": {
"description": "The two-letter country code",
"type": "string"
},
"location": {
"description": "The city",
"type": "string"
},
"unit": {
"enum": [
"celsius",
"fahrenheit"
],
"type": "string"
}
},
"required": [
"location",
"country"
],
"type": "object"
}
},
"type": "function"
}
],
"top_p": 1
}'
Exportez d'abord votre token :
export OVH_AI_ENDPOINTS_ACCESS_TOKEN="your_token_value"
Puis exécutez la requête :
curl -X 'POST' \
'https://oai.endpoints.kepler.ai.cloud.ovh.net/v1/chat/completions' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $OVH_AI_ENDPOINTS_ACCESS_TOKEN" \
-d '{
"max_tokens": 100,
"messages": [
{
"content": "What is the current weather in Paris?",
"role": "user"
}
],
"model": "Meta-Llama-3_3-70B-Instruct",
"seed": null,
"stream": true,
"temperature": 0.1,
"tool_choice": "auto",
"tools": [
{
"function": {
"description": "Get the current weather in a given location",
"name": "get_current_weather",
"parameters": {
"properties": {
"country": {
"description": "The two-letter country code",
"type": "string"
},
"location": {
"description": "The city",
"type": "string"
},
"unit": {
"enum": [
"celsius",
"fahrenheit"
],
"type": "string"
}
},
"required": [
"location",
"country"
],
"type": "object"
}
},
"type": "function"
}
],
"top_p": 1
}'
Vous obtiendrez des deltas d'appels d'outils dans les chunks d'événements côté serveur, au format suivant :
data: {...,"choices":[{"index":0,"delta":{"role":"assistant","content":""}}],...,"object":"chat.completion.chunk"}
data: {...,"choices":[{"index":0,"delta":{"role":"assistant","tool_calls":[{"index":0,"id":"chatcmpl-tool-e41bfee4ae1346bbbb4336061037e2b5","type":"function","function":{"name":"get_current_weather","arguments":""}}]}}],...,"object":"chat.completion.chunk"}
data: {...,"choices":[{"index":0,"delta":{"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"{\"country\": \""}}]}}],...,"object":"chat.completion.chunk"}
data: {...,"choices":[{"index":0,"delta":{"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"FR\""}}]}}],...,"object":"chat.completion.chunk"}
data: {...,"choices":[{"index":0,"delta":{"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":", \"location\": \""}}]}}],...,"object":"chat.completion.chunk"}
data: {...,"choices":[{"index":0,"delta":{"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"Paris\""}}]}}],...,"object":"chat.completion.chunk"}
data: {...,"choices":[{"index":0,"delta":{"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":", \"unit\": \""}}]}}],...,"object":"chat.completion.chunk"}
data: {...,"choices":[{"index":0,"delta":{"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"c"}}]}}],...,"object":"chat.completion.chunk"}
data: {...,"choices":[{"index":0,"delta":{"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":"elsius\"}"}}]}}],...,"object":"chat.completion.chunk"}
data: {...,"choices":[{"index":0,"delta":{"role":"assistant","tool_calls":[{"index":0,"function":{"arguments":""}}]},"finish_reason":"tool_calls"}],...,"object":"chat.completion.chunk"}
data: [DONE]
Le premier delta d'appel d'outil contient l'id unique de l'appel d'outil, ainsi qu'un delta de fonction avec le name de la fonction à appeler.
Les deltas de fonction suivants contiennent une partie des arguments à utiliser.
Pour parser ces chunks avec le SDK Python OpenAI, vous pouvez utiliser cet extrait de code :
final_tool_calls_dict = {}
for chunk in completion:
if len(chunk.choices) > 0:
for tool_call in chunk.choices[0].delta.tool_calls or []:
index = tool_call.index
if index not in final_tool_calls_dict:
final_tool_calls_dict[index] = tool_call
final_tool_calls_dict[index].function.arguments += tool_call.function.arguments
final_tool_calls = [v for (k, v) in sorted(final_tool_calls_dict.items())]
Appels d'outils en parallèle
Certains modèles sont capables de générer plusieurs appels d'outils en un seul tour (voir le tutoriel de suivi du temps ci-dessus pour un exemple). Pour contrôler ce comportement, la spécification OpenAI permet de transmettre un paramètre booléen parallel_tool_calls.
Si false, le modèle ne peut générer qu'un seul appel d'outil au maximum. Ce cas n'est actuellement pas pris en charge par AI Endpoints.
Si vous avez besoin que votre système ne traite qu'un seul appel d'outil à la fois, ou si le modèle que vous utilisez ne prend pas en charge plusieurs appels d'outils, nous vous suggérons de sélectionner le premier, de le traiter, puis de rappeler le modèle.
Notez que les modèles LLaMa ne prennent pas en charge plusieurs appels d'outils entre les messages utilisateur et assistant.
Prompting et paramètres additionnels
Quelques considérations supplémentaires concernant les prompts et les paramètres du modèle :
- La plupart des modèles ont tendance à mieux fonctionner avec une température plus basse pour l'appel de fonctions.
- L'utilisation d'un system prompt est recommandée, afin d'orienter le modèle vers l'utilisation des outils à sa disposition. Qu'un system prompt soit défini ou non, une description des outils sera généralement incluse dans les tokens envoyés au modèle (voir le chat template du modèle pour plus de détails).
- Si vous savez à l'avance que votre modèle doit appeler des outils, utilisez le paramètre
tool_choice=required pour vous assurer qu'il génère au moins un appel d'outil.
- Certains fournisseurs de modèles peuvent recommander des system prompts et paramètres spécifiques pour les sorties structurées et l'appel de fonctions. N'hésitez pas à consulter les pages des modèles pour approfondir leurs spécificités (exemple pour Llama 3.3 sur HuggingFace).
Conclusion
Dans ce guide, nous avons expliqué comment utiliser l'appel de fonctions avec les modèles AI Endpoints.
Nous avons fourni un aperçu complet de cette fonctionnalité qui peut vous aider à parfaire l'intégration du LLM dans votre propre application.
Aller plus loin
Parcourez la documentation AI Endpoints complète pour mieux comprendre les concepts principaux et démarrer.
Pour une formation ou une assistance technique sur la mise en œuvre de nos solutions, contactez votre commercial ou consultez la page Professional Services pour obtenir un devis et faire analyser votre projet par nos experts.
Votre avis nous intéresse !
N’hésitez pas à nous faire part de vos questions, retours et suggestions pour améliorer le service :