Sdílet prostřednictvím


Jak používat volání funkcí se službou Azure OpenAI Service (Preview)

Nejnovější verze gpt-35-turbo a gpt-4 jsou jemně vyladěné pro práci s funkcemi a umožňují určit, kdy a jak se má funkce volat. Pokud je jedna nebo více funkcí součástí vašeho požadavku, model určí, jestli by se některá z funkcí měla volat na základě kontextu výzvy. Když model určí, že se má funkce volat, odpoví objektem JSON, včetně argumentů funkce.

Modely formulují volání rozhraní API a strukturují výstupy dat, a to vše na základě zadaných funkcí. Je důležité si uvědomit, že zatímco modely můžou tato volání generovat, je na vás je spustit a zajistit, abyste zůstali pod kontrolou.

Na vysoké úrovni můžete rozdělit práci s funkcemi do tří kroků:

  1. Volání rozhraní API pro dokončování chatu s funkcemi a vstupem uživatele
  2. Použití odpovědi modelu k volání rozhraní API nebo funkce
  3. Znovu volejte rozhraní API pro dokončování chatu, včetně odpovědi z vaší funkce, abyste získali konečnou odpověď.

Důležité

Parametry functions jsou function_call zastaralé s vydáním 2023-12-01-preview verze rozhraní API. Nahrazením functions parametru tools je. Nahrazením function_call parametru tool_choice je.

Paralelní volání funkcí

Paralelní volání funkcí jsou podporována s:

Podporované modely

  • gpt-35-turbo (1106)
  • gpt-35-turbo (0125)
  • gpt-4 (1106-Preview)
  • gpt-4 (0125-Preview)

Podpora rozhraní API

Podpora paralelní funkce byla poprvé přidána ve verzi rozhraní API. 2023-12-01-preview

Paralelní volání funkcí umožňují společně provádět více volání funkcí, což umožňuje paralelní spouštění a načítání výsledků. Tím se sníží počet volání rozhraní API, které je potřeba provést, a může zlepšit celkový výkon.

Například pro jednoduchou aplikaci pro počasí můžete chtít načíst počasí na více místech najednou. Výsledkem bude zpráva o dokončení chatu se třemi voláními funkce v tool_calls poli, z nichž každý má jedinečný id. Pokud byste chtěli reagovat na tato volání funkce, přidali byste do konverzace 3 nové zprávy, z nichž každý obsahuje výsledek jednoho volání funkce s tool_call_id odkazem id na z tools_calls.

Níže uvádíme upravenou verzi příkladu OpenAI get_current_weather . Tento příklad jako u originálu z OpenAI představuje základní strukturu, ale nejedná se o plně funkční samostatný příklad. Při pokusu o spuštění tohoto kódu bez další úpravy dojde k chybě.

V tomto příkladu je definována jedna funkce get_current_weather. Model několikrát volá funkci a po odeslání odpovědi funkce zpět do modelu rozhodne o dalším kroku. Reaguje na zprávu, která uživateli říkala teplotu v San Franciscu, Tokiu a Paříži. V závislosti na dotazu se může rozhodnout znovu volat funkci.

Chcete-li vynutit, aby model volal konkrétní funkci, nastavte tool_choice parametr s konkrétním názvem funkce. Model můžete také vynutit, aby vygeneroval uživatelskou zprávu nastavením tool_choice: "none".

Poznámka:

Výchozí chování (tool_choice: "auto") je pro model rozhodnout o tom, jestli se má funkce volat, a pokud ano, která funkce se má volat.

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

Použití funkce v rozhraní API pro dokončování chatu (zastaralé)

Volání funkcí je k dispozici ve 2023-07-01-preview verzi rozhraní API a funguje s verzí 0613 gpt-35-turbo, gpt-35-turbo-16k, gpt-4 a gpt-4-32k.

Pokud chcete používat volání funkcí s rozhraním API pro dokončování chatu, musíte do požadavku zahrnout dvě nové vlastnosti: functions a function_call. Do požadavku můžete zahrnout jednu nebo více functions a dozvíte se více o tom, jak definovat funkce v oddílu definování funkcí . Mějte na paměti, že funkce se vloží do systémové zprávy pod kapucí, takže se funkce započítávají do vašeho využití tokenu.

Pokud jsou k dispozici funkce, je ve výchozím nastavení function_call nastavená "auto" a model rozhodne, jestli se má funkce volat, nebo ne. Případně můžete nastavit function_call parametr tak, aby vynutil, aby {"name": "<insert-function-name>"} rozhraní API volala konkrétní funkci, nebo můžete nastavit parametr tak, aby "none" zabránil modelu v volání libovolných funkcí.

Poznámka:

Verze 0.28.1 knihovny Python OpenAI je zastaralá. Doporučujeme používat 1.x. Informace o přechodu z 0.28.1 této 1.xmigrace najdete v našem průvodci migrací.


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

Odpověď z rozhraní API obsahuje function_call vlastnost, pokud model určuje, že by se měla volat funkce. Vlastnost function_call obsahuje název funkce, která se má volat, a argumenty, které se mají funkci předat. Argumenty jsou řetězec JSON, který můžete analyzovat a použít k volání funkce.

V některých případech model generuje jak content , tak function_calli . Například pro výzvu nad obsahem by mohlo říct něco jako "Sure, I can help you find some hotels in San Diego that match your criteria" spolu s function_call.

Práce s voláním funkce

V následující části najdete podrobnější informace o tom, jak efektivně používat funkce s rozhraním API pro dokončování chatu.

Definování funkcí

Funkce má tři hlavní parametry: name, descriptiona parameters. Parametr description je používán modelem k určení, kdy a jak volat funkci, aby bylo důležité poskytnout smysluplný popis toho, co funkce dělá.

parameters je objekt schématu JSON, který popisuje parametry, které funkce přijímá. Další informace o objektech schématu JSON najdete v referenčních informacích ke schématu JSON.

Pokud chcete popsat funkci, která nepřijímá žádné parametry, použijte {"type": "object", "properties": {}} jako hodnotu vlastnosti parameters .

Správa toku pomocí funkcí

Příklad v Pythonu


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

Příklad v PowerShellu

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

Příklad výstupu

{
  "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."
}

V příkladech neprovedeme žádné ověřování ani zpracování chyb, takže si ho budete chtít do kódu přidat.

Úplný příklad práce s funkcemi najdete v ukázkovém poznámkovém bloku při volání funkce. Složitější logiku můžete použít také pro zřetězování více volání funkcí, která je zahrnuta i v ukázce.

Příprava výzvy s využitím funkcí

Když definujete funkci jako součást požadavku, podrobnosti se vloží do systémové zprávy pomocí konkrétní syntaxe, na které byl model natrénován. To znamená, že funkce spotřebovávají tokeny ve výzvě a že můžete použít techniky přípravy k optimalizaci výkonu volání funkce. Model používá úplný kontext výzvy k určení, jestli by měla být volána funkce, včetně definice funkce, systémové zprávy a zpráv uživatelů.

Zlepšení kvality a spolehlivosti

Pokud model nevolá vaši funkci, když nebo jak očekáváte, můžete zkusit zlepšit kvalitu několika věcí.

Zadání dalších podrobností v definici funkce

Je důležité, abyste funkci poskytli smysluplně description a zadali popisy všech parametrů, které nemusí být pro model zřejmé. Například v popisu parametru location můžete zahrnout další podrobnosti a příklady ve formátu umístění.

"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)"
},
Poskytnutí dalšího kontextu v systémové zprávě

Systémovou zprávu lze také použít k poskytnutí dalšího kontextu modelu. Pokud máte například zavolánou search_hotels funkci, můžete do modelu zahrnout systémovou zprávu, jako je následující, a dát tak modelu pokyn, aby funkci volal, když uživatel požádá o pomoc s vyhledáním hotelu.

{"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."}
Řekněte modelu, aby se zeptal na objasnění otázek.

V některýchpřípadechch Například s search_hotels vámi by model chtěl požádat o objasnění, pokud žádost uživatele neobsahuje podrobnosti o location. Pokud chcete modelu dát pokyn, aby položil objasňující otázku, můžete do systémové zprávy zahrnout obsah podobný následujícímu příkladu.

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

Omezení chyb

Další oblastí, ve které může být příprava výzvy cenná, je snížení chyb ve voláních funkcí. Modely se vytrénují tak, aby generovaly volání funkcí odpovídající schématu, které definujete, ale modely vytvářejí volání funkce, které neodpovídá vámi definovanému schématu, nebo se pokusí volat funkci, kterou jste nezahrnuli.

Pokud zjistíte, že model generuje volání funkcí, která nebyla poskytnuta, zkuste do systémové zprávy zahrnout větu, která říká "Only use the functions you have been provided with.".

Zodpovědné používání volání funkcí

Stejně jako jakýkoli systém umělé inteligence představuje použití volání funkcí k integraci jazykových modelů s jinými nástroji a systémy potenciální rizika. Je důležité porozumět rizikům, která volání funkcí může představovat, a přijmout opatření k zajištění zodpovědného používání schopností.

Tady je několik tipů, které vám pomůžou bezpečně a bezpečně používat funkce:

  • Ověření volání funkce: Vždy ověřte volání funkce vygenerovaná modelem. To zahrnuje kontrolu parametrů, volání funkce a zajištění toho, aby volání odpovídalo zamýšlené akci.
  • Použití důvěryhodných dat a nástrojů: Používejte pouze data z důvěryhodných a ověřených zdrojů. Nedůvěryhodná data ve výstupu funkce se dají použít k tomu, aby model dal pokyn k zápisu volání funkcí jiným způsobem, než jste chtěli.
  • Postupujte podle principu nejnižšího oprávnění: Udělte funkci pouze minimální přístup potřebný k provedení své úlohy. To snižuje potenciální dopad, pokud je funkce zneužitá nebo zneužita. Pokud například používáte volání funkcí k dotazování databáze, měli byste aplikaci udělit přístup jen pro čtení k databázi. Neměli byste také záviset výhradně na vyloučení funkcí v definici funkce jako bezpečnostních prvků.
  • Zvažte skutečný dopad: Mějte na paměti skutečný dopad volání funkcí, která plánujete provést, zejména těch, které aktivují akce, jako je spouštění kódu, aktualizace databází nebo odesílání oznámení.
  • Implementujte kroky potvrzení uživatele: Zejména pro funkce, které provádějí akce, doporučujeme přidat krok, ve kterém uživatel akci před spuštěním potvrdí.

Další informace o našich doporučeních k zodpovědnému používání modelů Azure OpenAI najdete v přehledu postupů zodpovědné umělé inteligence pro modely Azure OpenAI.

Další kroky