Zmiana na lepsze. Jak rezygnacja z crewAI ulepszyła AMP.

Zrezygnowałem z crewAI! Postawiłem na RAG, który oparłem na zdefiniowanych przez siebie agentach. Wyszło zaskakująco dobrze!

AMP, czyli Agents of Mass Production, to mój projekt mający na celu ułatwienie mi pracy w opiece nad projektami. W poprzednim tekście głównie w przypływie ciekawości postawiłem na wykorzystanie crewAI do zbudowania procesu pomagającego w tworzeniu notatek z tekstów. Nowa wersja AMP przynosi dwie spore zmiany. Po pierwsze zrezygnowałem z crewAI na rzecz pełnego przejścia na langchain. Po drugie dodałem krok, w którym podsumowanie spotkania jest wzbogacane o informacje z poprzednich.

Pożegnania nadszedł czas.

W dalszym ciągu uważam crewAI za świetną bibliotekę do tworzenia agentów AI. Pomogła mi wgryźć się w temat, w dużej mierze za sprawą ciekawych przykładów oraz zrozumiałego procesu implementacji. Tworzę agentów, przypisuję im narzędzia, uruchamiam skrypt i wszystko się dzieje. Na dodatek wyniki są naprawdę dobre i pierwsze zautomatyzowane notatki ze spotkań powstały właśnie z pomocą crewAI. W takim razie, dlaczego postanowiłem zrezygnować z tego rozwiązania? Poszło przede wszystkim o kontrolę. Nie tylko na poziomie samego wykonywania akcji, ale także o zapanowanie nad kosztami.

CrewAI ma własne, zaszyte w kodzie, prompty. Do nich dodawane się informacje, które podaję ja, jako osoba, która opracowywała agentów oraz ich narzędzia. Problem pojawił się, gdy postanowiłem dodać etap polegający na dodawaniu informacji z poprzednich spotkań, do aktualnie opracowywanego podsumowywania. Zauważyłem, że bardzo wzrosły mi koszty używania mojego skryptu, a stało się to za sprawą większego zużycia tokenów. Głównie dlatego, że crewAI dokleja moje treści do swoich promptów, a więc ja, jako projektant i twórca, mam ograniczoną kontrolę nad kosztami. Być może bym to zaakceptował, gdyby nie to, że siedzi we mnie trudna do zwalczenia, potrzeba optymalizacji procesów i minimalizacji strat. Wiem, przerażające. Na dodatek w życiu prywatnym też kieruję się tą zasadą.

Uznałem, że do kolejnej iteracji spróbuje sam zbudować agenta z wykorzystaniem langchaina. Zdaję sobie sprawę z tego, że zamieniam jedną warstwę abstrakcji na drugą, jednak w tym przypadku mam na to uzasadnienie, które teraz wydaje mi się sensowne. Langchain udostępnia wiele rozwiązań do pracy z dokumentami, różnego typu. Ułatwia to ich dzielenie oraz przetwarzanie, dzięki czemu mogłem się skupić na projektowaniu samego procesu oraz tego, jak mają działać agenci. Nie ukrywam, że najpierw odwzorowałem to, co miałem już przygotowane w crewAI. Efekt? Podsumowanie spotkania wyszło bardzo dobre, przy znacznie niższych kosztach i przy większej kontroli nad tym, co dzieje się w skrypcie.

Idą jak po sznurku.

Planując kolejną iterację AMP, zacząłem się zastanawiać, ile wolności powinienem pozostawić agentom. Uznałem, że niewiele, że najwięcej decyzyjności po stronie AI warto wdrożyć w momencie wzbogacania treści spotkania. Wcześniej nie jest potrzebna. Wiem, jakiego projektu dotyczy transkrypcja, a więc mogę już sam wybrać, który zestaw dodatkowych informacji mnie interesuje. Teraz potrzebuję jedynie tego, aby skrypt zebrał dane ze wszystkich części spotkania, przygotował rozbudowanie streszczenie tematów, a następnie na jego podstawie opracował akcje i opisał decyzje, jakie zostały podjęte. Poniżej prezentuję przykładowy prompt wykorzystywany w trakcie tworzenia podsumowania.


Z tym etapem uporałem się szybko. Więcej czasu zajęło mi, zdecydowanie w jaki sposób będę wzbogacał informacje z aktualnego spotkania. Moim celem było sięgnięcie do poprzednich podsumowań, aby dodać treści, które mogły się już pojawić. Często w innym kontekście, ale być może równie ważnym z perspektywy ostatniego spotkania. Bywa, że jakieś tematy potrafią ciągnąć się tygodniami, więc dobrze byłoby, aby model był w stanie je wyszukiwać. W takim razie kto będzie decydował, o jakie informacje wzbogacić aktualnie opracowywane notatki? Uznałem, że to zadanie pozostawię modelowi językowemu. Z dobrym skutkiem.


Co się dzieje na powyższym przykładzie? Model zadaje pięć pytań na temat podsumowania, nad którym pracował inny agent. Dlaczego pięć, a nie trzy albo siedem? Przy trzech pytaniach zauważyłem, że pojawia się niewiele wartościowych informacji, przy siedmiu w podsumowaniu zaczęło się pojawiać dużo różnych śmieci. Ta piątka okazała się złotym środkiem. Jest więcej wątków, model nie traci skupienia na tym, co jest najważniejsze, ja jestem w stanie prześledzić, czy jakieś tematy były wcześniej poruszane. Przykład? Na spotkaniu omawiałem z zespołem strategię marketingową dla naszej nowej gry „Pocket Waifu Rekindled”. Model sięgnął do wcześniejszych notatek, świetnie je podsumował i nawet opracował krótki opis tego, co chcemy zrobić, aby nasz produkt był bardziej rozpoznawalny, więc jestem bardzo zadowolony z tego rozwiązania.

To jest zwykły RAG, a nie jakaś magia!

Jeśli pracujesz z modelami językowymi, to być może podobna myśl pojawiła ci się w głowie. Jednak ja zakładam, że ten tekst trafi też do osób, które znają chatGPT tylko i wyłącznie na poziomie przeglądarki i o wzbogacaniu kontekstu oraz bazach wektorowych niewiele słyszały. Ba! Ja sam miałem o tym mgliste pojęcie i dopiero za sprawą AiDevs uporządkowałem swoją wiedzę. Postanowiłem wykorzystać RAG, aby ulepszyć notatki ze spotkań, dodać do nich więcej informacji. Jednak w dalszym ciągu zależało mi na zoptymalizowaniu tego procesu oraz na stworzeniu lokalnej bazy. Absolutnie nie widzę potrzeby, aby informacje na temat projektów w firmie trafiały na jakąś chmurę.

Aby zbudować taką lokalną pamięć, potrzebowałem bazy wektorowej. Korzystam z bazy Qdrant, która działa na Raspberry Pi 5 8GB. Spisuje się świetnie, mam tak już kilka kolekcji, jedna z nich dotyczy notatek ze spotkań w pracy. Co w nich przechowuję? Teksty? Też, ale znacznie ważniejsze są wektory liczbowe, zwane też embeddingami. Czym są? Każdą treść, jaką ładuję do bazy, zamieniam najpierw na listę liczb, która odwzorowuje znacznie zawarte w konkretnym tekście. To nie jest robione dla każdego zdania, tylko dla całej treści, jaką zostanie przesłana! Tę operację wykonuje model językowy. Istotne jest tutaj to, że nie da się jej odwrócić! Z fragmentu spotkania jestem w stanie zrobić wektory, ale z wektorów już nie odtworzę konkretnego zapisu.

Właśnie dlatego tak istotne jest przechowywanie samej treści. Ja ją dołączam do wpisu w bazie wektorowej, ale nic nie stoi na przeszkodzie, aby trzymać je w innym miejscu, tym samym ograniczając liczbę potrzebnych zasobów. Uznałem, że ja przecież nie będę przetwarzał mnóstwa danych na potrzeby, na przykład, rozbudowanych rekomendacji dla użytkownika. Potrzebuję tylko tego, aby model mógł zadać pytania na wybrane przez siebie tematy i otrzymał odpowiedź. Tylko w jaki sposób to robi? Wcześniej wspomniałem o tym, że jednym z etapów mojego procesu, jest opracowanie pytań na temat notatek ze spotkań. To właśnie te pytania są wysyłane do bazy wektorowej!

Zanim to nastąpi, samo pytanie też musi zostać zamienione na embedding. Następnie zostaje wysłane do bazy, a jako zwrotka przychodzą rekordy będące najbliżej wartości z pytania. Nie chodzi tutaj do stuprocentowe dopasowanie, ale o wybranie wpisów, które będą leżały znaczeniowo najbliżej pytania. Gdy mój skrypt otrzyma te informacje, to buduje z nich podsumowanie, które następnie jest wykorzystywane do wzbogacenia streszczenia spotkania. Zanim zacząłem pisać kod, to ten proces sobie rozpisałem.

AMP po modyfikacjach

Jak te zmiany przełożyły się na pieniądze? Opracowanie jednego spotkania, bez wzbogacania podsumowania, z wykorzystaniem crewAI zamykało się w 4$. W nowym AMP, jedno spotkanie trwające 40 minut, razem z dodawaniem informacji z notatek, to koszt rzędu 0.70$. A jakość jest znacznie lepsza. Dlatego uważam, że warto czasem porzucić gotowe rozwiązania i spróbować stworzyć coś po swojemu. W moim przypadku udało mi się zwiększyć kontrolę nad tym, co się dzieje, a także znacznie zredukować koszty, bez straty jakości!

Co dalej z AMP? Na pewno chcę się jeszcze zmierzyć z opracowywaniem danych liczbowych i generowaniem raportów. Jednak, jak zawsze, wymaga to ode mnie odpowiedniego przygotowania dokumentów, aby model językowy skupił się na tym, co mu dostarczę i miał jak najmniej pola do wymyślania informacji.

//Kod drugiej iteracji AMP jest dostępny tutaj!