Freigeben über


Verwenden von Funktionsaufrufen mit Azure OpenAI Service (Vorschau)

Die neuesten Versionen von gpt-35-turbo und gpt-4 wurden für die Arbeit mit Funktionen optimiert und können bestimmen, wann und wie eine Funktion aufgerufen werden soll. Wenn eine oder mehrere Funktionen in Ihrer Anforderung enthalten sind, bestimmt das Modell basierend auf dem Kontext des Prompts, ob eine der Funktionen aufgerufen werden soll. Wenn das Modell bestimmt, dass eine Funktion aufgerufen werden soll, antwortet es mit einem JSON-Objekt, das die Argumente für die Funktion enthält.

Die Modelle formulieren API-Aufrufe und strukturieren Datenausgaben, die alle auf den von Ihnen angegebenen Funktionen basieren. Wichtig: Die Modelle können diese Aufrufe zwar generieren, aber es liegt an Ihnen, sie auszuführen. Auf diese Weise wird sichergestellt, dass Sie die Kontrolle behalten.

Im Allgemeinen kann die Arbeit mit Funktionen in drei Schritte unterteilt werden:

  1. Aufrufen der Chat Completions-API mit Ihren Funktionen und der Benutzereingabe
  2. Verwenden der Antwort des Modells zum Aufrufen Ihrer API oder Funktion
  3. Erneutes Aufrufen der Chat Completions-API, einschließlich der Antwort Ihrer Funktion, um eine endgültige Antwort zu erhalten

Wichtig

Die Parameter functions und function_call wurden mit der Veröffentlichung der Version 2023-12-01-preview der API als veraltet markiert. Der Ersatz für functions ist der Parameter tools. Der Ersatz für function_call ist der Parameter tool_choice.

Unterstützung für Funktionsaufruf

Paralleler Funktionsaufruf

  • gpt-35-turbo (1106)
  • gpt-35-turbo (0125)
  • gpt-4 (1106-Vorschau)
  • gpt-4 (0125-Preview)
  • gpt-4 (vision-preview)
  • gpt-4 (2024-04-09)
  • gpt-4o (2024-05-13)
  • gpt-4o-mini (2024-07-18)

Die Unterstützung für parallele Funktion wurde zuerst in der API-Version 2023-12-01-preview hinzugefügt.

Grundlegende Funktionsaufrufe mit Tools

  • Alle Modelle, die parallele Funktionsaufrufe unterstützen
  • gpt-4 (0613)
  • gpt-4-32k (0613)
  • gpt-35-turbo-16k (0613)
  • gpt-35-turbo (0613)

Beispiel für Einzeltool-/Funktionsaufrufe

Zunächst werden wir einen einfachen Funktionsaufruf demonstrieren, mit dem Sie die Zeit an drei fest kodierten Stellen mit einem einzigen definierten Tool/Funktion überprüfen können. Wir haben print-Anweisungen hinzugefügt, um die Ausführung des Codes leichter nachvollziehen zu können:

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

Ausgabe:

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.

Wenn wir eine Modellimplementierung verwenden, die parallele Funktionsaufrufe unterstützt, könnten wir dies in ein Beispiel für einen parallelen Funktionsaufruf umwandeln, indem wir das Nachrichten-Array so ändern, dass die Zeit an mehreren Stellen statt an einer abgefragt wird.

Um dies zu erreichen, tauschen Sie die Kommentare in diesen beiden Zeilen aus:

    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

Damit es so aussieht, und führen Sie den Code erneut aus:

    #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

Die folgende Ausgabe wird generiert:

Ausgabe:

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

Parallele Funktionsaufrufe ermöglichen es Ihnen, mehrere Funktionsaufrufe zusammen auszuführen, wodurch parallele Ausführung und Abruf von Ergebnissen ermöglicht werden. Dadurch wird die Anzahl der Aufrufe an die API reduziert, die ausgeführt werden müssen, und kann die Gesamtleistung verbessert werden.

In unserer einfachen Zeit-App haben wir zum Beispiel mehrere Zeiten gleichzeitig abgerufen. Das Ergebnis war eine Chat-Vervollständigungsnachricht mit drei Funktionsaufrufen im Array tool_calls, jeder mit einem eindeutigen id. Wenn Sie auf diese Funktionsaufrufe antworten möchten, fügen Sie der Unterhaltung drei neue Nachrichten hinzu, die jeweils das Ergebnis eines Funktionsaufrufs enthalten, wobei tool_call_id auf id von tools_calls verweist.

Um zu erzwingen, dass das Modell eine bestimmte Funktion aufruft, legen Sie den Parameter tool_choice mit einem bestimmten Funktionsnamen fest. Sie können auch erzwingen, dass das Modell eine Nachricht für Benutzer*innen generiert, indem Sie tool_choice: "none" festlegen.

Hinweis

Das Standardverhalten (tool_choice: "auto") dient dazu, dass das Modell selbst entscheiden kann, ob eine Funktion und welche Funktion aufgerufen werden soll.

Paralleler Funktionsaufruf mit mehreren Funktionen

Jetzt werden wir ein weiteres Beispiel für einen Funktionsaufruf demonstrieren, diesmal mit zwei verschiedenen definierten Tools/Funktionen.

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

Output

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?

Wichtig

Die JSON-Antwort ist möglicherweise nicht immer gültig, so dass Sie Ihrem Code eine zusätzliche Logik hinzufügen müssen, um Fehler behandeln zu können. In einigen Anwendungsfällen werden Sie feststellen, dass Sie eine Feinabstimmung vornehmen müssen, um die Leistung von Funktionsaufrufen zu verbessern.

Prompt Engineering mit Funktionen

Wenn Sie eine Funktion als Teil Ihrer Anforderung definieren, werden die Details mithilfe der spezifischen Syntax, für die das Modell trainiert wurde, in die Systemmeldung eingefügt. Das bedeutet, dass Funktionen Token in Ihrem Prompt nutzen und Sie Prompt-Engineering-Techniken anwenden können, um die Leistung Ihrer Funktionsaufrufe zu optimieren. Das Modell verwendet den vollständigen Kontext des Prompts, um zu bestimmen, ob eine Funktion aufgerufen werden soll, einschließlich der Funktionsdefinition, der Systemmeldung und der Benutzermeldungen.

Verbesserung von Qualität und Zuverlässigkeit

Wenn das Modell Ihre Funktion nicht wann oder wie erwartet aufruft, können Sie versuchen, die Qualität zu verbessern.

Angeben weiterer Details in der Funktionsdefinition

Es ist wichtig, einen aussagekräftigen description-Wert für die Funktion und Beschreibungen für jeden Parameter anzugeben, der für das Modell möglicherweise nicht offensichtlich ist. Beispielsweise können Sie in der Beschreibung für den location-Parameter zusätzliche Details und Beispiele für das Format des Speicherorts angeben.

"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)"
},
Angeben von mehr Kontext in der Systemmeldung

Die Systemmeldung kann auch verwendet werden, um mehr Kontext für das Modell bereitzustellen. Wenn Sie beispielsweise über eine Funktion mit dem Namen search_hotels verfügen, können Sie eine Systemmeldung wie die folgende einschließen, um das Modell anzuweisen, die Funktion aufzurufen, wenn ein*e Benutzer*in um Hilfe bei der Suche nach einem Hotel bittet.

{"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."}
Anweisen des Modells, klärende Fragen zu stellen

In einigen Fällen sollten Sie das Modell ggf. anweisen, klärende Fragen zu stellen, um zu verhindern, dass es Annahmen darüber trifft, welche Werte für Funktionen zu verwenden sind. Sie könnten das Modell bei search_hotels beispielsweise anweisen, um Klärung zu bitten, wenn die Benutzeranforderung keine Details zu locationenthält. Um das Modell anzuweisen, eine klärende Frage zu stellen, können Sie Inhalte wie im folgenden Beispiel in Ihre Systemmeldung aufnehmen.

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

Reduzieren von Fehlern

Ein weiterer Bereich, in dem das Prompt Engineering nützlich sein kann, ist die Reduzierung von Fehlern bei Funktionsaufrufen. Die Modelle werden trainiert, um Funktionsaufrufe zu generieren, die dem von Ihnen definierten Schema entsprechen. Sie erzeugen jedoch einen Funktionsaufruf, der nicht mit dem von Ihnen definierten Schema übereinstimmt, oder versuchen, eine Funktion aufzurufen, die Sie nicht eingeschlossen haben.

Wenn Sie feststellen, dass das Modell Funktionsaufrufe generiert, die nicht vorgesehen wurden, versuchen Sie, einen Satz wie "Only use the functions you have been provided with." in die Systemmeldung aufzunehmen.

Verantwortungsvolles Verwenden von Funktionsaufrufen

Wie bei jedem KI-System birgt die Verwendung von Funktionsaufrufen zur Integration von Sprachmodellen in andere Tools und Systeme potenzielle Risiken. Es ist wichtig, die Risiken zu verstehen, die Funktionsaufrufe darstellen können, und Maßnahmen zu ergreifen, um sicherzugehen, dass die Funktionen verantwortungsvoll genutzt werden.

Hier sind einige Tipps, die Ihnen dabei helfen, Funktionen sicher zu verwenden:

  • Überprüfen von Funktionsaufrufen: Überprüfen Sie immer die vom Modell generierten Funktionsaufrufe. Dazu zählt das Überprüfen der Parameter und der aufgerufenen Funktion. Außerdem müssen Sie sich vergewissern, dass der Aufruf der beabsichtigten Aktion entspricht.
  • Verwenden von vertrauenswürdigen Daten und Tools: Verwenden Sie nur Daten aus vertrauenswürdigen und verifizierten Quellen. Nicht vertrauenswürdige Daten in der Ausgabe einer Funktion können verwendet werden, um das Modell anzuweisen, Funktionsaufrufe auf nicht beabsichtigte Weise zu schreiben.
  • Anwenden des Prinzips der geringsten Rechte: Gewähren Sie nur den mindestens erforderlichen Zugriff, den die Funktion benötigt, um ihre Aufgabe zu erfüllen. Dadurch sind die potenziellen Auswirkungen weniger schwerwiegend, wenn eine Funktion missbraucht oder ausgenutzt wird. Wenn Sie beispielsweise Funktionsaufrufe zum Abfragen einer Datenbank verwenden, sollten Sie Ihrer Anwendung nur schreibgeschützten Zugriff auf die Datenbank gewähren. Funktionen in der Funktionsdefinition auszuschließen sollte nicht Ihre einzige Sicherheitsmaßnahme sein.
  • Berücksichtigen der realen Auswirkungen: Beachten Sie die realen Auswirkungen von Funktionsaufrufen, die Sie ausführen möchten, insbesondere solche, die Aktionen auslösen, z. B. das Ausführen von Code, das Aktualisieren von Datenbanken oder das Senden von Benachrichtigungen.
  • Implementieren von Benutzerbestätigungsschritten: Insbesondere für Funktionen, die Aktionen ausführen, wird empfohlen, einen Schritt aufzunehmen, in dem Benutzer*innen die Aktion bestätigen müssen, bevor sie ausgeführt wird.

Weitere Informationen zu unseren Empfehlungen zur verantwortungsvollen Verwendung von Azure OpenAI-Modellen finden Sie unter Übersicht über Methoden der verantwortungsbewussten KI-Anwendung für Azure OpenAI-Modelle.

Nächste Schritte