Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
На этом шаге руководства показано, как использовать инструменты функций с агентом, который работает на базе службы завершения чата Azure OpenAI.
Это важно
Не все типы агентов поддерживают средства функций. Некоторые могут поддерживать только пользовательские встроенные средства, не позволяя вызывающему предоставлять свои собственные функции. На этом шаге используется ChatClientAgent, который поддерживает инструменты функций.
Предпосылки
Предварительные требования и установка пакетов NuGet см. в разделе "Создание и запуск простого агента " в этом руководстве.
Создание агента с помощью средств функций
Средства функций — это просто пользовательский код, который нужно, чтобы агент мог вызывать при необходимости.
Вы можете превратить любой метод C# в инструмент функции, используя AIFunctionFactory.Create метод для создания AIFunction экземпляра из метода.
Если вам нужно предоставить дополнительные описания функции или его параметров агенту, чтобы он был более точно выбирать между разными функциями, можно использовать System.ComponentModel.DescriptionAttribute атрибут в методе и его параметрах.
Вот пример простой функции, которая имитирует получение данных о погоде для указанного местоположения. Он снабжен атрибутами описания для предоставления дополнительных сведений о себе и его параметре расположения агенту.
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.";
При создании агента теперь можно предоставить агенту функциональное средство, передав список инструментов в метод 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)]);
Предупреждение
DefaultAzureCredential удобно для разработки, но требует тщательного рассмотрения в рабочей среде. В рабочей среде рекомендуется использовать определенные учетные данные (например, ManagedIdentityCredential), чтобы избежать проблем с задержкой, непреднамеренной проверки данных аутентификации и потенциальных рисков безопасности из-за резервных механизмов.
Теперь вы можете просто запустить агент как обычно, и агент сможет вызывать инструмент функции GetWeather при необходимости.
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?"));
Подсказка
Полные примеры запуска см. в примерах .NET .
Это важно
Не все типы агентов поддерживают средства функций. Некоторые могут поддерживать только пользовательские встроенные средства, не позволяя вызывающему предоставлять свои собственные функции. На этом шаге используются агенты, созданные с помощью клиентов чата, которые поддерживают функциональные инструменты.
Предпосылки
Для предварительных требований и установки пакетов Python см. шаг Создание и запуск простого агента в этом учебном пособии.
Создание агента с помощью средств функций
Средства функций — это просто пользовательский код, который нужно, чтобы агент мог вызывать при необходимости.
Вы можете превратить любую функцию Python в средство-функцию, передав его параметру агента tools при создании агента.
Если вам нужно указать дополнительные описания функции или её параметров агенту, чтобы он мог более точно выбирать между разными функциями, можно использовать аннотации типов Python с Annotated и возможности Pydantic Field для предоставления описаний.
Вот пример простой функции, которая имитирует получение данных о погоде для указанного местоположения. В нем используются аннотации типов для предоставления дополнительных описаний об функции и ее параметре "расположение" агенту.
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."
Вы также можете использовать @tool декоратор для явного указания имени и описания функции:
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."
Если в декораторе не указаны параметры name и description, фреймворк автоматически будет использовать имя функции и docstring в качестве резервных вариантов.
Использование явных схем с @tool
Если вам нужен полный контроль над схемой, предоставляемой модели, передайте параметр schema в @tool.
Вы можете указать модель Pydantic или необработанный словарь схемы 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.",
Передача контекста, доступного только во время выполнения, в инструмент
Используйте обычные параметры функции для значений, которые должна предоставлять модель. Используется FunctionInvocationContext только для значений среды выполнения, таких как function_invocation_kwargs или текущий сеанс. Внедренный параметр контекста скрыт от схемы, предоставляемой модели.
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"},
Дополнительные сведения о ctx.kwargs, ctx.session и промежуточных слоях функций см. в разделе "Контекст среды выполнения".
Создание инструментов, предназначенных исключительно для деклараций
Если средство реализуется за пределами фреймворка (например, на стороне клиента в пользовательском интерфейсе), его можно объявить без реализации, используя FunctionTool(..., func=None).
Модель по-прежнему может анализировать и вызвать инструмент, а приложение может предоставить результат позже.
# 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"},
При создании агента теперь можно предоставить ему функциональный инструмент, передав его в параметр 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
)
Теперь вы можете просто запустить агент как обычно, и агент сможет вызывать инструмент функции get_weather при необходимости.
async def main():
result = await agent.run("What is the weather like in Amsterdam?")
print(result.text)
asyncio.run(main())
Создание класса с несколькими инструментами функций
Если несколько инструментов совместно используют зависимости или изменяемое состояние, заключите их в класс и передайте привязанные методы агенту. Используйте атрибуты класса для значений, которые модель не должна предоставлять, например клиенты службы, флаги компонентов или кэшированное состояние.
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
Этот шаблон хорошо подходит для длительного состояния инструмента. Используйте FunctionInvocationContext вместо, когда значение изменяется при каждом вызове.