Zmniejszanie halucynacji w pipeline bota konwersacyjnego typu RAG medycznego
Dowiedz się, jak hybrydowe wyszukiwanie, ponowna klasyfikacja oraz ścisła polityka zakazująca fałszerstw łączą się, aby stworzyć bardziej godnego zaufania chatbota do badań medycznych typu RAG.
Projekt rozpoczął się od prostego celu.
Chce się stworzyć chatbota, który będzie mógł odpowiadać na pytania w oparciu o artykuły z badań medycznych.
To powinno być dość proste, prawda?
Okazało się jednak inaczej.
Pierwotna implementacja opierała się na dość konwencjonalnym podejściu RAG: pobieranie dokumentów, generowanie embeddingów, przechowywanie ich w bazie danych wektorowej, wybieranie odpowiednich fragmentów i przekazywanie ich modelowi LLM.
Funkcjonowało to.
Tylko nie w sposób niezawodny.
A w kontekście medycznym „niezawodność” to poważna wada.
Chatbot, który odpowiada z pewnością siebie, ale błędnie, jest o wiele bardziej niebezpieczny niż ten, który przyznaje: „Nie mam wystarczających informacji, by na to odpowiedzieć.”
To uświadomienie doprowadziło do ciągłego doskonalenia procesu wyszukiwania informacji.
Pierwszy problem: halucynacje
Najpilniejszym problemem, który trzeba było rozwiązać, były halucynacje.
Modele językowe potrafią niezwykle dobrze generować odpowiedzi, które brzmią przekonująco, czasami nawet zbyt przekonująco.
Gdy dokumenty nie zawierały odpowiedzi, model często wypełniał tę lukę własną wiedzą wewnętrzną, zamiast przyznać do niepewności.
To zachowanie musiało ulec zmianie.
Odpowiedzi chatbota musiały pochodzić wyłącznie z dostarczonego materiału badawczego, a nie z wyobraźni modelu.
Dlatego zmieniła się podstawowa filozofia.
Zamiast traktować LLM jako autorytet w kwestiach faktów, rzeczywistym źródłem prawdy stały się pobraane dokumenty.
Rola LLM ograniczyła się do interpretacji tego kontekstu i ukształtowania go w spójną odpowiedź.
A gdy kontekst okazywał się niewystarczający?
System powinien odmówić udzielania domysłów.
Początek od podstawowego RAG
Pierwsza wersja tej architektury wyglądała prosto:
To przedstawia standardowy wzorzec RAG.
Wielki dokument jest dzielony na mniejsze fragmenty, z których każdy jest umieszczany i przechowywany w bazie danych wektorowej.
Gdy użytkownik wysyła pytanie, to również jest embedowane.
Następnie system szuka fragmentów, których embeddingi są semantycznie bliskie.
W teorii to proste.
Jednak szybko pojawił się pewien problem.
Semantyczna bliskość nie gwarantuje rzeczywistej istotności informacji.
Dlaczego wyszukiwanie wektorowe nie wystarczyło
Wyobraźmy sobie użytkownika, który pyta:
">Jakie są skutki oporności na insulinę?"
Szukanie semantyczne dobrze radzi sobie z zrozumieniem ogólnej intencji tego pytania.
To przydatne.
Jednak teksty medyczne są pełne precyzyjnej terminologii.
Terminy takie jak:
- oporność na insulinę
- HbA1c
- hiperglikemia
- metformina
- tolerancja na glukozę
To konkretne terminy mają duże znaczenie.
Czasami potrzebna jest zrozumienie ogólnego znaczenia.
Innym razem trzeba, aby system sam odnalazł dokładny termin.
Dlaczego ograniczać się do tylko jednej funkcji?
Rozwiązaniem było połączenie obu.
Pościg hybrydowy
Tutaj właśnie pоścig hybrydowy stał się kluczową częścią projektu.
Zamiast polegać wyłącznie na wyszukiwaniu opartym na wektorach, zastosowano połączenie wyszukiwania semantycznego z wyszukiwaniem opartym na słowach kluczowych.
Logika stojąca za tym jest dość intuicyjna.
Pościg semantyczny w istocie pyta:
"Który treść ma podobne znaczenie?"
Pościg oparty na słowach kluczowych natomiast pyta:
"Gdzie właściwie pojawiają się kluczowe terminy?"
Każda metoda ma swoje zalety.
A każda ma też swoje słabe strony.
W połączeniu obejmują one szerszy zakres zapytań.
Wynikowy proces wyglądał w ten sposób:
User Query
↓
┌─────────┴─────────┐
↓ ↓
Vector Search Keyword Search
↓ ↓
└─────────┬─────────┘
↓
Combined Results
↓
Reranker
↓
Best Context
↓
LLM
↓
Answer
To zmiany wpłynęły na sposób podejścia do wyszukiwania w przyszłości.
Pozostał jeszcze jeden problem.
Znalezienie czegoś nie oznacza, że to najlepsze rozwiązanie
Załóżmy, że krok wyszukiwania hybrydowego zwraca 20 fragmentów.
To brzmi obiecująco.
Ale czy każdy z tych fragmentów jest rzeczywiście przydatny?
Niekoniecznie.
Część fragmentów może być bardzo istotna dla tematu.
Inne mogą po prostu mieć wspólny słownictwo.
Kolejne mogą być tylko pośrednio powiązane i nie odpowiadać na rzeczywiste pytanie.
Dostarczanie ich wszystkich bezpośrednio do LLM nie jest idealnym rozwiązaniem.
W rzeczywistości może to zaszkodzić wynikowi.
Dodaje to więcej tokenów, większą ilość nieistotnego hałasu oraz wydłuża czas reakcji.
Dlatego wprowadzono dodatkowy etap.
Ponowna klasyfikacja.
Dlaczego ponowna klasyfikacja przyniosła efekt
Rola narzędzia do wyszukiwania można podsumować jako:
Wydobywanie możliwych kandydatów.
Rola narzędzia do ponownej klasyfikacji jest inna:
Określanie, które z tych kandydatów są rzeczywiście istotne.
Zamiast więc prostej łańcuchowej struktury:
Query → Search → LLM
proces ewoluował w kierunku:
Query
↓
Hybrid Search
↓
20 Candidate Chunks
↓
Reranker
↓
Top Relevant Chunks
↓
LLM
To rozdzielenie obowiązków ma znaczenie.
Pierwszy etap wyszukiwania może skupiać się na jak najszerszym zakresie kandydatów.
Etap ponownej klasyfikacji może następnie skupić się konkretnie na istotności i dokładności.
Dla chatbota do badań medycznych ta różnica okazała się szczególnie cenna, ponieważ fragment zawierający jedynie odpowiednią terminologię nie zawsze jest tym fragmentem, który faktycznie odpowiada na pytanie użytkownika.
Najważniejszy element: odmowa fałszowania
Oprócz wyszukiwania i ponownego sortowania, na etapie generowania dodano ścisłe ograniczenia.
Podstawowa instrukcja sprowadzała się do tego:
Use the provided context to answer.
Do not invent information.If the context doesn't contain enough information,
say that there isn't enough information available.
To wygląda niemal zbyt prosto, by mieć znaczenie.
A jednak wyraźnie zmienia sposób zachowania chatbota.
Zamiast zmuszać model do udzielenia odpowiedzi bez względu na wszystko, ten podejście daje mu możliwość wycofania się, gdy materiału po prostu nie ma.
To wyjście okazuje się kluczowe.
Czasami uczciwa odpowiedź brzmi mniej więcej tak:
„Nie udało mi się znaleźć wystarczająco dużo informacji w dostarczonym materiale badawczym.”
Nie każde pytanie zasługuje na pewną odpowiedź.
Czy halucynacje zostały więc całkowicie wyeliminowane?
Nie do końca.
Stało się to jasne podczas tworzenia systemu.
RAG rzeczywiście zmniejsza liczbę halucynacji i sprawia, że odpowiedzi są mocniej powiązane z rzeczywistymi źródłami.
Jednak twierdzenie, że halucynacje nie występują wcale, byłoby przesadą.
Nadal istnieje wiele punktów awarii.
Zestawnik może pobrać niewłaściwy fragment tekstu.
Samo dzielenie tekstu na fragmenty może usunąć ważny kontekst.
Nowy algorytm rankingowy może źle ocenić elementy.
Dokumenty, na których opiera się system, mogą od początku brakować informacji.
A nawet gdy wszystko działa poprawnie, model językowy może błędnie zinterpretować pobraany tekst.
Zatem prawdziwym celem nie jest:
">Stworzenie chatbota, który nigdy się nie myli."
Jest on bliższy:
„Stwórz system, w którym istnieje mniej możliwości błędu i który potrafi rozpoznać granice swojej rzeczywistej wiedzy.”
To o wiele bardziej osiągalny cel.
Projektowanie fragmentów okazało się kluczowe
Jedna z istotnych spostrzeżeń: dzielenie dokumentów na fragmenty to nie jest jednorazowy krok przetwarzania, który można po prostu skonfigurować.
Fragmenty zbyt duże zawierają niepowiązany treść.
Fragmenty zbyt małe mogą usunąć otaczający kontekst, od którego zależy sens stwierdzenia.
Pomaga traktowanie każdego fragmentu jako samodzielnej jednostki wiedzy, a nie arbitralnego kawałka tekstu.
Dobrze zaprojektowane fragmenty prowadzą bezpośrednio do lepszego wyszukiwania informacji.
A lepsze wyszukiwanie zazwyczaj przynosi lepsze ostateczne odpowiedzi.
Sprawny przepływ danych
Prawidłowość była tylko połową wyzwania; drugą połową był czas reakcji.
Jedna prośba RAG może uruchomić kilka różnych operacji:
User Query
↓
Embedding
↓
Vector Search
↓
Keyword Search
↓
Merge Results
↓
Reranking
↓
LLM
Wykonywanie ich wszystkich ściśle po kolei spowalnia cały proces.
Aby temu zaradzić, kroki pobierania danych zostały przekształcone tak, by w miarę możliwości wykonywać je asynchronicznie.
Zmieniony tok wyglądał mniej więcej w ten sposób:
User Query
↓
┌──────┴──────┐
↓ ↓
Vector Search Keyword Search
↓ ↓
└──────┬──────┘
↓
Rerank
↓
LLM
To zmniejszyło czas oczekiwania pomiędzy krokami, które w rzeczywistości nie zależały od siebie.
Sama dokładność to nie wszystko w przypadku dobrego systemu RAG.
Użytkownicy nie chcą siedzieć i czekać na odpowiedź.
Otrzymana architektura
Po kilku rundach udoskonalania proces przekształcił się w coś w rodzaju tego:
Medical Research Documents
↓
Document Processing
↓
Chunking
↓
Embeddings
↓
Vector Database
↓
User Query
↓
┌──────────┴──────────┐
↓ ↓
Semantic Search Keyword Search
↓ ↓
└──────────┬──────────┘
↓
Result Fusion
↓
Reranker
↓
Relevant Context
↓
Grounded Prompt
↓
LLM
↓
Final Response
Każdy komponent na tym diagramie ma określoną rolę.
To rozdzielenie stało się jedną z najcenniejszych lekcji z tego projektu.
Baza danych wektorowych nie służy do odpowiadania na pytania.
Narzędzie do wyszukiwania nie służy do generowania odpowiedzi.
Sztuczna inteligencja językowa nie jest domyślnie w stanie znać wszystkiego.
Każdy element pełni jedną funkcję.
I idealnie, gdy dobrze wykonuje tę funkcję.
Lekcje z procesu tworzenia
Głównym wnioskiem z całego tego ćwiczenia jest to, że RAG to o wiele więcej niż po prostu połączenie sztucznej inteligencji językowej z bazą danych wektorowych. Istnieje kilka elementów, które muszą być uwzględnione, a każdy z nich wymaga uwagi.
Jakość wyszukiwania jest niepodważalna
Nawet najsilniejszy model językowy nie może skompensować słabego kontekstu. Jeśli podasz mu słabe wyniki wyszukiwania, otrzymasz słabe odpowiedzi. To prosty przypadek zasady „to, co wchodzi, to i wychodzi”.
Wyszukiwanie hybrydowe sprawdza się
Szukanie semantyczne doskonale radzi sobie z rozpoznawaniem znaczenia i intencji. Szukanie według słów kluczowych jest skuteczne, gdy ważna jest precyzyjna terminologia. Ponieważ badania medyczne obejmują wiele dokładnych terminów i specyficznych sformułowań, połączenie obu podejść okazało się właściwym rozwiązaniem.
Reranking zasługuje na większe uznanie
Pojawienie się dwudziestu wyników kandydujących to już jeden wyzwanie. Zredukowanie ich do pięciu najlepszych to zupełnie inne wyzwanie. Reranking znajduje się pomiędzy tymi dwoma krokami i wypełnia powstałą lukę.
Większe okna kontekstowe nie gwarantują lepszych odpowiedzi
Na początku istniało założenie, że większa ilość odzyskanego treści naturalnie poprawi wyniki. To założenie nie okazało się prawdziwe. W praktyce pięć ściśle powiązanych fragmentów często przewyższało jakością dwadzieścia średnich.
Przyznanie się do niepewności to zaleta, a nie słabość
To może być najważniejsza lekcja ze wszystkich. System godny zaufania nie powinien czuć się zobowiązany do podawania odpowiedzi bez względu na okoliczności. Gdy odpowiednie informacje po prostu nie są dostępne, system powinien być skłonny to przyznać.
Kierunek dalszych działań
Poziom doskonałości wciąż wymaga poprawy. Obszary wartze dalszego zbadania to:
- Mocniejsze metody oceny wyników wyszukiwania
- Ponowne formułowanie zapytań
- Filtrowanie metadanych
- Ulepszone modele ponownego rankowania
- Odpowiedzi zawierające cytaty
- Ocena pewności oraz logika powstrzymania się od odpowiedzi
- Lepsza możliwość obserwacji procesu wyszukiwania
- Zautomatyzowane zbiory danych do oceny
- Dodatkowe ulepszenia w zakresie buforowania i opóźnień
Budowa odpowiedniego procesu oceny ma szczególne znaczenie, ponieważ ręczna weryfikacja kilku wyników generowanych przez chatboty nie jest skutecznym sposobem oceny jakości. Do kwestii, które warto zmierzyć, należą to, czy od samego początku udało się uzyskać prawidłowe informacje, czy generowana odpowiedź faktycznie opiera się na tych danych, oraz jak często system w ogóle nie udaje się dostarczyć odpowiedniego kontekstu. Te wskaźniki są o wiele ważniejsze niż subiektywne wrażenie, że odpowiedź „brzmi dobrze”.
Podsumowanie
To, co zaczęło się jako prosty chatbot typu RAG, przekształciło się w znacznie głębszą lekcję na temat tego, jak faktycznie działają systemy wyszukiwania informacji. Dyskusje na temat zastosowań AI często koncentrują się na modelach językowych, ale w architekturze RAG to właśnie proces wyszukiwania pełni większość pracy w tle.
Minimalna konfiguracja mogłaby wyglądać tak, jakby dokumenty trafiały do bazy danych wektorowej, a następnie do modelu LLM. Bardziej niezawodna wersja polega na tym, że dokumenty są najpierw dzielone na fragmenty, potem poddawane hybrydowemu wyszukiwaniu, następnie ponownie sortowane, by w końcu trafić jako uzasadniony kontekst przed dotarciem do modelu LLM. Nawet taki proces nadal ma możliwość dalszego rozwoju.
To właśnie ostatecznie sprawia, że budowa systemów RAG jest tak atrakcyjna: nie chodzi tu tylko o to, by model językowy wytwarzał tekst. Chodzi o upewnienie się, że tekst opiera się na odpowiednich informacjach, zanim model w ogóle coś powie.
Uwaga: ten projekt jest przeznaczony wyłącznie do celów badań technicznych i eksperymentowania. Nie zastępuje on profesjonalnej porady medycznej, diagnozy ani leczenia.
Literatura pokrewna
- Mapa poziomów koncepcji inżynierii SZI i kiedy są one ważne — Dowiedz się, które koncepcje inżynierii SZI decydują o tym, czy system w ogóle funkcjonuje, które są istotne podczas tworzenia rozwiązań do użycia w produkcji, a które mogą poczekać.
- Drugi mózg: Przekształcanie transkrypcji spotkań w graf wiedzy dostępną do zapytań — Wyjaśnia, jak system agentowy wyodrębnia entity z transkrypcji spotkań i przechowuje je w Cosmos DB, umożliwiając wyszukiwanie za pomocą języka naturalnego oraz eksplorację grafu wiedzy.