Wyjaśnienie agentów: narzędzia, prompty systemowe i pętla myśl-działanie
Przewodnik dla początkujących po tym, jak działają agenci AI: dlaczego modele do rozmów zapominają, jak opisywać narzędzia dla LLM, prompty systemowe, ReAct, agenci kodujące oraz obserwacje.
Współczesne agenty AI opierają się na niewielkiej liczbie podstawowych koncepcji: narzędziach, instrukcjach systemowych oraz cyklu powtarzających się działań polegających na myśleniu, działaniu i obserwowaniu. Gdy te elementy się połączą, większość frameworki dla agentów wygląda jak wariacje tego samego wzorca. Poniższe sekcje przedstawiają tę koncepcję od podstaw, zaczynając od tego, czym właściwie jest agent.
Czym jest agent
Agent to system, w którym model AI pracuje ze swoim otoczeniem, aby wykonać określone zadanie. łączy on rozumowanie, planowanie oraz realizację działań, zazwyczaj za pomocą zewnętrznych narzędzi. Większość agentów jest sterowana przez model LLM, chociaż model łączący widzenie z językiem może pełnić tę samą funkcję.
Pliki w Twojej aplikacji do czatowania są tracane
Oto fakt, który zaskakuje wielu ludzi: podczas rozmowy z ChatGPT lub podobnym asystentem wewnątrz modelu nie ma żadnej konwersacji. Nie przechowuje on niczego, nie śledzi żadnego bieżącego stanu i nie zachowuje żadnych informacji pomiędzy twoimi wiadomościami. Za każdym razem, gdy naciskasz przycisk wysłania, cała dotychczasowa wymiana zostaje połączona w jeden długi blok tekstu, a model czyta ten blok od początku.
Zobaczmy tę wymianę:
conversation = [
{"role": "user", "content": "I need help with my order"},
{"role": "assistant", "content": "Could you provide your order number?"},
{"role": "user", "content": "It's ORDER-123"},
]
Widzimy uporządkowaną listę kolejnych kroków z określonymi rolami, którą programiści przetwarzają w kodzie. Model jednak nigdy nie otrzymuje takiej listy. Zanim cokolwiek do niego dotrze, kolejne kroki są spłaszczane i łączone w jedną sekwencję tekstu, a jego jedynym zadaniem, jak zawsze, jest przewidzenie następnego tokena na podstawie wszystkiego, co przed nim znajduje się.
Nie istnieje żaden specjalny krok typu „zapamiętaj to”. Gdy model wydaje się przypominać numer zamówienia, nie chodzi o pamięć – numer po prostu nadal znajduje się w tekście, który model w danym momencie czyta.
Narzędzia
Narzędzie to funkcja, najlepiej o jednym jasnym celu, która jest przekazywana modelowi LLM. Typowe przykłady to:
- szukanie w internecie
- wytwarzanie obrazów
- odczytywanie dokumentów
- wzywanie API
Dobre narzędzie rozszerza możliwości modelu. Musi zawierać następujące elementy:
- tekstowy opis tego, co robi funkcja
Jak narzędzie jest faktycznie wywoływane
Kluczowym punktem jest to, że model językowy nie może bezpośrednio używać żadnego zewnętrznego narzędzia. Tekst trafia do niego i tekst jest z niego wyprowadzany, nic więcej. Stwierdzenie, że model „ma dostęp do narzędzi”, oznacza w rzeczywistości, że nauczył się zapisać wejście do narzędzia w formie tekstu. Gdy zapytamy o pogodę w Paryżu, model nie pobiera prognozy – zamiast tego wysyła ustrukturyzowaną wiadomość informującą, że należy uruchomić narzędzie do sprawdzania pogody.
Klasa agenta znajduje się pomiędzy użytkownikiem a modelem. Wykrywa tę wiadomość, uruchamia narzędzie, zbiera wynik i dodaje go do rozmowy, zanim odesła wszystko z powrotem do modelu. Dzięki temu dodatkowemu kontekstowi model może napisać normalną odpowiedź. Użytkownik ma wrażenie, jakby model bezpośrednio skontaktował się z usługą pogodową, podczas gdy to agent zajmował się całym koordynowaniem w tle.
Niewielki przykład
Dla ilustracji weźmy narzędzie kalkulatora, które robi tylko jedną rzecz – mnoży dwa liczby całkowite:
def multiply(a:int, b:int):
"Multiply two integers"
return a * b
Zmiana funkcji na narzędzie
Biblioteka Hugging Face transformers oferuje dekorator @tool, który otacza zwykłą funkcję w Pythonie, aby agent mógł ją zrozumieć. Najpierw należy dokonać importu:
from transformers import tool
Następnie funkcja z dekoracjami:
@tool
def multiply(a: int, b: int):
"""Multiply two integers."""
return a * b
Za kulisami dekorator zbiera metadane:
- nazwę funkcji
- jej opis
- nazwy argumentów
- typy argumentów
- typ zwracany
Ty metadane są później umieszczane w instrukcji, która mówi modelowi, jak poprawnie używać narzędzia.
Przyjrzenie się narzędziu
Po dekoracji narzędzie może opisać się samodzielnie w tekście:
print(multiply.to_string())
Wygenerowany wynik zawiera informacje w następującym stylu:
Tool Name: multiply
Description:
Multiply two integers.Arguments:
- a (int)
- b (int)
To ustrukturyzowane opis jest dokładnie tym, co agent pokazuje modelowi. LLM czyta je jak każdy inny tekst i decyduje, czy narzędzie pomoże w realizacji prośby użytkownika.
Przepływ pracy agenta
Agent działa w cyklu powtarzalnym: myśli (Thought), podejmuje działanie (Action), a następnie obserwuje (Observation).
- Thought. Część LLM agenta decyduje, co robić dalej.
- Action. Agent wywołuje narzędzia z wybranymi argumentami.
- Observation. Model bierze pod uwagę to, co zwróciło narzędzie.
Agent pozostaje w tym cyklu myślenia, działania i obserwacji, dopóki nie osiągnie swojego celu.
Wskazówka systemowa
Wskazówka systemowa to zbiór instrukcji przekazywanych modelowi przed każdą wiadomością użytkownika. Określa ona zachowanie, rolę, ograniczenia i cele całej rozmowy.
Gdy użytkownik coś pisze, model widzi coś więcej niż sam tekst. Zazwyczaj otrzymuje coś w takim kształcie:
<System Prompt>
You are a helpful programming assistant.
Always explain concepts before showing code.
If the user asks for unsafe code, refuse politely.
<User>
Explain binary search.
Polecenie systemowe ma wyższy priorytet niż polecenie użytkownika. Załóżmy, że mówi ono o konieczności zawsze odpowiadać po angielsku, a użytkownik prosi o odpowiedź po francusku. Model zazwyczaj będzie postępował zgodnie z poleceniem systemowym, chyba że aplikacja celowo pozwala na przełamanie tego priorytetu poprzez prośby użytkownika.
Polecenie systemowe agenta jest bardziej szczegółowe i opisuje narzędzia oraz sam cykl działania:
You are an AI assistant that can answer user questions.
You have access to the following tools:
Tool: search_web
Description:
Searches the web for up-to-date information.
Arguments:
- query (string)
Tool: calculator
Description:
Evaluates mathematical expressions.
Arguments:
- expression (string)
If a user's question requires current information, use search_web.
If a calculation is required, use calculator.
Otherwise, answer directly.
W tym komunikacie systemowym zdefiniowano trzy elementy:
- sposób, w jaki agent powinien się zachowywać
- narzędzia, których może używać, opisane w sposób pokazany w poprzednim rozdziale
- cykl Myślenie, Działanie, Obserwacja, wbudowany w instrukcje modelu
Każdy z tych trzech etapów wymaga bliższego przyjrzenia się.
Myśli
Myśli odzwierciedlają wewnętrzne rozumowanie i planowanie agenta podczas wykonywania zadania. Istnieją dwa powszechne style:
- chain-of-thought (CoT)
- ReAct (rozumowanie plus działanie)
Chain-of-thought to metoda sterowania, która skłania model do krok po kroku rozwiązywania problemu przed podjęciem ostatecznej odpowiedzi. Rozumowanie pozostaje wewnętrzne, co nadaje się do zadań logicznych i matematycznych, które nie wymagają żadnych zewnętrznych narzędzi.
ReAct to metoda, która również wymaga krok po kroku przemyśleń, ale łączy działania, takie jak wywołania narzędzi, pomiędzy poszczególnymi etapami rozumowania.
Oba podejścia umożliwiają modelowi LLM stopniowe rozwiązywanie problemów. Różnica polega na tym, że CoT opiera się wyłącznie na tym, co model już wie, natomiast ReAct łączy rozumowanie z działaniami. Dzięki temu model może korzystać z zewnętrznych narzędzi, zbierać nowe informacje i kierować swoje rozumowanie na podstawie tych wyników, co lepiej pasuje do dynamicznej pracy w rzeczywistym świecie, angażującej zewnętrzne systemy.
Działania: od myślenia do działania
Działania to kroki, które agent podejmuje w celu interakcji ze swoim otoczeniem. Pracownik obsługi klienta może na przykład pobrać dane klienta, zaproponować artykuły pomocowe lub przekazać sprawę człowiekowi.
Generator tekstu potrafi uruchomić rzeczywiste narzędzia za pomocą prostego wzorca zwanego stop and parse. Model sam w sobie nic nie wykonuje – tworzy uporządkowany wniosek opisujący to, co powinno się wydarzyć, a agent realizuje to za niego.
W rzeczywistości jest to ten sam cykl co wcześniej: model analizuje zadanie, wysyła odpowiednią akcję, na przykład żądanie do API pogodowego, po czym przestaje działać. Agent wykrywa tę akcję, uruchamia odpowiednie narzędzie i zwraca wynik jako obserwację. Na podstawie tej informacji model albo kontynuuje analizę, podejmuje kolejną akcję, albo udziela ostatecznej odpowiedzi.
Historcznie działania były wyrażane jako wywołania funkcji lub obiekty JSON określające narzędzie oraz jego argumenty. To działa, ale staje się nieporęczne, gdy proces wymaga wielu wywołań narzędzi. Agenty kodowe obierają inną drogę: zamiast opisywać działania w formacie JSON, model pisze wykonywalny kod w Pythonie. Pętle, warunki, zmienne oraz kilka wywołań narzędzi mogą wtedy dzielić jeden blok kodu, co jest bardziej wyraźne i efektywne przy złożonych zadaniach.
Klasyczna forma JSON wygląda tak:
{
"tool": "get_weather",
"arguments": {"location": "Tokyo"}
}
Agen kodu zamiast tego pisze wykonywalny fragment kodu:
# The agent writes actual Python code as its action
cities = ["Tokyo", "Paris", "New York", "London", "Sydney"]
temps = [get_weather(city) for city in cities]
avg_temp = sum(temps) / len(temps)
print(f"Average temperature: {avg_temp}")
Obserwacje: informacja zwrotna po każdej akcji
Rozumowanie i działanie to tylko połowa historii. Po podjęciu działań agent musi zrozumieć jego rezultat, i to właśnie pełni rolę obserwacja – informacja zwrotna otrzymana po wykonaniu akcji. Może to być wynik wyszukiwania w sieci, odpowiedź API, wyjście programu Pythona lub nawet komunikat błędu. Cokolwiek by to nie było, staje się nowymi informacjami pomocnymi przy wyborze następnego kroku.
Proces jest prosty. Agent generuje akcję, framework ją wykonuje, a wynik zostaje dodany do rozmowy jako obserwacja. LLM czyta zaktualizowany kontekst i kontynuuje pracę. Gdy ma wystarczająco dużo informacji, podaje ostateczną odpowiedź. W przeciwnym razie planuje kolejną akcję.
Obserwacje nie muszą kończyć się sukcesem. Gdy połączenie się nie udaje – z powodu błędu 404 Not Found z punktu końcowego lub błędu TypeError w kodzie napisanym w Pythonie – ten niepowodzenie nadal ma wartość. Komunikat o błędzie pokazuje agencie, co poszło nie tak, dzięki czemu jego następne działanie może skorygować sytuację zamiast powtarzać błąd.
To ciągłe cykliczne działanie sprawia, że agencje są adaptacyjne. Zamiast polegać wyłącznie na wiedzy wstępnie nauczonej, zbierają nowe fakty, uczą się na wynikach i doskonalą swoje podejście, aż zadanie zostanie wykonane.
Łączenie elementów
Agencje mogą wydawać się zupełnie nowym paradygmatem, ale powstają z połączenia kilku prostych idei. Model językowy analizuje problem, prompt systemu kształtuje jego zachowanie, narzędzia rozszerzają jego możliwości poza tekst, działania łączą go ze światem zewnętrznym, a obserwacje dostarczają informacji zwrotnej, dzięki czemu agencja może się dostosować.
Zrozumienie tych podstawowych elementów oraz zauważenie, jak mało „magii” kryje się w każdym z nich, to pierwszy krok do stworzenia własnych agentów. Asystenci programistyczni, kopiloty badawcze oraz autonomiczne procesy pracy opierają się wszystkie na tym samym cyklu Myślenie, Działanie, Obserwacja. Naturalnym następnym krokiem jest wdrożenie pierwszego agenta przy użyciu ekosystemu Hugging Face.