Przejdź do Treści

Budowanie aplikacji chmurowych opartych na AI: Co warto wiedzieć?

Marek Matczak
Jun 12, 2024

W ostatnim czasie zespół Capgemini miał okazję stworzyć kilka aplikacji biznesowych wykorzystujących sztuczną inteligencję, również tę generatywną – zawdzięczającą swoją niezwykłą popularność chatowi GPT. W tym artykule dzielę się z Wami swoimi spostrzeżeniami, które okazały się niezwykle istotne w trakcie budowania takich rozwiązań.

Kiedy mówmy o generatywnej sztucznej inteligencji, to niemal od razu myślimy o tzw. dużych modelach językowych (ang. Large Language Models, LLMs), które są wprawdzie jej najbardziej rozpoznawalnym, ale nie jedynym, elementem. Budowanie niezawodnych aplikacji opartych na sztucznej inteligencji wymaga holistycznego podejścia, w którym korzystamy z wyspecjalizowanych, najczęściej chmurowych, narzędzi AI. Co więcej, używamy ich w oparciu o najnowsze wzorce projektowe z obszaru AI, a także stosujemy sprawdzone w wielu projektach techniki inżynierii oprogramowania.

LLMy: zaglądamy do środka

Zakres wiedzy LLMów jest ograniczony i zależy od zbioru danych użytego w trakcie trenowania modeli. Podczas budowania aplikacji biznesowych niesie to ze sobą dwa podstawowe wyzwania: jak wzbogacić duże modele językowe o wiedzę specyficzną dla danego biznesu, np. o treści rozporządzeń dla pracowników oraz jak zapewnić, że zmiany w tych rozporządzeniach będą od razu widoczne w trakcie używania tych modeli. Pierwszym pomysłem, który się nasuwa, jest wytrenowanie własnego modelu od podstaw, względnie dotrenowanie modelu bazowego, z użyciem swoich danych i powtarzanie tego procesu, gdy konieczna jest ich aktualizacja. Te podejścia są jednak w większości przypadków niepraktyczne ze względu na ogromne koszty idące nawet w setki milionów złotych. Bardziej efektywnym rozwiązaniem jest metoda uczenia kontekstowego (ang. in-context learning). Polega ona na tym, że w zapytaniu wysyłanym do modelu, oprócz właściwego pytania, np. “Jaka jest procedura zgłaszania awarii sprzętu?”, wysyłamy również treść dokumentu opisującego treści procedur, w tym tej, o którą pytamy. W metodzie uczenia kontekstowego duże modele językowe nie wykorzystują zatem wiedzy pozyskanej w trakcie ich trenowania, ale używają zdolności do znaczeniowej analizy tekstu (zarówno dokumentu, jak i właściwego pytania). Co więcej, ta analiza odbywa się w trakcie generowania odpowiedzi, mówiąc kolokwialnie “w locie”. Ta metoda ma jednak również swoje ograniczenie. Jest nim rozmiar zapytania, czyli tzw. promptu, a co za tym idzie ograniczona ilość wiedzy, o jaką możemy rozbudować nasz model. Z tym ograniczeniem można sobie jednak poradzić. Jednym ze sposobów jest zastosowanie popularnego wzorca RAG (ang. Retrieval Augmented Generation), polegającego na umieszczeniu w prompcie tylko tych fragmentów dokumentów, które są istotne z punktu widzenia zadawanego pytania. Drugim sposobem jest… pozbycie się tego ograniczenia i użycie LLMu pozwalającego na ogromny rozmiar promptu idący w tysiące stron tekstu (np. Gemini 1.5 od Google).

RAG: inteligentne wyszukiwanie = mniejszy rozmiar promptu

RAG wykorzystuje możliwości kolejnych elementów z obszaru AI: zanurzenie (ang. embeddings) i wektorowe bazy danych (więcej o tych elementach w dalszej części artykułu). Kombinacja tych elementów pozwala na znalezienie dopasowania znaczeniowego między pytaniem, wracając do naszego przykładu: “Jaka jest procedura zgłaszania awarii sprzętu?”, a fragmentami dokumentów, które z dużym prawdopodobieństwem zawierają odpowiedź na to pytanie. Dzięki technice RAG znacząco ograniczamy rozmiar promptu oraz zwiększamy jakość generowanych odpowiedzi, która może być niższa, jeśli prompt zawiera nieistotne informacje, czyli tzw. “szum”.

LLMy z rozszerzonym oknem kontekstowym

Najnowsze LLMy pozwalają na zbudowanie promptu o rozmiarze odpowiadającym nawet ponad tysiącu stronom tekstu. To sporo. W wielu wypadkach rozmiar ten pozwoliłby na umieszczenie w prompcie np. wszystkich procedur firmy. Nie musimy wówczas implementować wzorca RAG. Zaraz, zaraz… Ale co ze wspomnianym wyżej „szumem”, który może przecież obniżyć jakość generowanych odpowiedzi? Okazuje się, że testy przeprowadzone na modelach z dużymi oknami kontekstowymi (inna nazwa na rozmiar promptu), zwane obrazowo szukaniem igły w stogu siana, dały bardzo obiecujące rezultaty i zdają się nie potwierdzać obaw związanych ze wspomnianym „szumem”: udało się w większości testów znaleźć przysłowiową igłę.

Które podejście wybrać?

RAG czy LLM z rozszerzonym oknem kontekstowym? W podjęciu decyzji może pomóc analiza kosztów obu rozwiązań. Koszt zapytania do LLMu zależy od wielkości promptu, ale w przypadku rozwiązania opartego na RAG musimy doliczyć koszt wektorowej bazy danych, obliczania zanurzeń oraz rozwiązania samego w sobie.

Dodatkowym argumentem przy wyborze rozwiązania powinna być ocena jakości generowanych odpowiedzi. Jak to zrobić? O tym w dalszej części artykułu.

Wykorzystanie kreatywności (lub jej ograniczenie)

Jedną z najbardziej spektakularnych cech LLMów jest ich kreatywność. Szukasz inspiracji, gdzie pojechać na wakacje i jak zaplanować tam czas? LLM jest w stanie wygenerować odpowiedź w ciągu kilku sekund! Ale uwaga: ta odpowiedź może zawierać zmyślone lub nieprawdziwe informacje (halucynacje). Dokładnego przeciwieństwa, czyli ograniczenia halucynacji, a zamiast kreatywności – odpowiedzi bazującej na faktycznych dokumentach, oczekiwalibyśmy natomiast od wirtualnego asystenta odpowiadającego na wspomniane wcześniej pytanie: “Jaka jest procedura zgłaszania awarii sprzętu?” Jak to zrobić? Okazuje się, że LLMy mają parametry, takie jak temperatura czy top_k, które umożliwiają kontrolowanie tych aspektów. Na przykład ustawienie temperatury na 0 i top_k na 1 sprawi, że odpowiedzi będą bardziej faktyczne.

Aby zwiększyć wiarygodność odpowiedzi, możemy dodać linki do dokumentów źródłowych, a nawet opatrzyć odpowiedź cytatami z tych źródeł. Możemy również poinstruować model (o tym jak to zrobić, w dalszej części artykułu), aby w razie, gdy nie można było znaleźć odpowiedzi w samym prompcie, nie „halucynował”, ale odpowiedział po prostu „nie wiem”. Warto wspomnieć przy tej okazji, że całkowite wyeliminowanie halucynacji z LLMów, które są modelami statystycznymi, a więc niedeterministycznymi, nie jest na ten moment możliwe. Należy ten fakt wziąć pod uwagę projektując rozwiązanie biznesowe. W niektórych wypadkach nie da się zupełnie wyeliminować człowieka w podjęciu decyzji biznesowej (ang. human in the loop).

Wektorowe reprezentacje: cichy bohater

Zanurzenia są wektorową reprezentacją znaczenia pojedynczego słowa czy fragmentu tekstu (ale również obrazu lub dźwięku). Ta „sucha” definicja nie oddaje jednak ogromnych możliwości zastosowania tego elementu sztucznej inteligencji w budowanych aplikacjach biznesowych. Mówiąc o znaczeniu mam na myśli jego cały kontekst z uwzględnieniem wielu niuansów (np. kulturowych). Zresztą najlepszym dowodem potwierdzającym te możliwości jest fakt, że zanurzenia są wykorzystywane w trakcie trenowania samych LLMów, a także za każdym razem, gdy wysyłamy do nich nasz prompt. Jakie mogą być potencjalne rozwiązania biznesowe z użyciem zanurzeń? Na przykład wyszukiwanie kontekstowe zamiast tradycyjnego bazującego na słowach kluczowych albo system rekomendacji produktów w oparciu o aktualny koszyk zamówień.

Budując aplikacje biznesowe z elementami AI najczęściej zaczynamy od LLMa, ale może się okazać, że nie jest on w ogóle potrzebny, bo to właśnie wektorowe reprezentacje są rozwiązaniem naszego wyzwania biznesowego. Warto też sprawdzić w dokumentacji technicznej czy wybrany model wektorowych reprezentacji wspiera język tekstów danej aplikacji (np. opisy produktów).

Wektorowa baza danych: znajdź podobieństwa

W jaki sposób wyszukać podobne znaczeniowo fragmenty dokumentów albo – jak wspomniano wcześniej w metodzie RAG – znaleźć te zawierające odpowiedź na zadane pytanie? Z pomocą przychodzą wektorowe bazy danych, które umozliwiają przechowywanie wektorów, a wraz z nimi np. tekstów. Co więcej, produkty te umozliwiają efektywne przeszukiwanie wielowymiarowych przestrzeni wektorowych w celu znalezienia tych znajdujących się blisko siebie, co za tym idzie, odpowiadających im podobnych znaczeniowo tekstów.

Jaką bazę wybrać?

Jaki produkt bazodanowy wybrać? Choć na rynku jest sporo specjalizowanych produktów, np. Pinecone, Amazon Kendra albo Azure AI Search, rozważyłbym użycie tradycyjnej, relacyjnej bazy danych z rozszerzeniem wektorowym, np. PostgreSQL i pgvector. Szczególnie w początkowej fazie budowania aplikacji, kiedy nie znamy jeszcze dokładnych wymagań wydajnościowych, warto postawić na takie hybrydowe rozwiązanie, tym bardziej, że w ten sposób znacząco ograniczymy koszty chmury.

Inżynieria Promptów: język AI

Treść, którą wysyłamy do LLMa, czli tzw. prompt, może zawierać nie tylko samo pytanie, ale również instrukcje wraz dodatkowymi informacjami. Na przykład, w opisywanym wcześniej podejściu uczenia kontekstowego, prompt zawiera instrukcję, aby odpowiedzieć na pytanie w oparciu o załączone fragmenty dokumentów. Nie jest to niczym innym niż programowaniem w języku naturalnym! Na potwierdzenie tych słów warto zacytować tutaj Andreja Karpathy’ego, badacza i popularyzatora AI: The hottest new programming language is English. Tak jak w tradycyjnym programowaniu posługujemy się pewnymi wzorcami, tak i w tym swoistym języku AI takich potrzebujemy. Sztukę tworzenia promptów określa się mianem inżynierii promptów. Choć ten termin brzmi bardzo poważnie, nie trzeba być tutaj specjalistą. Według mnie podstawowe techniki inżynierii promptów powinien znać każdy, a ich nauczanie powinno zacząć się już w szkole podstawowej!

Oprócz podstawowych technik mamy również zaawansowane, takie jak Chain-of-Thought czy ReAct. Ta ostatnia pozwala na złożone wnioskowanie angażujące wiele źródeł danych, zarówno wewnętrznych w danej organizacji, jak i zwnętrznych, np. Wikipedia.

Jakość ma znaczenie: struktura ponad wszystko

Jakość wygenerowanych przez LLM odpowiedzi w dużym stopniu zależy od jakości danych wejściowych. Formaty danych, takie jak Markdown, JSON czy HTML są ustrukturyzowane, np. są podzielone na rozdziały, w nich akapity, a w nich z kolei mogą być tekst czy tabele. Prompty tworzone w oparciu o takie ustrukturyzowane dane, ułatwiają LLMom zrozumienie kontekstu, a w konsekwencji generowanie sensownych odpowiedzi.

Dane nieustrukturyzowane, np. pliki w formacie PDF, obrazy czy diagramy, mogą wymagać wstępnego przetwarzania (tradycyjnie lub z użyciem sztucznej inteligencji) lub zastosowania multimodalnych LLMów (np. akceptujących na wejściu obrazy), np. Gemini Pro (Vision) czy GPT-4o, aby poprawnie zrozumieć kontekst. Posłużmy się przykładem. Pewien dokument PDF zawiera, oprócz tekstu, złożony wykres ilustrujący trendy sprzedaży. Multimodalny LLM potrafi wygenerować słowny opis tego wykresu, który wraz z pozostałą częścią dokumentu może posłużyć do wygenerowania odpowiedzi na pytanie dotyczące sprzedaży.

Aby poprawić jakość, warto pozyskać od użytkowników aplikacji informację zwrotną dotyczącą ich subiektywnej oceny trafności odpowiedzi. Przykładowa implementacja może mieć formę przycisków “lubię/nie lubię” czy formularza. Zebrane w ten sposób sugestie mogą posłużyć np. do doprecyzowania instrukcji w prompcie.

Testowanie w erze sztucznej inteligencji

Niedeterministyczny charakter LLMów oznacza, że powtarzając test dla tego samego wejścia możemy otrzymać za każdym razem nieco inną odpowiedź. Jak zatem testować takie aplikacje? Z pomocą znów przychodzi nasz “cichy bohater” – zanurzenie. Aby porówać oczekiwane odpowiedzi z tymi wygenerowanymi przez LLMy, wystarczy w obu wypadkach znaleźć wektorowe reprezentacje i porównać odległości między tymi wektorami. Wówczas nawet jeśli odpowiedź wyrażona jest w nieco inny sposób, ale nadal jest prawidłowa, można test uznać za pozytywny.

W trakcie budowania aplikacji, szczególnie chatbotów, testowanie promptów i ich odpowiedzi jest niezmierne ważnym elementem. Pamiętajmy, że prompt jest w zasadzie programem napisanym w języku naturalnym, więc konsekwencje braku testów są podobne do nieprzetestowanego kodu źródłowego. W przypadku niedeterministycznych LLMów brak testów promptów ma jeszcze większy negatywny wpływ na stabilność i niezawodność aplikacji.

Bezpieczeństwo: Tu nie ma kompromisów

Elementy AI w aplikacjach nie są wyjątkiem I również wymagają dodatkowej uwagi z punktu widzenia bezpieczeństwa. Jeśli do LLMa wysyłamy w prompcie treści spoza aplikacji (np. wprowadzone przez użytkownika albo przysłane mailem) musimy je sprawdzić czy nie zawierają np. instrukcji aby ujawnić poufne informacje albo kierują rozmowę na tematy nie związane z przenaczeniem danej aplikacji (tzw. prompt injection). Podobnie z generowanymi odpowiedziami: należy sprawdzić czy te nie zawierają treści mogących wpłynąć negatywnie na reputację danej firmy. Na szczęście są na rynku narzędzia, zarówno komercyjne, jak i open source, które umożliwiają skutecznie wdrożyć te środki bezpieczeństwa.

Miłego kodowania!

Budowanie aplikacji chmurowych opartych na sztucznej inteligencji jest sporym wyzwaniem. Temu wyzwaniu można jednak podołać, jeśli pozna się elementy oraz narzędzia AI, a także zastosuje wzorce i dobre praktyki z tego obszaru. Właśnie przybliżenie tych ostatnich było celem mojego artykułu. Mam nadzieję, że moje spostrzeżenia pomogą w tworzeniu wydajnych, bezpiecznych i innowacyjnych rozwiązań opartych na sztucznej inteligencji. Miłego kodowania!