Jak zaimplementować wyszukiwanie semantyczne w MongoDB
Dowiedz się, jak zaimplementować wyszukiwanie semantyczne w MongoDB za pomocą Pythona. Generuj wektorowe osadzenia, utwórz indeks Vector Search i uruchamiaj zapytania $vectorSearch.
To są momenty, w których zwykłe wyszukiwanie tekstowe nie wystarcza. W praktyce wygląda to tak:
Portal wsparcia klienta nie zwraca wyników, gdy użytkownik wpisuje „nie włącza się” zamiast dokładnego sformułowania użytego w artykule pomocy.
Platforma e-commerce nic nie znajduje, gdy kupujący szuka „czegoś ciepłego na zimę”, ponieważ żaden opis produktu nie zawiera dokładnie tych słów.
Baza wiedzy pomija właściwy dokument, bo użytkownik sformułował pytanie inaczej, niż napisano dokument.
Wyszukiwanie semantyczne rozwiązuje ten problem. Rozumie znaczenie i intencję zapytania, a nie tylko dopasowuje dokładne słowa.
Ten samouczek pokazuje, jak zaimplementować wyszukiwanie semantyczne w MongoDB przy użyciu Pythona i darmowego modelu osadzeń nomic-embed-text-v1.
Uwaga: nomic-embed-text-v1 zajmuje w pamięci około 0,27 GB, więc przed uruchomieniem jakiegokolwiek skryptu z tego samouczka upewnij się, że masz co najmniej 1 GB wolnej pamięci RAM. Podczas pierwszego uruchomienia model jest pobierany z Hugging Face, więc w zależności od połączenia internetowego przewidź dodatkowy czas. Wszystkie kolejne uruchomienia ładują model z lokalnego cache’u. Wnioskowanie na CPU jest znacząco wolniejsze niż na GPU. Na maszynach bez dedykowanego GPU model działa na CPU i używa RAM zamiast VRAM, dlatego generowanie osadzeń może trwać dłużej.
W tym samouczku nauczysz się:
Czym są wektorowe osadzenia i jak reprezentują znaczenie
Jak generować i przechowywać osadzenia w MongoDB
Jak utworzyć indeks MongoDB Vector Search
Jak zamienić zapytanie użytkownika na wektor
Jak uruchomić potok agregacji $vectorSearch i zinterpretować wyniki
Wszystkie przykłady kodu do tego samouczka znajdziesz w repozytorium GitHub.
Wyszukiwanie tekstowe vs wyszukiwanie semantyczne
Wyszukiwanie tekstowe dopasowuje dokumenty zawierające dokładne słowa z twojego zapytania. Wyszukiwanie semantyczne dopasowuje dokumenty niosące to samo znaczenie co twoje zapytanie, nawet jeśli używają zupełnie innych słów.
Poniższa tabela pokazuje, co zwraca każde podejście dla zapytania „heart problems”:
Treść dokumentu
Wyszukiwanie tekstowe
Wyszukiwanie semantyczne
Dlaczego wyszukiwanie tekstowe to zwraca
"...heart problems in adults..."
Tak
Tak
Zawiera dokładne słowa „heart problems”
"...cardiac conditions and symptoms..."
Nie
Tak
Nie zawiera dokładnych słów „heart problems”
"...risk factors for heart disease..."
Nie
Tak
Nie zawiera dokładnych słów „heart problems”
"...chest pain and shortness of breath..."
Nie
Tak
Nie zawiera dokładnych słów „heart problems”
Koncepcje wyszukiwania semantycznego
Trzy pojęcia są kluczowe dla wyszukiwania semantycznego w MongoDB. Pomogą ci zrozumieć, dlaczego każdy krok w tym samouczku działa tak, jak działa.
Wektorowe osadzenia
Model osadzeń konwertuje tekst na listę liczb o stałej długości, zwaną wektorem. Każda liczba wektora reprezentuje wymiar znaczenia.
Dwa teksty o podobnym znaczeniu dają wektory, które są do siebie numerycznie bliskie. „cardiac conditions” i „heart problems” lądują blisko siebie w przestrzeni wektorowej, mimo że nie mają wspólnych słów. Ta bliskość umożliwia wyszukiwanie semantyczne.
W tym samouczku używamy modelu osadzeń nomic-embed-text-v1, który jest darmowy, open-source i działa w całości na twojej lokalnej maszynie. Model automatycznie pobiera się z Hugging Face przy pierwszym uruchomieniu skryptu i zapisuje lokalnie na kolejne uruchomienia. Model produkuje 768 liczb na każde wejście.
Indeksy wyszukiwania wektorowego
Indeks wyszukiwania wektorowego mówi MongoDB, które pole zawiera osadzenia, ile wymiarów należy oczekiwać i której funkcji podobieństwa użyć do porównań. Musisz utworzyć ten indeks, zanim uruchomisz jakiekolwiek zapytania $vectorSearch.
Etap agregacji $vectorSearch
$vectorSearch to etap agregacji, który uruchamia wyszukiwanie. Przyjmuje wektor zapytania, przeszukuje zindeksowane pole i zwraca dokumenty uporządkowane według podobieństwa semantycznego. Łączysz go z $project i innymi etapami tak jak każdy inny potok agregacji.
Zaczynajmy.
Wymagania wstępne
Zanim zaczniesz, upewnij się, że masz przygotowane:
Zainstalowane pakiety Pythona: pymongo 4.7 lub nowszy, sentence-transformers i einops
Podstawowa znajomość Pythona i kolekcji MongoDB
Twój łańcuch połączenia Atlas, dostępny w interfejsie Atlas w **Database > Connect > Drivers**
Twój adres IP jest dozwolony w Atlas przed uruchomieniem skryptów. Przejdź w interfejsie Atlas do **Security > Network Access** i dodaj swój bieżący adres IP.
Skonfiguruj projekt
Utwórz folder dla projektu i przejdź do niego w terminalu:
mkdir mongodb-semantic-search
cd mongodb-semantic-searchObsługiwane przez
Utwórz i aktywuj wirtualne środowisko, aby odizolować zależności projektu:
Utworzysz jeden plik Pythona dla każdego kroku tego samouczka. Wszystkie pliki umieść w folderze mongodb-semantic-search.
Utwórz plik narzędzi do osadzeń
Utwórz plik o nazwie embedding_utils.py. Ten plik zawiera obie funkcje osadzeń używane w tym samouczku:
from sentence_transformers import SentenceTransformer
# Load the free, open-source embedding model.# The model downloads from Hugging Face on first run and saves locally.# trust_remote_code=True is required by this model:
model = SentenceTransformer("nomic-ai/nomic-embed-text-v1", trust_remote_code=True)defget_embedding(text, precision="float32"):# Use this function when embedding text you plan to store in MongoDB:return model.encode(text, precision=precision).tolist()defget_query_embedding(text, precision="float32"):# Use this function when embedding a user's search query:return model.encode(text, precision=precision).tolist()Obsługiwane przez
Ostrzeżenie: trust_remote_code=True pozwala modelowi wykonywać specyficzny dla modelu kod Pythona pobrany z Hugging Face na twojej maszynie. Jeśli kod źródłowy modelu na Hugging Face zostanie skompromitowany lub zaktualizowany o złośliwe zmiany, ten kod uruchomi się automatycznie w twoim środowisku. Zachowaj ostrożność przed użyciem tego parametru w środowisku produkcyjnym.
Generuj i przechowuj wektorowe osadzenia
Utwórz plik o nazwie generate_embeddings.py. Ten plik importuje funkcję osadzeń z embedding_utils.py, generuje wektor dla pola tekstowego każdego dokumentu i zapisuje pełny dokument, łącznie z osadzeniem, w MongoDB:
from embedding_utils import get_embedding
from pymongo import MongoClient
# Replace the placeholder with your Atlas connection string:
mongodb_client = MongoClient("mongodb+srv://<USERNAME>:<PASSWORD>@<HOST>/",
appname="devrel-tutorial-python-semantic-search")
collection = mongodb_client["sample_db"]["documents"]# Sample data:
sample_documents =[{"title":"MongoDB Atlas","text":"MongoDB Atlas is a fully managed cloud database."},{"title":"Vector Search","text":"Vector search finds results based on semantic meaning."},{"title":"Nomic AI","text":"nomic-embed-text-v1 is a free, open-source embedding model."},]
docs_to_insert =[]for doc in sample_documents:
embedding = get_embedding(doc["text"])
docs_to_insert.append({"title": doc["title"],"text": doc["text"],# The vector lives alongside your original data in the same document:"embedding": embedding
})# Drop the collection before each run to avoid inserting duplicate documents:
collection.drop()
result = collection.insert_many(docs_to_insert)print(f"Inserted {len(result.inserted_ids)} documents with embeddings.")
mongodb_client.close()Obsługiwane przez
W powyższym kodzie collection.drop() usuwa wszystkie dokumenty i indeksy w kolekcji przed każdym uruchomieniem. Ponowne uruchomienie generate_embeddings.py bez tej linii wstawia zduplikowane dokumenty, przez co $vectorSearch może zwrócić ten sam dokument wielokrotnie. Usunięcie kolekcji kasuje też indeks wyszukiwania wektorowego, więc za każdym razem, gdy ponownie uruchamiasz generate_embeddings.py, musisz ponownie uruchomić create_vector_index.py.
<All keys matched successfully>
Inserted 3 documents with embeddings.Obsługiwane przez
Każdy dokument w MongoDB zawiera teraz zarówno oryginalny tekst, jak i jego 768-wymiarowy wektor w polu embedding. Wektor żyje obok twoich danych w tym samym dokumencie, więc przy zapytaniu nie jest potrzebne osobne przechowywanie ani dodatkowe wyszukiwanie.
Utwórz indeks MongoDB Vector Search
Utwórz plik o nazwie create_vector_index.py. Ten plik definiuje i tworzy indeks wyszukiwania wektorowego na polu embedding, aby MongoDB mogło uruchamiać zapytania $vectorSearch na twojej kolekcji.
Definicja indeksu wymaga trzech pól:
path: pole, które przechowuje osadzenia (w tym samouczku embedding)
numDimensions: musi odpowiadać rozmiarowi wyjścia modelu (768 dla nomic-embed-text-v1)
similarity: funkcja porównawcza (dla tego modelu poprawna jest cosine)
Wartość numDimensions musi dokładnie odpowiadać twojemu modelowi osadzeń. Niezgodność spowoduje błąd tworzenia indeksu:
from pymongo.mongo_client import MongoClient
from pymongo.operations import SearchIndexModel
import time
# Replace the placeholder with your Atlas connection string:
mongodb_client = MongoClient("mongodb+srv://<USERNAME>:<PASSWORD>@<HOST>/",
appname="devrel-tutorial-python-semantic-search")# Point to the same database and collection you used in the previous step:
database = mongodb_client["sample_db"]
collection = database["documents"]# Define the vector search index.# The three required fields tell MongoDB what to index and how to compare vectors:
search_index_model = SearchIndexModel(
definition={"fields":[{"type":"vector","path":"embedding",# The field name from generate_embeddings.py"numDimensions":768,# nomic-embed-text-v1 always outputs 768 dimensions"similarity":"cosine"# Recommended similarity function for this model}]},
name="vector_index",type="vectorSearch")
result = collection.create_search_index(model=search_index_model)print("New search index named "+ result +" is building.")# Poll every five seconds until the index is ready to accept queries:print("Polling to check if the index is ready. This may take up to a minute.")
predicate =lambda index: index.get("queryable")isTruewhileTrue:
indices =list(collection.list_search_indexes(result))iflen(indices)and predicate(indices[0]):break
time.sleep(5)print(result +" is ready for querying.")
mongodb_client.close()Obsługiwane przez
New search index named vector_index is building.
Polling to check if the index is ready. This may take up to a minute.
vector_index is ready for querying.Obsługiwane przez
Zbudowanie indeksu trwa do minuty. Pętla odpytywania sprawdza co 5 sekund i kończy się dopiero, gdy MongoDB potwierdzi, że indeks jest gotowy do zapytań. Nie przechodź do następnego kroku, dopóki nie zobaczysz „vector_index is ready for querying.”
Zamień zapytanie wyszukiwania na wektor
Utwórz plik o nazwie generate_query_vector.py. Ten plik importuje funkcję get_query_embedding() z pliku embedding_utils.py. Uruchom plik generate_query_vector.py, aby sprawdzić, czy model osadzeń ładuje się poprawnie i tworzy 768-wymiarowy wektor:
Definiuje funkcję get_query_embedding(), którą importuje następny krok.
Możesz uruchomić go samodzielnie, aby zweryfikować, czy model działa poprawnie.
Musisz użyć tego samego modelu co w pierwszym kroku. Inny model tworzy wektory zajmujące inną przestrzeń liczbową, co uniemożliwia sensowne porównanie:
from embedding_utils import get_query_embedding
user_query ="I need an automated, scalable system for serious information storage"
query_vector = get_query_embedding(user_query)print(f"Query: '{user_query}'")print(f"Vector dimensions: {len(query_vector)}")print(f"First 5 values: {query_vector[:5]}")Obsługiwane przez
<All keys matched successfully>
Query: 'I need an automated, scalable system for serious information storage'
Vector dimensions: 768
First 5 values: [0.0025914530269801617, 0.09862980246543884, -0.023092379793524742, -0.0171672236174345, -0.05548065900802612]Obsługiwane przez
W powyższym wyniku Vector dimensions: 768 potwierdza, że wynik modelu pasuje do twoich przechowywanych osadzeń.
Uruchom zapytanie $vectorSearch
Utwórz plik o nazwie run_vector_search.py. Ten plik importuje funkcję get_query_embedding() z pliku embedding_utils.py i konwertuje termin wyszukiwania użytkownika na wektor. run_vector_search.py uruchamia potok agregacji $vectorSearch i wypisuje wyniki uporządkowane według podobieństwa semantycznego:
from embedding_utils import get_query_embedding
from pymongo import MongoClient
# Replace the placeholder with your Atlas connection string:
mongodb_client = MongoClient("mongodb+srv://<USERNAME>:<PASSWORD>@<HOST>/",
appname="devrel-tutorial-python-semantic-search")
collection = mongodb_client["sample_db"]["documents"]# Generate a query vector from the user's search input:
user_query ="I need an automated, scalable system for serious information storage"
query_vector = get_query_embedding(user_query)# Define the $vectorSearch aggregation pipeline:
pipeline =[{"$vectorSearch":{"index":"vector_index",# The index created in create_vector_index.py"path":"embedding",# The field that holds your stored vectors"queryVector": query_vector,# The vector generated from the user's query"numCandidates":150,# How many neighbors MongoDB considers"limit":3# How many results to return}},{"$project":{"_id":0,"title":1,"text":1,"score":{"$meta":"vectorSearchScore"# Relevance score for each result}}}]
results = collection.aggregate(pipeline)print(f"\nTop results for query: '{user_query}'\n")for doc in results:print(f"Title: {doc['title']}")print(f"Text: {doc['text']}")print(f"Score: {doc['score']:.4f}")print()
mongodb_client.close()Obsługiwane przez
W powyższym kodzie dwa parametry kontrolują zachowanie wyszukiwania:
numCandidates ustawia rozmiar początkowej puli wyszukiwania, którą MongoDB analizuje, zanim zawęzi do wyników końcowych. Większa wartość poprawia recall kosztem nieco dłuższego czasu.
limit określa liczbę zwracanych wyników. W tym samouczku limit ustawiono na 3, a numCandidates na 150. Dobrym punktem wyjścia jest ustawienie numCandidates na 10–15 razy więcej niż twój limit.
<All keys matched successfully>
Top results for query: 'I need an automated, scalable system for serious information storage.'
Title: MongoDB Atlas
Text: MongoDB Atlas is a fully managed cloud database.
Score: 0.7211
Title: Nomic AI
Text: nomic-embed-text-v1 is a free, open-source embedding model.
Score: 0.6818
Title: Vector Search
Text: Vector search finds results based on semantic meaning.
Score: 0.6642Obsługiwane przez
„MongoDB Atlas” ma najwyższy wynik, mimo że zapytanie „I need an automated, scalable system for serious information storage” nie dzieli żadnych słów z „MongoDB Atlas is a fully managed cloud database.” Wyszukiwanie zwraca go, ponieważ ich wektory są bliskie znaczeniowo: „...zautomatyzowany, skalowalny system do przechowywania informacji” semantycznie mapuje się na „...w pełni zarządzana baza danych w chmurze”. Wyszukiwanie tekstowe dla tego samego zapytania zwróciłoby zero wyników, ponieważ żadne z dokładnych słów zapytania nie pojawia się w żadnym dokumencie. Tak właśnie działa wyszukiwanie semantyczne.
Najważniejsze wnioski
MongoDB Vector Search działa na klastrze M0 (darmowa warstwa). Nie jest wymagana płatna subskrypcja.
Musisz używać tego samego modelu osadzeń zarówno do generowania przechowywanych osadzeń, jak i do generowania wektorów zapytań. Mieszanie modeli daje bezsensowne wyniki.
Wartość numDimensions w definicji indeksu musi dokładnie odpowiadać rozmiarowi wyjściowemu twojego modelu osadzeń. nomic-embed-text-v1 zawsze zwraca 768 wymiarów.
input_type="document" optymalizuje osadzenia do przechowywania. input_type="query" optymalizuje je pod wyszukiwanie. Używaj właściwego typu na każdym etapie.
numCandidates kontroluje szerokość sieci wyszukiwania, jaką MongoDB zarzuca, zanim zawęzi do końcowych wyników limit. Większa wartość poprawia recall kosztem czasu zapytania.
vectorSearchScore porządkuje wyniki według podobieństwa semantycznego. Wyniki nie muszą zawierać żadnych dokładnych słów z zapytania. Zakresy punktacji różnią się w zależności od modelu i zbioru danych, ale poniższe progi to użyteczny punkt wyjścia dla nomic-embed-text-v1 z kosinusowym podobieństwem:
0,9 i więcej: Prawie identyczne znaczenie. Dokument i zapytanie są semantycznie niemal takie same.
0,7–0,9: Silna trafność. Dokument wyraźnie odnosi się do intencji zapytania.
0,5–0,7: Umiarkowana trafność. Dokument jest tematycznie powiązany, ale używa innej ramy lub kontekstu.
Poniżej 0,5: Słaba trafność. Powiązanie jest luźne i wynik może być mało użyteczny.
Wszystkie przykłady kodu do tego samouczka znajdziesz w repozytorium GitHub.
How to Create Vector Embeddingswyjaśnia, jak generować wektorowe osadzenia dla danych tekstowych w twoich kolekcjach, używając modeli osadzeń od Voyage AI, OpenAI i innych dostawców open-source.
Czy potrzebuję płatnego planu Atlas, żeby wdrożyć wyszukiwanie semantyczne?⌄
Nie. Wszystkie cztery kroki w tym samouczku działają na klastrze M0 (darmowa warstwa), który jest bezpłatny.
Co się stanie, jeśli użyję innego modelu osadzeń dla mojego zapytania niż dla przechowywanych dokumentów?⌄
Twoje wyniki będą bezsensowne. Wektorów nie da się porównać, ponieważ różne modele mapują tekst na różne przestrzenie liczbowe. Zawsze używaj tego samego modelu do indeksowania i zapytań.
Jaka jest różnica między `numCandidates` a `limit`?⌄
numCandidates to liczba wektorów, które MongoDB analizuje podczas wyszukiwania. limit to liczba najlepszych wyników, które do ciebie wracają. Wyższa wartość numCandidates poprawia jakość wyników kosztem nieco wolniejszych zapytań. Dobrym punktem wyjścia jest ustawienie numCandidates na 10–15 razy więcej niż limit.
Czy mogę używać wyszukiwania semantycznego i tekstowego razem?⌄
Tak. MongoDB obsługuje wyszukiwanie hybrydowe, które łączy $vectorSearch i $search w jednym potoku.
Czy wyszukiwanie semantyczne działa w językach innych niż angielski?⌄
To zależy od twojego modelu osadzeń. nomic-embed-text-v1 jest trenowany głównie na angielskich tekstach. Do zastosowań wielojęzycznych wybierz wielojęzyczny model osadzeń wytrenowany na językach, które zawierają twoje dane.
To są momenty, w których zwykłe wyszukiwanie tekstowe nie wystarcza. W praktyce wygląda to tak:
Wyszukiwanie semantyczne rozwiązuje ten problem. Rozumie znaczenie i intencję zapytania, a nie tylko dopasowuje dokładne słowa.
Ten samouczek pokazuje, jak zaimplementować wyszukiwanie semantyczne w MongoDB przy użyciu Pythona i darmowego modelu osadzeń nomic-embed-text-v1.
Uwaga:
nomic-embed-text-v1zajmuje w pamięci około 0,27 GB, więc przed uruchomieniem jakiegokolwiek skryptu z tego samouczka upewnij się, że masz co najmniej 1 GB wolnej pamięci RAM. Podczas pierwszego uruchomienia model jest pobierany z Hugging Face, więc w zależności od połączenia internetowego przewidź dodatkowy czas. Wszystkie kolejne uruchomienia ładują model z lokalnego cache’u. Wnioskowanie na CPU jest znacząco wolniejsze niż na GPU. Na maszynach bez dedykowanego GPU model działa na CPU i używa RAM zamiast VRAM, dlatego generowanie osadzeń może trwać dłużej.W tym samouczku nauczysz się:
$vectorSearchi zinterpretować wynikiWszystkie przykłady kodu do tego samouczka znajdziesz w repozytorium GitHub.
Wyszukiwanie tekstowe vs wyszukiwanie semantyczne
Wyszukiwanie tekstowe dopasowuje dokumenty zawierające dokładne słowa z twojego zapytania. Wyszukiwanie semantyczne dopasowuje dokumenty niosące to samo znaczenie co twoje zapytanie, nawet jeśli używają zupełnie innych słów.
Poniższa tabela pokazuje, co zwraca każde podejście dla zapytania „heart problems”:
Koncepcje wyszukiwania semantycznego
Trzy pojęcia są kluczowe dla wyszukiwania semantycznego w MongoDB. Pomogą ci zrozumieć, dlaczego każdy krok w tym samouczku działa tak, jak działa.
Wektorowe osadzenia
Model osadzeń konwertuje tekst na listę liczb o stałej długości, zwaną wektorem. Każda liczba wektora reprezentuje wymiar znaczenia.
Dwa teksty o podobnym znaczeniu dają wektory, które są do siebie numerycznie bliskie. „cardiac conditions” i „heart problems” lądują blisko siebie w przestrzeni wektorowej, mimo że nie mają wspólnych słów. Ta bliskość umożliwia wyszukiwanie semantyczne.
W tym samouczku używamy modelu osadzeń
nomic-embed-text-v1, który jest darmowy, open-source i działa w całości na twojej lokalnej maszynie. Model automatycznie pobiera się z Hugging Face przy pierwszym uruchomieniu skryptu i zapisuje lokalnie na kolejne uruchomienia. Model produkuje 768 liczb na każde wejście.Indeksy wyszukiwania wektorowego
Indeks wyszukiwania wektorowego mówi MongoDB, które pole zawiera osadzenia, ile wymiarów należy oczekiwać i której funkcji podobieństwa użyć do porównań. Musisz utworzyć ten indeks, zanim uruchomisz jakiekolwiek zapytania
$vectorSearch.Etap agregacji
$vectorSearch$vectorSearchto etap agregacji, który uruchamia wyszukiwanie. Przyjmuje wektor zapytania, przeszukuje zindeksowane pole i zwraca dokumenty uporządkowane według podobieństwa semantycznego. Łączysz go z$projecti innymi etapami tak jak każdy inny potok agregacji.Zaczynajmy.
Wymagania wstępne
Zanim zaczniesz, upewnij się, że masz przygotowane:
pymongo4.7 lub nowszy,sentence-transformersieinopsSkonfiguruj projekt
Utwórz folder dla projektu i przejdź do niego w terminalu:
Utwórz i aktywuj wirtualne środowisko, aby odizolować zależności projektu:
W systemie Windows aktywuj wirtualne środowisko poleceniem:
Teraz zainstaluj wymagane pakiety:
Utworzysz jeden plik Pythona dla każdego kroku tego samouczka. Wszystkie pliki umieść w folderze
mongodb-semantic-search.Utwórz plik narzędzi do osadzeń
Utwórz plik o nazwie
embedding_utils.py. Ten plik zawiera obie funkcje osadzeń używane w tym samouczku:Ostrzeżenie:
trust_remote_code=Truepozwala modelowi wykonywać specyficzny dla modelu kod Pythona pobrany z Hugging Face na twojej maszynie. Jeśli kod źródłowy modelu na Hugging Face zostanie skompromitowany lub zaktualizowany o złośliwe zmiany, ten kod uruchomi się automatycznie w twoim środowisku. Zachowaj ostrożność przed użyciem tego parametru w środowisku produkcyjnym.Generuj i przechowuj wektorowe osadzenia
Utwórz plik o nazwie
generate_embeddings.py. Ten plik importuje funkcję osadzeń zembedding_utils.py, generuje wektor dla pola tekstowego każdego dokumentu i zapisuje pełny dokument, łącznie z osadzeniem, w MongoDB:W powyższym kodzie
collection.drop()usuwa wszystkie dokumenty i indeksy w kolekcji przed każdym uruchomieniem. Ponowne uruchomieniegenerate_embeddings.pybez tej linii wstawia zduplikowane dokumenty, przez co$vectorSearchmoże zwrócić ten sam dokument wielokrotnie. Usunięcie kolekcji kasuje też indeks wyszukiwania wektorowego, więc za każdym razem, gdy ponownie uruchamiaszgenerate_embeddings.py, musisz ponownie uruchomićcreate_vector_index.py.Uruchom skrypt:
W terminalu zobaczysz taki wynik:
Każdy dokument w MongoDB zawiera teraz zarówno oryginalny tekst, jak i jego 768-wymiarowy wektor w polu
embedding. Wektor żyje obok twoich danych w tym samym dokumencie, więc przy zapytaniu nie jest potrzebne osobne przechowywanie ani dodatkowe wyszukiwanie.Utwórz indeks MongoDB Vector Search
Utwórz plik o nazwie
create_vector_index.py. Ten plik definiuje i tworzy indeks wyszukiwania wektorowego na poluembedding, aby MongoDB mogło uruchamiać zapytania$vectorSearchna twojej kolekcji.Definicja indeksu wymaga trzech pól:
path: pole, które przechowuje osadzenia (w tym samouczkuembedding)numDimensions: musi odpowiadać rozmiarowi wyjścia modelu (768dlanomic-embed-text-v1)similarity: funkcja porównawcza (dla tego modelu poprawna jestcosine)Wartość
numDimensionsmusi dokładnie odpowiadać twojemu modelowi osadzeń. Niezgodność spowoduje błąd tworzenia indeksu:Uruchom skrypt:
W terminalu zobaczysz taki wynik:
Zbudowanie indeksu trwa do minuty. Pętla odpytywania sprawdza co 5 sekund i kończy się dopiero, gdy MongoDB potwierdzi, że indeks jest gotowy do zapytań. Nie przechodź do następnego kroku, dopóki nie zobaczysz „vector_index is ready for querying.”
Zamień zapytanie wyszukiwania na wektor
Utwórz plik o nazwie
generate_query_vector.py. Ten plik importuje funkcjęget_query_embedding()z plikuembedding_utils.py. Uruchom plikgenerate_query_vector.py, aby sprawdzić, czy model osadzeń ładuje się poprawnie i tworzy 768-wymiarowy wektor:get_query_embedding(), którą importuje następny krok.Musisz użyć tego samego modelu co w pierwszym kroku. Inny model tworzy wektory zajmujące inną przestrzeń liczbową, co uniemożliwia sensowne porównanie:
Uruchom skrypt:
Otrzymasz wynik podobny do tego:
W powyższym wyniku
Vector dimensions: 768potwierdza, że wynik modelu pasuje do twoich przechowywanych osadzeń.Uruchom zapytanie
$vectorSearchUtwórz plik o nazwie
run_vector_search.py. Ten plik importuje funkcjęget_query_embedding()z plikuembedding_utils.pyi konwertuje termin wyszukiwania użytkownika na wektor.run_vector_search.pyuruchamia potok agregacji$vectorSearchi wypisuje wyniki uporządkowane według podobieństwa semantycznego:W powyższym kodzie dwa parametry kontrolują zachowanie wyszukiwania:
numCandidatesustawia rozmiar początkowej puli wyszukiwania, którą MongoDB analizuje, zanim zawęzi do wyników końcowych. Większa wartość poprawia recall kosztem nieco dłuższego czasu.limitokreśla liczbę zwracanych wyników. W tym samouczkulimitustawiono na 3, a numCandidates na 150. Dobrym punktem wyjścia jest ustawienienumCandidatesna 10–15 razy więcej niż twój limit.Teraz uruchom skrypt:
W terminalu zobaczysz wynik podobny do tego:
„MongoDB Atlas” ma najwyższy wynik, mimo że zapytanie „I need an automated, scalable system for serious information storage” nie dzieli żadnych słów z „MongoDB Atlas is a fully managed cloud database.” Wyszukiwanie zwraca go, ponieważ ich wektory są bliskie znaczeniowo: „...zautomatyzowany, skalowalny system do przechowywania informacji” semantycznie mapuje się na „...w pełni zarządzana baza danych w chmurze”. Wyszukiwanie tekstowe dla tego samego zapytania zwróciłoby zero wyników, ponieważ żadne z dokładnych słów zapytania nie pojawia się w żadnym dokumencie. Tak właśnie działa wyszukiwanie semantyczne.
Najważniejsze wnioski
numDimensionsw definicji indeksu musi dokładnie odpowiadać rozmiarowi wyjściowemu twojego modelu osadzeń.nomic-embed-text-v1zawsze zwraca 768 wymiarów.input_type="document"optymalizuje osadzenia do przechowywania.input_type="query"optymalizuje je pod wyszukiwanie. Używaj właściwego typu na każdym etapie.numCandidateskontroluje szerokość sieci wyszukiwania, jaką MongoDB zarzuca, zanim zawęzi do końcowych wynikówlimit. Większa wartość poprawia recall kosztem czasu zapytania.vectorSearchScoreporządkuje wyniki według podobieństwa semantycznego. Wyniki nie muszą zawierać żadnych dokładnych słów z zapytania. Zakresy punktacji różnią się w zależności od modelu i zbioru danych, ale poniższe progi to użyteczny punkt wyjścia dlanomic-embed-text-v1z kosinusowym podobieństwem:Wszystkie przykłady kodu do tego samouczka znajdziesz w repozytorium GitHub.
Polecane materiały