Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Ez az oktatóanyag lépés bemutatja, hogyan használhat függvényeszközöket egy ügynökkel, ahol az ügynök az Azure OpenAI Csevegés befejezése szolgáltatásra épül.
Fontos
Nem minden ügynöktípus támogatja a funkció eszközöket. Egyesek csak egyéni beépített eszközöket támogathatnak, és nem teszik lehetővé, hogy a hívó saját függvényeket adjon meg. Ez a lépés egy ChatClientAgent, amely támogatja a függvényeszközöket.
Előfeltételek
Az előfeltételekről és a NuGet-csomagok telepítéséről lásd az egyszerű ügynök létrehozása és futtatása lépést ebben az oktatóanyagban.
Az ügynök létrehozása funkcióeszközökkel
A funkcióeszközök olyan egyéni kódok, amelyeket az ügynök szükség esetén meghívhat.
Bármely C#-metódust függvényeszközsé alakíthat, ha a AIFunctionFactory.Create metódus használatával létrehoz egy példányt AIFunction a metódusból.
Ha további leírásokat kell adnia a függvényről vagy annak paramétereiről az ügynöknek, hogy pontosabban tudjon választani a különböző függvények között, használhatja az System.ComponentModel.DescriptionAttribute attribútumot a metóduson és annak paraméterein.
Íme egy példa egy egyszerű függvényeszközre, amely meghamisít egy adott hely időjárását. Leírási attribútumokkal van díszítve, hogy további leírásokat adjon magáról és helyparaméteréről az ügynöknek.
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.";
Az ügynök létrehozásakor mostantól a függvényeszközt is átadhatja az ügynöknek, ha átadja az eszközök listáját a AsAIAgent metódusnak.
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)]);
Figyelmeztetés
DefaultAzureCredential a fejlesztéshez kényelmes, de a termelési környezetben gondos megfontolást igényel. Éles környezetben fontolja meg egy adott hitelesítő adat (pl. ManagedIdentityCredential) használatát a késési problémák elkerülése, a hitelesítő adatok nem szándékos próbálgatásának és a tartalék mechanizmusokból eredő esetleges biztonsági kockázatok elkerülése érdekében.
Most már csak a szokásos módon futtathatja az ügynököt, és szükség esetén az ügynök meghívhatja a GetWeather függvényeszközt.
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?"));
Jótanács
A teljes futtatható példákért tekintse meg a .NET-mintákat .
Fontos
Nem minden ügynöktípus támogatja a funkció eszközöket. Egyesek csak egyéni beépített eszközöket támogathatnak, és nem teszik lehetővé, hogy a hívó saját függvényeket adjon meg. Ez a lépés a chat ügyfeleken keresztül létrehozott ügynököket használja, amelyek támogatják a funkcióeszközöket.
Előfeltételek
Az előfeltételekről és a Python-csomagok telepítéséről lásd a Hozzon létre és futtasson egy egyszerű ügynököt lépést ebben az oktatóanyagban.
Az ügynök létrehozása funkcióeszközökkel
A funkcióeszközök olyan egyéni kódok, amelyeket az ügynök szükség esetén meghívhat.
Bármely Python-függvényt függvényeszközzé alakíthat, ha az ügynök tools paraméterének adja meg az ügynök létrehozásakor.
Ha további leírásokat kell adnia a függvényről vagy annak paramétereiről az ügynöknek, hogy pontosabban tudjon választani a különböző függvények között, a Python típusjegyzeteivel Annotated és Pydantic-jával Field leírásokat adhat meg.
Íme egy példa egy egyszerű függvényeszközre, amely meghamisít egy adott hely időjárását. Típusjegyzetekkel további leírásokat ad meg a függvényről és a helyparaméterről az ügynök számára.
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."
A @tool dekorátor segítségével egyértelműen megadhatja a függvény nevét és leírását.
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."
Ha nem adja meg a name és description paramétereket a @tool dekorátorban, a keretrendszer automatikusan a függvény nevét és a doksorját használja tartalékként.
Kifejezett sémák használata @tool
Amikor teljes mértékben kézben akarja tartani a modell számára megadott sémát, adja át a schema paramétert a @tool számára.
Pydantic-modellt vagy nyers JSON-sémaszótárat is megadhat.
# 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.",
Csak futásidejű környezet átadása egy eszköznek
Használjon normál függvényparamétereket a modell által megadott értékekhez. Csak futásidejű értékekhez használható FunctionInvocationContext , például function_invocation_kwargs az aktuális munkamenethez. Az injektált környezeti paraméter el van rejtve a modell számára közzétett séma elől.
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"},
A ctx.kwargsctx.session és a függvény köztes szoftverről további információt a Futtatókörnyezet című témakörben talál.
Csak deklarációs eszközök létrehozása
Ha egy eszköz a keretrendszeren kívül van megvalósítva (például ügyféloldali a felhasználói felületen), deklarálhatja implementáció nélkül a FunctionTool(..., func=None) segítségével.
A modell továbbra is tud érvelni és meghívni az eszközt, és az alkalmazás később is meg tudja adni az eredményt.
# 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"},
Az ügynök létrehozásakor most már megadhatja a függvényeszközt az ügynöknek, ha átadja azt a tools paraméternek.
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
)
Most már csak a szokásos módon futtathatja az ügynököt, és szükség esetén az ügynök meghívhatja a get_weather függvényeszközt.
async def main():
result = await agent.run("What is the weather like in Amsterdam?")
print(result.text)
asyncio.run(main())
Osztály létrehozása több függvényeszközzel
Ha több eszköz osztozik függőségeken vagy megváltoztatható állapoton, csomagolja őket egy osztályba, és adja át a kapcsolt metódusokat az ügynök számára. Használjon osztályattribútumokat olyan értékekhez, amelyeket a modell nem adhat meg, például szolgáltatásügyfeleket, funkciójelölőket vagy gyorsítótárazott állapotot.
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
Ez a minta jól illeszkedik a hosszú élettartamú eszközállapothoz. Használja FunctionInvocationContext inkább, ha az érték hívásonként változik.