(Kliknij powyższy obraz, aby obejrzeć wideo z tej lekcji)
Narzędzia są interesujące, ponieważ pozwalają agentom AI na posiadanie szerszego zakresu możliwości. Zamiast agenta mającego ograniczony zestaw działań, które może wykonać, dodanie narzędzia pozwala agentowi wykonywać szeroki zakres działań. W tym rozdziale przyjrzymy się wzorcowi projektowemu korzystania z narzędzi, który opisuje, jak agenci AI mogą używać konkretnych narzędzi do osiągania swoich celów.
W tej lekcji chcemy odpowiedzieć na następujące pytania:
Po ukończeniu tej lekcji będziesz potrafił:
Wzorzec projektowy korzystania z narzędzi koncentruje się na umożliwieniu LLM interakcji z zewnętrznymi narzędziami w celu osiągnięcia konkretnych celów. Narzędzia to kod, który może być wykonywany przez agenta, aby wykonać akcje. Narzędzie może być prostą funkcją, taką jak kalkulator, lub wywołaniem API do usługi zewnętrznej, np. wyszukiwanie cen akcji lub prognoza pogody. W kontekście agentów AI, narzędzia są projektowane tak, aby były wykonywane przez agentów jako odpowiedź na modelowo generowane wywołania funkcji.
Agenci AI mogą wykorzystywać narzędzia do wykonywania złożonych zadań, pozyskiwania informacji lub podejmowania decyzji. Wzorzec korzystania z narzędzi jest często stosowany w scenariuszach wymagających dynamicznej interakcji z zewnętrznymi systemami, takimi jak bazy danych, usługi internetowe czy interpretery kodu. Ta zdolność jest użyteczna w wielu różnych zastosowaniach, w tym:
Te bloki budulcowe pozwalają agentowi AI wykonywać szeroki zakres zadań. Przyjrzyjmy się kluczowym elementom potrzebnym do implementacji wzorca korzystania z narzędzi:
Schematy funkcji/narzędzi: Szczegółowe definicje dostępnych narzędzi, wraz z nazwą funkcji, celem, wymaganymi parametrami i oczekiwanymi wynikami. Schematy te pozwalają LLM zrozumieć, jakie narzędzia są dostępne i jak tworzyć poprawne wywołania.
Logika wykonywania funkcji: Określa, jak i kiedy narzędzia są wywoływane w oparciu o intencje użytkownika oraz kontekst konwersacji. Może obejmować moduły planowania, mechanizmy kierowania lub przepływy warunkowe, które dynamicznie decydują o użyciu narzędzi.
System obsługi wiadomości: Komponenty zarządzające przepływem konwersacyjnym między wejściami użytkownika, odpowiedziami LLM, wywołaniami narzędzi i ich wynikami.
Ramowy system integracji narzędzi: Infrastruktura łącząca agenta z różnymi narzędziami, czy to prostymi funkcjami, czy złożonymi usługami zewnętrznymi.
Obsługa błędów i walidacja: Mechanizmy radzenia sobie z błędami podczas wykonywania narzędzi, weryfikacji parametrów i zarządzania nieoczekiwanymi odpowiedziami.
Zarządzanie stanem: Śledzenie kontekstu rozmowy, poprzednich interakcji z narzędziami oraz danych trwałych, aby zapewnić spójność w wielokrotnych interakcjach.
Następnie przyjrzyjmy się szczegółowo wywoływaniu funkcji/narzędzi.
Wywoływanie funkcji jest głównym sposobem, w jaki umożliwiamy dużym modelom językowym (LLM) interakcję z narzędziami. Często zobaczysz użycie terminów ‘Funkcja’ i ‘Narzędzie’ zamiennie, ponieważ ‘funkcje’ (bloki wielokrotnego użytku kodu) są ‘narzędziami’, których agenci używają do wykonywania zadań. Aby kod funkcji mógł zostać wywołany, LLM musi porównać zapytanie użytkownika z opisem funkcji. W tym celu do LLM wysyłany jest schemat zawierający opisy wszystkich dostępnych funkcji. LLM wybiera następnie najbardziej odpowiednią funkcję do zadania i zwraca jej nazwę oraz argumenty. Wybrana funkcja jest wywoływana, jej odpowiedź jest przesyłana z powrotem do LLM, które wykorzystuje tę informację, by odpowiedzieć na zapytanie użytkownika.
Aby deweloperzy mogli zaimplementować wywoływanie funkcji dla agentów, potrzebne będą:
Użyjmy przykładu uzyskania aktualnego czasu w mieście, aby to zilustrować:
Zainicjuj LLM, który obsługuje wywoływanie funkcji:
Nie wszystkie modele obsługują wywoływanie funkcji, dlatego ważne jest, aby sprawdzić czy używany LLM to wspiera. Azure OpenAI obsługuje wywoływanie funkcji. Możemy zacząć od inicjacji klienta Azure OpenAI.
# Zainicjuj klienta Azure OpenAI
client = AzureOpenAI(
azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"),
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
api_version="2024-05-01-preview"
)
Utwórz schemat funkcji:
Następnie zdefiniujemy schemat JSON, który zawiera nazwę funkcji, opis tego, co funkcja robi, oraz nazwy i opisy parametrów funkcji. Następnie przekażemy ten schemat do wcześniej utworzonego klienta, wraz z zapytaniem użytkownika o czas w San Francisco. Ważne jest, aby zauważyć, że wywołanie narzędzia jest zwracane, nie końcowa odpowiedź na pytanie. Jak wspomniano wcześniej, LLM zwraca nazwę wybranej funkcji do zadania oraz argumenty, które zostaną do niej przekazane.
# Opis funkcji do odczytu przez model
tools = [
{
"type": "function",
"function": {
"name": "get_current_time",
"description": "Get the current time in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name, e.g. San Francisco",
},
},
"required": ["location"],
},
}
}
]
# Początkowa wiadomość użytkownika
messages = [{"role": "user", "content": "What's the current time in San Francisco"}]
# Pierwsze wywołanie API: Poproś model o użycie funkcji
response = client.chat.completions.create(
model=deployment_name,
messages=messages,
tools=tools,
tool_choice="auto",
)
# Przetwórz odpowiedź modelu
response_message = response.choices[0].message
messages.append(response_message)
print("Model's response:")
print(response_message)
Model's response:
ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_pOsKdUlqvdyttYB67MOj434b', function=Function(arguments='{"location":"San Francisco"}', name='get_current_time'), type='function')])
Kod funkcji potrzebny do wykonania zadania:
Gdy LLM wybrało, która funkcja ma zostać uruchomiona, kod wykonujący zadanie musi zostać zaimplementowany i wykonany. Możemy zaimplementować kod pobierający aktualny czas w Pythonie. Będziemy też musieli napisać kod do wydobycia nazwy i argumentów z response_message, aby uzyskać ostateczny wynik.
def get_current_time(location):
"""Get the current time for a given location"""
print(f"get_current_time called with location: {location}")
location_lower = location.lower()
for key, timezone in TIMEZONE_DATA.items():
if key in location_lower:
print(f"Timezone found for {key}")
current_time = datetime.now(ZoneInfo(timezone)).strftime("%I:%M %p")
return json.dumps({
"location": location,
"current_time": current_time
})
print(f"No timezone data found for {location_lower}")
return json.dumps({"location": location, "current_time": "unknown"})
# Obsługa wywołań funkcji
if response_message.tool_calls:
for tool_call in response_message.tool_calls:
if tool_call.function.name == "get_current_time":
function_args = json.loads(tool_call.function.arguments)
time_response = get_current_time(
location=function_args.get("location")
)
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": "get_current_time",
"content": time_response,
})
else:
print("No tool calls were made by the model.")
# Drugie wywołanie API: Pobierz ostateczną odpowiedź z modelu
final_response = client.chat.completions.create(
model=deployment_name,
messages=messages,
)
return final_response.choices[0].message.content
get_current_time called with location: San Francisco
Timezone found for san francisco
The current time in San Francisco is 09:24 AM.
Wywoływanie funkcji jest sercem większości, jeśli nie wszystkich projektów korzystania z narzędzi agentów, jednak implementacja od podstaw może być czasem wyzwaniem. Jak nauczyliśmy się w Lekcji 2, ramy agentowe zapewniają nam gotowe bloki budulcowe do implementacji korzystania z narzędzi.
Oto kilka przykładów, jak można implementować wzorzec projektowy korzystania z narzędzi, używając różnych ram agentowych:
Semantic Kernel to otwartoźródłowy framework AI dla programistów .NET, Python i Java pracujących z dużymi modelami językowymi (LLM). Upraszcza proces korzystania z wywoływania funkcji, automatycznie opisując twoje funkcje i ich parametry modelowi przez proces zwany serializacją. Obsługuje również komunikację dwukierunkową między modelem a twoim kodem. Kolejną zaletą używania frameworka agentowego, takiego jak Semantic Kernel, jest to, że daje dostęp do gotowych narzędzi, takich jak Wyszukiwanie plików oraz Interpreter kodu.
Poniższy diagram ilustruje proces wywoływania funkcji z Semantic Kernel:

W Semantic Kernel funkcje/narzędzia nazywane są wtyczkami (Plugins). Możemy przekonwertować funkcję get_current_time, którą widzieliśmy wcześniej, na wtyczkę poprzez przekształcenie jej w klasę z tą funkcją. Możemy także zaimportować dekorator kernel_function, który przyjmuje opis funkcji. Kiedy następnie tworzysz kernel z GetCurrentTimePlugin, kernel automatycznie zserializuje funkcję i jej parametry, tworząc schemat do wysłania do LLM.
from semantic_kernel.functions import kernel_function
class GetCurrentTimePlugin:
async def __init__(self, location):
self.location = location
@kernel_function(
description="Get the current time for a given location"
)
def get_current_time(location: str = ""):
...
from semantic_kernel import Kernel
# Utwórz jądro
kernel = Kernel()
# Utwórz wtyczkę
get_current_time_plugin = GetCurrentTimePlugin(location)
# Dodaj wtyczkę do jądra
kernel.add_plugin(get_current_time_plugin)
Azure AI Agent Service to nowszy framework agentowy zaprojektowany tak, aby umożliwić deweloperom bezpieczne tworzenie, wdrażanie i skalowanie wysokiej jakości, rozszerzalnych agentów AI bez konieczności zarządzania zapleczem obliczeniowym i przechowywaniem danych. Jest szczególnie przydatny dla zastosowań korporacyjnych, ponieważ jest w pełni zarządzaną usługą z zabezpieczeniami na poziomie korporacyjnym.
W porównaniu do bezpośredniej pracy z API LLM, Azure AI Agent Service oferuje kilka zalet, w tym:
Narzędzia dostępne w Azure AI Agent Service można podzielić na dwie kategorie:
Agent Service pozwala na używanie tych narzędzi razem jako zbiór narzędzi (toolset). Wykorzystuje także wątki (threads), które śledzą historię wiadomości z konkretnej rozmowy.
Wyobraź sobie, że jesteś agentem sprzedaży w firmie Contoso. Chcesz stworzyć agenta konwersacyjnego, który będzie odpowiadał na pytania dotyczące danych sprzedażowych.
Poniższy obraz ilustruje jak można użyć Azure AI Agent Service do analizy danych sprzedażowych:

Aby użyć któregokolwiek z tych narzędzi z usługą, możemy utworzyć klienta i zdefiniować narzędzie lub zbiór narzędzi. Aby praktycznie to zaimplementować, możemy użyć następującego kodu w Pythonie. LLM będzie mógł spojrzeć na toolset i zdecydować, czy użyć funkcji stworzonej przez użytkownika fetch_sales_data_using_sqlite_query, czy też wbudowanego Interpreter kodu, w zależności od zapytania użytkownika.
import os
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from fetch_sales_data_functions import fetch_sales_data_using_sqlite_query # funkcja fetch_sales_data_using_sqlite_query, którą można znaleźć w pliku fetch_sales_data_functions.py.
from azure.ai.projects.models import ToolSet, FunctionTool, CodeInterpreterTool
project_client = AIProjectClient.from_connection_string(
credential=DefaultAzureCredential(),
conn_str=os.environ["PROJECT_CONNECTION_STRING"],
)
# Inicjalizacja zestawu narzędzi
toolset = ToolSet()
# Inicjalizacja agenta wywołującego funkcje z funkcją fetch_sales_data_using_sqlite_query i dodanie go do zestawu narzędzi
fetch_data_function = FunctionTool(fetch_sales_data_using_sqlite_query)
toolset.add(fetch_data_function)
# Inicjalizacja narzędzia Code Interpreter i dodanie go do zestawu narzędzi.
code_interpreter = code_interpreter = CodeInterpreterTool()
toolset.add(code_interpreter)
agent = project_client.agents.create_agent(
model="gpt-4o-mini", name="my-agent", instructions="You are helpful agent",
toolset=toolset
)
Częstym problemem w przypadku dynamicznie generowanego przez LLM SQL jest bezpieczeństwo, a szczególnie ryzyko wstrzyknięcia SQL lub złośliwych działań, jak usunięcie lub manipulacja bazą danych. Chociaż te obawy są uzasadnione, można je skutecznie złagodzić odpowiednią konfiguracją uprawnień dostępu do bazy danych. W większości baz danych obejmuje to ustawienie bazy jako tylko do odczytu. Dla usług bazodanowych takich jak PostgreSQL czy Azure SQL, aplikacja powinna być przypisana do roli tylko do odczytu (SELECT). Uruchamianie aplikacji w bezpiecznym środowisku dodatkowo zwiększa ochronę. W scenariuszach korporacyjnych dane są zazwyczaj wyodrębniane i przekształcane z systemów operacyjnych do bazy danych tylko do odczytu lub hurtowni danych ze schematem przyjaznym dla użytkownika. Takie podejście zapewnia, że dane są bezpieczne, zoptymalizowane pod kątem wydajności i dostępności, a aplikacja ma ograniczony, tylko do odczytu dostęp.
Dołącz do Azure AI Foundry Discord, aby spotkać innych uczących się, uczestniczyć w godzinach konsultacji i uzyskać odpowiedzi na pytania dotyczące AI Agents.
Understanding Agentic Design Patterns
Zastrzeżenie:
Ten dokument został przetłumaczony przy użyciu usługi tłumaczeń AI Co-op Translator. Mimo że dążymy do jak największej dokładności, prosimy pamiętać, że tłumaczenia automatyczne mogą zawierać błędy lub nieścisłości. Oryginalny dokument w języku źródłowym należy traktować jako źródło ostateczne. W przypadku informacji krytycznych zaleca się skorzystanie z tłumaczenia wykonanego przez profesjonalnego tłumacza. Nie ponosimy odpowiedzialności za jakiekolwiek nieporozumienia lub błędne interpretacje wynikające z korzystania z tego tłumaczenia.