Stan, na którym działają agenci: Paimon między bazą a raportem

Agent, który przygotowuje decyzje kredytowe dla działu sprzedaży dystrybutora, rusza w poniedziałek. W środę administrator bazy pyta, kto co piętnaście sekund wykonuje to samo zapytanie na ERP. To agent. Dostał polecenie, żeby korzystać z aktualnych danych, a jedynym miejscem, gdzie aktualne dane istniały, była baza produkcyjna.
Tak zwykle wygląda pierwszy projekt agenta operacyjnego i zawodzi on w dwie strony naraz. Obciąża system zapisu odczytami, pod które nigdy nie był wymiarowany, a i tak odpowiada ze stanu, który jest mieszanką: trochę ERP, trochę tego, co wie system magazynowy, trochę tego, co agent pamięta z poprzedniego wywołania. Baza operacyjna i lakehouse to dwie różne pamięci jednej firmy. Agent operacyjny potrzebuje między nimi trzeciej rzeczy: tabeli bieżącego stanu, zasilanej z bazy, którą może czytać tak często, jak chce.
Dlaczego agent nie może odpytywać bazy produkcyjnej
Baza operacyjna jest strojona pod transakcje: krótkie zapisy, wyszukiwanie po kluczu z indeksu, blokady trzymane przez milisekundy. Agent zadaje inne pytania. Chce stanu jednego klienta złączonego z otwartymi zamówieniami, ostatnimi zwrotami, limitem kredytowym i historią płatności, a sekundę później tego samego dla następnego klienta. Po stronie OLTP to szerokie złączenie powtarzane bez końca.
Psują się trzy rzeczy. Baza zwalnia dla ludzi, którzy naprawdę księgują zamówienia. Agent widzi stan poprawny dla jednego systemu, a pomija pozostałe, bo system magazynowy i platforma e-commerce mają własne bazy. I nikt nie potrafi później powiedzieć, co agent widział, kiedy złożył daną sugestię, bo baza produkcyjna nie pamięta własnych poprzednich stanów.
Replika do odczytu rozwiązuje pierwszy problem i żaden z pozostałych.
Droga od zmiany do stanu
Wzorzec, który utrzymuje się w systemach enterprise, polega na tym, żeby baza ogłaszała swoje zmiany, a stan był budowany gdzie indziej.
Przechwytywanie zmian (change data capture). Konektor taki jak Debezium czyta własny dziennik transakcji bazy i emituje jedno zdarzenie na zmieniony wiersz: zamówienie dodane, status zmieniony, limit zmieniony. Baza nie wykonuje w tym celu żadnego dodatkowego zapytania; ten dziennik i tak już pisze.
Kontrakt zdarzenia. Każdy typ zdarzenia ma schemat w rejestrze schematów z regułami zgodności. To tu pole dodane przez zespół e-commerce nie przewraca agenta niżej w łańcuchu. Zwykłym nośnikiem jest Apache Avro; opisujemy go w osobnym artykule.
Procesor strumieni. Apache Flink konsumuje zdarzenia, łączy je po kluczu i zapisuje wynik do tabeli. Złączenie jest tym miejscem, w którym „stan klienta” składa się z ERP, systemu magazynowego i sklepu.
Tabela z kluczem głównym. Apache Paimon przechowuje ten wynik jako tabelę z kluczem klienta albo zamówienia, zorganizowaną jako drzewo LSM (log-structured merge-tree): nowe wersje wiersza lądują w małym górnym poziomie, a scalanie (compaction) spycha je w tle w dół. Wiersz, który zmienia się co minutę, nie zamienia tabeli w stertę małych plików, a czytelnik zawsze dostaje ostatnią scaloną wersję. Tabela jest też źródłem dziennika zmian, więc następne ogniwo może reagować na zmiany zamiast skanować.
Złączenie przez odczyt (lookup join). Flink potrafi odpytać tabelę Paimon z wnętrza strumienia, więc wzbogacenie nowego zamówienia o bieżący stan klienta to jedna operacja, a nie wywołanie bazy.
Infografika
Od zmiany w bazie do decyzji agenta
- 01Zmiana w systemie zapisuStatus zamówienia albo limit kredytowy zmienia się w ERP; dziennik transakcji to zapisuje.
- 02Przechwytywanie zmianDebezium czyta dziennik i emituje jedno zdarzenie na zmieniony wiersz.
- 03Kontrakt zdarzeniaZdarzenie niesie zarejestrowany schemat z regułami zgodności.
- 04Tabela stanu w Apache PaimonFlink łączy zdarzenia po kluczu w jedną tabelę bieżącego stanu.
- 05Agent czyta i decydujeAgent czyta tabelę stanu i przygotowuje sugestię razem z migawką, której użył.
- 06Zapis zwrotny przez APIZaakceptowana decyzja trafia do systemu zapisu jego własnym interfejsem, pod nazwanym użytkownikiem.
Które decyzje potrzebują sekund
Powyższy łańcuch potrafi dostarczyć stan opóźniony o sekundy względem bazy. Zanim go zbudujecie, ustalcie, które decyzje tego potrzebują. W większości firm ta lista jest krótka.
Kontrola kredytowa przy przyjęciu zamówienia potrzebuje bieżącego limitu i dzisiejszych otwartych zamówień: sekundy mają znaczenie, bo handlowiec jest na linii z klientem. Podział deficytowego zapasu między kanały potrzebuje minut. Rekomendacja, co zaproponować klientowi w przyszłym tygodniu, potrzebuje wczorajszego stanu i lepiej ją zasilać z historii w lakehouse niż z żywej tabeli.
Budowanie wszystkiego w najszybszej warstwie to częsty błąd. Każda warstwa niżej kosztuje mniej: mniej zdarzeń do przetworzenia, mniej scalania, prostszy tryb awarii. Wpiszcie wymaganie opóźnienia do specyfikacji każdej decyzji agenta, z osobą, która je potwierdziła, i pozwólcie wolnym być wolnymi.
Co agent czyta i gdzie pisze
Tabela stanu jest dla agenta tylko do odczytu. Czyta ją tak często, jak wymaga decyzja, i przy każdej sugestii zapisuje identyfikator migawki tabeli, której użył. Paimon przechowuje migawki i znaczniki dokładnie po to: znacznik przypina pliki migawki, więc stan z zeszłego wtorku da się odczytać ponownie, kiedy nowsze migawki już wygasły.
Zapis to inna sprawa. Wynik agenta jest propozycją: zwolnić zamówienie, wstrzymać, poprosić o przedpłatę. Gdy człowiek ją zaakceptuje, zmiana trafia do systemu zapisu przez jego własne API albo własny ekran, pod nazwanym użytkownikiem, z dołączonym uzasadnieniem agenta. Tabela stanu dowiaduje się o tej zmianie tak samo jak o każdej innej: z dziennika transakcji. Jest jeden autor prawdy i nie jest nim agent.
To domyka pętlę, której odpytywanie nigdy nie domykało. Agent widzi skutek własnej zaakceptowanej sugestii tą samą drogą co wszystko inne, więc jego kolejna decyzja zaczyna się od spójnego stanu.
Czas rzeczywisty jako cel sam w sobie
Tabela stanu świeża co do sekund zaprasza pulpit odświeżany co pięć sekund, regułę alarmu na każdą zmianę i agenta, który ocenia na nowo każdego klienta przy każdym zdarzeniu. Żadna z tych rzeczy nie jest decyzją biznesową. Każda dokłada obciążenia Flinkowi i scalania Paimonowi, a każda utrudnia powiedzenie, co system robił w danej chwili.
Zostawcie szybką ścieżkę decyzjom, które jej potrzebują. Wszystko inne czyta z lakehouse, gdzie te same zdarzenia lądują w Parquet pod formatem tabeli i gdzie sednem jest historia, nie świeżość. Jak Paimon działa od środka i ile kosztuje jego utrzymanie, opisuje profil Apache Paimon.
Jak się to testuje
Tabela stanu umożliwia rodzaj testów, którego odpytujący agent nigdy nie miał. Znacznik na tabeli Paimon i dzień zdarzeń z tematu to kompletny, powtarzalny zestaw danych testowych. Nową wersję agenta można puścić na tym zestawie, porównać jej sugestie z poprzednią wersją i z decyzjami, które ludzie faktycznie podjęli, zanim zobaczy żywe zamówienie.
W cyklu wytwarzania systemów AI (AI SDLC) staje się to standardowym krokiem: zestaw ewaluacyjny to migawka plus odtworzenie zdarzeń, kryterium odbioru to raport różnic, a notatka wydania mówi, wobec którego znacznika porównanie zostało wykonane. Agenci kodujący dobrze radzą sobie z generowaniem uprzęży do odtwarzania i zapytań porównawczych. Decyzja, jaka różnica jest dopuszczalna, zostaje przy właścicielu procesu.
Nasza część
W inżynierii agentów AI budujemy tę część między bazą a agentem: kontrakty zdarzeń, tabelę stanu z warstwami opóźnienia, ścieżkę odczytu z identyfikatorami migawek i zapis zwrotny przez system zapisu pod nazwanym użytkownikiem. Nie odsprzedajemy platform. Więcej o predictes na stronie głównej.
- agenci operacyjni
- Apache Paimon
- przechwytywanie zmian
- Apache Flink