2. Pełny przepływ systemu RAG

Kompletny RAG składa się z kilku etapów o różnych odpowiedzialnościach. Ich rozdzielenie pozwala ustalić, czy problem powstał w danych, wyszukiwaniu, konstrukcji promptu czy podczas generowania. Sama końcowa odpowiedź nie wystarcza do takiej diagnozy.

1. Co przejmujesz z M3

Indeks jest spójnym zestawem reprezentacji liczbowych, tekstów i opisu ich pochodzenia. Dokumenty przygotowano wcześniej. Po nadejściu pytania tworzysz embedding tego pytania i porównujesz go z zapisanymi wektorami. Nie musisz ponownie obliczać embeddingów wszystkich dokumentów dla każdego zapytania.

Plik w semantic_index/ Rola w M4
embeddings.npy Macierz wektorów fragmentów. W dostarczonym indeksie ma 10 wierszy i 1024 kolumny.
chunks.jsonl Teksty, chunk_id, vector_index i pełne metadata, w tym document_id oraz source.
index_metadata.json Opis modelu, wymiaru, normalizacji, identyfikatora indeksu i sum kontrolnych.

Wiersz macierzy musi odpowiadać właściwemu rekordowi tekstowemu. vector_index wskazuje wiersz, chunk_id identyfikuje fragment, a document_id jego dokument. Pozycja w rankingu może się zmieniać zależnie od pytania; to nie powód do zmiany identyfikatora fragmentu. Funkcja load_index() sprawdza zapisany zestaw przed użyciem.

2. Dwa modele i dwa rodzaje wyniku

Model embeddingowy bge-m3:latest zwraca wektor pytania. Model generujący qwen3:4b-instruct-2507-q4_K_M zwraca tekst. Pierwszy pomaga wybrać materiał, drugi opracowuje odpowiedź na jego podstawie. Zgodność modelu embeddingowego z indeksem obejmuje konkretny model_digest, a nie jedynie wspólną liczbę wymiarów.

pytanie → embedding pytania → ranking fragmentów
ranking → filtr → wspólna lista kontekstu
lista → tekst kontekstu → prompt → odpowiedź LLM
lista + odpowiedź → źródła i diagnostyka

LLM nie otrzymuje automatycznie macierzy ani całej bazy. W tym rozwiązaniu dostaje tekst promptu z wybranymi fragmentami i metadanymi. Gdy potrzebny fragment istnieje w indeksie, ale nie znalazł się w kontekście, generator nie ma podstaw do użycia go w odpowiedzi opartej wyłącznie na źródłach.

3. Funkcje na granicach etapów

Funkcja Wejście i wynik
create_embedding() Tekst pytania → wektor zgodny z indeksem.
search_local_index() Wektor pytania, macierz i rekordy → lista score + chunk.
normalize_search_results() Wyniki zagnieżdżone lub płaskie → płaskie rekordy z tekstem i metadanymi.
filter_results_for_context() Wyniki i próg → kandydaci spełniający warunek liczbowy.
prepare_context_results() Kandydaci → poprawne, unikalne fragmenty.
build_context() i build_rag_prompt() Fragmenty → tekst kontekstu → tekst gotowego promptu.
generate_with_ollama() Prompt → tekst odpowiedzi.
build_rag_result() Odpowiedź, kontekst i status → uporządkowany wynik ze źródłami.

Normalizacja wyników wyszukiwania oznacza tu ujednolicenie struktury rekordu. Nie jest tym samym co normalizacja L2 wektora z M3. Pozostawienie jednej nazwy dla jednej czynności pomaga odczytać kod i znaleźć błąd bez zmiany całego programu.

4. Gdzie szukać przyczyny

Jeżeli zaginął tekst warunku podczas dzielenia dokumentu, wracasz do przygotowania danych. Jeżeli tekst jest poprawny, lecz ranking go pomija, analizujesz retrieval. Jeśli oba potrzebne fragmenty trafiły do promptu, a model dopisał nieistniejący krok, sprawdzasz generację. Lepszy model generujący nie naprawia automatycznie błędnego mapowania macierzy na tekst.

Ćwiczenie 1. Odtwórz przepływ

Praca samodzielna offline

Rozpatrz cztery obserwacje. Nie uruchamiaj kodu.

  1. A: load_index odrzuca niezgodną sumę kontrolną chunks.jsonl. B: poprawny fragment o restarcie jest w indeksie, lecz ranking zwraca tylko kopię konfiguracji. C: prompt zawiera restart i kontrolę stanu, a model zaleca trzy restarty. D: odpowiedź ma [S2], ale aplikacja wyświetla przy nim inny fragment niż przekazany jako S2. Wskaż etap, który najpierw sprawdzisz w każdym przypadku.
  2. Ułóż kolejno: źródła, tekst promptu, ranking, pytanie, embedding pytania, odpowiedź modelu. Wyjaśnij, z jakiej listy powinna powstać lista źródeł.
  3. Zapisz, czy model generujący widzi wszystkie 10 fragmentów, jeśli top_k=3 i filtr pozostawił dwa. Uzasadnij odpowiedź.
  4. Wyjaśnij, dlaczego przypadek B nie dowodzi braku informacji w całym korpusie.
Sprawdź rozumienie

Czy rozdzielasz obecność informacji w indeksie, jej przekazanie modelowi i wykorzystanie w odpowiedzi?

Przejście do pakietu ćwiczeniowego

Jeżeli pracujesz również na komputerze, wykorzystaj kartę R1 oraz notebook M12_M4_R1_przeplyw_rag_start.ipynb.

R1 zapisuje mapa_przeplywu.json i proby.jsonl. Nie wywołuje modelu generującego; służy analizie indeksu i kodu. Zachowaj własną ocenę etapów.

ENHANCER+ · Politechnika Warszawska · podręcznik do samodzielnej nauki offline