„Czy agent będzie pamiętał, co ustaliliśmy?” to pytanie, które pada na każdym warsztacie. Odpowiedź brzmi „zależy, co masz na myśli”, i nie jest to wykręt.
Pod słowem „pamięć” kryją się trzy zupełnie różne mechanizmy. Mają inne ograniczenia, inne koszty i, co najważniejsze, zupełnie inne konsekwencje prawne. Mylenie ich prowadzi do wdrożeń, w których zespół jest przekonany, że nic nie zapisuje, a system zapisuje.
Okno kontekstowe to limit techniczny modelu. Ile tokenów mieści się w jednej operacji: pytanie, załączniki, instrukcja i dotychczasowa rozmowa razem. Nic tu nie jest zapisywane. Po prostu wszystko powyżej limitu przestaje być widoczne.
Stan sesji to dane przekazywane między krokami w ramach jednego uruchomienia. W ADK to jest ten mechanizm, w którym agent zapisuje wynik pod output_key, a następny czyta go przez {klucz} w instrukcji. Żyje tyle, ile sesja.
Pamięć długoterminowa to osobny magazyn, przeżywający sesje. Agent może z niego czytać na początku kolejnej rozmowy i dopisywać do niego w trakcie.
| Okno kontekstowe | Stan sesji | Pamięć |
|---|
| Czym jest | Limit modelu | Przepływ danych w uruchomieniu | Trwały magazyn |
| Jak długo żyje | Jedna operacja | Jedna sesja | Do usunięcia |
| Kto tym steruje | Nikt, to ograniczenie | Twój kod | Twoja konfiguracja |
| Co się psuje | Gubi się początek rozmowy | Nic, jeśli klucze są rozłączne | Zapisuje się coś, czego nie chciałeś |
| Czy to dane osobowe | Nie | Przejściowo | Tak, jeśli zapisujesz o ludziach |
Ostatni wiersz jest powodem, dla którego warto to rozdzielać precyzyjnie. Pierwsze dwie warstwy to mechanika działania. Trzecia to zbiór danych z retencją, dostępem i obowiązkiem usunięcia.
Stan sesji poznałeś, jeśli budowałeś kiedykolwiek pipeline. Wynik jednego agenta trafia do stanu, kolejny go stamtąd czyta.
scout = LlmAgent(name="zwiadowca", output_key="raport")
strategist = LlmAgent(
name="strateg",
instruction="Na podstawie raportu: {raport} przygotuj plan.",
)
Pamięć długoterminowa jest osobną warstwą i podłącza się ją jako serwis. W ADK są trzy warianty:
InMemoryMemoryService, czyli wszystko w pamięci procesu. Do prototypów i testów; znika przy restarcie.
VertexAiMemoryBankService, czyli zarządzany magazyn pamięci w Google Cloud.
VertexAiRagMemoryService, czyli pamięć oparta o korpus RAG, gdy wspomnienia mają być przeszukiwane semantycznie.
Do tego jest narzędzie doładowujące istotne wspomnienia na początku tury, dzięki czemu agent nie musi sam decydować, kiedy sięgnąć do pamięci.
Uwaga na starsze materiały
Jeśli natrafisz gdzieś na from google.adk.sessions.memory import MemoryBank, to jest nieaktualne. Klasa o takiej nazwie nie istnieje w bieżącym pakiecie. Serwisy pamięci mieszkają w google.adk.memory i nazywają się tak, jak wyżej. Sam trzymałem w materiałach szkoleniowych tę starą wersję dłużej, niż powinienem.
Kiedy zespół dochodzi do wniosku, że agent powinien pamiętać, dyskusja przechodzi natychmiast do tego, jak to zrobić. Pomijane jest pytanie ważniejsze: co ma pamiętać.
Domyślna odpowiedź brzmi „wszystko, co może się przydać”. Jest zła z trzech powodów.
Pamięć się zanieczyszcza. Zapisana preferencja z marca może być nieaktualna w lipcu, a agent nie ma jak tego stwierdzić. Będzie ją stosował z pełnym przekonaniem. To jest ten sam problem, co dwie wersje procedury w bazie dokumentów, tylko trudniejszy do zauważenia, bo nikt nie ogląda zawartości pamięci.
Więcej wspomnień to gorsze odpowiedzi. Doładowane wspomnienia zajmują miejsce w oknie kontekstowym i konkurują z treścią bieżącego zadania. Badanie Chroma na 18 modelach pokazuje, że nawet pojedynczy fragment tematycznie bliski, ale nietrafiony, obniża jakość odpowiedzi. Pamięć jest fabryką takich fragmentów. Pisałem o tym w tekście o higienie kontekstu.
Zapisujesz dane, których nie planowałeś zapisywać. Rozmowa z asystentem zawiera więcej, niż wynika z jej tematu. Ktoś wspomni o chorobie, o sytuacji w zespole, o kliencie. Automatyczne zapamiętywanie „co może się przydać” tworzy zbiór, o którego istnieniu nikt w organizacji nie wie.
Pamiętaj fakty, nie przebieg rozmowy. „Użytkownik pracuje w zespole płatności” to fakt użyteczny przez miesiące. Zapis całej wymiany zdań to szum, który za tydzień będzie tylko przeszkadzał.
Zapisuj wprost, nie automatycznie. Wspomnienie powstaje wtedy, gdy Twój kod zdecyduje, że powstaje, na podstawie jasnej reguły. Zdanie w instrukcji typu „zapamiętuj ważne informacje o użytkowniku” przenosi tę decyzję na model, a on nie zna Waszej polityki prywatności.
Zaplanuj usuwanie, zanim zaplanujesz zapisywanie. Jak człowiek ma poprosić o wyczyszczenie tego, co agent o nim wie, i kto to wykona. Jeśli nie ma odpowiedzi, nie włączaj pamięci trwałej. To nie jest formalność, tylko podstawowe pytanie o zbiór danych.
Najtrudniejszy przypadek z pamięcią wygląda tak: agent odpowiada dziwnie, ale nie błędnie. Trochę nie na temat, trochę zbyt pewnie, z założeniem, którego nikt w tej rozmowie nie wypowiedział.
Przyczyną jest zwykle wspomnienie sprzed tygodni, doładowane automatycznie i niewidoczne w zapisie bieżącej rozmowy. Człowiek analizujący problem czyta transkrypt, nie widzi w nim niczego podejrzanego i szuka błędu w instrukcji agenta, gdzie go nie ma.
To jest jakościowo inna klasa awarii niż wszystko pozostałe w systemie agentowym. Wejście, które wpłynęło na odpowiedź, nie występuje w zapisie tej odpowiedzi.
Trzy rzeczy, które to rozbrajają, każda tania.
Loguj, co zostało doładowane. Przy każdej turze zapisuj listę wspomnień, które trafiły do kontekstu. Bez tego diagnoza jest zgadywaniem. To jedna linia w logu i jedyna rzecz z tej trójki, która jest naprawdę obowiązkowa.
Pokaż to użytkownikowi. Jeśli interfejs na to pozwala, wyświetl w rogu, co agent o nim pamięta. Poza wartością dla zgodności ma to efekt praktyczny: użytkownik sam wyłapie nieaktualne wspomnienie szybciej niż jakikolwiek proces po Twojej stronie.
Przetestuj z pustą pamięcią. Kiedy odpowiedź wygląda podejrzanie, powtórz to samo pytanie w sesji bez dostępu do pamięci. Jeśli wynik się poprawia, masz przyczynę. To jest odpowiednik testu z odłączonymi dokumentami, który opisywałem przy wierności cytowania w RAG, i działa z tego samego powodu: izolujesz jedno źródło kontekstu, żeby sprawdzić jego wpływ.
Częste nieporozumienie: zespół zauważa, że agent gubi wątek w długiej rozmowie, i wnioskuje, że potrzebuje pamięci.
Nie potrzebuje. Gubienie wątku w jednej sesji to kwestia okna kontekstowego, a nie braku pamięci trwałej. Dołożenie magazynu wspomnień niczego tu nie poprawi, za to doda kolejne treści konkurujące o to samo ograniczone miejsce.
Rozróżnienie jest proste:
- Gubi wątek w tej samej rozmowie. To problem okna kontekstowego. Skróć sesję, streszczaj albo podziel zadanie.
- Nie kojarzy niczego z poprzedniej rozmowy. Dopiero to jest brak pamięci.
Pierwszego przypadku jest w praktyce znacznie więcej i pamięć trwała jest na niego złym lekarstwem, w dodatku z konsekwencjami prawnymi.
- Sprawdź, czy naprawdę potrzebujesz warstwy trzeciej. Jeśli agent obsługuje pojedyncze zadania i nie musi znać użytkownika, stan sesji wystarcza. To najczęstszy przypadek.
- Jeśli potrzebujesz, zacznij od
InMemoryMemoryService. Zobaczysz, co system faktycznie zapisuje, zanim to gdziekolwiek wyląduje.
- Wypisz listę faktów wartych zapamiętania. Nie kategorii, tylko konkretów. Zwykle jest ich mniej niż dziesięć i widok tej listy sam rozstrzyga wiele wątpliwości.
- Napisz procedurę usuwania, zanim wdrożysz zapisywanie. Jedno zdanie w dokumentacji i jedno polecenie, które to robi.
- Zajrzyj do zawartości pamięci po tygodniu. To jedyny sposób, żeby dowiedzieć się, co system uznał za warte zapamiętania. Zwykle jest to zaskakujące.
Definicje podstawowych pojęć zebrałem w słowniczku. Cała seria zaczyna się od drogi od czatu do systemu agentowego.