Poza polem czatu: architektura agenta AI WhatsApp na Google ADK
Jak asystent WhatsApp w produkcji łączy specjalistycznych agentów Google ADK, RAG, narzędzia deterministyczne, stan sesji, przekazanie zadania człowiekowi oraz ocenę opartą na trajektorii.
Większość demonstracji sztucznej inteligencji polega na polu tekstowym połączonym z modelem: wpada pytanie, pojawia się płynna odpowiedź i publiczność jest zadowolona. Produkt, od którego zależą rzeczywiści klienci, ma dłuższy wykaz wymagań. Musi pamiętać rozmowę, pracować z aktualnymi danymi firmy, podejmować działania, radzić sobie z awariami oraz przekazywać klienta do osoby, gdy automatyzacja nie wystarcza.
W tym artykule omówiono architekturę asystenta produkcyjnego działającego wewnątrz WhatsApp dla rynku ładowarek samochodów elektrycznych na Sri Lance. Służy on kierowcom pojazdów elektrycznych, właścicielom nieruchomości, którzy mogą mieć ładowarki, oraz osobom chcącym po prostu dowiedzieć się o ładowaniu samochodów elektrycznych. Na końcu uzyskasz konkretny plan elementów otaczających model oraz zestaw zasad projektowych, których możesz ponownie wykorzystać w swoim własnym agencie, niezależnie od kanału, w którym funkcjonuje.
Dlaczego kanał kształtuje produkt
Zespół wybrał WhatsApp, aby nikt nie musiał instalować kolejnej aplikacji tylko po to, by zadać pytanie. Docelowi użytkownicy już korzystają z WhatsAppa: wiedzą, jak wysyłać wiadomości, udostępniać lokalizację, przechowywać kontakty oraz odpowiadać na konkretne wiadomości w rozmowie. Spotkanie z użytkownikami tam całkowicie eliminuje problem wprowadzania ich w obsługę narzędzia. Zamiast uczyć ludzi korzystania z produktu opartego na sztucznej inteligencji, asystent pojawia się w narzędziu, które już rozumieją.
To wybór narzuca również ograniczenia, z którymi nigdy nie musi się mierzyć czatbot internetowy:
- Odpowiedzi muszą być krótkie, ponieważ długie odpowiedzi obciążają telefon.
- Wiadomości powinny przychodzić w naturalnym tempie, a nie jako jeden długi tekst.
- Prośby o lokalizację powinny wykorzystywać wbudowaną w WhatsApp interfejs do udostępniania lokalizacji.
- Dane kontaktowe powinny być prezentowane jako prawdziwa karta kontaktu, a nie jako wklejony tekst.
Celem jest rozmowa, która brzmi naturalnie w WhatsAppie, a nie chatbot stacjonarny wpisany do aplikacji do przesyłania wiadomości. Pamiętaj o tym w każdym kanale: konwencje interfejsu platformy stanowią część specyfikacji, a nie element dekoracyjny.
Ścieżka żądania od webhooka do odpowiedzi
Tło systemowe jest napisane w Pythonie przy użyciu Google’s Agent Development Kit (ADK) oraz FastAPI. ADK może stworzyć gotowy serwer API dla agenta, z wbudowanym wsparciem dla uruchamiania agentów, zarządzania sesjami oraz przesyłania wyników w formie zdarzeń. Ten serwer API działa na bazie FastAPI i Uvicorn, co ułatwia rozbudowę o dostosowany webhook WhatsAppa oraz punkty końcowe specyficzne dla danego biznesu.
Agent ADK składa się z czterech elementów:
- Modelu, np. Gemini.
- Instrukcji określających rolę i granice agenta.
Zrozumienie całego procesu od pierwszej wiadomości do końca ułatwia sformułowanie projektu:
- Użytkownik wysyła wiadomość przez WhatsApp, a Meta dostarcza ją do webhooka FastAPI.
- Backend analizuje wiadomość i odzwierciedla ją w Chatwoot, aby zespół obsługi mógł śledzić rozmowę.
- Backend znajduje sesję tego użytkownika i przekazuje wiadomość do ADK.
- ADK uruchamia koordynatora, który kieruje żądania: pytania techniczne do agenta EV, pytania dotyczące dochodów do agenta cenowego, wyszukiwanie stacji do agenta stacji.
- Wybrany agent albo wyszukuje informacje w bazie wiedzy Vertex AI, albo korzysta z narzędzia – na przykład do sprawdzania danych stacji, szacowania dochodów, wysyłania karty kontaktowej lub żądania lokalizacji użytkownika.
Zauważ, jak mało z tego procesu dotyczy samego modelu. Analiza tekstu, wyszukiwanie sesji, routowanie, formatowanie, dostawa i odzwierciedlanie to wszystko standardowe zadania backendu.
Jeden koordynator, trzej specjaliści
Asystent jest zorganizowany jako koordynator, który deleguje zadania trzem specjalistycznym agentom:
- Agent ds. infrastruktury EV zajmujący się typami ładowarek, ich instalacją i przepisami.
- Agent ds. cen i biznesu zajmujący się aspektami ekonomicznymi hostingu.
- Agent do wyszukiwania stacji zajmujący się znajdowaniem miejsc do ładowania.
Jedynym zadaniem koordynatora jest zrozumienie intencji użytkownika i przekazanie rozmowy odpowiedniemu specjaliście. Pytania dotyczące typów ładowarek trafiają do działu infrastruktury, zapytania właścicieli nieruchomości o potencjalne dochody są kierowane do działu cen, a prośby o stacje w pobliżu Galle trafiają do funkcji wyszukiwania stacji. Te przekazy są niewidoczne dla użytkownika, który ma wrażenie prowadzenia jednej, ciągłej rozmowy z jednym asystentem.
Opcją alternatywną był jeden duży agent z długim poleceniem systemowym oraz wszystkimi dołączonymi narzędziami. To sprawdza się przy prototypie, ale w miarę gromadzenia się narzędzi i toków rozmowy, rozdzielenie obowiązków przyniosło korzyści na trzy sposoby: każde polecenie pozostawało krótkie, łatwo było stwierdzić, który agent może używać którego narzędzia, a każdy tok mógł być testowany oddzielnie. Rozdzielenie koordynatora od specjalistów, jedna z udokumentowanych wzorców orkiestracji agentów, sprawiło również, że zmiany stały się tańsze, ponieważ proces ustalania cen mógł być zmieniony bez ingerencji w funkcję wyszukiwania stanowisk.
Istnieje koszt, który warto wymienić. Każda decyzja dotycząca kierowania zapytaniem to kolejna próba wywołania modelu, która może się nie udać, więc błędnie skierowane zapytanie zawiedzie w sposób, w jaki to nigdy nie zrobiłby pojedynczy agent. To jeden z powodów, dla których strategia oceny opisana później sprawdza, jaki agent i narzędzie zostały wybrane, a nie tylko ostateczne sformułowanie. Aby dowiedzieć się więcej na temat tego, jak kierowanie zapytaniami i agenci specjalistyczni współpracują ze sobą, zapoznaj się z agentami specjalistycznymi, routerem słów kluczowych i mechanizmem przerwania w LangGraph.
Oparte na kontrolowanej bazie wiedzy odpowiedzi
Pomocnik w firmie nie powinien wymyślać faktów, a ładowanie pojazdów elektrycznych wiąże się z wieloma detalami, które łatwo błędnie interpretować: pojemność ładowarek, czas ładowania, wymagania instalacyjne, przepisy, modele pojazdów oraz informacje specyficzne dla danej firmy. Wiele z tych elementów zmienia się z upływem czasu, a model ogólny ma ograniczoną wiedzę o lokalnym rynku.
Rozwiązaniem jest generowanie wzbogacone o wyszukiwanie informacji. Wiedza ta jest przechowywana jako korpus w silniku RAG Engine w Vertex AI, a przed udzieleniem odpowiedzi na pytanie techniczne agent może go zapytać o najbardziej relevantne fragmenty. Istnieją dwa oddzielne ścieżki wyszukiwania: jedna dotyczy ogólnej infrastruktury do ładowania pojazdów elektrycznych, a druga – modeli pojazdów i pytań dotyczących czasu ładowania. Taki podział korpusu pozwala utrzymać skupienie wyników, ponieważ pytanie o to, ile czasu potrzebuje na ładowanie konkretny samochód, nie konkuruje z dokumentami regulacyjnymi o najwyższe pozycje w wynikach.
Kluczową koncepcją jest podział pracy. Model nadal tworzy odpowiedź, ale dane pochodzą z źródeł kontrolowanych przez firmę i można je aktualizować bez konieczności ponownego szkolenia systemu.
Przekształcanie rozmowy w działanie
Największym krokiem naprzód było wyjście poza prostą odpowiadanie na pytania. Asystent posiada narzędzia, które wykonywają rzeczywiste zadania. Może on:
- Pytać backend rynku o liczbę stacji ładowania znajdujących się w pobliżu danej miejscowości.
- Wysyłać prośbę o lokalizację przez aplikację WhatsApp.
- Wysyłać wizytówkę firmy.
- Dzielić się lokalizacją biura w postaci znacznika na mapie.
- Oszacowywać potencjalne dochody dla osoby rozważającej umieszczenie stacji ładowania.
- Oznaczać rozmowę do przekazania człowiekowi, gdy użytkownik tego potrzebuje.
Dlaczego obliczenia dochodów są realizowane przy użyciu zwykłego Pythona
Przepływ przychodów pokazuje najważniejszą zasadę projektową w tym systemie. Asystent najpierw zbiera informacje o nieruchomości użytkownika oraz jego wymaganiach dotyczących opłat poprzez rozmowę. Następnie oblicza miesięczne zużycie energii, przewidywane przychody, koszt prądu, miesięczny zysk oraz roczny zysk.
To obliczanie odbywa się za pomocą deterministycznego Pythona, a nie jest wynikiem pracy modelu językowego. Modele są niewiarygodne pod względem arytmetyki, dlatego dane finansowe pokazywane potencjalnemu klientowi muszą być powtarzalne i poddawalne audytowi. Model zarządza dialogiem i wyodrębnia dane wejściowe; kod generuje liczby. Wynik jest przekazywany za pomocą ustrukturyzowanego szablonu w WhatsApp, a informacje o leadzie są zapisywane w Google Sheets.
Niech model służy do obsługi języka i podejmowania decyzji, natomiast zwykłe oprogramowanie należy używać do wszystkiego, co wymaga dokładności.
To zasada ma zastosowanie nie tylko w kwestiach cenowych: obsługa dat, konwersja jednostek, sprawdzanie kwalifikacji oraz wszystko, co ma znaczenie prawnicze lub finansowe, powinno znajdować się w kodzie wywoływanym przez model, a nie w wyniku jego działania.
Stan sesji to logika produktu
Dobre rozmowy zależą od tego, co przed nimi nastąpiło. Asystent utrzymuje oddzielną sesję dla każdego numeru WhatsApp, a w niej przechowywane są imię użytkownika, numer telefonu, wybrana opcja menu, ostatnie wiadomości, informacje o lokalizacji oraz identyfikator ostatniej wiadomości.
Zapisywanie identyfikatora ostatniej wiadomości umożliwia systemowi zrozumienie odpowiedzi na konkretną wiadomość z menu, co użytkownicy WhatsApp robią ciągle. Stan sesji pozwala również na naturalne kontynuowanie wieloetapowych procesów. Na przykład przeniesienie informacji o lokalizacji odbywa się w następujący sposób:
- Zapytaj, czy użytkownik chce podzielić się swoją lokalizacją.
Bez tego stanu każda wiadomość byłaby traktowana jako początek nowej rozmowy. Pamięć w agencie nie jest opcjonalnym dodatkiem; określa ona zachowanie produktu i zasługuje na taką samą uwagę projektową jak każda inna funkcja.
Formatowanie na małym ekranie
Zaskakującą lekcją okazało się to, że technicznie poprawna odpowiedź może nadal wydawać się błędna wyłącznie ze względu na swój kształt. Modele mają tendencję do tworzenia długich akapitów, list w formacie Markdown oraz kilku pomysłów umieszczonych w jednym bloku. To dobrze wygląda na komputerze stacjonarnym, ale kiepsko w oknie czatu.
Dedykowana warstwa formatowania zajmuje się tym problemem. Ona:
- Przekształca format Markdown na własną składnię formatowania WhatsAppa.
- Wykrywa listy ukryte w ciągłym tekście.
Krótkie przerwy pomiędzy fragmentami dają czytelnikowi czas na przyswojenie każdej myśli. Celem nie jest udawanie, że pisze człowiek; chodzi o kontrolowanie tempa. Indykatory pisania, wysyłane przez Meta API, pokazują, że odpowiedź jest przygotowywana.
Assystent reaguje również na niektóre wiadomości za pomocą emotikon, ale robi to selektywnie. Lekki model, taki jak Flash Lite, decyduje, czy dana wiadomość zasługuje na reakcję, a jeśli tak, to reakcja jest wysyłana przez Meta API. Wiadomości emocjonalne, ekscytujące, zabawne lub znaczące mogą otrzymać taką reakcję; rutynowe wiadomości, takie jak „ok”, „dziękuję” czy zwykłe instrukcje, zazwyczaj jej nie otrzymują. Użycie małego, taniego modelu do tej decyzji pobocznej zapewnia niską opóźnioność i koszty, podczas gdy główne agenty zajmują się treścią wiadomości. Takie szczegóły pojedynczo są niewielkie, ale łącznie decydują o tym, czy produkt wydaje się naturalny.
Zachowanie drogi do człowieka
Automatyzacja nigdy nie powinna stać się barierą pomiędzy klientami a firmą. Każda nadeszła rozmowa jest synchronizowana z Chatwoot, a dodawane są również odpowiedzi asystenta, dzięki czemu zespół obsługi zawsze widzi dokładnie to, co zostało powiedziane.
Gdy użytkownik prosi o kontakt z rzeczywistą osobą lub wykazuje oznaki frustracji, asystent uruchamia procedurę pomocy przez człowieka, która rejestruje zapytanie wraz z pytaniem użytkownika, aby zespół mógł się nim zająć. Ponieważ cała rozmowa jest już odzwierciedlona, osoba przejmująca zadanie nie musi prosić klienta o powtórzenie.
Automatyzacja powinna eliminować pracę powtarzalną, a nie uniemożliwiać kontakt z osobą.
Praca nad niezawodnością poza rozmową
System wysyła również kampanie szablonowe w WhatsApp, co stwarza subtelny problem: komunikat promocyjny nigdy nie powinien przerywać osoby, która jest w trakcie rozmowy o wsparciu. Przed wysłaniem system sprawdza, kiedy każdy odbiorca ostatnio wchodził w interakcję z asystentem. Ci, którzy rozmawiali niedawno, są na razie pozostawieni w spokoju – ich wiadomość jest zatrzymywana, zapisywana do SQLite i udostępniana punktowi końcowemu do ponownej próby wysłania później.
wokół tego kształtują się niepozorne funkcje, których potrzebuje każda usługa:
- Deduplikacja przychodzących wiadomości, ponieważ webhooki mogą dostarczyć ten sam zdarzenie kilka razy.
- Nadzór nad stanem usługi.
- Zarządzanie odnowieniem tokenów dostępu.
- Kontrola CORS w punktach końcowych HTTP.
- Rozwój oparty na Dockerze.
- Śledzenie błędów za pomocą Sentry.
Żadne z nich nie zrobi wrażenia na nikim podczas demonstracji. Wszystkie stają się niezbędne w momencie, gdy demonstracja przekształca się w usługę, od której zależą klienci.
Testowanie zachowania, a nie tylko tekstu
Agenty są trudniejsze do przetestowania niż zwykłe funkcje, ponieważ ten sam wprowadzony danych może dać nieco inne wyniki. Co gorsza, sposoby awarii nie są oczywiste z końcowego tekstu. Odpowiedź może wyglądać dobrze, mimo że użyto niewłaściwego narzędzia, albo można użyć właściwego narzędzia, ale wynik zostanie źle przekazany.
Dlatego zestaw narzędzi oceniających wykorzystuje symulowane rozmowy obejmujące kwestie związane z infrastrukturą, procesami cenowymi oraz rozmowy pomiędzy specjalistami. Sprawdzania te analizują ścieżkę działania narzędzi, czyli które agenty i narzędzia zostały wywołane w jakiej kolejności, a nie tylko sformułowanie końcowej odpowiedzi.
Zmiany w promptach są obsługiwane w ten sam sposób. Zamiast edytować prompt systemowy ręcznie, zespół eksperymentował z pętlą optymalizacyjną, w której kandydackie instrukcje były oceniane na podstawie ustalonej serii rozmów, w tym optymalizacji promptów opartej na GEPA. Kandydaty byli testowani wobec pytań treningowych, a oddzielny oceniający wykorzystujący Gemini oceniał każdą odpowiedź pod kątem dokładności i osobowości. Dzięki temu praca nad promptami staje się bardziej przypominająca inżynierię: zamiast przyjmować zmianę tylko dlatego, że brzmi lepiej, można porównać zachowanie w powtarzalnej serii rozmów. W przypadku każdego rozwiązania z modelem jako oceniającym istnieje jedna uwaga: oceniający ma własne uprzedzenia, więc warto sprawdzić jego oceny w porównaniu z osądem człowieka, zanim zaufa się mu przy ważnych decyzjach.
Główne wnioski
- Model stanowi jeden komponent; większość aspektów inżynieryjnych dotyczy routingu, wyszukiwania informacji, zarządzania stanem, narzędzi, formatowania, radzenia sobie z awariami oraz eskalacji problemów.
- Gdy prompty i listy narzędzi staną się trudne do zrozumienia, podziel rosnącego agenta na koordynatora oraz specjalistów zajmujących się konkretnymi zadaniami, a następnie przetestuj sam proces routingu.
- Uzasadniaj faktyczne odpowiedzi na podstawie bazy wiedzy, którą kontrolujesz, a dokładne obliczenia przechowuj w kodzie deterministycznym.
- Traktuj stan sesji oraz formatowanie specyficzne dla kanału jako kluczową logikę produktu.
- Zawsze zachowuj widoczną, łatwą do skorzystania ścieżkę kontaktu z człowiekiem.
- Oceniaj trajektorie działania narzędzi w ramach ustalonego zestawu rozmów, aby zmiany w promptach mogły być mierzone, a nie tylko domyślane.
Zawinięcie promptu w wywołanie API daje możliwość stworzenia demonstracji. Niezawodny agent to cały system, w którym modele językowe, dane, narzędzia, projekt produktu oraz tradycyjna inżynieria backendu każdy pełni rolę, w której jest najlepszy.