6. Od listy embeddingów do lokalnego indeksu

Lista wektorów wystarcza do pierwszego eksperymentu. Indeks pozwala uporządkować dane, zapisać je i ponownie wyszukać te same fragmenty po uruchomieniu nowej sesji. Jego najważniejszą cechą jest zachowanie zgodnego powiązania liczb z tekstami.

1. Embedding, macierz i indeks

Pojęcie Rola w M3
Embedding Wektor jednego tekstu. Sam nie zawiera nazwy źródła.
Macierz Wektory wielu fragmentów ułożone w wierszach. Kształt N × D: N fragmentów, D współrzędnych.
Indeks lokalny Macierz wraz z rekordami fragmentów, metadanymi i manifestem opisującym całość.

Dla 10 fragmentów i 1024 wymiarów macierz ma kształt (10, 1024). Po normalizacji każdego wiersza i pytania podobieństwa można policzyć przez embedding_matrix @ query_norm. Otrzymujesz po jednej liczbie dla każdego wiersza. Sortowanie tych wartości dopiero wyznacza kolejność wyniku.

Obliczenie w NumPy eliminuje część narzutu pętli Pythona, lecz nadal porównuje pytanie ze wszystkimi fragmentami. Jest to wyszukiwanie dokładne. Sam zapis do pliku NPY nie tworzy struktury przybliżonego wyszukiwania ANN i nie dowodzi przyspieszenia w każdym przypadku. M3 wybiera prosty indeks ze względu na czytelność i możliwość weryfikacji.

2. Zasada mapowania

Wiersz i musi oznaczać ten sam fragment

Wiersz i w macierzy odpowiada rekordowi na pozycji i w chunks.jsonl. Ten rekord ma vector_index = i. Zgodność samej liczby wierszy nie wystarcza, jeśli wektory i teksty zostały przemieszane.

Po odrzuceniu rekordu albo zmianie kolejności odtwórz ciąg indeksów od zera. Zachowaj oryginalne chunk_id i pełne metadane. Nie sortuj samej macierzy lub samego pliku rekordów. Ranking wyników jest osobną listą odwołań i nie wymaga przestawiania bazy.

3. Trzy pliki jednego indeksu

semantic_index/
    embeddings.npy
    chunks.jsonl
    index_metadata.json
Plik Zawartość i kontrola
embeddings.npy Znormalizowana macierz float32. Kształt, skończone wartości i normy wierszy muszą zgadzać się z założeniami.
chunks.jsonl Teksty, pełne metadane i vector_index. Wektorów nie powiela się w każdym rekordzie tego pliku.
index_metadata.json Manifest: wersja schematu, index_id, model, backend, wymiar, miara, normalizacja, liczba fragmentów, typ danych, nazwy plików, pochodzenie i data.

W manifestach pakietu schema_version jest tekstem "1.0", dimension liczbą 1024, metric ma wartość "cosine", normalized to logiczne true, a data_type to "float32". chunk_count opisuje liczbę wierszy. Tekst "true" nie zastępuje logicznego true; format pliku ma znaczenie dla walidacji.

Dodatkowo zachowano model_digest i sumy SHA-256 danych. Suma kontrolna pozwala wykryć zmianę zawartości od momentu zapisu, ale nie dowodzi poprawności tekstu ani prawidłowego mapowania. embedding_manifest.json opisuje etap R2; index_metadata.json opisuje gotowy indeks R5. Nie zastępują się wzajemnie.

4. Odczyt i test po restarcie

  1. Wczytaj manifest i sprawdź wymagane pola oraz zgodność konfiguracji.
  2. Odczytaj pliki wskazane w manifeście; sprawdź sumy, kształt macierzy, typ i liczbę rekordów.
  3. Zweryfikuj unikatowość chunk_id, ciąg vector_index i powiązanie z wektorami R2.
  4. W nowym procesie wczytaj zapisany indeks i odtwórz ranking dla zapisanego wektora kontrolnego.
  5. Porównaj identyfikatory i score przed oraz po zapisie. Drobne różnice zmiennoprzecinkowe oceniaj z określoną tolerancją.

search_local_index(query_embedding, embedding_matrix, chunk_records, top_k=3) zwraca elementy score i chunk. To inny kształt niż płaski wynik search_similar_chunks() z R4. Funkcja normalize_search_results() ujednolica strukturę wyników; nie normalizuje długości wektorów. Sprawdź tę różnicę, zanim napiszesz kod odczytujący chunk_id.

Ćwiczenie 5. Wykryj uszkodzone mapowanie

Praca samodzielna offline

Dydaktyczna macierz dwuwymiarowa ma dwa wiersze: wiersz 0 = [1, 0] dla tekstu D1, wiersz 1 = [0, 1] dla D2. Dla q = [1, 0] score wynoszą 1 i 0.

  1. Po omyłkowym sortowaniu plik rekordów ma kolejność: vector_index 0 → D2, vector_index 1 → D1. Jaki tekst zostanie zwrócony jako pierwszy?
  2. Wyjaśnij, dlaczego zgodna liczba rekordów i poprawne normy nie wykryły tego błędu.
  3. Zaproponuj naprawę, korzystając z oryginalnych par tekst–wektor.
  4. W drugim przypadku manifest podaje 10 fragmentów, macierz ma 9 wierszy, a chunks.jsonl 10 rekordów. Czy można kontynuować wyszukiwanie?
  5. Opisz test po restarcie, który nie korzysta z macierzy pozostającej w pamięci poprzedniej sesji.
Sprawdź rozumienie

Czy potrafisz wykazać, że wynik wskazuje właściwy tekst, a nie tylko poprawny numerycznie wiersz?

Przejście do pakietu ćwiczeniowego

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

Notebook tworzy semantic_index, zapisuje kontrola_restartu.json i sprawdza odczyt w osobnym procesie. Następnie wykonaj 07_sprawdzenie_indeksu_po_restarcie.ipynb w nowym kernelu. Kontrola z zapisanym wektorem pytania nie wymaga ponownego wywołania modelu.

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