Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Det här självstudiesteget visar hur du använder funktionsverktyg med en agent, där agenten bygger på tjänsten Azure OpenAI Chat Completion.
Viktigt!
Alla agenttyper stöder inte funktionsverktyg. Vissa kanske bara stöder anpassade inbyggda verktyg, utan att anroparen kan tillhandahålla sina egna funktioner. Det här steget använder en ChatClientAgent, som stöder funktionsverktyg.
Förutsättningar
Förutsättningar och installation av NuGet-paket finns i steget Skapa och kör en enkel agent i den här självstudien.
Skapa agenten med funktionsverktyg
Funktionsverktyg är bara anpassad kod som du vill att agenten ska kunna anropa när det behövs.
Du kan omvandla valfri C#-metod till ett funktionsverktyg genom att använda AIFunctionFactory.Create metoden för att skapa en AIFunction instans från metoden.
Om du behöver ange ytterligare beskrivningar om funktionen eller dess parametrar för agenten, så att den kan välja mellan olika funktioner mer exakt, kan du använda System.ComponentModel.DescriptionAttribute attributet för metoden och dess parametrar.
Här är ett exempel på ett enkelt funktionsverktyg som förfalskar att få vädret för en viss plats. Den är dekorerad med beskrivningsattribut för att ge ytterligare beskrivningar om sig själv och sin platsparameter för agenten.
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.";
När du skapar agenten kan du nu tillhandahålla funktionsverktyget till agenten genom att skicka en lista med verktyg till AsAIAgent metoden.
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)]);
Varning
DefaultAzureCredential är praktiskt för utveckling men kräver noggrant övervägande i produktion. I produktion bör du överväga att använda en specifik autentiseringsuppgift (t.ex. ManagedIdentityCredential) för att undvika problem med svarstid, oavsiktlig avsökning av autentiseringsuppgifter och potentiella säkerhetsrisker från reservmekanismer.
Nu kan du bara köra agenten som vanligt, så kan agenten anropa GetWeather funktionsverktyget när det behövs.
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?"));
Tips/Råd
Se .NET-exemplen för fullständiga körbara exempel.
Viktigt!
Alla agenttyper stöder inte funktionsverktyg. Vissa kanske bara stöder anpassade inbyggda verktyg, utan att anroparen kan tillhandahålla sina egna funktioner. I det här steget används agenter som skapats via chattklienter, som stöder funktionsverktyg.
Förutsättningar
Förutsättningar och installation av Python-paket finns i steget Skapa och kör en enkel agent i den här självstudien.
Skapa agenten med funktionsverktyg
Funktionsverktyg är bara anpassad kod som du vill att agenten ska kunna anropa när det behövs.
Du kan omvandla valfri Python-funktion till ett funktionsverktyg genom att skicka den till agentens tools parameter när du skapar agenten.
Om du behöver ange ytterligare beskrivningar om funktionen eller dess parametrar för agenten, så att den kan välja mellan olika funktioner mer exakt, kan du använda Pythons typanteckningar med Annotated och Pydantics Field för att ange beskrivningar.
Här är ett exempel på ett enkelt funktionsverktyg som förfalskar att få vädret för en viss plats. Den använder typanteckningar för att ge ytterligare beskrivningar om funktionen och dess platsparameter till agenten.
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."
Du kan också använda dekoratören @tool för att uttryckligen ange funktionens namn och beskrivning:
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."
Om du inte anger parametrarna name och description i dekoratören @tool använder ramverket automatiskt funktionens namn och dokumentsträng som återställningar.
Använda explicita scheman med @tool
När du behöver fullständig kontroll över det schema som exponeras för modellen skickar du parametern schema till @tool.
Du kan ange antingen en pydantisk modell eller en rå JSON-schemaordlista.
# 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.",
Skicka endast körningskontext till ett verktyg
Använd normala funktionsparametrar för värden som modellen ska ange. Använd FunctionInvocationContext endast för körningsvärden, till exempel function_invocation_kwargs eller den aktuella sessionen. Den inmatade kontextparametern är dold från schemat som exponeras för modellen.
import asyncio
from typing import Annotated
from agent_framework import Agent, 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 = Agent(
client=OpenAIResponsesClient(),
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"},
Mer information om ctx.kwargs, ctx.sessionoch mellanprogram för funktioner finns i Körningskontext.
Skapa endast deklarationsverktyg
Om ett verktyg implementeras utanför ramverket (till exempel klientsidan i ett användargränssnitt) kan du deklarera det utan en implementering med .FunctionTool(..., func=None)
Modellen kan fortfarande resonera om och anropa verktyget, och ditt program kan ge resultatet senare.
# 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"},
När du skapar agenten kan du nu tillhandahålla funktionsverktyget till agenten genom att skicka det till parametern 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
)
Nu kan du bara köra agenten som vanligt, så kan agenten anropa get_weather funktionsverktyget när det behövs.
async def main():
result = await agent.run("What is the weather like in Amsterdam?")
print(result.text)
asyncio.run(main())
Skapa en klass med flera funktionsverktyg
När flera verktyg delar beroenden eller föränderligt tillstånd omsluter du dem i en klass och skickar bundna metoder till agenten. Använd klassattribut för värden som modellen inte ska tillhandahålla, till exempel tjänstklienter, funktionsflaggor eller cachelagrat tillstånd.
import asyncio
from typing import Annotated
from agent_framework import Agent, 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 = Agent(
client=OpenAIResponsesClient(),
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
Det här mönstret passar bra för långlivade verktygstillstånd. Använd FunctionInvocationContext i stället när värdet ändras per anrop.