Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds
Powrót do kolekcji
Przewodnik11 min czytania

Weaviate, baza wektorowa z wyszukiwaniem hybrydowym

Weaviate łączy wyszukiwanie wektorowe z pełnotekstowym, ma wielodostępność i wbudowane wektoryzatory. Schemat, zapytania, ceny Flex i porównanie z Qdrantem.

Weaviate, wyszukiwanie znaczeniowe i słowne w jednym zapytaniu

Większość baz wektorowych robi jedną rzecz: znajduje fragmenty o podobnym znaczeniu. Problem w tym, że użytkownicy szukają też dokładnych ciągów znaków, a wektor nie odda numeru zamówienia ani kodu błędu. Weaviate ma oba mechanizmy wbudowane i łączy je w jednym zapytaniu.

Druga rzecz, która odróżnia tę bazę, to wielodostępność wbudowana w model danych. Aplikacja obsługująca setki klientów nie potrzebuje osobnej instancji dla każdego ani ręcznego filtrowania po identyfikatorze, bo izolacja jest częścią schematu.

Kolekcje i schemat

Dane organizujesz w kolekcje o zadeklarowanych właściwościach. Schemat nie jest obowiązkowy w sensie ścisłym, ale jego brak odbiera możliwość filtrowania i indeksowania, więc w praktyce zawsze go definiujesz.

Code
Python
import weaviate
from weaviate.classes.config import Property, DataType, Configure

klient = weaviate.connect_to_local()

klient.collections.create(
    "Dokument",
    properties=[
        Property(name="tresc", data_type=DataType.TEXT),
        Property(name="tytul", data_type=DataType.TEXT),
        Property(name="jezyk", data_type=DataType.TEXT),
        Property(name="rok", data_type=DataType.INT),
    ],
    vector_config=Configure.Vectors.text2vec_openai(),
)

Ostatnia linia jest tym, co odróżnia tę bazę od rozwiązań, w których osadzenia liczysz sam. Baza może wywołać model wektoryzujący za Ciebie, więc wstawiasz zwykły tekst i nie zajmujesz się przekształceniem.

To wygodne i ma jedną konsekwencję do przemyślenia. Baza musi mieć dostęp do dostawcy modelu i klucz, a przy wektoryzatorze chmurowym treść dokumentów wychodzi na zewnątrz. Przy danych wrażliwych sięgasz po wektoryzator uruchomiony lokalnie albo liczysz osadzenia we własnym kodzie i wstawiasz gotowe wektory.

Wyszukiwanie hybrydowe

To główny powód, dla którego ludzie wybierają tę bazę, więc warto zrozumieć, co dokładnie robi.

Code
Python
kolekcja = klient.collections.get("Dokument")

wyniki = kolekcja.query.hybrid(
    query="blad przy logowaniu ERR_AUTH_401",
    alpha=0.5,
    limit=5,
    filters=Filter.by_property("jezyk").equal("pl"),
)

Baza wykonuje dwa wyszukiwania równolegle, wektorowe i słowne, po czym łączy wyniki, przydzielając punkty według pozycji na obu listach. Fragment obecny w obu wypada wyżej niż fragment obecny tylko w jednej.

Parametr sterujący proporcją jest tu najważniejszy. Wartość zero to czyste wyszukiwanie słowne, wartość jeden to czyste znaczeniowe, a wartości pośrednie mieszają jedno z drugim. Punkt wyjścia w okolicach połowy sprawdza się w większości przypadków, ale przy dokumentacji technicznej pełnej nazw własnych warto przesunąć go w stronę wyszukiwania słownego.

Największa korzyść ujawnia się w zapytaniach mieszanych, gdzie użytkownik podaje opis problemu razem z konkretnym kodem. Samo wyszukiwanie znaczeniowe zgubi kod, samo słowne zgubi opis, a połączenie znajduje właściwy fragment.

Wielodostępność

Aplikacja obsługująca wielu klientów staje przed pytaniem, jak odseparować ich dane. Rozwiązanie przez filtr po identyfikatorze działa, dopóki ktoś nie zapomni go dodać, a wtedy jest wyciekiem.

Code
Python
klient.collections.create(
    "DokumentKlienta",
    multi_tenancy_config=Configure.multi_tenancy(enabled=True),
    properties=[Property(name="tresc", data_type=DataType.TEXT)],
)

kolekcja = klient.collections.get("DokumentKlienta")
kolekcja.tenants.create(["klient-118", "klient-119"])

dane_klienta = kolekcja.with_tenant("klient-118")

Każdy najemca dostaje własny fragment indeksu, więc zapytanie fizycznie nie może zwrócić danych innego. To różnica jakościowa wobec filtrowania, bo bezpieczeństwo wynika ze struktury, a nie z dyscypliny przy pisaniu zapytań.

Drugą zaletą jest zarządzanie kosztem. Najemcy nieaktywni można przenieść w stan uśpienia, gdzie ich dane schodzą do tańszego magazynu i nie zajmują pamięci. Przy usłudze z tysiącem klientów, z których aktywnych jest stu, oszczędność bywa znaczna.

Trzecia to usuwanie. Klient odchodzi, kasujesz jego najemcę i wszystkie dane znikają jednym wywołaniem, bez wyszukiwania wpisów po identyfikatorze. Przy wymogach dotyczących usuwania danych na żądanie ta właściwość zamienia procedurę na jedno wywołanie, zamiast na skrypt, który trzeba potem udokumentować.

Filtrowanie i przenoszenie danych

Filtry działają obok wyszukiwania, a nie po nim, więc warunek zawęża zbiór kandydatów, zamiast odsiewać gotowe wyniki. To różnica istotna dla poprawności: przy odsiewaniu po fakcie wąski warunek potrafi zostawić pustą listę mimo pasujących wpisów w bazie.

Code
Python
from weaviate.classes.query import Filter

wyniki = kolekcja.query.near_text(
    query="polityka zwrotow",
    limit=5,
    filters=(
        Filter.by_property("jezyk").equal("pl")
        & Filter.by_property("rok").greater_or_equal(2025)
    ),
)

Warunki da się łączyć operatorami logicznymi, więc typowe zapytanie z trzema ograniczeniami mieści się w jednym wyrażeniu. Właściwości używane w filtrach warto oznaczyć jako indeksowane, bo bez tego baza przegląda je liniowo.

Osobną sprawą jest wstawianie dużych partii danych. Wstawianie po jednym obiekcie przy stu tysiącach fragmentów to sto tysięcy podróży do bazy, więc używa się wstawiania wsadowego z kontrolą błędów.

Code
Python
with kolekcja.batch.dynamic() as partia:
    for fragment in fragmenty:
        partia.add_object(properties=fragment)

if kolekcja.batch.failed_objects:
    print(f"Nie zapisano: {len(kolekcja.batch.failed_objects)}")

Sprawdzenie listy niezapisanych obiektów jest tu obowiązkowe. Wstawianie wsadowe nie przerywa się przy pojedynczym błędzie, więc bez tej kontroli część fragmentów po cichu nie trafi do indeksu, a zauważysz to dopiero przy braku odpowiedzi na pytanie.

Agent zapytań

Baza udostępnia też warstwę, która sama planuje wyszukiwanie: zamienia pytanie w języku naturalnym na sekwencję zapytań, wykonuje je i składa odpowiedź.

To wygodne przy prototypie, bo zdejmuje z Ciebie budowanie logiki wyszukiwania. Ma jednak dwie konsekwencje. Pierwsza to koszt, bo agent jest rozliczany osobno: plan Free daje tysiąc zapytań miesięcznie, a osobna subskrypcja za 30 USD miesięcznie na organizację obejmuje cztery tysiące zapytań i pozwala przekraczać ten próg z rozliczeniem za zużycie. Druga to przewidywalność, bo trudniej diagnozować, dlaczego odpowiedź jest zła, gdy nie wiesz, jakie zapytania powstały.

Praktyczne podejście polega na użyciu agenta do zbadania, jakie zapytania działają, a potem zapisaniu tej logiki we własnym kodzie. Zyskujesz kontrolę i przewidywalny koszt.

Ceny

WariantKosztDla kogo
Wersja otwarta0 USDWdrożenie u siebie, pełna kontrola
Free0 USD bezterminowoJeden klaster na konto, nauka i mały projekt
Flexod 45 USD miesięcznieRozliczenie za zużycie, bez zobowiązania
Premiumod 400 USD miesięcznieUmowa przedpłacona, wariant współdzielony albo dedykowany

Dwie rzeczy w tej tabeli zmieniły się względem starszych opisów. Wygasający po dwóch tygodniach Sandbox zastąpił plan Free bez terminu ważności: jeden klaster na użytkownika, sto tysięcy obiektów, gigabajt pamięci i dziesięć gigabajtów dysku, jedna kolekcja i najwyżej trzej najemcy, z możliwością przejścia na plan płatny bez utraty danych. Zniknął też plan Plus, który cennik wymieniał między Flex a Premium.

Rozliczenie w wersji zarządzanej opiera się na trzech wymiarach: liczbie wymiarów wektorowych (liczba obiektów razy wymiarowość indeksu razy współczynnik replikacji), zajętości dysku i wielkości kopii zapasowych. Stawki zależą od typu indeksu, metody kompresji oraz od dostawcy chmury i regionu, więc włączona kwantyzacja obniża rachunek wprost, a nie tylko zużycie pamięci.

Osadzenia to osobna pozycja i tu wszystko zależy od tego, czyj model wywołujesz. Przy wektoryzatorze wskazującym na zewnętrznego dostawcę rachunek wystawia ten dostawca, nie baza. Przy usłudze Weaviate Embeddings płacisz operatorowi bazy od tokenów, w chwili pisania od 0,025 do 0,065 USD za milion, przy czym plan Free ma tu przydział dwóch tysięcy zapytań dziennie. Przy indeksowaniu miliona fragmentów ta pozycja bywa większa niż miesięczny koszt samej bazy.

Utrzymanie i pamięć

Indeks wektorowy działa szybko, dopóki mieści się w pamięci, i zwalnia skokowo, gdy zaczyna być czytany z dysku. To najczęstsza przyczyna sytuacji, w której baza działała dobrze przez pół roku, a potem nagle przestała.

Punktem wyjścia do oszacowania jest rozmiar wektora razy liczba fragmentów, plus narzut struktury indeksu. Milion wektorów o wymiarowości tysiąc pięćset trzydzieści sześć to około sześciu gigabajtów samych danych, a indeks dokłada swoje.

Baza oferuje kilka mechanizmów zmniejszania tego zapotrzebowania. Kompresja wektorów, zarówno przez zmniejszenie precyzji, jak i przez kwantyzację, potrafi zredukować zajętość kilkukrotnie przy niewielkiej stracie trafności. Warto włączyć ją przy tworzeniu kolekcji, bo późniejsza zmiana wymaga przebudowy indeksu.

Drugim mechanizmem jest przeniesienie rzadko używanych danych do tańszej warstwy. W układzie wielodostępnym robi się to na poziomie najemcy, co jest wygodniejsze niż decydowanie o pojedynczych obiektach.

Trzecim jest replikacja, potrzebna nie tyle dla wydajności, co dla dostępności. Pojedyncza instancja oznacza, że awaria maszyny to przerwa w działaniu wyszukiwania, więc przy wdrożeniu produkcyjnym warto policzyć, ile kosztuje druga kopia, i porównać to z kosztem przerwy.

Weaviate kontra alternatywy

NarzędzieMocna stronaSłabośćKiedy wybrać
WeaviateHybryda i wielodostępność w komplecie, wektoryzatoryWięcej pojęć do opanowaniaUsługa wielu klientów, wyszukiwanie mieszane
QdrantWydajność i filtrowanie, prosty modelWielodostępność przez filtryDuży wolumen, złożone filtry
ChromaNajprostszy startMniej możliwości produkcyjnychPrototyp i wczesna produkcja
pgvectorWektory obok danych relacyjnychStrojenie po Twojej stronieProjekt już na PostgreSQL

Wybór między dwoma pierwszymi wierszami sprowadza się do tego, czy potrzebujesz wielodostępności i wyszukiwania hybrydowego jako gotowych mechanizmów. Jeśli tak, pierwszy wiersz oszczędza tygodnie pracy. Jeśli budujesz jedno wyszukiwanie dla jednej aplikacji, prostszy model drugiego bywa lepszy.

Ostatni wiersz warto rozważyć zawsze, gdy aplikacja i tak używa PostgreSQL, a fragmentów jest kilkadziesiąt tysięcy. Rozszerzenie do istniejącej bazy oszczędza całą osobną usługę do utrzymania.

Przy porównaniu jedna rzecz umyka najczęściej: wybór bazy rzadko przesądza o jakości wyszukiwania. Sposób cięcia dokumentów, dobór modelu osadzeń i obecność filtrów wpływają na trafność bardziej niż różnice między tymi narzędziami. Bazę zmienia się, gdy brakuje konkretnej możliwości, na przykład wielodostępności albo hybrydy, a nie dlatego, że wyniki są słabe.

Drugi praktyczny wniosek dotyczy kolejności prac. Zacznij od prostego rozwiązania i zmierz trafność na własnych pytaniach, notując, ile razy właściwy fragment znalazł się w pierwszej trójce. Dopiero gdy wiesz, gdzie leży problem, sięgaj po bardziej rozbudowaną bazę, bo inaczej dokładasz złożoność, nie wiedząc, czy cokolwiek naprawia. Migracja między tymi bazami jest zresztą stosunkowo prosta, bo dane trzymasz w plikach źródłowych, a osadzenia można przeliczyć.

Zmiana kolejności wyników

Wyszukiwanie hybrydowe zwraca listę kandydatów uporządkowaną według podobieństwa, co nie zawsze odpowiada temu, co jest najbardziej pomocne. Osobny model porządkujący ocenia parę pytanie i fragment razem, więc widzi więcej niż odległość między wektorami.

Układ wygląda tak: baza zwraca dwadzieścia kandydatów, model porządkujący ocenia każdego z osobna, a do promptu trafia pięć najlepszych. Kosztuje to jedno dodatkowe wywołanie na zapytanie i zwykle zauważalnie poprawia trafność.

Warto jednak sprawdzić, czy w Twoim przypadku faktycznie poprawia, bo to nie jest darmowe. Na zestawie trzydziestu prawdziwych pytań porównaj trafność bez zmiany kolejności i z nią. Jeśli różnica jest niewielka, oszczędzasz wywołanie i opóźnienie.

Alternatywą tańszą i często wystarczającą jest zwiększenie liczby zwracanych fragmentów przy jednoczesnym doprecyzowaniu filtrów. Nierzadko problem leży nie w kolejności, tylko w tym, że właściwego fragmentu w ogóle nie ma w zwróconym zbiorze.

Typowe błędy

Pierwszy to poleganie na wyszukiwaniu znaczeniowym przy zapytaniach o identyfikatory. Numer zamówienia i kod błędu to zadanie dla wyszukiwania słownego, więc bez hybrydy albo bez filtra baza zwróci coś podobnego zamiast tego właściwego.

Drugi to filtrowanie po identyfikatorze klienta zamiast użycia wielodostępności. Działa, dopóki ktoś nie napisze zapytania bez filtra, a wtedy jest wyciekiem danych między klientami.

Trzeci to wektoryzator chmurowy przy danych, które nie mogą opuścić firmy. Baza wysyła wtedy treść dokumentów do dostawcy modelu, co bywa przeoczone, bo dzieje się poza Twoim kodem.

Czwarty to indeksowanie całych dokumentów zamiast fragmentów. Wektor policzony dla dwudziestu stron opisuje wszystko i nic konkretnie, a model dostaje potem ścianę tekstu.

Piąty to pozostawienie parametru proporcji na wartości domyślnej bez sprawdzenia. Właściwa wartość zależy od charakteru treści i różnica w trafności bywa większa niż między dwoma modelami osadzeń.

Szósty to brak zestawu testowego. Trzydzieści prawdziwych pytań z zaznaczonym oczekiwanym fragmentem pozwala porównać ustawienia, a bez nich strojenie sprowadza się do wrażeń.

FAQ

Czym Weaviate różni się od Qdranta?

Weaviate ma wbudowane wyszukiwanie hybrydowe, wielodostępność i wektoryzatory wywołujące model za Ciebie. Qdrant stawia na wydajność i zaawansowane filtrowanie przy prostszym modelu danych. Jeśli budujesz usługę dla wielu klientów, pierwszy oszczędza pracy; jeśli jedno wyszukiwanie o dużym wolumenie, drugi bywa szybszy.

Czy Weaviate jest darmowy?

Wersja otwarta tak i uruchamiasz ją u siebie bez opłat licencyjnych. Wersja zarządzana ma plan Free bez terminu ważności, ograniczony do jednego klastra i stu tysięcy obiektów, a plany płatne zaczynają się od czterdziestu pięciu dolarów miesięcznie, z rozliczeniem za wymiary wektorowe, dysk i kopie zapasowe.

Co daje wyszukiwanie hybrydowe?

Łączy wyniki wyszukiwania znaczeniowego i słownego, więc znajduje zarówno fragmenty o podobnym sensie, jak i te zawierające dokładny ciąg znaków. Największą różnicę widać w dokumentacji technicznej pełnej nazw własnych, kodów i numerów, gdzie samo wyszukiwanie wektorowe zawodzi.

Czy muszę liczyć osadzenia samodzielnie?

Nie, baza może wywołać model wektoryzujący za Ciebie, więc wstawiasz zwykły tekst. Przy danych wrażliwych warto jednak liczyć osadzenia we własnym kodzie albo użyć wektoryzatora uruchomionego lokalnie, bo wariant chmurowy wysyła treść dokumentów do dostawcy modelu.

Jak to działa przy wielu klientach?

Przez wielodostępność wbudowaną w kolekcję, gdzie każdy najemca ma własny fragment indeksu. Zapytanie w kontekście jednego najemcy fizycznie nie sięgnie danych innego, więc izolacja wynika ze struktury, a nie z pamiętania o filtrze. Nieaktywnych najemców można uśpić, żeby nie zajmowali pamięci.

Dokumentacja stoi na stronie projektu, a szczegóły rozliczenia opisuje wpis o zmianie cennika.