Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
V tomto kurzu se dozvíte, jak používat nástroje funkcí s agentem, kde je agent založený na službě Dokončování chatu Azure OpenAI.
Důležité
Ne všechny typy agentů podporují funkční nástroje. Některé můžou podporovat jenom vlastní integrované nástroje, aniž by volající mohl poskytovat vlastní funkce. Tento krok používá ChatClientAgent, který podporuje funkční nástroje.
Požadavky
Informace o požadavcích a instalaci balíčků NuGet naleznete v kroku Vytvoření a spuštění jednoduchého agenta v tomto kurzu.
Vytvoření agenta pomocí nástrojů funkcí
Nástroje funkcí jsou jen vlastní kód, který může agent použít, když je to potřeba.
Libovolnou metodu jazyka C# můžete převést na nástroj funkce pomocí AIFunctionFactory.Create metody k vytvoření AIFunction instance z této metody.
Pokud potřebujete do agenta zadat další popisy funkce nebo jeho parametrů, aby bylo možné přesněji zvolit mezi různými funkcemi, můžete použít System.ComponentModel.DescriptionAttribute atribut metody a jeho parametrů.
Tady je příklad jednoduchého funkčního nástroje, který zfalšuje počasí pro dané místo. Je opatřen atributy popisu, aby poskytoval další informace o sobě a parametru umístění agenta.
using System.ComponentModel;
[Description("Get the weather for a given location.")]
static string GetWeather([Description("The location to get the weather for.")] string location)
=> $"The weather in {location} is cloudy with a high of 15°C.";
Při vytváření agenta teď můžete agentu poskytnout nástroj funkce předáním seznamu nástrojů metodě AsAIAgent .
using System;
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OpenAI;
AIAgent agent = new AzureOpenAIClient(
new Uri("https://<myresource>.openai.azure.com"),
new DefaultAzureCredential())
.GetChatClient("gpt-4o-mini")
.AsAIAgent(instructions: "You are a helpful assistant", tools: [AIFunctionFactory.Create(GetWeather)]);
Výstraha
DefaultAzureCredential je vhodný pro vývoj, ale vyžaduje pečlivé zvážení v produkčním prostředí. V produkčním prostředí zvažte použití konkrétních přihlašovacích údajů (např ManagedIdentityCredential. ) k zabránění problémům s latencí, neúmyslnému testování přihlašovacích údajů a potenciálním bezpečnostním rizikům z náhradních mechanismů.
Nyní můžete agenta spustit obvyklým způsobem a agent bude moct v případě potřeby volat funkční nástroj GetWeather.
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?"));
Návod
Najdete kompletní spustitelné příklady v ukázkách .NET.
Důležité
Ne všechny typy agentů podporují funkční nástroje. Některé můžou podporovat jenom vlastní integrované nástroje, aniž by volající mohl poskytovat vlastní funkce. Tento krok využívá agenty vytvořené prostřednictvím chatovacích klientů, které podporují funkční nástroje.
Požadavky
Informace o požadavcích a instalaci balíčků Pythonu najdete v části Vytvoření a spuštění jednoduchého agenta v tomto kurzu.
Vytvoření agenta pomocí nástrojů funkcí
Nástroje funkcí jsou jen vlastní kód, který může agent použít, když je to potřeba.
Libovolnou funkci Pythonu můžete převést na nástroj funkce tak, že ji při vytváření agenta tools předáte parametru agenta.
Pokud potřebujete do agenta zadat další popisy funkce nebo jeho parametrů, aby bylo možné přesněji zvolit mezi různými funkcemi, můžete k zadání popisů použít poznámky typu Pythonu a Annotated Pydantic Field .
Tady je příklad jednoduchého funkčního nástroje, který zfalšuje počasí pro dané místo. Poznámky typu se využívají k poskytnutí dodatečných popisů funkce a jejího parametru umístění agentovi.
from typing import Annotated
from pydantic import Field
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
"""Get the weather for a given location."""
return f"The weather in {location} is cloudy with a high of 15°C."
Dekorátor můžete také použít @tool k explicitní zadání názvu a popisu funkce:
from typing import Annotated
from pydantic import Field
from agent_framework import tool
@tool(name="weather_tool", description="Retrieves weather information for any location")
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
return f"The weather in {location} is cloudy with a high of 15°C."
Pokud v dekorátoru name nezadáte parametry description a @tool, framework automaticky použije název funkce a docstring jako náhradní.
Použití explicitních schémat s využitím @tool
Pokud potřebujete úplnou kontrolu nad schématem vystaveným modelem, předejte parametr schema@tool.
Můžete zadat Pydantický model nebo nezpracovaný slovník schématu JSON.
# Load environment variables from .env file
load_dotenv()
# Approach 1: Pydantic model as explicit schema
class WeatherInput(BaseModel):
"""Input schema for the weather tool."""
location: Annotated[str, Field(description="The city name to get weather for")]
unit: Annotated[str, Field(description="Temperature unit: celsius or fahrenheit")] = "celsius"
@tool(
name="get_weather",
description="Get the current weather for a given location.",
schema=WeatherInput,
approval_mode="never_require",
"""Get the current weather for a location."""
return f"The weather in {location} is 22 degrees {unit}."
# Approach 2: JSON schema dictionary as explicit schema
get_current_time_schema = {
"type": "object",
"properties": {
"timezone": {"type": "string", "description": "The timezone to get the current time for", "default": "UTC"},
},
}
@tool(
name="get_current_time",
description="Get the current time in a given timezone.",
Předání kontextu pouze za běhu do nástroje
Pro hodnoty, které má model zadat, použijte normální parametry funkce. Používá se FunctionInvocationContext pro hodnoty jen za běhu, například function_invocation_kwargs pro aktuální relaci. Vložený kontextový parametr je skrytý ze schématu vystaveného modelu.
import asyncio
from typing import Annotated
from agent_framework import FunctionInvocationContext, tool
from agent_framework.openai import OpenAIResponsesClient
from dotenv import load_dotenv
from pydantic import Field
# Define the function tool with explicit invocation context.
# The context parameter can also be declared as an untyped ``ctx`` parameter.
@tool(approval_mode="never_require")
def get_weather(
location: Annotated[str, Field(description="The location to get the weather for.")],
ctx: FunctionInvocationContext,
) -> str:
"""Get the weather for a given location."""
# Extract the injected argument from the explicit context
user_id = ctx.kwargs.get("user_id", "unknown")
# Simulate using the user_id for logging or personalization
print(f"Getting weather for user: {user_id}")
return f"The weather in {location} is cloudy with a high of 15°C."
async def main() -> None:
agent = OpenAIResponsesClient().as_agent(
name="WeatherAgent",
instructions="You are a helpful weather assistant.",
tools=[get_weather],
)
# Pass the runtime context explicitly when running the agent.
response = await agent.run(
"What is the weather like in Amsterdam?",
function_invocation_kwargs={"user_id": "user_123"},
)
Další podrobnosti o middlewaru ctx.kwargs, ctx.sessiona funkce naleznete v tématu Kontext modulu runtime.
Vytváření nástrojů jen pro deklaraci
Pokud je nástroj implementovaný mimo architekturu (například na straně klienta v uživatelském rozhraní), můžete jej deklarovat bez implementace pomocí FunctionTool(..., func=None).
Model může stále uvažovat o nástroji a volat ho, a vaše aplikace může poskytnout výsledek později.
# Load environment variables from .env file
load_dotenv()
# A declaration-only tool: the schema is sent to the LLM, but the framework
# has no implementation to execute. The caller must supply the result.
get_user_location = FunctionTool(
name="get_user_location",
func=None,
description="Get the user's current city. Only the client application can resolve this.",
input_model={
"type": "object",
"properties": {
"reason": {"type": "string", "description": "Why the location is needed"},
Při vytváření agenta teď můžete agentu poskytnout nástroj funkce tím, že ho předáte parametru tools .
import asyncio
from agent_framework.azure import AzureOpenAIChatClient
from azure.identity import AzureCliCredential
agent = AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
instructions="You are a helpful assistant",
tools=get_weather
)
Nyní můžete agenta spustit obvyklým způsobem a agent bude moct v případě potřeby volat funkční nástroj get_weather.
async def main():
result = await agent.run("What is the weather like in Amsterdam?")
print(result.text)
asyncio.run(main())
Vytvoření třídy s více nástroji funkcí
Pokud několik nástrojů sdílí závislosti nebo proměnlivý stav, zabalte je do třídy a předejte vázané metody agentu. Použijte atributy třídy pro hodnoty, které model nesmí poskytovat, jako jsou klienti služeb, příznaky funkcí nebo stav v mezipaměti.
import asyncio
from typing import Annotated
from agent_framework import tool
from agent_framework.openai import OpenAIResponsesClient
from dotenv import load_dotenv
class MyFunctionClass:
def __init__(self, safe: bool = False) -> None:
"""Simple class with two tools: divide and add.
The safe parameter controls whether divide raises on division by zero or returns `infinity` for divide by zero.
"""
self.safe = safe
def divide(
self,
a: Annotated[int, "Numerator"],
b: Annotated[int, "Denominator"],
) -> str:
"""Divide two numbers, safe to use also with 0 as denominator."""
result = "∞" if b == 0 and self.safe else a / b
return f"{a} / {b} = {result}"
def add(
self,
x: Annotated[int, "First number"],
y: Annotated[int, "Second number"],
) -> str:
return f"{x} + {y} = {x + y}"
async def main():
# Creating my function class with safe division enabled
tools = MyFunctionClass(safe=True)
# Applying the tool decorator to one of the methods of the class
add_function = tool(description="Add two numbers.")(tools.add)
agent = OpenAIResponsesClient().as_agent(
name="ToolAgent",
instructions="Use the provided tools.",
)
print("=" * 60)
print("Step 1: Call divide(10, 0) - tool returns infinity")
query = "Divide 10 by 0"
response = await agent.run(
query,
tools=[add_function, tools.divide],
)
print(f"Response: {response.text}")
print("=" * 60)
print("Step 2: Call set safe to False and call again")
# Disabling safe mode to allow exceptions
tools.safe = False
response = await agent.run(query, tools=[add_function, tools.divide])
Tento vzorec je vhodný pro trvalý stav nástroje. Místo toho použijte FunctionInvocationContext, když se hodnota změní při každém vyvolání.