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.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
AIAgent agent = new AIProjectClient(
new Uri("<your-foundry-project-endpoint>"),
new DefaultAzureCredential())
.AsAIAgent(
model: "gpt-4o-mini",
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.
# 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",
)
def get_weather(location: str, unit: str = "celsius") -> str:
"""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.",
schema=get_current_time_schema,
approval_mode="never_require",
)
def get_current_time(timezone: str = "UTC") -> str:
"""Get the current time."""
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 Agent, FunctionInvocationContext, tool
from agent_framework.openai import OpenAIChatClient
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 = Agent(
client=OpenAIChatClient(),
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"},
)
print(f"Agent: {response.text}")
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.
# 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"},
},
"required": ["reason"],
},
)
Při vytváření agenta teď můžete agentu poskytnout nástroj funkce tím, že ho předáte parametru tools .
import asyncio
import os
from agent_framework.openai import OpenAIChatCompletionClient
from azure.identity import AzureCliCredential
agent = OpenAIChatCompletionClient(
model=os.environ["AZURE_OPENAI_CHAT_COMPLETION_MODEL"],
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
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 Agent, tool
from agent_framework.openai import OpenAIChatClient
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 = Agent(
client=OpenAIChatClient(),
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
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í.
Nástroje funkcí
Nástroje pro funkce umožňují agentům volat vlastní funkce Go. Balíček functool nabízí jednoduchý způsob, jak definovat nástroje bezpečné pro typ pomocí automatického generování schématu.
Definujte funkční nástroj
import (
"context"
"github.com/microsoft/agent-framework-go/tool"
"github.com/microsoft/agent-framework-go/tool/functool"
)
var weatherTool = functool.MustNew(functool.Config{
Name: "weather",
Description: "Get the current weather for a given location",
}, func(_ context.Context, location string) (string, error) {
return fmt.Sprintf("The weather in %s is cloudy with a high of 15°C.", location), nil
})
Podpis funkce určuje vstupní schéma nástroje. Parametr context.Context je vložen rozhraním a není vystaven modelu.
Typy strukturovaných vstupů
Pro nástroje s více parametry definujte strukturu:
type WeatherInput struct {
Location string `json:"location" jsonschema:"description=The city to check weather for"`
Unit string `json:"unit" jsonschema:"description=Temperature unit (celsius or fahrenheit),enum=celsius,enum=fahrenheit"`
}
var weatherTool = functool.MustNew(functool.Config{
Name: "weather",
Description: "Get weather for a location",
}, func(_ context.Context, input WeatherInput) (string, error) {
return fmt.Sprintf("Weather in %s: 15°%s", input.Location, input.Unit), nil
})
Vytvoření agenta pomocí nástrojů
a := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
Instructions: "You are a helpful assistant.",
Config: agent.Config{
Tools: []tool.Tool{weatherTool},
},
})
resp, err := a.RunText(ctx, "What is the weather like in Amsterdam?").Collect()
Použijte agenta jako funkční nástroj
Jakýkoli agent může být zabalený jako nástroj funkce pro použití jiným agentem:
import "github.com/microsoft/agent-framework-go/tool/agenttool"
weatherAgent := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
Instructions: "You answer questions about the weather.",
Config: agent.Config{
Name: "WeatherAgent",
Description: "An agent that answers weather questions.",
Tools: []tool.Tool{weatherTool},
},
})
mainAgent := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
Instructions: "You are a helpful assistant who responds in French.",
Config: agent.Config{
Tools: []tool.Tool{agenttool.New(weatherAgent, agenttool.Config{})},
},
})
Použijte místní nástroj shellu
Go SDK obsahuje tool/shelltool pro místní spouštění v shellu. Nástroj vyžaduje schválení ve výchozím nastavení a dá se spárovat s poskytovatelem kontextu prostředí, aby model zná aktuální řadu prostředí, pracovní adresář a běžné verze nástrojů.
import "github.com/microsoft/agent-framework-go/tool/shelltool"
shell, err := shelltool.NewLocal(shelltool.LocalConfig{
Mode: shelltool.ModeStateless,
})
if err != nil {
return err
}
defer shell.Close()
envProvider := shelltool.NewEnvironmentProvider(shell, shelltool.EnvironmentProviderConfig{})
a := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
Instructions: "Run shell commands only when needed and summarize the result.",
Config: agent.Config{
Tools: []tool.Tool{shell},
ContextProviders: []agent.ContextProvider{envProvider},
},
})
Použijte shelltool.ModeStateless , když by se každé volání mělo spustit v novém prostředí. Používejte shelltool.ModePersistent pouze tehdy, když v rámci jedné relace agenta potřebujete, aby stav shellu, například změněné adresáře nebo exportované proměnné prostředí, přetrval napříč voláními. Nastavte AcknowledgeUnsafe: true pouze tehdy, když zajistíte nezávislou izolační hranici a nepotřebujete integrovanou schvalovací bránu.
Návod
Úplné příklady najdete v ukázce nástrojů pro funkce, ukázce agenta jako nástroje a ukázce shellu s prostředím.
Další kroky
Řízení dostupnosti nástrojů za běhu
Během spuštění agenta můžete pomocí FunctionInvocationContext.add_tools() / remove_tools() přidávat nebo odebírat nástroje, řídit volání prostřednictvím middlewaru funkcí nebo pomocí tool_choice vynutit konkrétní první volání. Úplné vzory najdete v tématu Řízení dostupnosti nástrojů .