Podręcznik uczestnika z objaśnieniami, przykładami i ćwiczeniami do samodzielnej nauki do Modułu 3
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 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
- Wczytaj manifest i sprawdź wymagane pola oraz zgodność konfiguracji.
- Odczytaj pliki wskazane w manifeście; sprawdź sumy, kształt macierzy, typ i liczbę rekordów.
- Zweryfikuj unikatowość chunk_id, ciąg vector_index i powiązanie z wektorami R2.
- W nowym procesie wczytaj zapisany indeks i odtwórz ranking dla zapisanego wektora kontrolnego.
- 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
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.
- Po omyłkowym sortowaniu plik rekordów ma kolejność: vector_index 0 → D2, vector_index 1 → D1. Jaki tekst zostanie zwrócony jako pierwszy?
- Wyjaśnij, dlaczego zgodna liczba rekordów i poprawne normy nie wykryły tego błędu.
- Zaproponuj naprawę, korzystając z oryginalnych par tekst–wektor.
- W drugim przypadku manifest podaje 10 fragmentów, macierz ma 9 wierszy, a chunks.jsonl 10 rekordów. Czy można kontynuować wyszukiwanie?
- Opisz test po restarcie, który nie korzysta z macierzy pozostającej w pamięci poprzedniej sesji.
Czy potrafisz wykazać, że wynik wskazuje właściwy tekst, a nie tylko poprawny numerycznie wiersz?
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.