Delen via


Functie-aanroepen gebruiken met Azure OpenAI Service (preview)

De nieuwste versies van gpt-35-turbo en gpt-4 zijn afgestemd op het werken met functies en kunnen bepalen wanneer en hoe een functie moet worden aangeroepen. Als een of meer functies zijn opgenomen in uw aanvraag, bepaalt het model of een van de functies moet worden aangeroepen op basis van de context van de prompt. Wanneer het model bepaalt dat een functie moet worden aangeroepen, reageert het met een JSON-object, inclusief de argumenten voor de functie.

De modellen formuleren API-aanroepen en structureer gegevensuitvoer, allemaal op basis van de functies die u opgeeft. Het is belangrijk om te weten dat terwijl de modellen deze aanroepen kunnen genereren, het aan u is om ze uit te voeren, zodat u de controle behoudt.

Op hoog niveau kunt u het werken met functies in drie stappen opsplitsen:

  1. Roep de API voor voltooiing van de chat aan met uw functies en de invoer van de gebruiker
  2. Het antwoord van het model gebruiken om uw API of functie aan te roepen
  3. Roep de API voor voltooiingen van de chat opnieuw aan, inclusief het antwoord van uw functie om een definitief antwoord te krijgen

Belangrijk

De functions en function_call parameters zijn afgeschaft met de release van de versie van de 2023-12-01-preview API. De vervanging voor functions is de tools parameter. De vervanging voor function_call is de tool_choice parameter.

Ondersteuning voor functiegesprekken

Parallelle functie aanroepen

  • gpt-35-turbo (1106)
  • gpt-35-turbo (0125)
  • gpt-4 (1106-preview)
  • gpt-4 (0125-preview)
  • gpt-4 (vision-preview)
  • gpt-4 (2024-04-09)
  • gpt-4o (2024-05-13)

Ondersteuning voor parallelle functie is voor het eerst toegevoegd in API-versie 2023-12-01-preview

Eenvoudige functie aanroepen met hulpprogramma's

  • Alle modellen die ondersteuning bieden voor parallelle functie-aanroepen
  • gpt-4 (0613)
  • gpt-4-32k (0613)
  • gpt-35-turbo-16k (0613)
  • gpt-35-turbo (0613)

Voorbeeld van het aanroepen van één hulpprogramma/functie

Eerst laten we een eenvoudige functie-aanroep van speelgoed zien die de tijd op drie vastgelegde locaties kan controleren met één hulpprogramma/functie gedefinieerd. We hebben afdrukinstructies toegevoegd om de uitvoering van de code gemakkelijker te maken:

import os
import json
from openai import AzureOpenAI
from datetime import datetime
from zoneinfo import ZoneInfo

# Initialize the Azure OpenAI client
client = AzureOpenAI(
    azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"), 
    api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
    api_version="2024-05-01-preview"
)

# Define the deployment you want to use for your chat completions API calls

deployment_name = "<YOUR_DEPLOYMENT_NAME_HERE>"

# Simplified timezone data
TIMEZONE_DATA = {
    "tokyo": "Asia/Tokyo",
    "san francisco": "America/Los_Angeles",
    "paris": "Europe/Paris"
}

def get_current_time(location):
    """Get the current time for a given location"""
    print(f"get_current_time called with location: {location}")  
    location_lower = location.lower()
    
    for key, timezone in TIMEZONE_DATA.items():
        if key in location_lower:
            print(f"Timezone found for {key}")  
            current_time = datetime.now(ZoneInfo(timezone)).strftime("%I:%M %p")
            return json.dumps({
                "location": location,
                "current_time": current_time
            })
    
    print(f"No timezone data found for {location_lower}")  
    return json.dumps({"location": location, "current_time": "unknown"})

def run_conversation():
    # Initial user message
    messages = [{"role": "user", "content": "What's the current time in San Francisco"}] # Single function call
    #messages = [{"role": "user", "content": "What's the current time in San Francisco, Tokyo, and Paris?"}] # Parallel function call with a single tool/function defined

    # Define the function for the model
    tools = [
        {
            "type": "function",
            "function": {
                "name": "get_current_time",
                "description": "Get the current time in a given location",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "The city name, e.g. San Francisco",
                        },
                    },
                    "required": ["location"],
                },
            }
        }
    ]

    # First API call: Ask the model to use the function
    response = client.chat.completions.create(
        model=deployment_name,
        messages=messages,
        tools=tools,
        tool_choice="auto",
    )

    # Process the model's response
    response_message = response.choices[0].message
    messages.append(response_message)

    print("Model's response:")  
    print(response_message)  

    # Handle function calls
    if response_message.tool_calls:
        for tool_call in response_message.tool_calls:
            if tool_call.function.name == "get_current_time":
                function_args = json.loads(tool_call.function.arguments)
                print(f"Function arguments: {function_args}")  
                time_response = get_current_time(
                    location=function_args.get("location")
                )
                messages.append({
                    "tool_call_id": tool_call.id,
                    "role": "tool",
                    "name": "get_current_time",
                    "content": time_response,
                })
    else:
        print("No tool calls were made by the model.")  

    # Second API call: Get the final response from the model
    final_response = client.chat.completions.create(
        model=deployment_name,
        messages=messages,
    )

    return final_response.choices[0].message.content

# Run the conversation and print the result
print(run_conversation())

Uitvoer:

Model's response:
ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_pOsKdUlqvdyttYB67MOj434b', function=Function(arguments='{"location":"San Francisco"}', name='get_current_time'), type='function')])
Function arguments: {'location': 'San Francisco'}
get_current_time called with location: San Francisco
Timezone found for san francisco
The current time in San Francisco is 09:24 AM.

Als we een modelimplementatie gebruiken die ondersteuning biedt voor parallelle functie-aanroepen, kunnen we dit omzetten in een voorbeeld van een parallelle functie die wordt aangeroepen door de berichtenmatrix te wijzigen om te vragen naar de tijd op meerdere locaties in plaats van één.

U kunt dit doen door de opmerkingen in deze twee regels te wisselen:

    messages = [{"role": "user", "content": "What's the current time in San Francisco"}] # Single function call
    #messages = [{"role": "user", "content": "What's the current time in San Francisco, Tokyo, and Paris?"}] # Parallel function call with a single tool/function defined

U ziet er als volgt uit en voert de code opnieuw uit:

    #messages = [{"role": "user", "content": "What's the current time in San Francisco"}] # Single function call
    messages = [{"role": "user", "content": "What's the current time in San Francisco, Tokyo, and Paris?"}] # Parallel function call with a single tool/function defined

Hiermee wordt de volgende uitvoer gegenereerd:

Uitvoer:

Model's response:
ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_IjcAVz9JOv5BXwUx1jd076C1', function=Function(arguments='{"location": "San Francisco"}', name='get_current_time'), type='function'), ChatCompletionMessageToolCall(id='call_XIPQYTCtKIaNCCPTdvwjkaSN', function=Function(arguments='{"location": "Tokyo"}', name='get_current_time'), type='function'), ChatCompletionMessageToolCall(id='call_OHIB5aJzO8HGqanmsdzfytvp', function=Function(arguments='{"location": "Paris"}', name='get_current_time'), type='function')])
Function arguments: {'location': 'San Francisco'}
get_current_time called with location: San Francisco
Timezone found for san francisco
Function arguments: {'location': 'Tokyo'}
get_current_time called with location: Tokyo
Timezone found for tokyo
Function arguments: {'location': 'Paris'}
get_current_time called with location: Paris
Timezone found for paris
As of now, the current times are:

- **San Francisco:** 11:15 AM
- **Tokyo:** 03:15 AM (next day)
- **Paris:** 08:15 PM

Met parallelle functieaanroepen kunt u meerdere functieaanroepen tegelijk uitvoeren, waardoor parallelle uitvoering en het ophalen van resultaten mogelijk zijn. Dit vermindert het aantal aanroepen naar de API die moet worden uitgevoerd en kan de algehele prestaties verbeteren.

In onze eenvoudige tijd-app hebben we bijvoorbeeld meerdere keren tegelijk opgehaald. Dit resulteerde in een chatvoltooiingsbericht met drie functie-aanroepen in de tool_calls matrix, elk met een unieke id. Als u wilt reageren op deze functie-aanroepen, voegt u drie nieuwe berichten toe aan het gesprek, elk met het resultaat van één functie-aanroep, met een tool_call_id verwijzing naar de id waaruit tools_calls.

Als u wilt afdwingen dat het model een specifieke functie aanroept, stelt u de tool_choice parameter in met een specifieke functienaam. U kunt het model ook dwingen om een gebruikersgericht bericht te genereren door de instelling in te stellen tool_choice: "none".

Notitie

Het standaardgedrag (tool_choice: "auto") is bedoeld om het model zelf te laten beslissen of een functie moet worden aangeroepen en als dat het zo is welke functie moet worden aangeroepen.

Parallelle functie aanroepen met meerdere functies

Nu laten we een ander voorbeeld van een speelgoedfunctie zien waarin twee verschillende hulpprogramma's/functies zijn gedefinieerd.

import os
import json
from openai import AzureOpenAI
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo

# Initialize the Azure OpenAI client
client = AzureOpenAI(
    azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"), 
    api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
    api_version="2024-05-01-preview"
)

# Provide the model deployment name you want to use for this example

deployment_name = "YOUR_DEPLOYMENT_NAME_HERE" 

# Simplified weather data
WEATHER_DATA = {
    "tokyo": {"temperature": "10", "unit": "celsius"},
    "san francisco": {"temperature": "72", "unit": "fahrenheit"},
    "paris": {"temperature": "22", "unit": "celsius"}
}

# Simplified timezone data
TIMEZONE_DATA = {
    "tokyo": "Asia/Tokyo",
    "san francisco": "America/Los_Angeles",
    "paris": "Europe/Paris"
}

def get_current_weather(location, unit=None):
    """Get the current weather for a given location"""
    print(f"get_current_weather called with location: {location}, unit: {unit}")  
    
    for key in WEATHER_DATA:
        if key in location_lower:
            print(f"Weather data found for {key}")  
            weather = WEATHER_DATA[key]
            return json.dumps({
                "location": location,
                "temperature": weather["temperature"],
                "unit": unit if unit else weather["unit"]
            })
    
    print(f"No weather data found for {location_lower}")  
    return json.dumps({"location": location, "temperature": "unknown"})

def get_current_time(location):
    """Get the current time for a given location"""
    print(f"get_current_time called with location: {location}")  
    location_lower = location.lower()
    
    for key, timezone in TIMEZONE_DATA.items():
        if key in location_lower:
            print(f"Timezone found for {key}")  
            current_time = datetime.now(ZoneInfo(timezone)).strftime("%I:%M %p")
            return json.dumps({
                "location": location,
                "current_time": current_time
            })
    
    print(f"No timezone data found for {location_lower}")  
    return json.dumps({"location": location, "current_time": "unknown"})

def run_conversation():
    # Initial user message
    messages = [{"role": "user", "content": "What's the weather and current time in San Francisco, Tokyo, and Paris?"}]

    # Define the functions for the model
    tools = [
        {
            "type": "function",
            "function": {
                "name": "get_current_weather",
                "description": "Get the current weather in a given location",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "The city name, e.g. San Francisco",
                        },
                        "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                    },
                    "required": ["location"],
                },
            }
        },
        {
            "type": "function",
            "function": {
                "name": "get_current_time",
                "description": "Get the current time in a given location",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "location": {
                            "type": "string",
                            "description": "The city name, e.g. San Francisco",
                        },
                    },
                    "required": ["location"],
                },
            }
        }
    ]

    # First API call: Ask the model to use the functions
    response = client.chat.completions.create(
        model=deployment_name,
        messages=messages,
        tools=tools,
        tool_choice="auto",
    )

    # Process the model's response
    response_message = response.choices[0].message
    messages.append(response_message)

    print("Model's response:")  
    print(response_message)  

    # Handle function calls
    if response_message.tool_calls:
        for tool_call in response_message.tool_calls:
            function_name = tool_call.function.name
            function_args = json.loads(tool_call.function.arguments)
            print(f"Function call: {function_name}")  
            print(f"Function arguments: {function_args}")  
            
            if function_name == "get_current_weather":
                function_response = get_current_weather(
                    location=function_args.get("location"),
                    unit=function_args.get("unit")
                )
            elif function_name == "get_current_time":
                function_response = get_current_time(
                    location=function_args.get("location")
                )
            else:
                function_response = json.dumps({"error": "Unknown function"})
            
            messages.append({
                "tool_call_id": tool_call.id,
                "role": "tool",
                "name": function_name,
                "content": function_response,
            })
    else:
        print("No tool calls were made by the model.")  

    # Second API call: Get the final response from the model
    final_response = client.chat.completions.create(
        model=deployment_name,
        messages=messages,
    )

    return final_response.choices[0].message.content

# Run the conversation and print the result
print(run_conversation())

Uitvoer

Model's response:
ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_djHAeQP0DFEVZ2qptrO0CYC4', function=Function(arguments='{"location": "San Francisco", "unit": "celsius"}', name='get_current_weather'), type='function'), ChatCompletionMessageToolCall(id='call_q2f1HPKKUUj81yUa3ITLOZFs', function=Function(arguments='{"location": "Tokyo", "unit": "celsius"}', name='get_current_weather'), type='function'), ChatCompletionMessageToolCall(id='call_6TEY5Imtr17PaB4UhWDaPxiX', function=Function(arguments='{"location": "Paris", "unit": "celsius"}', name='get_current_weather'), type='function'), ChatCompletionMessageToolCall(id='call_vpzJ3jElpKZXA9abdbVMoauu', function=Function(arguments='{"location": "San Francisco"}', name='get_current_time'), type='function'), ChatCompletionMessageToolCall(id='call_1ag0MCIsEjlwbpAqIXJbZcQj', function=Function(arguments='{"location": "Tokyo"}', name='get_current_time'), type='function'), ChatCompletionMessageToolCall(id='call_ukOu3kfYOZR8lpxGRpdkhhdD', function=Function(arguments='{"location": "Paris"}', name='get_current_time'), type='function')])
Function call: get_current_weather
Function arguments: {'location': 'San Francisco', 'unit': 'celsius'}
get_current_weather called with location: San Francisco, unit: celsius
Weather data found for san francisco
Function call: get_current_weather
Function arguments: {'location': 'Tokyo', 'unit': 'celsius'}
get_current_weather called with location: Tokyo, unit: celsius
Weather data found for tokyo
Function call: get_current_weather
Function arguments: {'location': 'Paris', 'unit': 'celsius'}
get_current_weather called with location: Paris, unit: celsius
Weather data found for paris
Function call: get_current_time
Function arguments: {'location': 'San Francisco'}
get_current_time called with location: San Francisco
Timezone found for san francisco
Function call: get_current_time
Function arguments: {'location': 'Tokyo'}
get_current_time called with location: Tokyo
Timezone found for tokyo
Function call: get_current_time
Function arguments: {'location': 'Paris'}
get_current_time called with location: Paris
Timezone found for paris
Here's the current information for the three cities:

### San Francisco
- **Time:** 09:13 AM
- **Weather:** 72°C (quite warm!)

### Tokyo
- **Time:** 01:13 AM (next day)
- **Weather:** 10°C

### Paris
- **Time:** 06:13 PM
- **Weather:** 22°C

Is there anything else you need?

Belangrijk

Het JSON-antwoord is mogelijk niet altijd geldig, dus u moet extra logica toevoegen aan uw code om fouten te kunnen verwerken. Voor sommige gebruiksscenario's moet u mogelijk fine-tuning gebruiken om de prestaties van functie-aanroepen te verbeteren.

Vragen om engineering met functies

Wanneer u een functie definieert als onderdeel van uw aanvraag, worden de details opgenomen in het systeembericht met behulp van specifieke syntaxis waarop het model is getraind. Dit betekent dat functies tokens in uw prompt verbruiken en dat u prompt engineeringtechnieken kunt toepassen om de prestaties van uw functie-aanroepen te optimaliseren. Het model gebruikt de volledige context van de prompt om te bepalen of een functie moet worden aangeroepen, inclusief functiedefinitie, het systeembericht en de gebruikersberichten.

Kwaliteit en betrouwbaarheid verbeteren

Als het model uw functie niet aanroept wanneer of hoe u verwacht, zijn er een paar dingen die u kunt proberen om de kwaliteit te verbeteren.

Geef meer informatie op in uw functiedefinitie

Het is belangrijk dat u een zinvolle description functie opgeeft en beschrijvingen opgeeft voor een parameter die mogelijk niet duidelijk is voor het model. In de beschrijving voor de location parameter kunt u bijvoorbeeld extra details en voorbeelden opnemen over de indeling van de locatie.

"location": {
    "type": "string",
    "description": "The location of the hotel. The location should include the city and the state's abbreviation (i.e. Seattle, WA or Miami, FL)"
},
Geef meer context op in het systeembericht

Het systeembericht kan ook worden gebruikt om meer context aan het model te bieden. Als u bijvoorbeeld een functie hebt die u hebt aangeroepen search_hotels , kunt u een systeembericht zoals het volgende opnemen om het model te instrueren om de functie aan te roepen wanneer een gebruiker om hulp vraagt bij het vinden van een hotel.

{"role": "system", "content": "You're an AI assistant designed to help users search for hotels. When a user asks for help finding a hotel, you should call the search_hotels function."}
Het model instrueren om vragen te stellen

In sommige gevallen wilt u het model instrueren om vragen te stellen om aannames te voorkomen over welke waarden moeten worden gebruikt met functies. U wilt bijvoorbeeld search_hotels dat het model om verduidelijking vraagt als de gebruikersaanvraag geen details over locationbevat. Als u het model wilt instrueren om een duidelijkere vraag te stellen, kunt u inhoud opnemen zoals in het volgende voorbeeld in uw systeembericht.

{"role": "system", "content": "Don't make assumptions about what values to use with functions. Ask for clarification if a user request is ambiguous."}

Fouten verminderen

Een ander gebied waar prompt-engineering waardevol kan zijn, is het verminderen van fouten in functie-aanroepen. De modellen worden getraind om functie-aanroepen te genereren die overeenkomen met het schema dat u definieert, maar de modellen produceren een functie-aanroep die niet overeenkomt met het schema dat u hebt gedefinieerd of een functie probeert aan te roepen die u niet hebt opgenomen.

Als u merkt dat het model functieaanroepen genereert die niet zijn opgegeven, kunt u een zin opnemen in het systeembericht met de tekst "Only use the functions you have been provided with.".

Het gebruik van functie-aanroepen op verantwoorde wijze

Net als elk AI-systeem biedt het gebruik van functie-aanroepen om taalmodellen te integreren met andere hulpprogramma's en systemen potentiële risico's. Het is belangrijk om inzicht te hebben in de risico's die functiegesprekken kunnen opleveren en maatregelen kunnen nemen om ervoor te zorgen dat u de mogelijkheden op verantwoorde wijze gebruikt.

Hier volgen enkele tips om u te helpen functies veilig en veilig te gebruiken:

  • Functie-aanroepen valideren: controleer altijd de functie-aanroepen die zijn gegenereerd door het model. Dit omvat het controleren van de parameters, de functie die wordt aangeroepen en ervoor zorgen dat de aanroep overeenkomt met de beoogde actie.
  • Vertrouwde gegevens en hulpprogramma's gebruiken: gebruik alleen gegevens uit vertrouwde en geverifieerde bronnen. Niet-vertrouwde gegevens in de uitvoer van een functie kunnen worden gebruikt om het model te instrueren om functie-aanroepen op een andere manier te schrijven dan u bedoelde.
  • Volg het principe van minimale bevoegdheden: ververleent alleen de minimale toegang die nodig is voor de functie om de taak uit te voeren. Dit vermindert de mogelijke impact als een functie wordt misbruikt of misbruikt. Als u bijvoorbeeld functieoproepen gebruikt om een query uit te voeren op een database, moet u uw toepassing alleen-lezentoegang geven tot de database. U moet ook niet alleen afhankelijk zijn van het uitsluiten van mogelijkheden in de functiedefinitie als beveiligingsbeheer.
  • Houd rekening met echte impact: houd rekening met de werkelijke impact van functie-aanroepen die u wilt uitvoeren, met name die acties activeren, zoals het uitvoeren van code, het bijwerken van databases of het verzenden van meldingen.
  • Implementeer gebruikersbevestigingsstappen: met name voor functies die acties ondernemen, raden we u aan een stap op te nemen waarbij de gebruiker de actie bevestigt voordat deze wordt uitgevoerd.

Zie het overzicht van verantwoorde AI-procedures voor Azure OpenAI-modellen voor Azure OpenAI-modellen voor meer informatie over onze aanbevelingen voor het gebruik van Azure OpenAI-modellen.

Volgende stappen