Dela via


Använda funktionsanrop med Azure OpenAI Service (förhandsversion)

De senaste versionerna av gpt-35-turbo och gpt-4 är finjusterade för att fungera med funktioner och kan både avgöra när och hur en funktion ska anropas. Om en eller flera funktioner ingår i din begäran avgör modellen om någon av funktionerna ska anropas baserat på promptens kontext. När modellen fastställer att en funktion ska anropas svarar den med ett JSON-objekt, inklusive argumenten för funktionen.

Modellerna formulerar API-anrop och strukturerar datautdata, allt baserat på de funktioner du anger. Det är viktigt att observera att även om modellerna kan generera dessa anrop är det upp till dig att köra dem, vilket säkerställer att du har kontroll.

På hög nivå kan du dela upp arbetet med funktioner i tre steg:

  1. Anropa API:et för chattens slutförande med dina funktioner och användarens indata
  2. Använd modellens svar för att anropa ditt API eller din funktion
  3. Anropa API:et för chattens slutförande igen, inklusive svaret från din funktion för att få ett slutligt svar

Viktigt!

Parametrarna functions och function_call har inaktuella med versionen av API: 2023-12-01-preview ets version. Ersättningen för functions är parametern tools . Ersättningen för function_call är parametern tool_choice .

Parallell funktionsanrop

Parallella funktionsanrop stöds med:

Modeller som stöds

  • gpt-35-turbo (1106)
  • gpt-35-turbo (0125)
  • gpt-4 (1106-förhandsversion)
  • gpt-4 (0125-Preview)

API-stöd

Stöd för parallell funktion lades först till i API-version 2023-12-01-preview

Med parallella funktionsanrop kan du utföra flera funktionsanrop tillsammans, vilket möjliggör parallell körning och hämtning av resultat. Detta minskar antalet anrop till API:et som behöver göras och kan förbättra den övergripande prestandan.

För en enkel väderapp kanske du vill hämta vädret på flera platser samtidigt. Detta resulterar i ett meddelande om chattens slutförande med tre funktionsanrop i matrisen tool_calls , var och en med en unik id. Om du vill svara på dessa funktionsanrop lägger du till tre nya meddelanden i konversationen, som var och en innehåller resultatet av ett funktionsanrop, med en tool_call_id referens id från tools_calls.

Nedan tillhandahåller vi en modifierad version av OpenAI:s get_current_weather exempel. Det här exemplet som med originalet från OpenAI är att tillhandahålla den grundläggande strukturen, men är inte ett fullständigt fungerande fristående exempel. Om du försöker köra den här koden utan ytterligare ändringar skulle det resultera i ett fel.

I det här exemplet definieras en enskild funktion get_current_weather. Modellen anropar funktionen flera gånger, och när funktionssvaret har skickats tillbaka till modellen bestämmer den nästa steg. Det svarar med ett användaranslutet meddelande som berättade för användaren temperaturen i San Francisco, Tokyo och Paris. Beroende på frågan kan den välja att anropa en funktion igen.

Om du vill tvinga modellen att anropa en specifik funktion anger du parametern tool_choice med ett specifikt funktionsnamn. Du kan också tvinga modellen att generera ett användaranslutet meddelande genom att ange tool_choice: "none".

Kommentar

Standardbeteendet (tool_choice: "auto") är att modellen på egen hand bestämmer om en funktion ska anropas och i så sätt vilken funktion som ska anropas.

import os
from openai import AzureOpenAI
import json

client = AzureOpenAI(
  azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"), 
  api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
  api_version="2024-03-01-preview"
)


# Example function hard coded to return the same weather
# In production, this could be your backend API or an external API
def get_current_weather(location, unit="fahrenheit"):
    """Get the current weather in a given location"""
    if "tokyo" in location.lower():
        return json.dumps({"location": "Tokyo", "temperature": "10", "unit": unit})
    elif "san francisco" in location.lower():
        return json.dumps({"location": "San Francisco", "temperature": "72", "unit": unit})
    elif "paris" in location.lower():
        return json.dumps({"location": "Paris", "temperature": "22", "unit": unit})
    else:
        return json.dumps({"location": location, "temperature": "unknown"})

def run_conversation():
    # Step 1: send the conversation and available functions to the model
    messages = [{"role": "user", "content": "What's the weather like in San Francisco, Tokyo, and Paris?"}]
    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 and state, e.g. San Francisco, CA",
                        },
                        "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                    },
                    "required": ["location"],
                },
            },
        }
    ]
    response = client.chat.completions.create(
        model="<REPLACE_WITH_YOUR_MODEL_DEPLOYMENT_NAME>",
        messages=messages,
        tools=tools,
        tool_choice="auto",  # auto is default, but we'll be explicit
    )
    response_message = response.choices[0].message
    tool_calls = response_message.tool_calls
    # Step 2: check if the model wanted to call a function
    if tool_calls:
        # Step 3: call the function
        # Note: the JSON response may not always be valid; be sure to handle errors
        available_functions = {
            "get_current_weather": get_current_weather,
        }  # only one function in this example, but you can have multiple
        messages.append(response_message)  # extend conversation with assistant's reply
        # Step 4: send the info for each function call and function response to the model
        for tool_call in tool_calls:
            function_name = tool_call.function.name
            function_to_call = available_functions[function_name]
            function_args = json.loads(tool_call.function.arguments)
            function_response = function_to_call(
                location=function_args.get("location"),
                unit=function_args.get("unit"),
            )
            messages.append(
                {
                    "tool_call_id": tool_call.id,
                    "role": "tool",
                    "name": function_name,
                    "content": function_response,
                }
            )  # extend conversation with function response
        second_response = client.chat.completions.create(
            model="<REPLACE_WITH_YOUR_1106_MODEL_DEPLOYMENT_NAME>",
            messages=messages,
        )  # get a new response from the model where it can see the function response
        return second_response
print(run_conversation())

Använda funktionen i API:et för chattavslut (inaktuell)

Funktionsanrop är tillgängligt i 2023-07-01-preview API-versionen och fungerar med version 0613 av gpt-35-turbo, gpt-35-turbo-16k, gpt-4 och gpt-4-32k.

Om du vill använda funktionsanrop med API:et För att slutföra chatten måste du inkludera två nya egenskaper i din begäran: functions och function_call. Du kan inkludera en eller flera functions i din begäran och du kan lära dig mer om hur du definierar funktioner i avsnittet definiera funktioner . Tänk på att funktioner matas in i systemmeddelandet under huven så att funktioner räknas mot din tokenanvändning.

När funktioner tillhandahålls är som standard function_call inställt på "auto" och modellen avgör om en funktion ska anropas eller inte. Du kan också ange parametern function_call till {"name": "<insert-function-name>"} för att tvinga API:et att anropa en specifik funktion, eller så kan du ställa in parametern för "none" att förhindra att modellen anropar några funktioner.

Kommentar

OpenAI Python-biblioteksversionen 0.28.1 är inaktuell. Vi rekommenderar att du använder 1.x. I vår migreringsguide finns information om hur du går från 0.28.1 till 1.x.


import os
import openai

openai.api_key = os.getenv("AZURE_OPENAI_API_KEY")
openai.api_version = "2023-07-01-preview"
openai.api_type = "azure"
openai.api_base = os.getenv("AZURE_OPENAI_ENDPOINT")

messages= [
    {"role": "user", "content": "Find beachfront hotels in San Diego for less than $300 a month with free breakfast."}
]

functions= [  
    {
        "name": "search_hotels",
        "description": "Retrieves hotels from the search index based on the parameters provided",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "The location of the hotel (i.e. Seattle, WA)"
                },
                "max_price": {
                    "type": "number",
                    "description": "The maximum price for the hotel"
                },
                "features": {
                    "type": "string",
                    "description": "A comma separated list of features (i.e. beachfront, free wifi, etc.)"
                }
            },
            "required": ["location"]
        }
    }
]  

response = openai.ChatCompletion.create(
    engine="gpt-35-turbo-0613", # engine = "deployment_name"
    messages=messages,
    functions=functions,
    function_call="auto", 
)

print(response['choices'][0]['message'])
{
  "role": "assistant",
  "function_call": {
    "name": "search_hotels",
    "arguments": "{\n  \"location\": \"San Diego\",\n  \"max_price\": 300,\n  \"features\": \"beachfront,free breakfast\"\n}"
  }
}

Svaret från API:et innehåller en function_call egenskap om modellen avgör att en funktion ska anropas. Egenskapen function_call innehåller namnet på funktionen som ska anropas och argumenten som ska skickas till funktionen. Argumenten är en JSON-sträng som du kan parsa och använda för att anropa din funktion.

I vissa fall genererar modellen både content och en function_call. Till exempel för uppmaningen ovan innehållet kan säga något i stil med "Visst, jag kan hjälpa dig att hitta några hotell i San Diego som matchar dina kriterier" tillsammans med function_call.

Arbeta med funktionsanrop

I följande avsnitt beskrivs mer detaljerat hur du effektivt använder funktioner med API:et för chattslutsättningar.

Definiera funktioner

En funktion har tre huvudparametrar: name, descriptionoch parameters. Parametern description används av modellen för att avgöra när och hur funktionen ska anropas, så det är viktigt att ge en meningsfull beskrivning av vad funktionen gör.

parameters är ett JSON-schemaobjekt som beskriver de parametrar som funktionen accepterar. Du kan läsa mer om JSON-schemaobjekt i JSON-schemareferensen.

Om du vill beskriva en funktion som inte accepterar några parametrar använder {"type": "object", "properties": {}} du som värde för egenskapen parameters .

Hantera flödet med funktioner

Exempel i Python.


response = openai.ChatCompletion.create(
    deployment_id="gpt-35-turbo-0613",
    messages=messages,
    functions=functions,
    function_call="auto", 
)
response_message = response["choices"][0]["message"]

# Check if the model wants to call a function
if response_message.get("function_call"):

    # Call the function. The JSON response may not always be valid so make sure to handle errors
    function_name = response_message["function_call"]["name"]

    available_functions = {
            "search_hotels": search_hotels,
    }
    function_to_call = available_functions[function_name] 

    function_args = json.loads(response_message["function_call"]["arguments"])
    function_response = function_to_call(**function_args)

    # Add the assistant response and function response to the messages
    messages.append( # adding assistant response to messages
        {
            "role": response_message["role"],
            "function_call": {
                "name": function_name,
                "arguments": response_message["function_call"]["arguments"],
            },
            "content": None
        }
    )
    messages.append( # adding function response to messages
        {
            "role": "function",
            "name": function_name,
            "content": function_response,
        }
    ) 

    # Call the API again to get the final response from the model
    second_response = openai.ChatCompletion.create(
            messages=messages,
            deployment_id="gpt-35-turbo-0613"
            # optionally, you could provide functions in the second call as well
        )
    print(second_response["choices"][0]["message"])
else:
    print(response["choices"][0]["message"])

Exempel i PowerShell.

# continues from the previous PowerShell example

$response = Invoke-RestMethod -Uri $url -Headers $headers -Body $body -Method Post -ContentType 'application/json'
$response.choices[0].message | ConvertTo-Json

# Check if the model wants to call a function
if ($null -ne $response.choices[0].message.function_call) {

    $functionName  = $response.choices[0].message.function_call.name
    $functionArgs = $response.choices[0].message.function_call.arguments

    # Add the assistant response and function response to the messages
    $messages += @{
        role          = $response.choices[0].message.role
        function_call = @{
            name      = $functionName
            arguments = $functionArgs
        }
        content       = 'None'
    }
    $messages += @{
        role          = 'function'
        name          = $response.choices[0].message.function_call.name
        content       = "$functionName($functionArgs)"
    }

    # Call the API again to get the final response from the model
    
    # these API arguments are introduced in model version 0613
    $body = [ordered]@{
        messages      = $messages
        functions         = $functions
        function_call   = 'auto'
    } | ConvertTo-Json -depth 6

    $url = "$($openai.api_base)/openai/deployments/$($openai.name)/chat/completions?api-version=$($openai.api_version)"

    $secondResponse = Invoke-RestMethod -Uri $url -Headers $headers -Body $body -Method Post -ContentType 'application/json'
    $secondResponse.choices[0].message | ConvertTo-Json
}

Exempel på utdata.

{
  "role": "assistant",
  "content": "I'm sorry, but I couldn't find any beachfront hotels in San Diego for less than $300 a month with free breakfast."
}

I exemplen utför vi ingen validering eller felhantering, så du vill lägga till den i koden.

Ett fullständigt exempel på hur du arbetar med funktioner finns i exempelanteckningsboken för funktionsanrop. Du kan också använda mer komplex logik för att länka flera funktionsanrop tillsammans, vilket även beskrivs i exemplet.

Fråga efter teknik med funktioner

När du definierar en funktion som en del av din begäran matas informationen in i systemmeddelandet med hjälp av specifik syntax som modellen har tränats på. Det innebär att funktioner använder token i prompten och att du kan använda teknik för att optimera prestanda för dina funktionsanrop. Modellen använder den fullständiga kontexten för prompten för att avgöra om en funktion ska anropas, inklusive funktionsdefinition, systemmeddelande och användarmeddelanden.

Förbättra kvalitet och tillförlitlighet

Om modellen inte anropar din funktion när eller hur du förväntar dig finns det några saker du kan försöka förbättra kvaliteten på.

Ange mer information i funktionsdefinitionen

Det är viktigt att du anger en meningsfull description funktion och anger beskrivningar för alla parametrar som kanske inte är uppenbara för modellen. I beskrivningen för parametern location kan du till exempel inkludera extra information och exempel på platsens format.

"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)"
},
Ange mer kontext i systemmeddelandet

Systemmeddelandet kan också användas för att ge modellen mer kontext. Om du till exempel har en funktion med namnet search_hotels kan du inkludera ett systemmeddelande som följande för att instruera modellen att anropa funktionen när en användare ber om hjälp med att hitta ett hotell.

{"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."}
Instruera modellen att ställa klargörande frågor

I vissa fall vill du instruera modellen att ställa klargörande frågor för att förhindra antaganden om vilka värden som ska användas med funktioner. Du vill till exempel search_hotels att modellen ska be om förtydligande om användarbegäran inte innehåller information om location. Om du vill instruera modellen att ställa en klargörande fråga kan du inkludera innehåll som nästa exempel i systemmeddelandet.

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

Minska fel

Ett annat område där promptteknik kan vara värdefull är att minska felen i funktionsanrop. Modellerna tränas att generera funktionsanrop som matchar det schema som du definierar, men modellerna skapar ett funktionsanrop som inte matchar schemat du definierade eller försöker anropa en funktion som du inte tog med.

Om du upptäcker att modellen genererar funktionsanrop som inte har angetts kan du prova att inkludera en mening i systemmeddelandet som säger "Only use the functions you have been provided with.".

Använda funktionsanrop på ett ansvarsfullt sätt

Precis som alla AI-system innebär användning av funktionsanrop för att integrera språkmodeller med andra verktyg och system potentiella risker. Det är viktigt att förstå de risker som funktionsanrop kan medföra och vidta åtgärder för att säkerställa att du använder funktionerna på ett ansvarsfullt sätt.

Här följer några tips som hjälper dig att använda funktioner på ett säkert och säkert sätt:

  • Verifiera funktionsanrop: Verifiera alltid de funktionsanrop som genereras av modellen. Detta inkluderar att kontrollera parametrarna, funktionen som anropas och se till att anropet överensstämmer med den avsedda åtgärden.
  • Använd betrodda data och verktyg: Använd endast data från betrodda och verifierade källor. Ej betrodda data i en funktions utdata kan användas för att instruera modellen att skriva funktionsanrop på ett annat sätt än du avsåg.
  • Följ principen för minsta behörighet: Bevilja endast den minsta åtkomst som krävs för att funktionen ska kunna utföra sitt jobb. Detta minskar den potentiella effekten om en funktion missbrukas eller utnyttjas. Om du till exempel använder funktionsanrop för att fråga en databas bör du bara ge programmet skrivskyddad åtkomst till databasen. Du bör inte heller enbart vara beroende av att exkludera funktioner i funktionsdefinitionen som en säkerhetskontroll.
  • Överväg verklig påverkan: Var medveten om den verkliga effekten av funktionsanrop som du planerar att köra, särskilt de som utlöser åtgärder som att köra kod, uppdatera databaser eller skicka meddelanden.
  • Implementera steg för användarbekräftelse: Särskilt för funktioner som vidtar åtgärder rekommenderar vi att du inkluderar ett steg där användaren bekräftar åtgärden innan den körs.

Mer information om våra rekommendationer om hur du använder Azure OpenAI-modeller på ett ansvarsfullt sätt finns i Översikt över ansvarsfulla AI-metoder för Azure OpenAI-modeller.

Nästa steg