Bunlar, klasik metin aramasının yetersiz kaldığı anlar. Pratikte bunun nasıl göründüğü şöyledir:
- Bir müşteri destek portalı, kullanıcı yardım makalesindeki ifadeyle birebir aynı cümleyi yazmak yerine "açılmıyor" yazdığında sonuç döndürmez.
- Bir e-ticaret platformu, bir alışverişçi "kış için sıcak bir şey" aradığında, hiçbir ürün açıklaması bu kelimeleri aynen içermediği için sonuç bulamaz.
- Bir bilgi bankası, kullanıcı soruyu belgedekinden farklı bir şekilde ifade ettiği için doğru belgeyi kaçırır.
Anlamsal arama bunu çözer. Tam kelime eşleşmesi yerine bir sorgunun anlamını ve niyetini anlar.
Bu eğitim, Python ve ücretsiz nomic-embed-text-v1 gömme modelini kullanarak MongoDB’de anlamsal aramayı nasıl uygulayacağınızı gösterir.
Not: nomic-embed-text-v1 bellek içine yüklendiğinde yaklaşık 0,27 GB’tır; bu nedenle bu eğitimdeki betiklerden herhangi birini çalıştırmadan önce makinenizde en az 1 GB boş RAM olduğundan emin olun. İlk çalıştırma modeli Hugging Face’ten indirir; internet bağlantınıza bağlı olarak ekstra zaman tanıyın. Sonraki tüm çalıştırmalar modeli yerel önbelleğinizden yükler. CPU tahmini, GPU tahmininden belirgin şekilde daha yavaştır. Ayrık bir GPU’su olmayan makinelerde model CPU üzerinde çalışır ve VRAM yerine RAM kullanır; bu nedenle gömme üretimi daha uzun sürebilir.
Bu eğitimde şunları öğreneceksiniz:
- Vektör gömmeleri nedir ve anlamı nasıl temsil ederler
- MongoDB’de gömmeler nasıl üretilir ve saklanır
- MongoDB Vector Search dizini nasıl oluşturulur
- Bir kullanıcı sorgusu vektöre nasıl dönüştürülür
$vectorSearchtoplama hattı nasıl çalıştırılır ve sonuçlar nasıl yorumlanır
Bu eğitime ait tüm kod örneklerini GitHub deposunda bulabilirsiniz.
Metin Araması ve Anlamsal Arama
Metin araması, sorgunuzdaki kelimelerin aynısını içeren belgeleri eşleştirir. Anlamsal arama ise tamamen farklı kelimeler kullanılsa bile sorgunuzla aynı anlamı taşıyan belgeleri bulur.
Aşağıdaki tablo, "kalp sorunları" arama sorgusu için her yaklaşımın ne döndürdüğünü gösterir:
| Belge metni | Metin araması | Anlamsal arama | Metin aramasının döndürme nedeni |
|---|---|---|---|
| "...yetişkinlerde kalp sorunları..." | Evet | Evet | "kalp sorunları" ifadesini aynen içerir |
| "...kardiyak durumlar ve semptomlar..." | Hayır | Evet | "kalp sorunları" ifadesini aynen içermez |
| "...kalp hastalığı için risk faktörleri..." | Hayır | Evet | "kalp sorunları" ifadesini aynen içermez |
| "...göğüs ağrısı ve nefes darlığı..." | Hayır | Evet | "kalp sorunları" ifadesini aynen içermez |
Anlamsal Arama Kavramları
MongoDB’de anlamsal aramanın üç temel kavramı vardır. Bu kavramlar, bu eğitimdeki her adımın neden bu şekilde çalıştığını anlamanıza yardımcı olur.
Vektör gömmeleri
Bir gömme modeli, metni vektör adı verilen sabit uzunlukta bir sayı listesine dönüştürür. Vektördeki her sayı, anlamın bir boyutunu temsil eder.
Benzer anlamlara sahip iki metin, sayısal olarak birbirine yakın vektörler üretir. "kardiyak durumlar" ve "kalp sorunları" ortak kelime paylaşmasalar da vektör uzayında birbirine yakın yer alır. Bu yakınlık, anlamsal aramayı mümkün kılar.
Bu eğitimde, ücretsiz, açık kaynaklı ve tamamen yerel makinenizde çalışan nomic-embed-text-v1 gömme modeli kullanılmaktadır. Betiği ilk kez çalıştırdığınızda model otomatik olarak Hugging Face’ten indirilir ve sonraki tüm çalıştırmalar için yerel olarak saklanır. Model, her girdi için 768 sayı üretir.
Vektör arama dizinleri
Bir vektör arama dizini, MongoDB’ye hangi alanın gömmeleri tuttuğunu, kaç boyut beklemesi gerektiğini ve karşılaştırma için hangi benzerlik fonksiyonunu kullanacağını söyler. Herhangi bir $vectorSearch sorgusunu çalıştırmadan önce bu dizini oluşturmanız gerekir.
$vectorSearch toplama aşaması
$vectorSearch, aramayı çalıştıran toplama aşamasıdır. Bir sorgu vektörü kabul eder, dizinlenmiş alanı arar ve belgeleri anlamsal benzerliğe göre sıralı olarak döndürür. Diğer toplama hatlarında olduğu gibi bunu $project ve diğer aşamalarla zincirlersiniz.
Şimdi başlayalım.
Önkoşullar
Başlamadan önce aşağıdakilerin hazır olduğundan emin olun:
- Python 3.8 veya daha yenisi kurulu
- M0 (Ücretsiz katman) kümeyle kurulmuş bir MongoDB Atlas hesabı
pymongo4.7 veya üzeri,sentence-transformersveeinopsPython paketleri kurulu- Python ve MongoDB koleksiyonlarıyla temel düzeyde aşinalık
- Atlas bağlantı dizeniz; Atlas arayüzünde **Database > Connect > Drivers** altında bulunur
- Herhangi bir betiği çalıştırmadan önce IP adresinizin Atlas’ta izinli olması. Atlas arayüzünde **Security > Network Access** bölümüne gidip mevcut IP adresinizi ekleyin.
Projenizi Kurun
Projeniz için bir klasör oluşturun ve terminalinizde içine gidin:
mkdir mongodb-semantic-search
cd mongodb-semantic-search
Proje bağımlılıklarınızı izole etmek için bir sanal ortam oluşturup etkinleştirin:
python -m venv venv
source venv/bin/activate
Windows’ta sanal ortamı şu komutla etkinleştirin:
venv\Scripts\activate
Şimdi gerekli paketleri kurun:
pip install pymongo sentence-transformers einops
Bu eğitimin her adımı için birer Python dosyası oluşturacaksınız. Tüm dosyalar mongodb-semantic-search klasörüne gidecek.
Gömme Yardımcıları Dosyasını Oluşturun
embedding_utils.py adlı bir dosya oluşturun. Bu dosya, bu eğitimde kullanılan her iki gömme fonksiyonunu da içerir:
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)
def get_embedding(text, precision="float32"):
# Use this function when embedding text you plan to store in MongoDB:
return model.encode(text, precision=precision).tolist()
def get_query_embedding(text, precision="float32"):
# Use this function when embedding a user's search query:
return model.encode(text, precision=precision).tolist()
Uyarı: trust_remote_code=True, modelin Hugging Face’ten indirilen modele özgü Python kodunu makinenizde çalıştırmasına izin verir. Hugging Face’teki model kaynak kodu ele geçirilir veya kötü amaçlı değişikliklerle güncellenirse, bu kod ortamınızda otomatik olarak çalışır. Bu parametreyi üretim dağıtımında kullanmadan önce dikkatli olun.
Vektör Gömeleri Üretin ve Saklayın
generate_embeddings.py adlı bir dosya oluşturun. Bu dosya, embedding_utils.py içinden gömme fonksiyonunu içe aktarır, her belgenin metin alanı için bir vektör üretir ve gömme dahil tam belgeyi MongoDB’de saklar:
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()
Yukarıdaki kodda collection.drop(), her çalıştırmadan önce koleksiyondaki tüm belgeleri ve dizinleri siler. generate_embeddings.py dosyasını bu satır olmadan yeniden çalıştırmak, yinelenen belgeler ekler ve bu durum $vectorSearch’ün aynı belgeyi birden çok kez döndürmesine yol açar. Koleksiyonu düşürmek, vektör arama dizinini de siler; bu nedenle generate_embeddings.py’yi her yeniden çalıştırdığınızda create_vector_index.py’yi de yeniden çalıştırmanız gerekir.
Betiği çalıştırın:
python generate_embeddings.py
Terminalinizde aşağıdaki çıktıyı alacaksınız:
<All keys matched successfully>
Inserted 3 documents with embeddings.
Artık MongoDB’deki her belge, orijinal metni ve embedding alanında 768 boyutlu vektörünü barındırır. Vektör, verilerinizle aynı belgede yan yana bulunur; bu nedenle sorgu anında ayrı bir depolama veya arama gerekmez.
MongoDB Vector Search Dizini Oluşturun
create_vector_index.py adlı bir dosya oluşturun. Bu dosya, embedding alanında bir vektör arama dizini tanımlar ve oluşturur; böylece MongoDB koleksiyonunuza karşı $vectorSearch sorguları çalıştırabilir.
Dizin tanımı üç alan gerektirir:
path: gömmelerin bulunduğu alan (bu eğitimdeembedding)numDimensions: modelin çıktı boyutuyla eşleşmelidir (nomic-embed-text-v1için768)similarity: karşılaştırma fonksiyonu (bu model içincosinedoğrudur)
numDimensions değeri, gömme modelinizle tam olarak eşleşmelidir. Eşleşmeme, dizin oluşturmanın başarısız olmasına neden olur:
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") is True
while True:
indices = list(collection.list_search_indexes(result))
if len(indices) and predicate(indices[0]):
break
time.sleep(5)
print(result + " is ready for querying.")
mongodb_client.close()
Betiği çalıştırın:
python create_vector_index.py
Terminalinizde aşağıdaki çıktıyı alacaksınız:
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.
Dizin inşası bir dakikaya kadar sürebilir. Yoklama döngüsü her 5 saniyede bir kontrol eder ve MongoDB dizinin sorgulanabilir olduğunu onayladığında çıkar. "vector_index is ready for querying." ifadesini görmeden bir sonraki adıma geçmeyin.
Arama Sorgunuzu Bir Vektöre Dönüştürün
generate_query_vector.py adlı bir dosya oluşturun. Bu dosya, embedding_utils.py dosyasından get_query_embedding() fonksiyonunu içe aktarır. generate_query_vector.py dosyasını çalıştırarak gömme modelinin doğru şekilde yüklendiğini ve 768 boyutlu bir vektör ürettiğini doğrulayın:
get_query_embedding()fonksiyonunu tanımlar; bir sonraki adımda içe aktarılacaktır.- Modelin doğru çalıştığını doğrulamak için bunu tek başına çalıştırabilirsiniz.
Burada, ilk adımda kullandığınız modelin aynısını kullanmalısınız. Farklı bir model, farklı bir sayısal uzayı dolduran vektörler üretir; bu da karşılaştırmayı anlamsız kılar:
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]}")
Betiği çalıştırın:
python generate_query_vector.py
Buna benzer bir çıktı alacaksınız:
<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]
Yukarıdaki çıktıda Vector dimensions: 768, model çıktısının depoladığınız gömmelerle eşleştiğini doğrular.
$vectorSearch Sorgusu Çalıştırın
run_vector_search.py adlı bir dosya oluşturun. Bu dosya, embedding_utils.py dosyasından get_query_embedding() fonksiyonunu içe aktarır ve bir kullanıcının arama terimini vektöre dönüştürür. run_vector_search.py, bir $vectorSearch toplama hattı çalıştırır ve sonuçları anlamsal benzerliğe göre sıralı olarak yazdırır:
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()
Yukarıdaki kodda iki parametre arama davranışını kontrol eder:
numCandidates, MongoDB’nin nihai sonuçlara daraltmadan önce incelediği ilk arama havuzunun boyutunu ayarlar. Daha büyük bir değer anımsamayı iyileştirir ancak biraz daha uzun sürer.limit, kaç sonuç elde edeceğinizi belirler. Bu eğitimdelimit3, numCandidates ise 150 olarak ayarlanmıştır. Yaygın bir başlangıç noktası,numCandidates’ı limitinizin 10–15 katı olarak belirlemektir.
Şimdi betiği çalıştırın:
python run_vector_search.py
Buna benzer bir çıktı alacaksınız:
<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.6642
"MongoDB Atlas", "I need an automated, scalable system for serious information storage" sorgusuyla ortak kelime paylaşmasa bile en yüksek puanı alır. Arama bunu döndürür çünkü vektörleri anlam bakımından yakındır: "...bilgi depolama için otomatik, ölçeklenebilir bir sistem" ifadesi anlamsal olarak "...tamamen yönetilen bir bulut veritabanı"na karşılık gelir. Aynı sorgu için yapılacak bir metin araması sıfır sonuç döndürür; çünkü hiçbir belge sorgudaki kelimelerin aynısını içermez. Bu, anlamsal aramanın amaçlandığı gibi çalıştığını gösterir.
Önemli Noktalar
- MongoDB Vector Search, M0 Ücretsiz katman kümesinde çalışır. Ücretli bir plan gerekmez.
- Saklanan gömmeleri üretirken de sorgu vektörlerini üretirken de aynı gömme modelini kullanmalısınız. Modelleri karıştırmak anlamsız sonuçlar üretir.
numDimensionsdeğeri, dizin tanımınızda gömme modelinizin çıktı boyutuyla tam olarak eşleşmelidir.nomic-embed-text-v1her zaman 768 boyut üretir.input_type="document", depolama için gömmeleri optimize eder.input_type="query", geri getirme için optimize eder. Her aşamada doğru türü kullanın.numCandidates, MongoDB’nin nihailimitsonuçlarına daraltmadan önce attığı arama ağının boyutunu kontrol eder. Daha büyük bir değer, sorgu süresi pahasına anımsamayı iyileştirir.vectorSearchScore, sonuçları anlamsal benzerliğe göre sıralar. Sonuçların, sorgudaki kelimelerin hiçbirini aynen içermesi gerekmez. Puan aralıkları modele ve veri kümesine göre değişir; ancak aşağıdaki sınırlar,nomic-embed-text-v1için kosinüs benzerliğiyle iyi bir başlangıç noktasıdır:- 0,9 ve üzeri: Neredeyse özdeş anlam. Belge ve sorgu anlamsal olarak neredeyse aynıdır.
- 0,7 ile 0,9: Güçlü alaka. Belge, sorgu niyetiyle açıkça ilişkilidir.
- 0,5 ile 0,7: Orta düzeyde alaka. Belge konu olarak ilgili olsa da farklı çerçeveleme veya bağlam kullanır.
- 0,5’in altı: Zayıf alaka. Bağlantı gevşektir ve sonuç faydalı olmayabilir.
Bu eğitime ait tüm kod örneklerini GitHub deposunda bulabilirsiniz.
Ek Okuma
- MongoDB Vector Search genel bakış, filtreleme ve kantifikasyon dahil MongoDB Vector Search’ün tüm yeteneklerini kapsar.
- Hibrit arama nasıl yapılır, tek bir sorguda vektör arama ve tam metin aramayı nasıl birleştireceğinizi gösterir.
- Vektör Gömeleri Nasıl Oluşturulur, koleksiyonlarınızdaki metin verileri için Voyage AI, OpenAI ve diğer açık kaynak model sağlayıcılarının gömme modellerini kullanarak vektör gömmelerini nasıl üreteceğinizi açıklar.
- MongoDB ile Bilgi Getirmeyle Güçlendirilmiş Üretim (RAG), bir RAG uygulamasında getirme katmanı olarak anlamsal aramayı nasıl kullanacağınızı gösterir.
SSS
Anlamsal aramayı uygulamak için ücretli bir Atlas planına ihtiyacım var mı?
Hayır. Bu eğitimdeki dört adımın tamamı, ücretsiz olan M0 Ücretsiz katman kümesinde çalışır.
Sorgum için, saklanan belgelerimdekinden farklı bir gömme modeli kullanırsam ne olur?
Sonuçlarınız anlamsız olacaktır. Farklı modeller, metni farklı sayısal uzaylara eşler; dolayısıyla vektörler karşılaştırılamaz. Dizinleme ve sorgulama için her zaman aynı modeli kullanın.
`numCandidates` ile `limit` arasındaki fark nedir?
numCandidates, MongoDB’nin arama sırasında incelediği vektör sayısıdır. limit, size döndürdüğü en iyi sonuçların sayısıdır. Daha yüksek bir numCandidates değeri, sorguları biraz yavaşlatma pahasına sonuç kalitesini artırır. Yaygın bir başlangıç noktası, numCandidates’ı limit’inizin 10 ila 15 katı olarak ayarlamaktır.
Anlamsal aramayı ve metin aramasını birlikte kullanabilir miyim?
Evet. MongoDB, tek bir hatta $vectorSearch ve $search’ü birleştiren hibrit aramayı destekler.
Anlamsal arama, İngilizceden başka diller için de çalışır mı?
Kullandığınız gömme modeline bağlıdır. nomic-embed-text-v1 ağırlıklı olarak İngilizce metin üzerinde eğitilmiştir. Çok dilli kullanım senaryoları için, verilerinizin içerdiği dillere göre eğitilmiş çok dilli bir gömme modeli seçin.

