Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
L’appel d’outils programmatique permet à un modèle d’utiliser du code pour orchestrer des outils pendant une requête de l’API Responses. Au lieu d’exiger un tour de modèle distinct pour chaque appel d’outil, le modèle peut générer un programme qui appelle des outils et traite leurs résultats. Le programme peut effectuer des opérations telles que l’embranchement ou l’itération.
Cet article explique quand l’appel d’outil programmatique est utile et comment il diffère de l’appel de fonction, de l’appel d’outils parallèles et de la recherche d’outils.
Considérations relatives à la disponibilité
Avant d’implémenter l’appel d’outils programmatiques, vérifiez que votre déploiement de modèle Azure OpenAI et la version du SDK prennent en charge la fonctionnalité. Ne supposez pas que la prise en charge de la Responses API établit également la prise en charge de l’appel d’outils par programmation.
Pour la configuration du point de terminaison et de l’authentification, consultez Utiliser l’API Responses Azure OpenAI.
Appel de l’outil programmatique et appel de fonction
Avec l’appel de fonction standard, votre application participe généralement à chaque étape d’appel d’outils :
Modèle -> Appel d’outil -> l’application exécute l’outil -> Modèle -> Appel d’outil suivant -> Application exécute l’outil -> Modèle
Avec l’appel d’outils par programmation, le modèle peut générer du code qui orchestre plusieurs opérations d’outil :
Modèle -> programme généré -> Opérations de l’outil -> Résultat du programme -> modèle
Cette approche peut réduire le nombre d’itérations du modèle nécessaires pour les workflows impliquant plusieurs outils.
Ces flux illustrent la différence conceptuelle dans l’orchestration. Ils ne spécifient pas quelles opérations votre application ou le service exécute.
Exemple : comparer l’inventaire avec la demande
Cet exemple Python expose deux fonctions définies par l’application qui retournent des exemples d’inventaire et de données de demande. Le modèle utilise l’appel programmatique d’outils pour comparer les résultats. Votre application exécute les fonctions et retourne leurs résultats afin que le runtime puisse reprendre le programme généré.
Les blocs de code forment un script. Combinez-les dans l’ordre indiqué.
Client Azure OpenAI
Utilisez un déploiement Azure OpenAI qui prend en charge l’appel d’outils programmatiques et une version du kit de développement logiciel (SDK) OpenAI qui inclut output_schema, allowed_callers et les informations de l’appelant. Installez les packages azure-identity et openai dans votre environnement Python :
pip install --upgrade openai azure-identity
Configurez l’authentification Microsoft Entra ID comme décrit dans Utiliser l’API Azure OpenAI Responses. Votre identité doit être autorisée à appeler votre Azure déploiement OpenAI.
Remplacez YOUR-RESOURCE-NAME par le nom de votre ressource. La valeur model plus loin dans l’exemple est votre nom de déploiement Azure, et non un identificateur de catalogue de modèles.
import json
from azure.identity import DefaultAzureCredential, get_bearer_token_provider
from openai import OpenAI
# Use the Azure OpenAI v1 endpoint and Microsoft Entra ID authentication.
endpoint = "https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/"
credential = DefaultAzureCredential()
token_provider = get_bearer_token_provider(
credential, "https://cognitiveservices.azure.com/.default"
)
openai = OpenAI(base_url=endpoint, api_key=token_provider)
Fonctions définies par l’application
Les fonctions retournent des exemples de données fixes : 42 unités disponibles et 31 unités demandées pour la référence SKU spécifiée. Remplacez ces implémentations par vos sources de données d’inventaire et de demande dans votre application.
def get_inventory(sku):
return {"sku": sku, "available_units": 42}
def get_demand(sku):
return {"sku": sku, "requested_units": 31}
implementations = {
"get_inventory": get_inventory,
"get_demand": get_demand,
}
Définitions d’outils
Chaque fonction déclare un schéma d’entrée et un output_schema décrivant le résultat JSON. Définir allowed_callers sur ["programmatic"] rend la fonction disponible pour les programmes générés plutôt que pour les appels directs au modèle.
tools = [
{
"type": "function",
"name": "get_inventory",
"description": "Return the SKU and available inventory units.",
"strict": True,
"parameters": {
"type": "object",
"properties": {"sku": {"type": "string"}},
"required": ["sku"],
"additionalProperties": False,
},
"output_schema": {
"type": "object",
"properties": {
"sku": {"type": "string"},
"available_units": {"type": "number"},
},
"required": ["sku", "available_units"],
"additionalProperties": False,
},
"allowed_callers": ["programmatic"],
}
]
Ajoutez la fonction de demande et la fonctionnalité d’appel de l’outil programmatique à la même liste :
tools.extend([
{
"type": "function",
"name": "get_demand",
"description": "Return the SKU and requested demand units.",
"strict": True,
"parameters": {
"type": "object",
"properties": {"sku": {"type": "string"}},
"required": ["sku"],
"additionalProperties": False,
},
"output_schema": {
"type": "object",
"properties": {
"sku": {"type": "string"},
"requested_units": {"type": "number"},
},
"required": ["sku", "requested_units"],
"additionalProperties": False,
},
"allowed_callers": ["programmatic"],
},
{"type": "programmatic_tool_calling"},
])
Résultats de l’outil et informations de l’appelant
L’application distribue les appels de fonction par nom et sérialise chaque résultat. Conservez les informations caller de l'appel afin que le runtime puisse reprendre le programme approprié. Les noms d’outils inconnus et les arguments non valides déclenchent des erreurs plutôt que de retourner des résultats fabriqués.
def run_tool(call):
run = implementations.get(call.name)
if run is None:
raise ValueError(f"Unknown tool: {call.name}")
arguments = json.loads(call.arguments)
if (
not isinstance(arguments, dict)
or set(arguments) != {"sku"}
or not isinstance(arguments["sku"], str)
):
raise ValueError(f"Invalid arguments for tool: {call.name}")
result = run(**arguments)
output = {
"type": "function_call_output",
"call_id": call.call_id,
"output": json.dumps(result),
}
if call.caller is not None:
output["caller"] = call.caller.model_dump(exclude_none=True)
return output
Continuation de la réponse
Remplacez YOUR-MODEL-DEPLOYMENT par le nom de votre déploiement Azure OpenAI pris en charge.
Avec store=False, l’application fait progresser la conversation. Conservez chaque élément de sortie, y compris les éléments de programme et de raisonnement, avant d’ajouter les résultats de l’outil. La boucle s’arrête sur une réponse ou un refus final et génère une erreur en cas d’échec d’une réponse ou si la limite de requête est atteinte.
input_items = [
{"role": "user", "content": "Compare inventory with demand for sku_123."}
]
MAX_REQUESTS = 10
for _ in range(MAX_REQUESTS):
response = openai.responses.create(
model="YOUR-MODEL-DEPLOYMENT",
store=False, input=input_items, tools=tools,
)
if response.status != "completed":
raise RuntimeError(f"Response ended with status {response.status}")
input_items.extend(
item.model_dump(exclude_none=True) for item in response.output
)
calls = [item for item in response.output if item.type == "function_call"]
if calls:
input_items.extend(run_tool(call) for call in calls)
continue
if response.output_text:
print(response.output_text)
break
refusals = [
part.refusal for item in response.output if item.type == "message"
for part in item.content if part.type == "refusal"
]
if refusals:
print("\n".join(refusals))
break
else:
raise RuntimeError("Programmatic tool calling exceeded the request limit")
La réponse finale doit expliquer que l’inventaire couvre la demande : 42 unités disponibles moins 31 unités demandées donnent 11 unités. La formulation peut varier. Un refus est imprimé à la place si le modèle refuse la demande.
L’application exécute les fonctions d’inventaire et de demande, tandis que le programme généré coordonne leur utilisation et traite les résultats.
Quand utiliser l’appel de l’outil programmatique
Envisagez d’appeler un outil programmatique lorsqu’une tâche :
- Nécessite plusieurs appels d’outils connexes.
- Contient une logique conditionnelle.
- Nécessite une itération sur les résultats de l’outil.
- Effectue le traitement intermédiaire des données avant de produire une réponse.
- Dans le cas contraire, il faudrait des interactions du modèle répétées pour coordonner les outils.
Pour les flux de travail simples qui impliquent une ou deux fonctions indépendantes, l’appel de fonction standard peut être plus facile à implémenter.
Appel d’outils programmatiques et appel d’outils parallèles
Les appels d’outils parallèles et l’appel d’outils programmatique répondent à différents besoins d’orchestration.
Utilisez l’appel d’outils parallèles lorsque plusieurs opérations indépendantes peuvent s’exécuter en même temps. Par exemple, récupérez la météo pour cinq emplacements indépendants.
Utilisez un appel d’outils programmatique lorsque les opérations d’outil nécessitent la coordination, le calcul intermédiaire, la création de branches ou l’itération. Par exemple, récupérez les commandes d’un client, sélectionnez les commandes qui correspondent à une condition et interrogez les informations d’expédition pour ces commandes.
Appel d’outils programmatiques et recherche d’outils
La recherche d’outils détermine quelles définitions d’outils sont chargées dans le contexte du modèle.
L’appel d’outils programmatique contrôle la façon dont le modèle orchestre les outils une fois qu’ils sont disponibles.
La distinction est entre la découverte d’outils et l’orchestration des outils. Leur relation conceptuelle n’établit pas si votre déploiement prend en charge l’utilisation des deux fonctionnalités dans la même requête.
Considérations relatives à la sécurité
Traitez les programmes générés comme du code non fiable.
Lors de l’exposition d'outils :
- Suivez le principe du moindre privilège.
- Valider les arguments de l’outil.
- Restreindre l’accès aux opérations sensibles.
- Authentifiez et autorisez les opérations indépendamment de la sortie du modèle.
- Journalisez l’exécution de l’outil pour l’audit et les diagnostics sans enregistrer de secrets ni de données sensibles inutiles.
- Évitez d’exposer des outils ou des données inutiles.
Ne vous fiez pas au code généré par un modèle en tant que délimitation d’autorisation.