Zmiana modeli embeddingów RAG bez ponownego indeksowania: jak działa rebasis
Zmień modele embeddingu RAG bez ponownego indeksowania: rebasis mapuje nowe wektory zapytań do starego indeksu za pomocą małego adaptera i informuje, gdy łączenie nie przyniesie efektu.
Źródła: Changing the Embedding Model in a RAG System Without Deleting the Index: Why and How I Built rebasis
Udoskonalanie modelu embeddingowego używanego w systemach generacji wzbogaconej o wyszukiwanie wydaje się rutynowe, dopóki istniejący indeks wektorowy nie staje się przeszkodą. Narzędzie open-source w Pythonie o nazwie rebasis jest przeznaczone właśnie do rozwiązania tego konkretnego problemu. Trenuje ono mały adapter, który przekształca wektory zapytań z nowego modelu embeddingowego do przestrzeni, którą już rozumie stary indeks. Dzięki temu pełne ponowne indeksowanie może zostać odłożone lub przeprowadzone stopniowo i pod nadzorem.
Narzędzie testuje kilka rodzajów mapowania (ortogonalny Procrustes z centrowaniem, afiniczne, sieci o niskim rzędzie oraz sieci o małych resztkach) w ramach jednego wspólnego protokołu oceny. Podaje informacje nie tylko na temat jakości dopasowania. Ocenia również, o ile lepszy jest nowy model w danym korpusie, oraz czy dostosowany system przewyższa pozostanie przy starym rozwiązaniu. Przedziały ufności uzyskane metodą bootstrap, kilka metryk wyszukiwania, „odciski palców” ustawień kodowania, powtarzalne zapisy audytowe oraz procedura migracji odporna na awarie sprawiają, że aktualizacja staje się decyzją mierzalną, a nie tylko zaufaniem bez podstaw.
Tematy to RAG, dewiacja embeddingów, bazy danych wektorowych, zgodność wsteczna, migracja modeli, ocena wyszukiwania oraz przybliżone wyszukiwanie najbliższego sąsiada.
Dlaczego model embeddingów zostaje zamknięty
Budowa systemu RAG wymaga od Ciebie czegoś więcej niż tylko modelu językowego i bazy danych wektorowej. Musisz także uwzględnić system współrzędnych danego modelu embeddingu obowiązującego w dniu indeksowania. Dokumenty, niezależnie od tego, czy jest ich tysiące, czy miliony, są dzielone na fragmenty, kodowane i zapisywane w indeksie. Prędzej czy później pojawia się szybszy, lepszy lub bardziej odpowiedni model embeddingu, a wtedy zaczynają się problemy: wektor zapytania z nowego modelu nie ma żadnego znaczenia dla indeksu utworzonego przy użyciu starego modelu.
„Po prostu zaindeksuj wszystko na nowo” to powszechna rada. Technicznie jest ona słuszna, ale często kosztowna. Duża osobista baza wiedzy, zestaw dokumentacji wewnętrznej, baza kodu lub długoterminowa pamięć agenta muszą zostać ponownie podzielone na fragmenty i poddane procesowi embeddingu, co wymaga czasu, zasobów obliczeniowych, budżetu API oraz niesie ze sobą ryzyko operacyjne. Dlatego wiele systemów pozostaje przy przestarzałym modelu długo po tym, jak istnieje już lepszy.
rebasis został stworzony po to, by złamać to uwięzienie. Jego deklarowanym celem jest umożliwienie lokalnemu systemowi RAG zmiany modelu embeddingu bez usuwania istniejącego indeksu wektorowego.
Zmieniaj zapytanie, a nie indeks
Dwa modele embeddingu nie tworzą porównywalnych przestrzeni. Jeśli zakodujemy jedno zdanie za pomocą każdego z nich, wymiary mogą się różnić, ale różnice są głębsze: znaczenie każdej osi, centrum przestrzeni, sposób skalowania oraz układ sąsiedztw semantycznych mogą ulec zmianie. Wektor zapytania z nowego modelu, wysłany bezpośrednio do starszego indeksu, zwraca w dużej mierze bezsensowne wyniki. Niektóre bazy danych wektorowych odrzucają takie zapytania całkowicie, ponieważ wymiary nie odpowiadają strukturze zbioru.
Odpowiedzią narzędzia jest mały, nauczony adapter. Bierze wektor zapytania z nowego modelu i mapuje go do przestrzeni używanej przez istniejący indeks. Aby nauczyć się tej mapowania, te same teksty są kodowane zarówno przez stary, jak i nowy model, co daje wektory w parach. Jeśli związek pomiędzy tymi dwiema przestrzeniami jest wystarczająco nauczalny, nowy wektor zapytania może zostać przekształcony w coś znaczącego dla starego indeksu.
Praktyczne korzyści są duże: nowy model może natychmiast obsługiwać zapytania, a wektory dokumentów w indeksie pozostają nietknięte. Integracja z aplikacją jest celowo prosta. Najpierw import:
from rebasis import Bridge
Następnie ładujemy adapter i umieszczamy go na ścieżce zapytania:
bridge = Bridge.load("adapters/minilm-to-bge.rbs")query_vector = new_model.encode(["how do I deploy to production?"])
query_vector = bridge.to_index_space(query_vector)
results = collection.query(query_embeddings=query_vector, n_results=10)
Bridge to cienka warstwa znajdująca się na głównej ścieżce aplikacji RAG. Gdy adapter zostaje załadowany, sprawdza tożsamości modeli, profile kodowania, wymiary oraz integralność pliku adaptera. Następnie każde zapytanie wymaga jedynie operacji macierzowej. Rejestracja zdarzeń, tworzenie słownika oraz powtarzane weryfikacje są celowo pomijane, ponieważ niewielka wygoda nie powinna przeradzać się w koszt ponoszony przy każdej prośbie. Nie jest również potrzebna karta GPU, ponieważ w takim skali przesyłanie danych między urządzeniami zwykle kosztuje więcej niż sama mnożenie.
Matymatyka stojąca za domyślnym adapterem
Nazwijmy stary model embeddingowy f_old, a nowy f_new, i weźmy n dokumentów zakodowanych za pomocą obu. Daje to dwie macierze danych, po jednej w każdej przestrzeni. Celem jest nauczenie funkcji mapującej nową przestrzeń do starej, a w swojej ogólnej postaci cel treningu minimalizuje odległość normy Frobeniusa pomiędzy zmapowanymi nowymi wektorami a starymi.
Metodą domyślną jest zcentralizowany Orthogonal Procrustes. Najpierw odjęto średnie wartości kolumn w obu macierzach. W przypadku przestrzeni o równej wymiarowości warunkiem jest to, aby transformacja była macierzą ortogonalną przypominającą rotację. Przeprowadza się rozkład wartości singularnych iloczynu zcentralizowanych macierzy, a najlepsza macierz ortogonalna ma postać zamkniętą, utworzoną przez pomnożenie wektorów singularnych lewego i prawego na siebie. Zapytanie jest następnie przekształcane poprzez zcentralizowanie go względem średniej nowej przestrzeni, jej obrót oraz dodanie z powrotem średniej starej przestrzeni. To jest klasyczny problem Procrustesa, badany od lat 60. XX wieku.
W tym rozwiązaniu nie występuje żadna optymalizacja iteracyjna, więc nie ma szybkości uczenia się ani konieczności wyboru liczby epok. Te same dane wejściowe zawsze dają ten sam wynik transformacji.
Wektory są normalizowane pod względem długości przed dopasowaniem, a ponownie po zastosowaniu adaptera, dzięki czemu podobieństwo kosinusowe sprowadza się do iloczynu skalarnego. Centrowanie jest ważne, ponieważ przestrzenie embeddingów są anizotropowe i mają wspólną składową średniej. Jej usunięcie pozwala uniknąć konieczności reprezentowania przesunięcia, którego nie może wyrazić zwykła rotacja. Jeśli para modeli wymaga większej swobody, stosuje się alternatywy afiniczne, o niskim rzędzie lub resztkowe.
Wynika z tego jedna istotna pod względem praktycznym cecha: koszt szkolenia zależy od liczby dopasowanych par, a nie od rozmiaru korpusu. Adapter można dostosować na podstawie zaledwie kilku tysięcy reprezentatywnych par, nawet gdy indeks zawiera setki tysięcy rekordów. Transformacja pełnej macierzy wymaga zasobów proporcjonalnych do iloczynu dwóch wymiarów na każde zapytanie i wykorzystuje pamięć parametrów o podobnej wielkości. Faktoryzacja typu rank-r obniża koszt zapytania do mniej więcej r razy większej wartości niż suma wymiarów. Jako konkretny przykład, macierz 768 na 768 z typem danych float32 zajmuje około 2,36 MB, co jest znikomą ilością w porównaniu z oszczędnościami wynikającymi z uniknięcia ponownego budowania indeksu.
Dlaczego jeden metod transformacji nie wystarcza
Związek pomiędzy dwoma przestrzeniami embeddingów jest często bliski rotacji, ale nie w przypadku każdej pary modeli. Dlatego rebasis nie zakłada, że jeden algorytm będzie działał we wszystkich sytuacjach. Wychodzi od Orthogonal Procrustes – metody o zamkniętej postaci służącej do optymalnego ułożenia dwóch dopasowanych zbiorów punktów. Rzeczywiste przestrzenie mogą jednak wykazywać przesunięcia średnich, różnice w skali w poszczególnych wymiarach oraz komponenty nieliniowe.
Przy użyciu flagi --method auto narzędzie testuje kilka kandydatów na tym samym podziale danych i przy tej samej obróbce wstępnej, a następnie je porównuje:
- Procrustes w wariantach zcentrowanym i klasycznym.
- Mapa liniowa z regularizacją typu ridge.
- Mapa afinna niskiego rzędu.
- Procrustes z skalą dla każdego wymiaru.
- Gdy dostępny jest PyTorch, mała sieć MLP typu residual.
CSLS nie jest narzucany w ramach mapowania; on również konkuruje jako kandydat. Uzasadnienie jest praktyczne – w przestrzeniach wysokowymiarowych może złagodzić problem „hubness” w przypadku słabych adapterów, ale może zaszkodzić już dobrze ustawionej aliancji. Celem nie jest długa lista nazw algorytmów, lecz zwycięzca wybrany na podstawie pomiarów na danych nieuwzględnionych w treningu. Gdy kilku kandydatów znajduje się w tej samej strefie niepewności, narzędzie preferuje ten z mniejszą liczbą parametrów i niższym kosztem.
Dane treningowe i ewaluacyjne pozostają całkowicie oddzielone przez cały proces, i to nie jest tylko konwencja – narzędzie sprawdza ich nakładanie się w czasie wykonywania. Ocena adaptera na podstawie przykładów, których się nauczył, dałaby imponującą liczbę, która jednak niczego nie dowodzi.
Modele asymetrycznego embeddingu również są traktowane w sposób szczegółowy. W rodzinie E5 na przykład prefiksy query: i passage: oznaczają, że ten sam tekst jest kodowany inaczej w zależności od swojej roli, a inne modele używają instrukcji dotyczących zapytań lub dokumentów w tym samym celu. Jeśli dostosujesz adapter do par z kodowanymi dokumentami i zastosujesz go do wektorów z kodowanymi zapytaniami, stworzysz klasyczny przypadek niezgodności między fazą treningu a eksploatacji. Z tego powodu profil kodowania w rebasis uwzględnia znacznie więcej informacji niż sama nazwa modelu: wymiary, normalizację, mechanizmy agregacji, prefiksy zapytania i dokumentu oraz wszelkie wymiary typu Matryoshka. Adapter stworzony pod nieodpowiednim profilem jest odrzucany podczas ładowania, zamiast cicho zwracać słabe wyniki.
Jak to wpisuje się w wcześniejsze badania
Kwestia kompatybilności embeddingów pomiędzy różnymi wersjami jest długo istniejącym problemem. Szkolenie zgodne z zasadami zgodności wstecznej ogranicza nowy model podczas treningu, aby jego reprezentacje pozostały porównywalne z tymi starszymi. Szkolenie zgodne z zasadami zgodności wstecznej działa w przeciwnym kierunku – przygotowuje dodatkowe informacje podczas treningu starego modelu, aby późniejsze aktualizacje były łatwiejsze. Oba podejścia nadają się do dużych systemów wyszukiwania, które kontrolują cały cykl życia modelu od etapu projektowania.
rebasis rozwiązuje inny rodzaj sytuacji. Indeks już istnieje, stare i nowe modele zostały wytrenowane oddzielnie, a nikt nie może ingerować w żaden z procesów treningowych. Dlatego stanowi warstwę kompatybilności post-hoc. Opiera się na metodzie Orthogonal Procrustes, transformacjach niskorankowych oraz nowszych rozwiązaniach z serii Drift-Adapter, a jej własnym wkładem jest aspekt inżynieryjny – pakowanie tych koncepcji w jeden lokalny narzędzie, które dodatkowo umożliwia pomiary, wybór adapterów, stosowanie teorii decyzji, abstrakcje dotyczące magazynów, bezpieczną migrację oraz proces pracy umożliwiający powtarzalne audyty.
CSLS pochodzi z literatury dotyczącej wyrażania wzajemnych powiązań między językami za pomocą embeddingów. Bierze pod uwagę gęstość lokalnej okolicy zapytania i celu, a także kara wektory „hub”, które stają się najbliższymi sąsiadami zbyt wielu zapytań. Mówiąc w uproszczeniu, ocenia parę jako dwukrotność podobieństwa kosinowego minus wyraz zależny od gęstości dla każdej ze stron. Eksperymenty przeprowadzone na własnym korpusie danych projektu wykazały, że pomaga on w przypadku słabych mapowań, a czasami szkodzi silnym, dlatego jest mierzony, a nie stosowany ślepo.
Narzędzie, które czasami mówi ci, byś go nie używał
Na wczesnym etapie projektu okazało się, że pytanie „Czy można zbudować most pomiędzy tymi dwoma przestrzeniami?” samo w sobie jest niewłaściwe. Ważniejsze są trzy pytania:
- Czy nowy model embeddingów rzeczywiście jest lepszy na tych konkretnych danych?
- Ile z jakości pełnego ponownego indeksowania zachowuje adapter?
- Czy metoda łączenia jest lepsza niż po prostu pozostanie przy obecnym modelu?
Dlatego to probe, a nie fit, jest przedstawiane jako kluczowa komenda. Łączy ona próbkowanie, embedowanie, tworzenie danych referencyjnych, dopasowywanie kandydatów, obliczanie metryk oraz ostateczną decyzję w jedną ścieżkę pomiarową, przy czym nigdy nie zapisuje danych do istniejącego indeksu.
Jedną z kluczowych miar jest ARR, Adapted Recall Retention: jakość dostosowanej wyszukiwarki wyrażona jako ułamek tego, co dałoby pełne ponowne indeksowanie z nowym modelem. Wysokie wartości ARR same w sobie nie wystarczają. Jeśli nowy model ledwo poprawia wyniki w porównaniu z starym, adapter ma niewielką wartość praktyczną. Jeśli nowy model stanowi duży krok naprzód, ale adapter nie potrafi przenieść tej korzyści, pełne ponowne indeksowanie może być właściwym rozwiązaniem.
Decyzja zależy zatem od wskaźnika punktu równowagi:
bridge_advantage = ARR × upgrade_gain
Zapisanie tego sprawia, że logika staje się jaśniejsza. Niech Ra oznacza Recall@k dla dostosowanego systemu, Rn dla systemu w pełni przerejestrowanego z nowym modelem, a Ro dla obecnego, starego systemu. ARR to zatem wzrost wydajności dostosowanego systemu w porównaniu ze starym, podzielony przez wzrost wydajności systemu po pełnej rejestracji w porównaniu ze starym, natomiast zysk z ulepszenia to stosunek Rn do Ro. Mnożąc je ze sobą, wyrazy Rn się anulują, pozostawiając Ra podzielone przez Ro – czyli porównanie dostosowanego systemu bezpośrednio z rzeczywistą alternatywą użytkownika, jaką jest brak żadnych działań.
Każdy czynnik odpowiada na proste pytanie. ARR pokazuje, jak duża część idealnego przedefiniowania indeksu została zachowana. Wzrost efektywności po aktualizacji wskazuje, o ile lepszy jest nowy model. Ich iloczyn pokazuje, czy przechodzenie na nowy model faktycznie przyczynia się do postępu. Wartość powyżej 1 oznacza, że przechodzenie na nowy model jest korzystniejsze niż pozostanie przy obecnym; poniżej 1 oznacza, że nie jest. Gdy wynik jest zbyt blisko progu, narzędzie nie może zapewnić pewności. W takim przypadku wynik jest oznaczony jako graniczny, a zalecany jest większy próbka.
Przy dostępnych prawdziwych zapisach zapytań oraz identyfikatorach dokumentów ocenionych przez ludzi, probe może zmierzyć rzeczywisty wzrost efektywności nowego modelu w tym zbiorze danych. Bez takiego zapisu jako zapytania mogą być użyte dokumenty pozostawione na boku, a syntetyczne zapytania oparte na słowach kluczowych dają przybliżoną ocenę. Każdy wynik wskazuje poziom swoich dowodów, dzięki czemu wynik zawiera zarówno ocenę, jak i podstawy, na których została ona ustalona.
Panel pomiarów, a nie jedna liczba
Recall@k jest główną osią decyzyjną, ale jakość wyszukiwania nie jest przedstawiana za pomocą pojedynczej wartości. Jedno wykonanie probe generuje kilka uzupełniających się wskaźników:
- MRR@k pokazuje, na jak wysokim poziomie znajduje się pierwszy istotny wynik.
- nDCG@k bierze pod uwagę zarówno stopień istotności, jak i pozycję w rankingu.
- Top-k overlap pokazuje, jak dużą część otoczenia oryginalnych wyników zachowuje dostosowany zbiór wyników.
- Korelacja Spearmana pokazuje, w jakim stopniu pogarsza się wewnętrzne uporządkowanie wspólnych wyników.
- Odległość Kolmogorowa-Smirnowa mierzy, o ile kalibracja wpływa na rozkład ocen podobieństwa.
- Tail ARR określa jakość najrzadszych klastrów w odniesieniu do średniej globalnej, dzięki czemu ujawnia się odchylenia, które bardziej wpływają na niektóre obszary.
Różnice te są istotne. Dwa systemy mogą zwracać te same dokumenty w różnej kolejności, czego nie może dostrzec wskaźnik recall, natomiast może to zrobić nDCG. Podobnie ranking może wydawać się w porządku, podczas gdy kształt rozkładu ocen zmienia się na tyle, że uniemożliwia działanie filtru z sztywnym progiem. Jeśli wyniki oparte na recall i nDCG się różnią, rebasis zgłasza tę różnicę i nie zastępuje po cichu jednego wskaźnika drugim.
Niepewność powinna być uwzględniona w wyniku
Wartość ARR zmierzona na próbce jest szacunkiem punktowym, dlatego narzędzie określa 95-procentowy przedział ufności na podstawie 2000 ponownych prób bootstrapowych, zgodnie z metodą Efrona. Na poziomie dowodowym T1 ARR stanowi stosunek dwóch średnich. Ponowne losowanie licznika i mianownika niezależnie niszczyłoby ich statystyczną zależność, dlatego w przypadku stosunku sparowanego bootstrap wykorzystuje te same indeksy zapytań dla obu wartości. Granice przedziału odpowiadają 2,5-procentowemu i 97,5-procentowemu percentylowi uzyskanej rozkładu.
Paryzowanie zachowuje rzeczywisty związek: zapytanie trudne dla adaptera zazwyczaj jest również trudne dla orakula. Gdy przedział obejmuje próg decyzyjny, wynik nie jest uznawany za ostateczny. Zamiast mylić się co do miejsc dziesiętnych z naukową pewnością, precyzja pomiaru staje się częścią decyzji. Ziarno losowania, strategia próbkowania oraz wersja metryki trafiają do rejestru audytowego, dzięki czemu przedział można odtworzyć.
Projekt wskazuje, że pomiar bezpośrednio określił kierunek działań. Zgodnie z opublikowanym raportem porównano stary model, prostą zamianę modeli, dostosowaną metodę wyszukiwania oraz pełną reindeksację na identycznych zbiorkach zapytań, w ramach 11 korpusów, 398 010 dokumentów i 10 346 rzeczywistych zapytań użytkowników. Wykorzystano ludzkie oceny istotności, a główne wyniki zostały ocenione niezależnie za pomocą ranx, zamiast polegać wyłącznie na własnym kodzie metryki narzędzia. Według tych danych prosta zamiana zachowała około 12,5% jakości pełnej reindeksacji, natomiast metoda łącząca zachowała około 71%, co stanowi około 6,4 raza większą efektywność niż prosta zamiana.
Bardziej wymownym wynikiem jest to, że metoda łączenia nie zawsze była skuteczna. Okazała się rzeczywiście przydatna tylko w 12 z 62 sprawdzonych par modeli i korpusów. Zasada decyzyjna wskazała właściwy kierunek w 61 z 62 przypadków, w tym w 32 z 33 przypadków dotyczących korpusów, których nie widziała przed ustaleniem tej zasady. Narzędzie zasługuje na zaufanie, gdy podaje uczciwą odpowiedź, np. „przeprowadź ponowną indeksację tutaj” lub „nie potrzebujesz tej aktualizacji”, a także gdy mówi „użyj mnie”.
Całkowity proces w interfejsie linii poleceń
rebasis to nie tylko funkcja biblioteki. Jego interfejs linii poleceń przekształca zmianę modelu w łatwy do zarządzania proces. Zaczyna się od sprawdzenia środowiska oraz dostępnych magazynów i narzędzi do włączania danych:
# Inspect the environment and available store/embedder support
rebasis doctor
Następnie następują trzy etapy rzeczywistego procesu: najpierw pomiary i wybór ścieżki, następnie zamontowanie adaptera, a w końcu migracja indeksu w tle w partiach, gdy będzie gotowy.
# Measure first and choose the right path
rebasis probe --store chroma:///path/to/db#notes \
--old sentence-transformers/all-MiniLM-L6-v2 \
--new BAAI/bge-base-en-v1.5 \
--queries queries.jsonl --sample 10000 --report report.html# Fit the appropriate adapter
rebasis fit --store chroma:///path/to/db#notes \
--old sentence-transformers/all-MiniLM-L6-v2 \
--new BAAI/bge-base-en-v1.5 \
--method auto --pairs 4000 \
--out adapters/minilm-to-bge.rbs# When ready, migrate the index in background batches
rebasis migrate --adapter adapters/minilm-to-bge.rbs \
--store chroma:///path/to/db#notes --priority access --limit 5000
Wynikowy adapter .rbs przechowuje coś więcej niż tylko wagi. Jego manifest zawiera informacje o tożsamości starych i nowych modeli, wymiarach wektorów, kierunku oraz odciskach palców profilu kodowania. Tensorzy są przechowywane w formacie safetensors, a razem z nimi przekazywane są wyniki kalibracji ocen i oceny. Adapter stanowi zatem przenośny, sprawdzalny zapis tego, jakie modele i warunki go stworzyły, a hashe tensorów można ponownie obliczyć w celu weryfikacji integralności.
Kalibracja wyników wymaga szczególnej uwagi. Transformacja może zachować kolejność rankingów, ale jednocześnie zmienić wartości bezwzględnych ocen podobieństwa. Aplikacja z ustalonym progiem, np. similarity > 0.7, może w ten sposób po cichu odrzucać wyniki. Aby temu zaradzić, narzędzie stosuje monotonowy kalibrator izotoniczny, który przywraca wyniki do starej skali bez zmiany ich kolejności, a jednocześnie ostrzega systemy, które polegają na stałych progach.
Behawior obliczeniowy i pamięciowy
Narzędzie, które teoretycznie nie musi trzymać całego korpusu w pamięci, może go jednak przypadkowo załadować. W rebasis iteratorzy korpusu przesyłają rekordy strumieniowo, więc maksymalna ilość pamięci potrzebna podczas migracji wynosi mnożnik rozmiaru partii przez wymiar wektora. Czas wykonywania rośnie wraz z liczbą rekordów, ale korpus użytkownika nigdy nie jest przechowywany w RAM. Gdy ilość pamięci zbliża się do limitu --max-memory, rozmiar partii może się zmniejszyć, a zadanie z zapisami kontrolnymi może zostać wstrzymane zamiast zakończone.
Macierz podobieństwa używana do wyszukiwania wartości prawdziwych oraz do przeprowadzania zapytań w zależności od wielkości próbki również nie jest budowana w pełnym wymiarze. Zapytania są przetwarzane w blokach. Każdy blok dokonuje mnożenia macierzy, wybiera najlepsze k wyników i usuwa tymczasową macierz ocen. Pełne sortowanie kosztowałoby S log S na każdy wiersz. Użycie argpartition sprawia, że oczekiwany koszt selekcji na wiersz pozostaje liniowy względem S. W przypadku znormalizowanych wektorów float32 wyszukiwanie kosinusowe sprowadza się do jednego mnożenia macierzy, co pozwala kontrolować zarówno zużycie pamięci, jak i różnice pomiędzy platformami związanymi z typem danych.
W tym projekcie procesor jest elementem kluczowym, a nie rozwiązaniem drugorzędnym. Karta graficzna może znacznie przyspieszyć generowanie embeddingów, ale transfer danych między urządzeniem a serwerem może zniwelować te korzyści przy małej liczbie operacji adaptatora. Testy ekwiwalencji urządzeń porównują tolerancje wyników, a także zidentyfikowane zestawy sąsiadów oraz przede wszystkim to, czy identyczne dane prowadzą do identycznej ostatecznej decyzji. Niewielka różnica liczbowa, która sprawia, że wartość ARR przekracza próg na poziomie 0,95, nie jest akceptowalną zmiennością sprzętową; jest to uznawane za wadę w zachowaniu produktu.
Migracja odporna na przerwy
Dzięki temu rozwiązaniu indeks nie musi być zmieniany od razu; system może nadal działać poprzez adaptator tak długo, jak to konieczne. Jeśli indeks ma zostać przeniesiony trwale, funkcja migrate przenosi rekordy do nowego miejsca partiami, a w tym przypadku bezpieczeństwo danych ma pierwszeństwo przed szybkością przetwarzania.
Każda partia rozpoczyna się od odczytu obecnych wektorów, które są kopiowane do przechowalni cieniowej przed jakimkolwiek nadpisaniem. Następnie zapisywane są przekształcone wektory, a próbka zapisanych rekordów jest ponownie odczytywana w celu ich weryfikacji. Na końcu narzędzie nie polega wyłącznie na swoim aktualnym identyfikatorze klienta – ponownie otwiera przechowalnię poprzez nowe połączenie i ponownie pobiera próbki w celu zapewnienia trwałości danych, dzięki czemu cache po stronie klienta nie może ukryć tego, co faktycznie trafiło do trwałego przechowywania.
Silnik migracji opiera się na czterech niezmiennikach:
- W przechowalni cieniowej musi istnieć oryginalny wektor typu float32 przed zmianą jego rekordu.
- Próbka po zapisie z każdej ukończonej partii musi być dostępna do odczytu w ramach dopuszczalnych błędów.
- Zakończona operacja musi nadal być weryfikowana po ponownym otwarciu przechowalni poprzez nowe połączenie.
Kolejność tych działań stanowi podstawę argumentu dotyczącego bezpieczeństwa w przypadku awarii. Jeśli proces ulegnie zakończeniu po zapisie w kopii cienia, ale przed zapisem do głównej bazy danych, powstanie nieszkodliwa dodatkowa kopia. Jeśli te dwa kroki zostaną zamienione miejscami, ta sama przerwa może trwale zniszczyć oryginalny wektor.
Kolejka migracji pełni jednocześnie rolę punktu kontrolnego, dzięki czemu polecenie --resume kontynuuje pracę od ostatniej ukończonej partii. Narzędzie może monitorować obciążenie pamięci i stan baterii, a dziennik dostępów może umieszczać najczęściej wykorzystywane rekordy na początku. Jeśli wynik nie spełnia oczekiwań, polecenie rollback przywraca oryginały z kopii cienia. Umowy współdzielone pomiędzy różnymi backendami (Chroma, LanceDB, sqlite-vec, Qdrant, FAISS oraz wersja w pamięci) zapewniają, że te operacje mają wszędzie to samo znaczenie.
Wtyczki dla różnych rozwiązań
Local RAG nie opiera się na pojedynczej bazie danych wektorowej ani dostawcy embeddingów, dlatego przechowywanie danych i generowanie embeddingów odbywa się za pośrednictwem rejestrów opartych na wtyczkach. Obsługiwane bazy danych to: Chroma, LanceDB, sqlite-vec, Qdrant i FAISS, a także backend działający w pamięci. Do generowania embeddingów wykorzystuje się narzędzia takie jak sentence-transformers, fastembed, Ollama, API kompatybilne z OpenAI, llama.cpp oraz wektory przeliczone z góry.
Podstawowa instalacja ma działać bez PyTorch. Podstawowe funkcje probe, metoda dopasowania Procrustesa oraz logika decyzyjna działają przy użyciu NumPy, SciPy i scikit-learn, natomiast ciężkie lub specyficzne dla platform zależności instaluje się tylko wtedy, gdy są one potrzebne. Pakiety od third party mogą dostarczyć punkt wejścia rebasis.stores lub rebasis.embedders, aby umożliwić integrację bez konieczności modyfikowania projektu.
Prywatność, logowanie i powtarzalność
Zgodnie z projektem rebasis nie wysyła żadnych lokalnych danych nigdzie. Nie posiada telemetrii typu „phone-home” ani licznika zużycia, a teksty dokumentów oraz wektory nigdy nie trafiają do dzienników. Ponieważ informacje można odtworzyć na podstawie embeddingu, wektory są traktowane jako równie wrażliwe jak zwykły tekst. Obsługa OpenTelemetry dostępna jest jako opcja, jest wyłączona domyślnie i eksportuje dane wyłącznie do własnego kolektora użytkownika.
Każda decyzja może być zapisana w dzienniku audytowym, do którego można jedynie dodawać nowe wpisy, dzięki czemu pozostaje on możliwy do odtworzenia. Wpisy zawierają identyfikatory modeli, odciski palców profili, metodę próbkowania, wartość seed, progi, wersję metryki, wersję rebasis oraz szczegóły środowiska. Wpisy są połączone łańcuchem hash, co umożliwia wykrycie późniejszych uszkodzeń lub częściowych modyfikacji. Polecenie rebasis audit replay ponownie uruchamia wcześniejsze pomiary, aby ustalić, czy różnica wynika z regresji oprogramowania, czy ze zmian w korpusie danych.
Czego ma dowieść pakiet otwartego oprogramowania
rebasis jest udostępniany na zasadach licencji Apache 2.0, a jego głównym celem jest umożliwienie weryfikacji jego twierdzeń oraz czytelności kodu. W repozytorium znajdziesz zapisy decyzji architektonicznych dotyczących kluczowych wyborów, scenariusze referencyjne, dane z rzeczywistych zbiorów danych, limity wydajności, testy kontraktowe dla poszczególnych warstw backendowych, testy CLI wykonywane od początku do końca oraz dokumentację dla współtwórców. Strategia testowa obejmuje nie tylko scenariusze idealne, ale także sprawdza spójność numeryczną pomiędzy urządzeniami, limity pamięci, właściwości adapterów, kontrakty przechowywania oraz trwałość procesów migracji i odwracania zmian.
Proces CI jest skonfigurowany tak, aby działać z Pythonem 3.12 i 3.13 na systemach Linux i macOS – dwóch systemach o różnych zasadach zarządzania pamięcią. Wersje zależności spełniające minimalne wymagania mają własny etap wykonywania, a osobny proces sprawdza, czy dodatkowe elementy takie jak PyTorch czy OpenTelemetry nie przenikają do głównego pakietu. Sprawdzanie typów odbywa się za pomocą mypy --strict, jakość kodu jest kontrolowana przez Ruff, granice warstw – przez import-linter, a linki do dokumentacji – przez MkDocs w trybie strict. Ideą tego podejścia jest to, że zaufanie do oprogramowania otwartego źródłowego opiera się mniej na mocnych twierdzeniach w README, a bardziej na pokazaniu, jakie testy i pomiary je potwierdzają.
Zmiany w modelu bez konieczności wyboru „wszystko albo nic”
Podstawowym problemem nie jest wybór technologii, lecz koszt jej zmiany. W miarę rozwoju systemów RAG ich indeksy stają się inwestycjami w infrastrukturę, a wybór modelu embeddingu przekształca się w decyzję o znacznie trudniejszym odwróceniu, niż powinno to być. Ideą rebasis jest złagodzenie tego powiązania.
Gdy pojawia się nowy model, pierwszym krokiem powinno być sprawdzenie, czy faktycznie radzi sobie lepiej na własnych danych. Jeśli tak, następnym krokiem jest ustalenie, czy można stworzyć niezawodny most łączący go z obecnym indeksem. Jeśli most jest wystarczająco dobry, nowy model można natychmiast wykorzystać. Jeśli z czasem chce się osiągnąć pełną jakość, migracja może odbywać się w kontrolowanych partiach z gwarancjami weryfikacji i odwrócenia działań. A jeśli most okazuje się niewystarczający, powinno to zostać odkryte przed kosztownym eksperymentem w środowisku produkcyjnym, a nie w trakcie niego.
To właśnie przestrzeń decyzyjną oferuje to narzędzie: najpierw pomiary, następnie łączenie, a w razie potrzeby bezpieczna migracja. Jest to otwarte narzędzie, którego celem jest wzmocnienie lokalnej infrastruktury RAG, złagodzenie konieczności wyboru modeli do wgrania oraz zwiększenie przejrzystości aktualizacji modeli; jest również dostępne dla programistów, którzy mogą je sprawdzić, wypróbować na rzeczywistych zbiorkach danych i przyczynić się do jego dalszego rozwoju.
Literatura pokrewna
- Notatki praktyczne: Bazy danych wektorowych do produkcji RAG: indeksowanie, wyszukiwanie hybrydowe — Szczegółowy przewodnik po Notatkach praktycznych: Bazy danych wektorowych do produkcji RAG: indeksowanie, wyszukiwanie hybrydowe: umowy, sprawdzenia oraz gotowe fragmenty kodu dla zespołów wdrażających ten model.
- RAG w zwykłym Pythonie: dzielenie na fragmenty, TF-IDF, podobieństwo kosinowe i formułowanie zapytań — Budowanie systemu generacji wzbogaconej o wyszukiwanie wyłącznie za pomocą modułu matematycznego: dzielenie na fragmenty metodą okna przesuwającego się, wektory TF-IDF, ranking kosinowy, konkretne zapytania i ich ograniczenia.