(Kliknij powyższy obraz, aby obejrzeć wideo z tej lekcji)
Narzędzia są interesujące, ponieważ pozwalają agentom AI na szerszy zakres możliwości. Zamiast ograniczonego zestawu działań, które agent może wykonać, dodanie narzędzia umożliwia agentowi wykonywanie wielu różnych zadań. W tym rozdziale przyjrzymy się wzorcowi projektowemu korzystania z narzędzi, który opisuje, jak agenci AI mogą używać konkretnych narzędzi do realizacji swoich celów.
W tej lekcji odpowiemy na następujące pytania:
Po ukończeniu tej lekcji będziesz potrafił:
Wzorzec projektowy korzystania z narzędzi koncentruje się na umożliwieniu modelom językowym (LLM) interakcji z zewnętrznymi narzędziami w celu osiągnięcia konkretnych celów. Narzędzia to fragmenty kodu, które agent może wykonać, aby wykonać określone działania. Narzędziem może być prosta funkcja, na przykład kalkulator, lub wywołanie API usługi zewnętrznej, takiej jak sprawdzanie cen akcji czy prognoza pogody. W kontekście agentów AI narzędzia są projektowane tak, aby mogły być wywoływane przez agentów w odpowiedzi na generowane przez model wywołania funkcji.
Agenci AI mogą wykorzystywać narzędzia do realizacji 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 systemami zewnętrznymi, takimi jak bazy danych, usługi internetowe czy interpretery kodu. Ta zdolność jest przydatna w wielu różnych zastosowaniach, w tym:
Te bloki konstrukcyjne pozwalają agentowi AI realizować 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, w tym nazwa funkcji, cel, wymagane parametry i oczekiwane wyniki. Schematy te pozwalają LLM zrozumieć, jakie narzędzia są dostępne i jak konstruować prawidłowe zapytania.
Logika wywoływania funkcji: Określa, jak i kiedy narzędzia są wywoływane na podstawie intencji użytkownika i kontekstu rozmowy. Może obejmować moduły planujące, mechanizmy routingu lub warunkowe przepływy decydujące o dynamicznym użyciu narzędzi.
System obsługi wiadomości: Komponenty zarządzające przepływem konwersacji 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, zarówno prostymi funkcjami, jak i złożonymi usługami zewnętrznymi.
Obsługa błędów i walidacja: Mechanizmy radzenia sobie z niepowodzeniami podczas wykonywania narzędzi, walidacji parametrów i zarządzania nieoczekiwanymi odpowiedziami.
Zarządzanie stanem: Śledzi kontekst rozmowy, wcześniejsze interakcje z narzędziami oraz dane trwałe, aby zapewnić spójność podczas wieloetapowych interakcji.
Przyjrzyjmy się teraz wywoływaniu funkcji/narzędzi bardziej szczegółowo.
Wywoływanie funkcji jest podstawowym sposobem, w jaki umożliwiamy dużym modelom językowym (LLM) interakcję z narzędziami. Często terminy „Funkcja” i „Narzędzie” są używane zamiennie, ponieważ „funkcje” (fragmenty 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 najbardziej odpowiednią funkcję do zadania i zwraca jej nazwę oraz argumenty. Następnie wywoływana jest wybrana funkcja, a jej odpowiedź jest przesyłana z powrotem do LLM, które wykorzystuje te informacje, aby odpowiedzieć na zapytanie użytkownika.
Aby deweloperzy mogli zaimplementować wywoływanie funkcji dla agentów, potrzebne są:
Posłużmy się przykładem pobrania aktualnego czasu w mieście:
Zainicjuj model LLM obsługujący wywoływanie funkcji:
Nie wszystkie modele obsługują wywoływanie funkcji, dlatego ważne jest, aby sprawdzić, czy używany model to umożliwia. Azure OpenAI obsługuje wywoływanie funkcji. Możemy zacząć od inicjalizacji klienta Azure OpenAI.
# Initialize the Azure OpenAI client
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 zawierający nazwę funkcji, opis jej działania 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 zwracane jest wywołanie narzędzia, a nie ostateczna odpowiedź na pytanie. Jak wspomniano wcześniej, LLM zwraca nazwę wybranej funkcji oraz argumenty, które do niej zostaną przekazane.
# Function description for the model to read
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"],
},
}
}
]
# Initial user message
messages = [{"role": "user", "content": "What's the current time in San Francisco"}]
# First API call: Ask the model to use the function
response = client.chat.completions.create(
model=deployment_name,
messages=messages,
tools=tools,
tool_choice="auto",
)
# Process the model's response
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:
Teraz, gdy LLM wybrał funkcję do uruchomienia, kod realizujący zadanie musi zostać zaimplementowany i wykonany. Możemy zaimplementować kod pobierający aktualny czas w Pythonie. Konieczne będzie również napisanie kodu do wyodrębnienia nazwy funkcji 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"})
# Handle function calls
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.")
# Second API call: Get the final response from the model
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, wzorców korzystania z narzędzi w agentach, jednak implementacja od podstaw może być czasem wyzwaniem. Jak dowiedzieliśmy się w Lekcji 2, frameworki agentowe dostarczają gotowe bloki konstrukcyjne do implementacji korzystania z narzędzi.
Oto kilka przykładów, jak można zaimplementować wzorzec korzystania z narzędzi, używając różnych frameworków agentowych:
Semantic Kernel to otwartoźródłowy framework AI dla programistów .NET, Pythona i Javy pracujących z dużymi modelami językowymi (LLM). Upraszcza proces wywoływania funkcji, automatycznie opisując Twoje funkcje i ich parametry modelowi poprzez proces zwany serializacją. Obsługuje również dwukierunkową komunikację między modelem a Twoim kodem. Kolejną zaletą korzystania z frameworka agentowego takiego jak Semantic Kernel jest możliwość dostępu do gotowych narzędzi, takich jak File Search i Code Interpreter.
Poniższy diagram ilustruje proces wywoływania funkcji z Semantic Kernel:
W Semantic Kernel funkcje/narzędzia nazywane są Pluginami. Możemy użyć dekoratora get_current_time
function we saw earlier into a plugin by turning it into a class with the function in it. We can also import the kernel_function
, który przyjmuje opis funkcji. Gdy następnie tworzysz kernel z GetCurrentTimePlugin, kernel automatycznie serializuje 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
# Create the kernel
kernel = Kernel()
# Create the plugin
get_current_time_plugin = GetCurrentTimePlugin(location)
# Add the plugin to the kernel
kernel.add_plugin(get_current_time_plugin)
Azure AI Agent Service to nowszy framework agentowy zaprojektowany, aby umożliwić deweloperom bezpieczne tworzenie, wdrażanie i skalowanie wysokiej jakości, rozszerzalnych agentów AI bez konieczności zarządzania zasobami obliczeniowymi i pamięciowymi. Jest szczególnie przydatny w zastosowaniach korporacyjnych, ponieważ jest w pełni zarządzaną usługą z bezpieczeństwem na poziomie przedsiębiorstwa.
W porównaniu z bezpośrednim korzystaniem 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 korzystanie z tych narzędzi razem jako toolset
. It also utilizes threads
which keep track of the history of messages from a particular conversation.
Imagine you are a sales agent at a company called Contoso. You want to develop a conversational agent that can answer questions about your sales data.
The following image illustrates how you could use Azure AI Agent Service to analyze your sales data:
To use any of these tools with the service we can create a client and define a tool or toolset. To implement this practically we can use the following Python code. The LLM will be able to look at the toolset and decide whether to use the user created function, fetch_sales_data_using_sqlite_query
, lub z gotowego Code Interpreter, w zależności od zapytania użytkownika.
import os
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from fecth_sales_data_functions import fetch_sales_data_using_sqlite_query # fetch_sales_data_using_sqlite_query function which can be found in a fetch_sales_data_functions.py file.
from azure.ai.projects.models import ToolSet, FunctionTool, CodeInterpreterTool
project_client = AIProjectClient.from_connection_string(
credential=DefaultAzureCredential(),
conn_str=os.environ["PROJECT_CONNECTION_STRING"],
)
# Initialize function calling agent with the fetch_sales_data_using_sqlite_query function and adding it to the toolset
fetch_data_function = FunctionTool(fetch_sales_data_using_sqlite_query)
toolset = ToolSet()
toolset.add(fetch_data_function)
# Initialize Code Interpreter tool and adding it to the toolset.
code_interpreter = code_interpreter = CodeInterpreterTool()
toolset = ToolSet()
toolset.add(code_interpreter)
agent = project_client.agents.create_agent(
model="gpt-4o-mini", name="my-agent", instructions="You are helpful agent",
toolset=toolset
)
Powszechnym problemem przy dynamicznie generowanym SQL przez LLM jest bezpieczeństwo, szczególnie ryzyko SQL injection lub działań złośliwych, takich jak usuwanie lub manipulowanie bazą danych. Chociaż te obawy są zasadne, można je skutecznie ograniczyć poprzez odpowiednią konfigurację uprawnień dostępu do bazy danych. W większości baz danych oznacza to skonfigurowanie bazy jako tylko do odczytu. W usługach bazodanowych takich jak PostgreSQL czy Azure SQL, aplikacji powinno się przypisać rolę tylko do odczytu (SELECT).
Uruchamianie aplikacji w bezpiecznym środowisku dodatkowo zwiększa ochronę. W scenariuszach korporacyjnych dane są zazwyczaj wydobywane i transformowane z systemów operacyjnych do bazy tylko do odczytu lub hurtowni danych z przyjaznym schematem. Takie podejście zapewnia bezpieczeństwo danych, optymalizację pod kątem wydajności i dostępności oraz ograniczony, tylko do odczytu dostęp aplikacji.
Zrozumienie wzorców projektowych agentów
Zastrzeżenie:
Niniejszy dokument został przetłumaczony za pomocą usługi tłumaczenia AI Co-op Translator. Chociaż dokładamy starań, aby tłumaczenie było jak najdokładniejsze, prosimy pamiętać, że automatyczne tłumaczenia mogą zawierać błędy lub nieścisłości. Oryginalny dokument w jego języku źródłowym należy uważać za źródło autorytatywne. W przypadku informacji krytycznych zalecane jest skorzystanie z profesjonalnego tłumaczenia wykonanego przez człowieka. Nie ponosimy odpowiedzialności za jakiekolwiek nieporozumienia lub błędne interpretacje wynikające z użycia tego tłumaczenia.