Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Langkah tutorial ini menunjukkan kepada Anda cara menggunakan alat fungsi dengan agen, yang didasarkan pada layanan Penyelesaian Obrolan Azure OpenAI.
Penting
Tidak semua jenis agen mendukung alat fitur. Beberapa mungkin hanya mendukung alat bawaan kustom, tanpa mengizinkan pemanggil untuk menyediakan fungsi mereka sendiri. Langkah ini menggunakan ChatClientAgent, yang mendukung alat fungsi.
Prasyarat
Untuk prasyarat dan menginstal paket NuGet, lihat langkah Membuat dan menjalankan agen sederhana dalam tutorial ini.
Membuat agen dengan alat fungsi
Alat fungsi hanyalah kode kustom yang Anda inginkan agar agen dapat memanggil saat diperlukan.
Anda dapat mengubah metode C# apa pun menjadi alat fungsi, dengan menggunakan AIFunctionFactory.Create metode untuk membuat AIFunction instans dari metode .
Jika Anda perlu memberikan deskripsi tambahan tentang fungsi atau parameternya ke agen, sehingga dapat lebih akurat memilih antara fungsi yang berbeda, Anda dapat menggunakan System.ComponentModel.DescriptionAttribute atribut pada metode dan parameternya.
Berikut adalah contoh perangkat fungsi sederhana yang mensimulasikan pengambilan cuaca untuk lokasi tertentu. Ini dihiasi dengan atribut deskripsi untuk memberikan deskripsi tambahan tentang dirinya sendiri dan parameter lokasinya kepada agen.
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.";
Saat membuat agen, Anda sekarang dapat menyediakan alat kepada agen dengan meneruskan daftar alat ke metode 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)]);
Peringatan
DefaultAzureCredential nyaman untuk pengembangan tetapi membutuhkan pertimbangan yang cermat dalam produksi. Dalam produksi, pertimbangkan untuk menggunakan kredensial tertentu (misalnya, ManagedIdentityCredential) untuk menghindari masalah latensi, pemeriksaan kredensial yang tidak diinginkan, dan potensi risiko keamanan dari mekanisme fallback.
Sekarang Anda hanya dapat menjalankan agen seperti biasa, dan agen akan dapat memanggil GetWeather alat fungsi ketika diperlukan.
Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?"));
Petunjuk / Saran
Lihat sampel .NET untuk contoh lengkap yang dapat dijalankan.
Penting
Tidak semua jenis agen mendukung alat fitur. Beberapa mungkin hanya mendukung alat bawaan kustom, tanpa mengizinkan pemanggil untuk menyediakan fungsi mereka sendiri. Langkah ini menggunakan agen yang dibuat melalui klien obrolan, yang memang mendukung alat fungsional.
Prasyarat
Untuk prasyarat dan menginstal paket Python, lihat langkah Membuat dan menjalankan agen sederhana dalam tutorial ini.
Membuat agen dengan alat fungsi
Alat fungsi hanyalah kode kustom yang Anda inginkan agar agen dapat memanggil saat diperlukan.
Anda dapat mengubah fungsi Python apa pun menjadi alat fungsi dengan meneruskannya ke parameter agen tools saat membuat agen.
Jika Anda perlu memberikan deskripsi tambahan tentang fungsi atau parameternya ke agen, sehingga dapat memilih lebih akurat antara fungsi yang berbeda, Anda dapat menggunakan anotasi jenis Python dengan Annotated dan Pydantic Field untuk memberikan deskripsi.
Berikut adalah contoh perangkat fungsi sederhana yang mensimulasikan pengambilan cuaca untuk lokasi tertentu. Ini menggunakan anotasi jenis untuk memberikan deskripsi tambahan tentang fungsi dan parameter lokasinya kepada agen.
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."
Anda juga dapat menggunakan @tool dekorator untuk secara eksplisit menentukan nama dan deskripsi fungsi:
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."
Jika Anda tidak menentukan parameter name dan description di dekorasi @tool, kerangka kerja akan secara otomatis menggunakan nama fungsi dan docstring sebagai alternatif.
Menggunakan skema eksplisit dengan @tool
Ketika Anda memerlukan kontrol penuh atas skema yang terekspos ke model, teruskan schema parameter ke @tool.
Anda dapat menyediakan model Pydantic atau kamus skema JSON mentah.
# 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."""
Meneruskan konteks runtime saja ke alat
Gunakan parameter fungsi normal untuk nilai yang harus disediakan model. Gunakan FunctionInvocationContext untuk nilai khusus runtime seperti function_invocation_kwargs atau sesi saat ini. Parameter konteks yang disuntikkan disembunyikan dari skema yang terekspos ke model.
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}")
Untuk detail selengkapnya tentang ctx.kwargs, ctx.session, dan middleware fungsi, lihat Konteks Runtime.
Membuat alat khusus deklarasi
Jika alat diimplementasikan di luar kerangka kerja (misalnya, sisi klien dalam UI), Anda dapat mendeklarasikannya tanpa implementasi menggunakan FunctionTool(..., func=None).
Model masih dapat beralasan tentang dan memanggil alat, dan aplikasi Anda dapat memberikan hasilnya nanti.
# 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"],
},
)
Saat membuat agen, Anda sekarang dapat menyediakan fungsi alat ke agen, dengan meneruskannya ke parameter 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
)
Sekarang Anda hanya dapat menjalankan agen seperti biasa, dan agen akan dapat memanggil get_weather alat fungsi ketika diperlukan.
async def main():
result = await agent.run("What is the weather like in Amsterdam?")
print(result.text)
asyncio.run(main())
Membuat kelas dengan beberapa alat fungsi
Saat beberapa alat berbagi dependensi atau status yang dapat diubah, membungkusnya dalam sebuah kelas dan berikan metode yang terikat ke agen. Gunakan atribut kelas untuk nilai yang tidak boleh disediakan model, seperti klien layanan, bendera fitur, atau status cache.
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
Pola ini cocok untuk status operasional alat yang berumur panjang. Gunakan FunctionInvocationContext sebagai gantinya saat nilai berubah per pemanggilan.
Alat fungsi
Function tools memungkinkan agen memanggil fungsi Go kustom. Paket ini functool menyediakan cara sederhana untuk menentukan alat jenis aman dengan pembuatan skema otomatis.
Menentukan alat fungsi
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
})
Tanda tangan fungsi menentukan skema input alat. Parameter context.Context disuntikkan oleh kerangka kerja dan tidak terekspos ke model.
Jenis input terstruktur
Untuk alat dengan beberapa parameter, tentukan struktur:
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
})
Membuat agen dengan alat
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()
Gunakan agen sebagai alat fungsi
Setiap agen dapat dibungkus sebagai alat fungsi untuk digunakan oleh agen lain:
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{})},
},
})
Menggunakan alat shell lokal
Go SDK mencakup tool/shelltool untuk eksekusi shell lokal. Alat ini memerlukan persetujuan secara default dan dapat dipasangkan dengan penyedia konteks lingkungan sehingga model mengetahui keluarga shell saat ini, direktori kerja, dan versi alat umum.
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},
},
})
Gunakan shelltool.ModeStateless saat setiap panggilan harus berjalan di shell baru. Gunakan shelltool.ModePersistent hanya jika satu sesi agen memerlukan status shell, misalnya direktori yang telah diubah atau variabel lingkungan yang telah diekspor, agar tetap dipertahankan di seluruh pemanggilan. Atur AcknowledgeUnsafe: true hanya saat Anda memberikan batas isolasi independen dan tidak memerlukan gerbang persetujuan bawaan.
Petunjuk / Saran
Lihat sampel alat fungsi, agen sebagai sampel alat, dan shell dengan sampel lingkungan untuk contoh lengkap.
Langkah selanjutnya
Mengontrol ketersediaan alat saat runtime
Anda dapat menambahkan atau menghapus alat selama proses eksekusi agen menggunakan FunctionInvocationContext.add_tools() / remove_tools(), mengontrol panggilan melalui middleware fungsi, atau memaksa panggilan pertama tertentu dengan tool_choice. Lihat Mengontrol ketersediaan alat untuk pola lengkap.