Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Narzędzia zaplecza używają normalnego potoku narzędzia MAF. AG-UI dodaje zdarzenia transportu, aby klient mógł obserwować wywołanie i wynik; nie wprowadza oddzielnej abstrakcji narzędzi.
Dodawanie narzędzia zaplecza
Zdefiniuj i zarejestruj narzędzie tak, jak w przypadku dowolnego agenta MAF:
using System.ComponentModel;
using Microsoft.Extensions.AI;
[Description("Get the weather for a location.")]
static string GetWeather(
[Description("The city to look up.")] string location) =>
$"The weather in {location} is sunny.";
AITool getWeather = AIFunctionFactory.Create(GetWeather, name: "get_weather");
AIAgent agent = chatClient.AsAIAgent(tools: [getWeather]);
app.MapAGUIServer("/", agent);
W przypadku złożonych typów żądań lub odpowiedzi skonfiguruj to samo JsonSerializerOptions dla ASP.NET Core i AIFunctionFactory.Create.
Wskazówka
Zobacz przykładowe narzędzia zaplecza .NET, aby uzyskać pełną implementację.
Aby zapoznać się ze schematami narzędzi, wstrzyknięciem zależności, obsługą błędów i ogólnym projektem narzędzi, zobacz Używanie narzędzi funkcji z agentem.
mapowanie zdarzeń AG-UI
Gdy agent wywołuje narzędzie:
-
FunctionCallContentjest emitowany jako AG-UITOOL_CALL_START,TOOL_CALL_ARGSiTOOL_CALL_ENDzdarzenia. -
FunctionResultContentjest emitowany jakoTOOL_CALL_RESULTzdarzenie. - Tekst i inna zawartość agenta nadal przesyłają strumieniowo normalnie.
Klient .NET otrzymuje przetłumaczoną zawartość jako FunctionCallContent i FunctionResultContent:
await foreach (AgentResponseUpdate update in agent.RunStreamingAsync(messages, session))
{
foreach (AIContent content in update.Contents)
{
if (content is FunctionCallContent call)
{
Console.WriteLine($"Calling {call.Name}");
}
else if (content is FunctionResultContent result)
{
Console.WriteLine($"Result: {result.Result}");
}
}
}
Wyniki narzędzia to wartości oparte na modelu, które AG-UI również uwidaczniają klienta. Aby emitować stan udostępnionego interfejsu użytkownika oprócz wyniku narzędzia, użyj jawnych mapowań opisanych w temacie Zarządzanie stanem.
Następne kroki
W tym samouczku pokazano, jak dodać narzędzia funkcjonalne do agentów AG-UI. Narzędzia funkcji to niestandardowe funkcje języka Python, które agent może wywoływać w celu wykonywania określonych zadań, takich jak pobieranie danych, wykonywanie obliczeń lub interakcja z systemami zewnętrznymi. Dzięki AG-UI te narzędzia są wykonywane po stronie serwera, a ich wyniki są automatycznie streamowane do klienta.
Wymagania wstępne
Przed rozpoczęciem upewnij się, że ukończyłeś samouczek Wprowadzenie i posiadasz:
- Python 3.10 lub nowszy
-
agent-framework-ag-uiZainstalowano - Skonfigurowano usługę Azure OpenAI
- Podstawowa wiedza na temat konfiguracji serwera AG-UI i klienta
Note
Przykłady te używają DefaultAzureCredential do uwierzytelniania. Upewnij się, że uwierzytelniasz się przy użyciu platformy Azure (np. za pośrednictwem polecenia az login). Aby uzyskać więcej informacji, zobacz dokumentację usługi Azure Identity.
Co to jest renderowanie narzędzi zaplecza?
Renderowanie narzędzi zaplecza oznacza:
- Narzędzia funkcji są definiowane na serwerze
- Agent sztucznej inteligencji decyduje, kiedy wywołać te narzędzia
- Narzędzia są wykonywane na zapleczu (po stronie serwera)
- Zdarzenia wywołań narzędzi i wyniki są przesyłane strumieniowo do klienta w czasie rzeczywistym
- Klient otrzymuje aktualizacje dotyczące postępu wykonywania narzędzia
Takie podejście zapewnia:
- Zabezpieczenia: Poufne operacje pozostają na serwerze
- Spójność: wszyscy klienci używają tych samych implementacji narzędzi
- Przezroczystość: klienci mogą wyświetlać postęp wykonywania narzędzi
- Elastyczność: Aktualizowanie narzędzi bez zmieniania kodu klienta
Tworzenie narzędzi funkcji
Podstawowe narzędzie funkcji
Dowolną funkcję języka Python można przekształcić w narzędzie przy użyciu dekoratora @tool :
from typing import Annotated
from pydantic import Field
from agent_framework import tool
@tool
def get_weather(
location: Annotated[str, Field(description="The city")],
) -> str:
"""Get the current weather for a location."""
# In a real application, you would call a weather API
return f"The weather in {location} is sunny with a temperature of 22°C."
Kluczowe pojęcia
-
@tooldekorator: oznacza funkcję jako dostępną dla agenta - Adnotacje typów: podaj informacje o typie parametrów
-
AnnotatediField: Dodaj opisy, aby ułatwić agentowi zrozumienie parametrów - Docstring: opisuje działanie funkcji (pomaga agentowi zdecydować, kiedy go używać)
- Wartość zwracana: wynik zwrócony do agenta (i przesyłany strumieniowo do klienta)
Wielofunkcyjne narzędzia
Możesz udostępnić wiele narzędzi, aby zapewnić agentowi więcej możliwości:
from typing import Any
from agent_framework import tool
@tool
def get_weather(
location: Annotated[str, Field(description="The city.")],
) -> str:
"""Get the current weather for a location."""
return f"The weather in {location} is sunny with a temperature of 22°C."
@tool
def get_forecast(
location: Annotated[str, Field(description="The city.")],
days: Annotated[int, Field(description="Number of days to forecast")] = 3,
) -> dict[str, Any]:
"""Get the weather forecast for a location."""
return {
"location": location,
"days": days,
"forecast": [
{"day": 1, "weather": "Sunny", "high": 24, "low": 18},
{"day": 2, "weather": "Partly cloudy", "high": 22, "low": 17},
{"day": 3, "weather": "Rainy", "high": 19, "low": 15},
],
}
Tworzenie serwera AG-UI za pomocą narzędzi funkcyjnych
Oto kompletna implementacja serwera z narzędziami funkcji:
"""AG-UI server with backend tool rendering."""
import os
from typing import Annotated, Any
from agent_framework import Agent, tool
from agent_framework.openai import OpenAIChatCompletionClient
from agent_framework_ag_ui import add_agent_framework_fastapi_endpoint
from azure.identity import AzureCliCredential
from fastapi import FastAPI
from pydantic import Field
# Define function tools
@tool
def get_weather(
location: Annotated[str, Field(description="The city")],
) -> str:
"""Get the current weather for a location."""
# Simulated weather data
return f"The weather in {location} is sunny with a temperature of 22°C."
@tool
def search_restaurants(
location: Annotated[str, Field(description="The city to search in")],
cuisine: Annotated[str, Field(description="Type of cuisine")] = "any",
) -> dict[str, Any]:
"""Search for restaurants in a location."""
# Simulated restaurant data
return {
"location": location,
"cuisine": cuisine,
"results": [
{"name": "The Golden Fork", "rating": 4.5, "price": "$$"},
{"name": "Bella Italia", "rating": 4.2, "price": "$$$"},
{"name": "Spice Garden", "rating": 4.7, "price": "$$"},
],
}
# Read required configuration
endpoint = os.environ.get("AZURE_OPENAI_ENDPOINT")
deployment_name = os.environ.get("AZURE_OPENAI_CHAT_COMPLETION_MODEL")
if not endpoint:
raise ValueError("AZURE_OPENAI_ENDPOINT environment variable is required")
if not deployment_name:
raise ValueError("AZURE_OPENAI_CHAT_COMPLETION_MODEL environment variable is required")
chat_client = OpenAIChatCompletionClient(
model=deployment_name,
azure_endpoint=endpoint,
api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
credential=AzureCliCredential(),
)
# Create agent with tools
agent = Agent(
name="TravelAssistant",
instructions="You are a helpful travel assistant. Use the available tools to help users plan their trips.",
client=chat_client,
tools=[get_weather, search_restaurants],
)
# Create FastAPI app
app = FastAPI(title="AG-UI Travel Assistant")
add_agent_framework_fastapi_endpoint(app, agent, "/")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="127.0.0.1", port=8888)
Informacje o zdarzeniach narzędzi
Gdy agent wywołuje narzędzie, klient odbiera kilka zdarzeń:
Zdarzenia wywołania narzędzia
# 1. TOOL_CALL_START - Tool execution begins
{
"type": "TOOL_CALL_START",
"toolCallId": "call_abc123",
"toolCallName": "get_weather"
}
# 2. TOOL_CALL_ARGS - Tool arguments (may stream in chunks)
{
"type": "TOOL_CALL_ARGS",
"toolCallId": "call_abc123",
"delta": "{\"location\": \"Paris, France\"}"
}
# 3. TOOL_CALL_END - Arguments complete
{
"type": "TOOL_CALL_END",
"toolCallId": "call_abc123"
}
# 4. TOOL_CALL_RESULT - Tool execution result
{
"type": "TOOL_CALL_RESULT",
"toolCallId": "call_abc123",
"content": "The weather in Paris, France is sunny with a temperature of 22°C."
}
Ulepszony klient dla zdarzeń narzędzi
Oto ulepszony klient korzystający z AGUIChatClient, który wyświetla wykonanie narzędzia.
"""AG-UI client with tool event handling."""
import asyncio
import os
from agent_framework import Agent
from agent_framework_ag_ui import AGUIChatClient
async def main():
"""Main client loop with tool event display."""
server_url = os.environ.get("AGUI_SERVER_URL", "http://127.0.0.1:8888/")
print(f"Connecting to AG-UI server at: {server_url}\n")
# Create AG-UI chat client
chat_client = AGUIChatClient(endpoint=server_url)
# Create agent with the chat client
agent = Agent(
name="ClientAgent",
client=chat_client,
instructions="You are a helpful assistant.",
)
# Get a thread for conversation continuity
thread = agent.create_session()
try:
while True:
message = input("\nUser (:q or quit to exit): ")
if not message.strip():
continue
if message.lower() in (":q", "quit"):
break
print("\nAssistant: ", end="", flush=True)
async for update in agent.run(message, session=thread, stream=True):
# Display text content
if update.text:
print(f"\033[96m{update.text}\033[0m", end="", flush=True)
# Display tool calls and results
for content in update.contents:
if content.type == "function_call":
print(f"\n\033[95m[Calling tool: {content.name}]\033[0m")
elif content.type == "function_result":
result_text = content.result if isinstance(content.result, str) else str(content.result)
print(f"\033[94m[Tool result: {result_text}]\033[0m")
print("\n")
except KeyboardInterrupt:
print("\n\nExiting...")
except Exception as e:
print(f"\n\033[91mError: {e}\033[0m")
if __name__ == "__main__":
asyncio.run(main())
Przykładowa interakcja
Po uruchomieniu rozszerzonego serwera i klienta:
User (:q or quit to exit): What's the weather like in Paris and suggest some Italian restaurants?
[Run Started]
[Tool Call: get_weather]
[Tool Result: The weather in Paris, France is sunny with a temperature of 22°C.]
[Tool Call: search_restaurants]
[Tool Result: {"location": "Paris", "cuisine": "Italian", "results": [...]}]
Based on the current weather in Paris (sunny, 22°C) and your interest in Italian cuisine,
I'd recommend visiting Bella Italia, which has a 4.2 rating. The weather is perfect for
outdoor dining!
[Run Finished]
Najlepsze rozwiązania dotyczące implementacji narzędzi
Obsługa błędów
Obsługuj błędy płynnie w swoich narzędziach.
@tool
def get_weather(
location: Annotated[str, Field(description="The city.")],
) -> str:
"""Get the current weather for a location."""
try:
# Call weather API
result = call_weather_api(location)
return f"The weather in {location} is {result['condition']} with temperature {result['temp']}°C."
except Exception as e:
return f"Unable to retrieve weather for {location}. Error: {str(e)}"
Rozbudowane typy zwracane
Zwróć dane ustrukturyzowane, jeśli jest to konieczne:
@tool
def analyze_sentiment(
text: Annotated[str, Field(description="The text to analyze")],
) -> dict[str, Any]:
"""Analyze the sentiment of text."""
# Perform sentiment analysis
return {
"text": text,
"sentiment": "positive",
"confidence": 0.87,
"scores": {
"positive": 0.87,
"neutral": 0.10,
"negative": 0.03,
},
}
Dokumentacja opisowa
Podaj jasne opisy, aby ułatwić agentowi zrozumienie, kiedy należy używać narzędzi:
@tool
def book_flight(
origin: Annotated[str, Field(description="Departure city and airport code, e.g., 'New York, JFK'")],
destination: Annotated[str, Field(description="Arrival city and airport code, e.g., 'London, LHR'")],
date: Annotated[str, Field(description="Departure date in YYYY-MM-DD format")],
passengers: Annotated[int, Field(description="Number of passengers")] = 1,
) -> dict[str, Any]:
"""
Book a flight for specified passengers from origin to destination.
This tool should be used when the user wants to book or reserve airline tickets.
Do not use this for searching flights - use search_flights instead.
"""
# Implementation
pass
Organizacja narzędzi za pomocą klas
W przypadku powiązanych narzędzi organizuj je w klasie:
from agent_framework import tool
class WeatherTools:
"""Collection of weather-related tools."""
def __init__(self, api_key: str):
self.api_key = api_key
@tool
def get_current_weather(
self,
location: Annotated[str, Field(description="The city.")],
) -> str:
"""Get current weather for a location."""
# Use self.api_key to call API
return f"Current weather in {location}: Sunny, 22°C"
@tool
def get_forecast(
self,
location: Annotated[str, Field(description="The city.")],
days: Annotated[int, Field(description="Number of days")] = 3,
) -> dict[str, Any]:
"""Get weather forecast for a location."""
# Use self.api_key to call API
return {"location": location, "forecast": [...]}
# Create tools instance
weather_tools = WeatherTools(api_key="your-api-key")
# Create agent with class-based tools
agent = Agent(
name="WeatherAgent",
instructions="You are a weather assistant.",
client=OpenAIChatCompletionClient(...),
tools=[
weather_tools.get_current_weather,
weather_tools.get_forecast,
],
)
Dalsze kroki
Teraz, po zapoznaniu się z renderowaniem narzędzi zaplecza, możesz:
- Tworzenie narzędzi zaawansowanych: dowiedz się więcej o tworzeniu narzędzi funkcji za pomocą platformy Agent Framework
Dodatkowe zasoby
Serwery go AG-UI mogą uwidaczniać normalne narzędzia funkcji platformy Agent Framework. Utwórz narzędzia za pomocą tool/functoolpolecenia , dołącz je do hostowanego agenta i obsłuż agenta za pomocą polecenia aguiprovider.NewJSONHTTPHandler.
searchRestaurants := functool.MustNew(functool.Config{
Name: "search_restaurants",
Description: "Search for restaurants in a location.",
}, func(ctx context.Context, in restaurantSearchRequest) (restaurantSearchResponse, error) {
return restaurantSearchResponse{
Location: in.Location,
Cuisine: in.Cuisine,
Results: []restaurantInfo{{Name: "The Golden Fork", Cuisine: in.Cuisine}},
}, nil
})
a := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
Config: agent.Config{
Tools: []tool.Tool{searchRestaurants},
},
})
Wskazówka
Zobacz przykład narzędzi backendowych AG-UI, aby zobaczyć kompletny, działający przykład.