Strona główna / Artykuły / Uwagi praktyczne: Część II — Gdy RAG nie zwraca niczego

Uwagi praktyczne: Część II — Gdy RAG nie zwraca niczego

Krok po kroku instrukcja obsługi Notatki praktyczne: Część II — Gdy RAG nie zwraca niczego: umowy, sprawdzenia oraz miejsca na kod do wstawienia dla zespołów stosujących ten wzorzec.

1540 słów

Niech to służy jako wersja przeznaczona dla operatorów, zawierająca zasady przedstawione w „Część II — Gdy RAG nie zwraca żadnych wyników”: wyraźne etapy, uporządkowane sekcje kodu oraz notatki naprawcze, które przetrwają przeniesienie obowiązków.

Jak debugować i naprawiać puste wyniki wyszukiwania w systemach AI

Podejście opisane w „Jak debugować i naprawiać” działa najlepiej, gdy traktuje się je jako mierzalną powierzchnię do analizy. Zapisz jeden idealny zapis rozmowy, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian, zanim rozszerzysz zakres pracy. Utrzymuj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności czytania całej struktury. Oddziel zasady dzielenia na fragmenty od zasad wyszukiwania. Zmiana jednych nie powinna zmuszać do przepisywania drugich, gdy zmieniają się metryki jakości.

1. Zacznij od indeksowania i embeddingów

Etap 1 „Start With Indexing” działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię. Zapisz jeden idealny przypadek, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Zdokumentuj zarówno prawidłowy przebieg procesu, jak i ścieżkę naprawczą. Próby ponownych działań, kontrola przez ludzi oraz obsługa wiadomości nieodebranych stanowią część produktu, a nie elementy dodawane później. Oddziel zasadę dzielenia na fragmenty od zasady wyszukiwania. Zmiana jednej nie powinna zmuszać do przepisywania drugiej, gdy zmieniają się metryki jakości.

2. Sprawdź progi, semantykę ocen i filtry

Faza oceny dwóch progów sprawdzania działa najlepiej, gdy traktuje się ją jako mierzalną powierzchnię. Zapisz jeden idealny przepis, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok zawiedzie, awaria powinna wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Oddziel zasadę dzielenia na fragmenty od zasady pobierania danych. Zmiana jednej nie powinna zmuszać do przepisywania drugiej, gdy zmieniają się metryki jakości.

results = vector_store.search(query_embedding, top_k=10)
for r in results:
    print(r.score, r.metadata.get('source'))

3. Przepisywanie zapytań i jakość fragmentów

Faza przepisywania zapytań kontrolnych składa się z trzech etapów i działa najlepiej, gdy jest traktowana jako mierzalna powierzchnia do analizy. Zapisz jeden idealny przykład działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia działań, zanim rozszerzysz zakres pracy. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzucaj ciche, częściowe ukończenie zadań. Rozdziel politykę dzielenia na fragmenty od polityki wyszukiwania. Zmiana jednej z nich nie powinna zmuszać do przepisania drugiej, gdy zmieniają się metryki jakości.

4. Użyj hybrydowego wyszukiwania dla lepszej pamięci przywoławczej

Faza hybrydowego wyszukiwania w ramach strategii 4 Use funkcjonuje najlepiej, gdy traktowana jest jako mierzalna zmienna. Zanim rozszerzysz zakres, udokumentuj jeden idealny przypadek działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian. Zapisz czasy wykonywania operacji oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Rozdziel politykę dzielenia na fragmenty od polityki wyszukiwania. Zmiana jednej z nich nie powinna zmuszać do przepisywania drugiej, gdy zmieniają się metryki jakości. Faza hybrydowego wyszukiwania w ramach strategii 4 Use funkcjonuje najlepiej, gdy traktowana jest jako mierzalna zmienna. Zanim rozszerzysz zakres, udokumentuj jeden idealny przypadek działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian. Udokumentuj zarówno optymalną ścieżkę działania, jak i ścieżkę naprawczą. Próby ponownego wyszukiwania, kontrola przez ludzi oraz obsługa wiadomości błędowych stanowią część produktu, a nie elementy dodawane później.

5. Wyszukuj szeroko, a następnie ponownie sklasyfikuj

W fazie 5 „Retrieve Broadly Then” należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok zawiedzie, powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Należy podawać fragmenty tekstu, które faktycznie stanowią podstawę odpowiedzi. Bez tych odniesień operatorzy nie będą w stanie odróżnić halucynacji od luki w indeksowaniu.

6. Rozszerz zapytanie i stwórz wyraźną ścieżkę awaryjną

W fazie 6 „Rozszerzenie zapytania” należy określić dane wejściowe, osobę odpowiedzialną za tę etap oraz kryteria zakończenia przed modyfikacją kodu. Operatorzy powinni móc ponownie uruchomić ten etap na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Traktuj tę fazę jako umowę pomiędzy danymi wejściowymi a zweryfikowanymi wynikami. Nadaj nazwy poszczególnym elementom, zdefiniuj kryteria sukcesu i odrzuć przypadkowe, częściowe ukończenie zadania. Podaj fragmenty tekstu, które faktycznie stanowią podstawę odpowiedzi. Bez tych odniesień operatorzy nie będą w stanie odróżnić halucynacji od luki w indeksowaniu.

docs = retrieve(query)
if not useful(docs): docs = retrieve(expand(query), hybrid=True)
if not useful(docs): return ask_for_clarification_or_no_answer()

7. Bardziej odporna architektura produkcyjna

W fazie 7 A More Resilient należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie wykonać ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy odnotować czasy wykonywania oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy proces przechodzi z środowiska demonstracyjnego do współdzielonych środowisk. Należy podać fragmenty tekstu, które faktycznie stanowiły podstawę odpowiedzi. Bez tych odniesień operatorzy nie mogą odróżnić halucynacji od luki w indeksowaniu. W fazie 7 A More Resilient należy zdefiniować dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie wykonać ten krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Należy udokumentować zarówno prawidłowy przebieg procesu, jak i ścieżkę naprawczą. Próby ponownych wykonań, kontrole ludzkie oraz obsługa wiadomości błędnych stanowią część produktu, a nie elementy dodawane później.

8. Uczynienie procesu pobierania danych widocznym

Podczas przechodzenia przez etap 8 „Uczynienie procesu pobierania danych widocznym”, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Wolno preferować małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok się nie powiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany łańcuch operacji. Zmierz stopień odzyskiwania informacji na ustalonej serii pytań przed dostosowywaniem promptów. Częste zmiany promptów rzadko naprawiają słabe możliwości pobierania danych.

log({
  'query': query, 'rewritten': rewritten_query, 'filters': filters,
  'candidate_count': len(raw_results), 'scores': scores,
  'selected_chunk_ids': selected_ids, 'fallback': fallback_stage
})

Lista kontrolna operacyjna

Podczas przechodzenia przez etap Listy kontrolnej operacyjnej, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie.

Zachowaj konfigurację poza kodem aplikacji. Pliki środowiskowe, magazyny tajnych danych oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności przeglądania całej struktury.

Mierz stopę odzyskiwania informacji na ustalonej serii pytań przed dostosowywaniem promptów. Częste zmiany promptów rzadko naprawiają słabe mechanizmy wyszukiwania.

Zdefiniuj wersje zależności i zapisz hash obrazu użytego do demonstracji. Reprodukowalność jest ważniejsza od lokalnej wiedzy specjalistów.

Dokumentuj zarówno prawidłowy przebieg działania, jak i ścieżki naprawcze. Próby ponownych działań, kontrola przez ludzi oraz obsługa nieudanych wiadomości stanowią część produktu, a nie elementy dodawane później.

Mierz stopę odzyskiwania informacji na ustalonej serii pytań przed dostosowywaniem promptów. Częste zmiany promptów rzadko naprawiają słabe mechanizmy wyszukiwania.

Zanim wdrożysz cały stack, zamroź wersje, utwórz dokładny zapis dla kluczowych etapów i potwierdź kroki odwracania zmian. Środowiska współdzielone wymagają ograniczeń szybkości, weryfikacji użytkowników oraz wyraźnego właściciela odpowiedzialnego za rotację haseł. Wolimy nudną niezawodność od sprytnych, jednorazowych demonstracji.

Uwaga dotycząca partii 429668e62b58: nie umieszczaj kluczy dostawcy w repozytorium, ustaw ograniczenie liczby tokenów na sesję i przechowuj zapisy obok plików testowych, aby późniejsze zmiany modeli pozostawały porównywalne.

Dla notatki dotyczącej wzmocnienia bezpieczeństwa na etapie 0 zdefiniuj dane wejściowe, osobę odpowiedzialną za dany krok oraz kryteria zakończenia przed zmianą kodu. Operatorzy powinni móc ponownie uruchomić dany krok na podstawie znanego punktu kontrolnego, bez konieczności zgadywania ukrytego stanu. Konfigurację należy przechowywać oddzielnie od kodu aplikacji – pliki środowiskowe, magazyny haseł oraz flagi funkcjonalne powinny znajdować się w jednym miejscu, które operatorzy mogą sprawdzić bez konieczności przeglądania całej struktury.

Szczegół wzmocnienia 0/735: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

Podczas przechodzenia przez pierwszy etap notatki dotyczącej wzmocnienia, najpierw zapisz umowę: wymagane dane wejściowe, sygnał sukcesu oraz to, co dzieje się w przypadku częściowego niepowodzenia. Taka lista kontrolna zapewnia uczciwość późniejszych zmian w kodzie. Wolniej wybieraj małe, testowalne jednostki zamiast rozbudowanych skryptów. Gdy jakiś krok się nie powiedzie, błąd powinien wskazywać na konkretną odpowiedzialność, a nie na skomplikowany proces.

Szczegół wzmocnienia 1/735: zmierz czas wykonywania, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdoty.

Krok 2 notatki dotyczącej wzmocnienia bezpieczeństwa działa najlepiej, gdy traktuje się go jako mierzalną powierzchnię. Zapisz jeden idealny przypadek działania, jeden przypadek awarii oraz notatkę dotyczącą cofnięcia zmian przed rozszerzeniem zakresu. Zapisz czasy wykonywania operacji oraz koszt tokenów lub zapytań obok wyników funkcjonalnych. Wczesna widoczność kosztów zapobiega niespodziewanym rachunkom, gdy ścieżka przechodzi z środowiska demonstracyjnego do współdzielonych środowisk.

Szczegóły wzmocnienia bezpieczeństwa 2/735: zmierz czas wykonywania operacji, klasę błędu oraz zużycie tokenów dla tej notatki, a następnie zdecyduj, czy zachować zmianę na podstawie ustalonego zestawu pytań, a nie jedynie anegdot.

Literatura pokrewna

  • Praktyczne notatki: Skalowanie RAG do 10 milionów dokumentów, część 2: Optymalizacja — Szczegółowy przewodnik po Praktycznych notatkach: Skalowanie RAG do 10 milionów dokumentów, część 2: Optymalizacja: umowy, sprawdzenia oraz miejsca na kod do wstawienia dla zespołów wdrażających ten wzorzec.
  • Praktyczne notatki: Poprawa wydajności RAG — Część 2: HyDE (Hypotetyczny dokument) — Szczegółowy przewodnik po Praktycznych notatkach: Poprawa wydajności RAG — Część 2: HyDE (Hypotetyczny dokument): umowy, sprawdzenia oraz miejsca na kod do wstawienia dla zespołów wdrażających ten wzorzec.