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ů:
- Volání rozhraní API pro dokončování chatu s funkcemi a vstupem uživatele
- Použití odpovědi modelu k volání rozhraní API nebo funkce
- 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.x
migrace 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_call
i . 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
, description
a 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
- Další informace o Azure OpenAI.
- Další příklady práce s funkcemi najdete v úložišti GitHub s ukázkami Azure OpenAI.
- Začněte s modelem GPT-35-Turbo pomocí rychlého startu GPT-35-Turbo.
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro