Pinecone, baza wektorowa do wyszukiwania semantycznego i RAG
Pinecone przechowuje embeddingi i znajduje wektory najbardziej podobne do zapytania. Nie stawiasz serwera, nie dobierasz typu indeksu i nie martwisz się o repliki, bo usługa działa w modelu bezserwerowym, a płacisz za odczyty, zapisy i zajęte miejsce. To upraszcza start i komplikuje przewidywanie rachunku.
Po co osobna baza na wektory
Wyszukiwanie po słowach kluczowych znajdzie dokument zawierający frazę, ale nie znajdzie tego, który mówi to samo innymi słowami. Embedding zamienia tekst na wektor liczb, a odległość między wektorami odpowiada podobieństwu znaczeń. Zapytanie o zwrot towaru trafi wtedy w akapit o odstąpieniu od umowy, mimo braku wspólnych słów.
Bazę wektorową bierzesz wtedy, gdy takich wektorów jest dużo, a odpowiedź ma przychodzić w kilkadziesiąt milisekund. Przy dziesięciu tysiącach fragmentów wystarczy pgvector na Postgresie, który już masz. Przy kilku milionach i wymaganiu stałego czasu odpowiedzi wyspecjalizowana usługa zaczyna mieć przewagę, bo indeksowanie i skalowanie odczytów jest jej głównym zadaniem.
Trzeba przy tym rozumieć, że baza wektorowa nie rozwiązuje problemu jakości sama z siebie. Odpowiada wyłącznie za to, żeby szybko znaleźć wektory najbliższe zapytaniu. Czy te wektory reprezentują sensowne fragmenty, zależy od podziału dokumentów i od modelu embeddingów, a więc od decyzji podjętych wcześniej. Zmiana bazy przy słabych wynikach zwykle niczego nie poprawia, bo problem leży o krok wcześniej.
Drugim powodem jest podział pracy. Zespół, który nie chce utrzymywać kolejnej bazy z kopiami zapasowymi i aktualizacjami, kupuje usługę i płaci za brak tej odpowiedzialności.
Model rozliczeń i jednostki
Rachunek składa się z trzech pozycji, a nie z ceny za instancję.
| Pozycja | Stawka | Uwagi |
|---|---|---|
| Plan Starter | 0 USD | 2 GB miejsca, 2 mln jednostek zapisu, 1 mln odczytu miesięcznie |
| Plan Standard | minimum 50 USD miesięcznie | Opłata minimalna niezależnie od zużycia |
| Miejsce | 0,33 USD za GB miesięcznie | Liczone od rozmiaru wektorów wraz z metadanymi |
| Jednostki zapisu | od 4 do 4,50 USD za milion | Stawka zalezy od chmury i regionu; jeden upsert to zwykle kilka jednostek |
| Jednostki odczytu | od 16 do 18 USD za milion | Stawka zalezy od chmury i regionu; jedno zapytanie potrafi kosztować od 1 do 10 jednostek |
Najczęstsze zaskoczenie dotyczy jednostek odczytu. Zapytanie bez filtrów po niewielkim zbiorze zużywa jedną jednostkę, ale to samo zapytanie z filtrowaniem po metadanych na dużym indeksie kosztuje ich kilka albo kilkanaście. Rachunek rośnie więc nie z liczby użytkowników, tylko z tego, jak precyzyjnie filtrujesz.
Podobnie z zapisem. Dodanie jednego wektora o 1536 wymiarach razem z metadanymi to zwykle trzy do czterech jednostek, nie jedna. Przy jednorazowym załadowaniu miliona fragmentów wychodzi z tego realny koszt, który warto policzyć przed uruchomieniem importu.
Pierwszy indeks
pip install pineconefrom pinecone import Pinecone, ServerlessSpec
pc = Pinecone(api_key=os.environ["PINECONE_API_KEY"])
pc.create_index(
name="dokumentacja",
dimension=1536,
metric="cosine",
spec=ServerlessSpec(cloud="aws", region="us-east-1")
)
index = pc.Index("dokumentacja")Liczba wymiarów musi odpowiadać modelowi embeddingów i nie da się jej później zmienić. Model text-embedding-3-small z OpenAI daje 1536 wymiarów, a mniejsze modele otwartoźródłowe często 384. Ta różnica przekłada się wprost na koszt miejsca, bo wektor 1536 wymiarowy zajmuje czterokrotnie więcej niż 384 wymiarowy przy tej samej liczbie fragmentów.
Zapis i wyszukiwanie mieszczą się w kilku linijkach.
index.upsert(
vectors=[
{
"id": "regulamin-4",
"values": embedding,
"metadata": {"sekcja": "zwroty", "jezyk": "pl", "wersja": 3}
}
],
namespace="produkcja"
)
wyniki = index.query(
vector=embedding_zapytania,
top_k=4,
include_metadata=True,
filter={"jezyk": "pl", "wersja": {"$gte": 3}},
namespace="produkcja"
)Identyfikator wektora nadajesz sam i warto, żeby wynikał z pochodzenia fragmentu, na przykład z identyfikatora dokumentu i numeru części. Wtedy ponowne przetworzenie dokumentu nadpisze stare wektory zamiast tworzyć duplikaty.
Namespace i wielodostępność
Namespace dzieli indeks na rozłączne przestrzenie. Zapytanie zawsze dotyczy jednej z nich, więc dane różnych klientów nie mieszają się nawet przy błędzie w filtrze.
To lepszy sposób na wielodostępność niż filtrowanie po polu metadanych z identyfikatorem klienta. Filtr można pominąć przez pomyłkę, a namespace trzeba wskazać świadomie. Operacje na przestrzeniach nie są dodatkowo płatne.
Ostrożnie natomiast z liczbą indeksów. Wiele małych indeksów działa gorzej niż jeden większy podzielony na przestrzenie, bo każdy indeks ma własny narzut. Regułą jest jeden indeks na model embeddingów i przestrzeń na klienta albo na środowisko.
Przy usuwaniu klienta z systemu skasowanie całej przestrzeni jest jedną operacją, co bywa istotne przy żądaniu usunięcia danych.
Przestrzenie przydają się także przy zmianie sposobu przetwarzania dokumentów. Zamiast nadpisywać dane produkcyjne, zapisujesz nową wersję obok, porównujesz wyniki na tym samym zestawie pytań i przełączasz aplikację dopiero po sprawdzeniu. Stara przestrzeń zostaje jako wariant do powrotu, a jej skasowanie po tygodniu to jedno wywołanie. Ten sam mechanizm obsługuje wersjonowanie modelu embeddingów, o ile wymiary się zgadzają.
Wbudowane embeddingi i reranking
Pinecone potrafi sam liczyć embeddingi, więc wysyłasz tekst zamiast wektorów. Znika wtedy jeden krok w potoku i jedna zależność, ale wiążesz się z modelami dostępnymi u dostawcy.
Ciekawszym elementem jest reranking. Wyszukiwanie wektorowe zwraca kandydatów szybko, lecz kolejność bywa niedokładna, zwłaszcza gdy zapytanie zawiera nazwy własne albo numery wersji. Model przestawiający wyniki bierze dwadzieścia kandydatów i układa je ponownie, patrząc na pełną treść, a nie na sam wektor.
Praktyka jest taka: pobierz dwadzieścia wyników, przepuść je przez reranking, przekaż modelowi cztery najlepsze. Jakość odpowiedzi w systemie RAG rośnie po tym kroku wyraźniej niż po zmianie modelu językowego na większy, a koszt jest ułamkiem tej różnicy.
Wyszukiwanie hybrydowe
Samo podobieństwo semantyczne gubi zapytania precyzyjne. Pytanie o błąd ERR_2041 albo o wersję 3.2.1 znajdzie fragmenty o podobnej tematyce, ale niekoniecznie ten jeden z konkretnym numerem.
Rozwiązaniem jest połączenie wektorów z wyszukiwaniem po słowach. Pinecone obsługuje wektory rzadkie obok gęstych, dzięki czemu jedno zapytanie łączy oba sygnały. Alternatywą jest równoległe odpytanie bazy pełnotekstowej i połączenie wyników po stronie aplikacji.
Tańszym obejściem bywa wykrycie wzorca w zapytaniu. Jeśli użytkownik wpisał ciąg wyglądający na kod błędu albo numer wersji, warto najpierw odpytać własną bazę zwykłym zapytaniem, a wyszukiwanie wektorowe potraktować jako uzupełnienie. Dla wielu produktów to załatwia większość przypadków bez dokładania kolejnej warstwy.
Sprawdź to na własnych danych, zanim uznasz temat za rozwiązany. Zbiór dwudziestu zapytań, które użytkownicy naprawdę wpisują, wraz z oczekiwanym dokumentem, pokazuje różnicę między konfiguracjami lepiej niż dowolny benchmark.
Jak mierzyć jakość wyszukiwania
Najczęstszy błąd w projektach RAG polega na ocenianiu całości po odpowiedzi modelu. Gdy odpowiedź jest zła, winą obarcza się model, choć w większości przypadków zawiodło wyszukiwanie, a model po prostu nie dostał właściwego fragmentu.
Rozdziel te dwie warstwy pomiarem. Zbierz trzydzieści realnych pytań i dla każdego wskaż ręcznie fragment, który powinien się znaleźć w wynikach. Potem sprawdzaj jedną liczbę: w ilu procentach zapytań właściwy fragment trafił do pierwszej czwórki.
def trafnosc(zestaw, k=4):
trafione = 0
for pytanie, oczekiwany_id in zestaw:
wynik = index.query(vector=embed(pytanie), top_k=k, namespace="produkcja")
if oczekiwany_id in [d["id"] for d in wynik["matches"]]:
trafione += 1
return trafione / len(zestaw)Ta jedna liczba mówi więcej niż intuicja. Poniżej siedemdziesięciu procent nie ma sensu stroić promptu, bo problem leży w danych albo w podziale dokumentów. Powyżej dziewięćdziesięciu dalsze zmiany w wyszukiwaniu dają coraz mniej, a przestrzeń na poprawę przenosi się do instrukcji dla modelu.
Zestaw pytań warto zbierać z prawdziwych logów, nie wymyślać przy biurku. Pytania układane przez autora systemu brzmią jak dokumentacja, którą indeksuje, więc trafiają zbyt łatwo i zawyżają wynik.
Mierz też przy każdej zmianie podziału na fragmenty. Przejście z fragmentów po 400 znaków na 800 potrafi podnieść trafność o kilkanaście punktów albo ją obniżyć, zależnie od rodzaju dokumentów, a bez pomiaru pozostaje to kwestią przekonań.
Osobno pilnuj opóźnień. Czas odpowiedzi indeksu bywa stabilny, ale całość rośnie przez liczenie embeddingu zapytania i reranking. Zmierz wszystkie trzy odcinki osobno, zanim zaczniesz optymalizować ten niewłaściwy.
Ile to realnie kosztuje
Policzmy typową bazę wiedzy: sto tysięcy fragmentów po 1536 wymiarów, dziesięć tysięcy zapytań miesięcznie.
Miejsce to około 0,6 GB wektorów z metadanymi, czyli mniej niż jeden dolar. Jednorazowy import stu tysięcy wektorów przy czterech jednostkach zapisu na wektor daje 400 tysięcy jednostek, poniżej dwóch dolarów. Dziesięć tysięcy zapytań po pięć jednostek odczytu to 50 tysięcy jednostek, czyli około dolara.
Suma zużycia wychodzi w okolicach kilku dolarów, ale na planie Standard i tak zapłacisz minimum 50 USD miesięcznie. Wniosek jest praktyczny: przy małych zbiorach płacisz głównie za wygodę, a nie za zasoby. Próg opłacalności wobec pgvectora na Postgresie, który i tak masz w projekcie, przesuwa się gdzieś w okolice miliona wektorów albo wymagania ostrego czasu odpowiedzi.
Pinecone kontra alternatywy
| Rozwiązanie | Mocna strona | Słabość | Kiedy wybrać |
|---|---|---|---|
| Pinecone | Zero utrzymania, stabilne opóźnienia przy dużej skali | Opłata minimalna, trudne prognozowanie kosztu | Miliony wektorów, zespół bez czasu na infrastrukturę |
| pgvector | Jedna baza na wszystko, transakcje razem z danymi | Wymaga strojenia indeksu przy dużych zbiorach | Do miliona wektorów, dane już w Postgresie |
| Qdrant | Otwarty kod, dobre filtrowanie, wersja na własny serwer | Utrzymanie po Twojej stronie | Dane wrażliwe, potrzeba pełnej kontroli |
| Weaviate | Wbudowane moduły, wyszukiwanie hybrydowe | Bardziej rozbudowana konfiguracja | Złożone scenariusze wyszukiwania |
Warto też pamiętać o regionie. Indeks postawiony w Wirginii odpowiada aplikacji z Frankfurtu o dobre sto milisekund wolniej, zanim jeszcze zacznie liczyć cokolwiek. Przy trzech wywołaniach na jedno pytanie użytkownika robi się z tego różnica odczuwalna w interfejsie.
Migracja między tymi rozwiązaniami nie jest droga, bo wektory da się przenieść, o ile zachowasz ten sam model embeddingów. Znacznie droższa jest zmiana modelu, ponieważ wymaga przeliczenia całego zbioru od nowa.
Zanim jednak dołożysz osobną bazę do stosu, sprawdź, czy nie masz już czegoś, co to udźwignie. Elasticsearch obsługuje wektory obok wyszukiwania pełnotekstowego, więc daje hybrydę bez kolejnej usługi, a Atlas Vector Search robi to samo wewnątrz bazy dokumentowej, którą aplikacja i tak już odpytuje. Osobna baza wektorowa wygrywa dopiero na skali i na jakości wyszukiwania, nie z zasady.
Typowe błędy
Pierwszy to wrzucanie pełnej treści dokumentu do metadanych. Metadane wchodzą do rozmiaru indeksu i podnoszą koszt miejsca, a i tak zwykle potrzebujesz tylko identyfikatora, żeby pobrać tekst z własnej bazy.
Drugi to brak strategii aktualizacji. Dokument zmieniony po miesiącu zostawia w indeksie stare fragmenty, jeśli identyfikatory są losowe. Wynik: model dostaje dwie sprzeczne wersje tego samego zapisu.
Trzeci to top_k ustawione na pięćdziesiąt w nadziei na lepsze wyniki. Więcej kandydatów to więcej jednostek odczytu i dłuższy prompt, a jakość rośnie tylko do pewnego progu. Lepiej pobrać dwadzieścia i przepuścić przez reranking.
Czwarty to brak środowiska testowego. Osobna przestrzeń dla danych roboczych kosztuje tyle co nic, a pozwala przetestować zmianę w podziale dokumentów bez psucia wyników produkcyjnych.
Piąty to pomijanie limitów zapytań przy imporcie. Ładowanie w wielkich partiach bez opóźnień kończy się błędami, po których część danych zostaje niezapisana, zwykle bez wyraźnego komunikatu w logu aplikacji.
FAQ
Czy Pinecone ma darmowy plan?
Tak, plan Starter daje 2 GB miejsca, 2 miliony jednostek zapisu i milion jednostek odczytu miesięcznie, bez karty i bez opłaty minimalnej. Wystarcza do prototypu i do niewielkiej bazy wiedzy. Plan Standard zaczyna się od 50 USD miesięcznie jako opłata minimalna.
Kiedy wybrać pgvector zamiast Pinecone?
Gdy dane już siedzą w Postgresie, zbiór nie przekracza rzędu miliona wektorów i akceptujesz strojenie indeksu. Wtedy oszczędzasz osobną usługę, a wyszukiwanie wektorowe łączysz z filtrami SQL w jednym zapytaniu. Powyżej tej skali utrzymanie zaczyna kosztować więcej niż abonament.
Czy da się zmienić liczbę wymiarów w istniejącym indeksie?
Nie. Liczba wymiarów jest ustalana przy tworzeniu indeksu i wiąże się z modelem embeddingów. Zmiana modelu oznacza nowy indeks i przeliczenie całego zbioru, więc wybór modelu na starcie jest decyzją na dłużej.
Jak zintegrować Pinecone z aplikacją w Next.js?
Wywołania kieruj wyłącznie z serwera, bo klucz API nie może trafić do przeglądarki. W praktyce robisz trasę API, która liczy embedding zapytania, odpytuje indeks i zwraca fragmenty. Gotowe integracje ma też LangChain, jeśli budujesz pełny potok RAG.
Czy Pinecone przechowuje oryginalny tekst?
Przechowuje wektory i metadane, które sam mu przekażesz. Oryginalną treść trzymaj we własnej bazie i w metadanych zapisuj tylko identyfikator oraz pola potrzebne do filtrowania. Ten układ jest tańszy i ułatwia usunięcie danych na żądanie użytkownika.
Zasady naliczania opisuje dokumentacja kosztów, a cennik stoi na pinecone.io.