Strona główna / Artykuły

Osiem najlepszych praktyk RAG przetestowanych na 746 stronach podręczników

Które popularne optymalizacje RAG przetrwały testy na trzech podręcznikach produktowych: usuwanie miękkich hyfenów, dostosowywanie rozmiaru fragmentów, planowanie ścieżek przetwarzania, progi eskalacji oraz ponowna klasyfikacja.

Wydawca: REACTAPP.TOP9 min czytania2005 słów

Źródła: I Measured Every RAG “Best Practice” on 746 Pages of Product Manuals. Only Four Survived.

Bot wsparcia stworzony na podstawie trzech rzeczywistych plików PDF – 408-stronicowego podręcznika użytkownika pojazdu elektrycznego, 329-stronicowego przewodnika telewizyjnego oraz 9-stronicowego ulotnika zawierającego bezprzewodowy myszkę – stał się platformą do testowania ośmiu popularnych optymalizacji typu RAG. Zasada była ścisła: nic nie zostawało przyjęte, chyba że pomiary przeprowadzone na tym korpusie, porównane z etykietowanymi odpowiedziami, potwierdzały skuteczność rozwiązania. Literatura i nawyki nie liczyły się.

W rezultacie dokładność wzrosła z 72% do 89%, podczas gdy liczba tokenów promptu na zapytanie spadła z 14 do 57%. Działo się to dzięki czterem zmianom, a nie ośmiu. Dwie z odrzuconych koncepcji negatywnie wpłynęły na wyniki, a jedna z wdrożonych optymalizacji okazała się nigdy nie być wykonywana. Całe badanie kosztowało około 0,015 dolara w postaci wywołań API.

Oto jak radziły sobie poszczególne pomysły. Najcenniejszym elementem na liście wcale nie jest technika typu RAG.

Błąd większy niż jakikolwiek hiperparametr

Zanim dostosujesz proces wyszukiwania, sprawdź, co faktycznie trafiło do indeksu. Wszyscy potwierdzają, że plik PDF został zinterpretowany. Lepszym pytaniem jest to, w jakim stanie znajduje się tekst.

Bezpieczny pętla daje na to odpowiedź:

SOFT = "­"    # U+00AD, the soft hyphen
for manual in manuals:
    print(manual.name, extract(manual).count(SOFT))

W instrukcji obsługi samochodu widniała liczba 2,272.

Miękki przecinek to instrukcja składacza tekstu dla programu renderującego: należy przerwać słowo w tym miejscu, jeśli wiersz się wyczerpie. Czytnik PDF ją stosuje i ukrywa ją, więc nie jest widoczna dla oka, natomiast narzędzie do wydobywania tekstu przekazuje ją w stanie surowym. Na stronie widnieje poprawne słowo, podczas gdy indeks otrzymuje takie ciągi znaków jak ve, miękki przecinek, nowy wiersz, hicle.

W tej instrukcji 999 różnych słów zostało podzielonych na pół, w tym wielokrotnie najważniejsze rzeczownik w każdej instrukcji obsługi samochodu. Słowo Vehicle pojawiło się 1,486 razy jako całe słowo, podczas gdy powinno pojawić się 1,580 razy. Dziewięćdziesiąt cztery takie wystąpienia nie dało się znaleźć za pomocą wyszukiwania.

To jednocześnie uszkadza każdą ścieżkę wyszukiwania. Wyszukiwanie według słów kluczowych dopasowuje się do dosłownych ciągów znaków, a „hicle” nie jest równoznaczne z „vehicle”, bez żadnych punktów za częściowe dopasowanie. Wyszukiwanie wektorowe radzi sobie gorzej, niż się spodziewano, ponieważ modele embeddingów dzielą tekst na fragmenty poniżej poziomu słów, a fragment taki jak „hicle” rozpada się na bezsensowne części. Nawet szczęśliwe dopasowanie wprowadza zniekształcony kontekst do promptu.

Poprawka wymaga tylko jednej linijki, ale obok niej kryje się pułapka. Tekst wyrównany również się rozpada przy prawdziwych myślnikach. Słowo „cus-tomer” powinno zostać połączone z powrotem w „customer”, ale „toll-free” musi pozostać podzielone myślnikiem, a odróżnienie ich wymaga słownika. Było ich 95, a wszystkie pozostały uszkodzone, przy czym liczba została zapisana. Znany brak 95 słów to zupełnie inny artefakt niż ciche domysły, które potajemnie psują korpus. Żaden rozmiar kawałków nie może przywrócić słowa, którego indeks nigdy nie traktował jako słowa.

Najlepszy rozmiar kawałków to pułapka

Większe fragmenty zawierają więcej kontekstu, dzięki czemu odpowiadają na większą liczbę pytań, ale jednocześnie na stałe włączają do każdego zapytania dodatkowy, nieistotny tekst. Istnieje nakładanie się, aby odpowiedź znajdująca się na granicy nie została podzielona na dwie części.

Przetestowano dziewięć konfiguracji w porównaniu z kluczem odpowiedzi. Dokładność można zmierzyć bez żadnych kosztów, natomiast to właśnie koszty są związane z jej pomiarem.

Nakładanie się nigdy nie uzasadniło swojego istnienia, choć nie w sposób, jaki sugeruje pierwsze przeczytanie. Przy 700 znakach usunięcie nakładania się dało wzrost o 11 punktów, co wydaje się negatywne, dopóki nie sprawdzi się drugi przypadek: przy 1800 znakach nakładanie się na poziomie 0, 100 i 200 przyniosło dokładnie 89% wyniku. Jedno porównanie wskazuje, że nakładanie się jest kosztowne, a inne, że nie ma żadnego wpływu.

Przyczyną obu tych wyników jest statystyka, która prawie w ogóle nie pojawiła się na stronie. We wszystkich konfiguracjach, nawet najmniejszych, każda odpowiedź mieściła się w całości w jednym fragmencie, a żadna nie była przecinana na granicy. Przekrycie stanowiło zabezpieczenie przed problemem, którego brakuje w tym korpusie, dlatego jego wartość wahała się między zerem a ujemną wartością. Sprawdzenie, jak często odpowiedzi rzeczywiście przekraczają granicę, powinno poprzedzać płacenie tej opłaty.

Następnie pojawia się pułapka. Najlepszy wynik, 89%, uzyskano przy 1400 znakach i 200 jednostkach przekrycia. Wybór tej opcji oznacza wysyłanie 1283 tokenów na zapytanie zamiast 750, co stanowi 71% więcej na każde zapytanie przez cały okres używania produktu. Przy 18 pytaniach w zestawie 89% oznacza 16 poprawnych odpowiedzi, a 83% – 15. Najlepsza konfiguracja przewyższa najtańszą dokładnie o jedno pytanie.

Zatem zwycięzca nie powinien być wybierany automatycznie. Należy wybrać najtańszą konfigurację, której wynik nie różni się znacząco od wyniku zwycięzcy – w tym przypadku oznacza to różnicę do 8 punktów. Zgodnie z tą zasadą sześć z dziewięciu konfiguracji uzyskało równe wyniki, a wygrała najtańsza z nich. Dokładność wzrosła z 72% do 83%, a ponadto koszty były niższe – była to pierwsza „bezpłatna obiada” projektu, osiągnięta dzięki odmowie optymalizacji mierzonej metryki.

Filtr, który kosztował 22 punkty

Korpus obejmuje trzy produkty. Pytanie dotyczące myszy nie ma powodu, by przeszukiwać 408-stronicowy podręcznik samochodowy, ponieważ dwa pozostałe dokumenty oferują jedynie szanse na błąd. Plan polegał na wykryciu produktu i ograniczeniu wyszukiwania do tego właśnie podręcznika.

Zadanie to wykonał klasyfikator. Z prawidłowym wynikiem w 78% przypadków, w czasie krótszym niż 4 ms i bez żadnych kosztów, co stanowi solidną większość w porównaniu z przeszukiwaniem trzy razy większej ilości tekstu. Mimo to dokładność spadła o 22 punkty.

Ujawnienie się tego mechanizmu zajęło niezwykle długo. Błędny filtr nie obniża rankingu prawidłowej odpowiedzi – po prostu ją usuwa. Bez filtrowania pomieszana wyszukiwarka wśród wszystkich trzech podręczników nadal znajduje właściwy fragment, być może na pozycji 4 zamiast 1, a narzędzie do ponownego rankingu może go uratować. Przy użyciu filtrowania błędnie skierowane pytanie przeszukuje niewłaściwy dokument, a poprawny fragment nie trafia na niski ranking, ponieważ nie występuje w zestawie kandydatów.

Klasyfikator, który ma 78% trafności, zatem nie kosztuje odrobiny jakości. Ustala sztywny limit 78% dla wszystkich kolejnych etapów, bez względu na to, jak dobry jest reszta procesu.

Rozwiązaniem nie jest dokładniejszy klasyfikator, lecz możliwość powstrzymania się od decyzji: stosuj filtr tylko wtedy, gdy jesteś pewien, a przeszukaj wszystko, gdy wyniki dwóch najpopularniejszych produktów są bliskie siebie. W pytaniu typu „jak połączyć to przez Bluetooth?” słowo „to” ma duże znaczenie, a klasyfikator jest tak samo niepewny jak każdy inny.

Lub całkowicie pominąć proces inferencji

Najtańszy router to opcja wybieralna z listy. W przypadku takiego narzędzia zadanie pytania o to, o który produkt chodzi, wymaga tylko jednego kliknięcia, które użytkownik i tak często wykonuje, otwierając czat z strony pomocy produktu. To natychmiast rozwiązuje niejednoznaczność, którą klasyfikator może jedynie zgadywać, a filtr zawsze podaje prawidłową odpowiedź.

Liczby są dokładne. Klasyfikator błędnie skierował 4 z 18 pytań. Poszukiwanie bez filtra znalazło 15 odpowiedzi, a z filtrem – 11; każdy błędny kierunek przekształcił trafienie w nieudane poszukiwanie. Gdy usuniemy te błędne kierunki, dokładność pozostanie bez zmian, a precyzja obiecana przez filtr również się pojawi.

Optymalizacja, która nigdy nie została uruchomiona

Tę część można by pokuszenie usunąć dla zachowania wizerunku.

Plan zakładał odpowiadanie za pomocą taniego modelu 20B, gdy wyniki wyszukiwania wydawały się pewne, a przechodzenie na model 120B, gdy nie były one pewne. Błędne odpowiedzi zazwyczaj pojawiają się w miejscach, gdzie wyniki wyszukiwania były niepewne, a narzędzie do ponownego rankingu już generuje ocenę pewności, więc nie generuje to dodatkowych kosztów.

Progiem ustawiono wartość 0,0, co wydawało się zasadne: kodownik krzyżowy wytwarza logit, a sigmoid(0) równa się 0,5; spadek poniżej zera oznacza wzrost prawdopodobieństwa, gdy najważniejszy fragment jest bardziej prawdopodobnie nieistotny niż istotny. Wyświetlenie rzeczywistej rozkładu pokazywało coś innego – zaobserwowane najwyższe wyniki miały minimalną wartość 3,24, medianę 8,29 oraz maksymalną wartość 10,00.

Progiem był wartość poniżej najniższego kiedykolwiek zaobserwowanego wyniku, więc nigdy nie został aktywowany, ani razu. Zasada eskalacji była identyczna co zawsze używanie tańszego modelu, plus dodatkowe obciążenia w postaci wiersza w tabeli wyników, który nic nie mierzył, choć wyglądał jak wynik badania. Progiem równym zero nie jest neutralny standard – to twierdzenie dotyczące rozkładu, którego nikt nie sprawdził, a każdy taki absolutny próg logit ma tę wadę, ponieważ rozkład zmienia się, gdy zmienia się narzędzie sortowania lub zbiór danych.

Rozwiązaniem było wyliczenie tej liczby. Należy uruchomić tylko dwa punkty końcowe – jeden dla przypadków rzeczywistych, zawsze tani, oraz drugi dla przypadków trudnych, zawsze drogi – przy jednoczesnym rejestrowaniu wyniku, poprawności i kosztu każdego pytania. Każdy próg pomiędzy nimi oznacza ponowne przetworzenie już obecnych w pamięci danych, bez żadnych dodatkowych wywołań API, przy dokładnym przeskanowaniu wszystkich przypadków zamiast tylko ich próbek.

Test przyniósł zaskoczenie: każdy próg zmienia jedynie koszt, a dokładność pozostaje niezmienna. Diagnoza wyjaśnia dlaczego. Spośród dwunastu pytań udało się odzyskać tylko jedno, co oznacza, że tani model zawiodł, natomiast droższy odniósł sukces. To pytanie uzyskało ocenę 10,00, co stanowi maksimum w zakresie, podczas gdy pytania, które tani model już poprawnie rozwiązał, miały medianę 8,29. Jedynym przypadkiem awarii wartym podjęcia działań korygujących był ten, co system odzyskiwania danych oceniał jako najpewniejszy, więc żadna z zasad opartych na reakcji w przypadku niepewności nie może go wykryć przy żadnym progu. Sygnał kierunkowy nie potrafi przewidzieć tego, co miał przewidzieć.

Pojawił się również jeden skutek uboczny. Test w czasie rzeczywistym pokazał wynik 92%, natomiast ponowne przetworzenie już opłaconych rekordów przewidziało 83%. Różnica nie wynika z żadnego progu – pochodzi od faktu, że system oceniający LLM różnie ocenia identyczne odpowiedzi przy drugim przeglądzie i unika w ten sposób podawania informacji o 9-punktowym wzroście, który jest jedynie szumem.

Zmiana, która przyniosła podwójną korzyść

Ponowna sortowanie było najczystszym rozwiązaniem, a jego powód warto zarówno zrozumieć, jak i przyjąć do praktyki.

Wyszukiwanie wektorowe umieszcza pytanie oraz każdy fragment osobno, za pomocą modelu, który nigdy nie traktuje ich jako pary. Kodownik krzyżowy natomiast przyjmuje parę jako jeden wejście i ocenia ją bezpośrednio, co jest znacznie dokładniejsze, ale zbyt wolne, by stosować je wobec całego korpusu. Dlatego ten proces pozyskuje tanio 25 kandydatów, ponownie je sortuje i zachowuje 4 najlepsze.

Wskaźnik poprawności wzrósł z 83% do 89%. Bardziej istotną informacją jest to, gdzie znalazła się odpowiedź. Przed ponownym sortowaniem prawidłowy fragment zazwyczaj zajmował drugie lub trzecie miejsce, więc wysyłano pięć takich fragmentów dla pewności. Po sortowaniu zwykle znajdował się on na pierwszym miejscu, a wystarczały cztery fragmenty. Zadowolenie się podstawową dokładnością pozwala obniżyć liczbę fragmentów do dwóch, co oznacza 57% mniej tokenów.

Ponieważ kolejność poprawia się, mniej fragmentów osiąga tę samą dokładność, a to właśnie tokeny promptu są naliczane. Ta zmiana zapewnia wyższą dokładność przy jednoczesnej obniżce kosztów. Jej cena to 73 ms pracy lokalnego procesora, w porównaniu z 1 252 ms przy użyciu modelu LLM – różnica, której nikt nie zauważy.

Co pozostaje bez zmian

  • Należy sprawdzić dane wejściowe przed użyciem mechanizmu wyszukiwania. Tani pętla może albo ujawnić problemy, takie jak problem z hyfenami, albo potwierdzić, że nie ma ograniczeń, co sprawia, że późniejsze działania są bezpieczniejsze.
  • Domyślna konfiguracja to zazwyczaj wartość ustalona przez kogoś innego, albo w ogóle żadna. Przekrycie na poziomie 100 nigdy nie pomaga, a progi na poziomie 0,0 nigdy nie są aktywowane, i w środowisku produkcyjnym żadne z nich się nie ujawni. Jedynym objawem byłby wyższy rachunek bez żadnego wyjaśnienia.
  • Warto rozważyć, jak zachowuje się optymalizacja w przypadkach błędów, a nie tylko to, jak często się one zdarzają. Filtr, który 22% czasu pomija dane, ale jedynie przestawia wyniki, można zaakceptować. Taki natomiast, który 22% czasu pomija dane i sprawia, że odpowiedź jest niedostępna, nie nadaje się do użycia.
  • Odrzucona idea to również rezultat. Cztery pomysły pozostawione bez wdrożenia to kolejne cztery elementy, które nie wymagają konserwacji, monitoringu, wersjonowania ani alertów w środku nocy.

Istnieje jedna uwaga. Klucz odpowiedzi zawiera 18 zweryfikowanych par pytań i odpowiedzi, więc jedno pytanie jest warte 5,6 punktu. Awaria w przetwarzaniu wynikająca z 22 punktów dotyczy czterech pytań, co jest wystarczające, aby podjąć działania. Wynik z 11 punktami dotyczy dwóch pytań, więc jest co najwyżej orientacyjny. Klucz odpowiedzi opracowany na podstawie własnych danych zespołu powinien mieć pierwszeństwo przed ufaniem liczbom kogokolwiek innego. Pełne przetworzenie zajmuje około pięciu centów na procesorze laptopa, przy czym istnieje sztywne ograniczenie budżetowe, które stanowi wyjątek zamiast pokazywać tę wartość na fakturze.