Programmatisch tools aanroepen met de Azure OpenAI Responses API

Met programmatisch aanroepen van hulpprogramma's kan een model code gebruiken om hulpprogramma's te orkestreren tijdens een aanvraag aan de Responses API. In plaats van voor elke aanroep van het hulpprogramma een afzonderlijke modelbeurt te vereisen, kan het model een programma genereren dat hulpprogramma's aanroept en hun resultaten verwerkt. Het programma kan bewerkingen uitvoeren, zoals vertakking of iteratie.

In dit artikel wordt uitgelegd wanneer programmatisch tools aanroepen nuttig is en hoe dit verschilt van functieoproepen, parallel aanroepen van tools en zoeken in tools.

Overwegingen voor beschikbaarheid

Voordat u programmatisch aanroepen van hulpprogramma's implementeert, moet u controleren of uw Azure OpenAI-modelimplementatie en SDK-versie ondersteuning bieden voor de functie. Neem niet aan dat ondersteuning voor de Responses API ook betekent dat er ondersteuning is voor programmatisch aanroepen van hulpprogramma's.

Zie De Azure OpenAI-antwoorden-API gebruiken voor het instellen van eindpunten en verificatie.

Programmatische toolaanroepen en functie-aanroepen

Bij het aanroepen van standaardfuncties neemt uw toepassing doorgaans deel aan elke stap voor het aanroepen van hulpprogramma's:

Model -> hulpprogramma-aanroep -> toepassing voert hulpprogramma uit -> model -> volgende hulpprogramma-aanroep -> toepassing voert hulpprogramma uit -> model

Met het aanroepen van programmatische hulpprogramma's kan het model code genereren waarmee meerdere hulpprogrammabewerkingen worden gecoördineerd:

Model -> gegenereerd programma -> hulpprogrammabewerkingen -> programmaresultaat -> model

Deze aanpak kan het aantal benodigde modelbeurten voor werkstromen met verschillende hulpprogramma's verminderen.

Deze stromen illustreren het conceptuele verschil in orkestratie. Ze geven niet op welke bewerkingen uw toepassing of de service uitvoert.

Voorbeeld: Voorraad vergelijken met vraag

In dit Python voorbeeld worden twee door de toepassing gedefinieerde functies weergegeven die voorbeeldinventaris- en vraaggegevens retourneren. Het model maakt gebruik van programmatisch aanroepen van hulpprogramma's om de resultaten te vergelijken. Uw toepassing voert de functies uit en retourneert de resultaten, zodat de runtime het gegenereerde programma kan hervatten.

De codeblokken vormen één script. Combineer ze in de weergegeven volgorde.

Azure OpenAI client

Gebruik een Azure OpenAI-implementatie die ondersteuning biedt voor het programmatisch aanroepen van hulpprogramma's en een OpenAI SDK-versie die output_schema, allowed_callers en aanroepergegevens bevat. Installeer de openai en azure-identity pakketten in uw Python-omgeving:

pip install --upgrade openai azure-identity

Configureer Microsoft Entra ID-verificatie, zoals beschreven in De Azure OpenAI Responses API gebruiken. Uw identiteit heeft toestemming nodig om uw Azure OpenAI-deployment aan te roepen.

Vervang YOUR-RESOURCE-NAME door de resourcenaam. De model waarde verderop in het voorbeeld is uw Azure implementatienaam, niet een modelcatalogus-id.

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)

door de toepassing gedefinieerde functies

De functies retourneren vaste voorbeeldgegevens: 42 beschikbare eenheden en 31 aangevraagde eenheden voor de opgegeven SKU. Vervang hun implementaties door uw voorraad- en gegevensbronnen voor vraag in uw applicatie.

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,
}

Tooldefinities

Elke functie declareert een invoerschema en een output_schema die het JSON-resultaat beschrijft. allowed_callers op ["programmatic"] instellen maakt de functie beschikbaar voor gegenereerde programma's in plaats van directe modeloproepen.

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"],
    }
]

Voeg de vraagfunctie en de mogelijkheid voor programmatisch aanroepen van tools toe aan dezelfde lijst:

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"},
])

Resultaten van hulpprogramma's en informatie over de aanroeper

De toepassing roept functieaanroepen op naam aan en serialiseert elk resultaat. Behoud de gegevens van caller de aanroep zodat de runtime de uitvoering van het juiste programma kan hervatten. Onbekende hulpprogrammanamen en ongeldige argumenten veroorzaken fouten in plaats van verzonnen resultaten te retourneren.

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

Vervolg van het antwoord

Vervang YOUR-MODEL-DEPLOYMENT door de naam van uw ondersteunde Azure OpenAI-implementatie.

Met store=False zet de toepassing het gesprek voort. Bewaar elk uitvoeritem, inclusief programma- en redeneringsitems, voordat u hulpprogrammaresultaten toevoegt. De lus stopt bij een eindantwoord of weigering en genereert een fout als een antwoord mislukt of de aanvraaglimiet is bereikt.

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")

In het laatste antwoord moet worden uitgelegd dat de voorraad de vraag dekt: 42 beschikbare eenheden minus 31 aangevraagde eenheden, blijven er 11 eenheden over. De formulering kan variëren. In plaats daarvan wordt een weigering afgedrukt als het model de aanvraag weigert.

De toepassing voert de inventaris- en vraagfuncties uit, terwijl het gegenereerde programma het gebruik coördineert en de resultaten verwerkt.

Wanneer programmatische toolaanroepen gebruiken

Overweeg programmatisch aanroepen van hulpprogramma's wanneer een taak:

  • Hiervoor zijn verschillende gerelateerde hulpprogramma-aanroepen vereist.
  • Bevat voorwaardelijke logica.
  • Moet over de resultaten van het hulpprogramma itereren.
  • Voert tussenliggende gegevensverwerking uit voordat een antwoord wordt geproduceerd.
  • Anders zouden herhaalde modelbeurten nodig zijn om tools te coördineren.

Voor eenvoudige werkstromen die betrekking hebben op een of twee onafhankelijke functies, zijn standaard functie-aanroepen mogelijk eenvoudiger te implementeren.

Programmatisch aanroepen van tools en parallel aanroepen van tools

Parallel aanroepen van hulpprogramma's en programmatisch aanroepen van hulpprogramma's voldoen aan verschillende orkestratiebehoeften.

Gebruik parallelle toolaanroepen wanneer verschillende onafhankelijke bewerkingen tegelijkertijd kunnen worden uitgevoerd. Haal bijvoorbeeld het weer op voor vijf afzonderlijke locaties.

Gebruik programmatisch aanroepen van tools wanneer bewerkingen van hulpprogramma's coördinatie, tussenliggende berekeningen, vertakkingen of iteratie vereisen. Haal bijvoorbeeld de orders van een klant op, selecteer orders die overeenkomen met een voorwaarde en voer een query uit op verzendgegevens voor die orders.

Zoeken naar tools bepaalt welke hulpprogrammadefinities in de context van het model worden geladen.

Programmatische toolaanroepinstellingen bepalen hoe het model hulpprogramma's organiseert nadat ze beschikbaar zijn.

Het onderscheid is tussen hulpprogrammadetectie en orkestratie van hulpprogramma's. De conceptuele relatie bepaalt niet of uw implementatie beide functies in dezelfde aanvraag ondersteunt.

Beveiligingsoverwegingen

Behandel gegenereerde programma's als niet-vertrouwde code.

Bij het beschikbaar maken van hulpprogramma's:

  • Volg het principe van minimale rechten.
  • Hulpprogrammaargumenten valideren.
  • Toegang tot gevoelige bewerkingen beperken.
  • Verifieer en autoriseer bewerkingen onafhankelijk van modeluitvoer.
  • Leg de uitvoering van hulpprogramma's vast voor controle en diagnose zonder geheimen of onnodige gevoelige gegevens op te nemen.
  • Vermijd het blootstellen van onnodige hulpprogramma's of gegevens.

Vertrouw niet op door het model gegenereerde code als autorisatiegrens.