موتورهای جستجوی مبتنی بر کلمات کلیدی سنتی از درک زمینه عاجز هستند. اگر کاربری عبارت «چگونه لوله شکسته را تعمیر کنم» را جستجو کند، جستجوی کلمه کلیدی ممکن است اسنادی که شامل «تعمیر لولهکشی» یا «رفع نشتی» هستند را از قلم بیندازد. اینجاست که جستجوی معنایی میدرخشد. با تبدیل متن به نمایشهای برداری ابعادی بالا (Embeddings)، میتوانیم معنای نهفته در محتوا را به جای تطبیق دقیق رشتهها درک کنیم. برای توسعهدهندگانی که سیستمهای تولید تقویتشده با بازیابی (RAG) میسازند، جستجوی معنایی صرفاً یک بهینهسازی نیست، بلکه گام حیاتی اولیه برای بازیابی زمینههای مرتبط برای مدلهای زبانی بزرگ (LLM) است.
جستجوی معنایی چگونه کار میکند؟
جستجوی معنایی بر اصل شباهت کسینوس یا فاصله ضرب داخلی بین بردارها عمل میکند. این فرآیند شامل دو مرحله اصلی است:
- تولید Embedding: با استفاده از یک مدل ترنسفورمر از پیش آموزشدیده (مانند Sentence-BERT یا API Embedding از OpenAI)، تکههای متن به بردارهای عددی تبدیل میشوند. معانی مشابه منجر به بردارهایی میشوند که در فضای چندبُعدی به هم نزدیکترند.
- بازیابی برداری: هنگامی که یک پرسش مطرح میشود، آن نیز به یک بردار تبدیل میشود. سپس سیستم در یک شاخص برداری جستجو میکند تا $K$ همسایه نزدیکترین (KNN) به بردار پرسش را پیدا کند.
پیادهسازی جستجوی معنایی با FAISS
Facebook AI Similarity Search (FAISS) یک کتابخانه محبوب برای جستجوی کارآمد شباهت روی بردارهای متراکم است. در زیر یک مثال عملی از راهاندازی یک خط لوله جستجوی معنایی با استفاده از Python، FAISS و ترنسفورمرهای Hugging Face آورده شده است.
import faiss
import numpy as np
from transformers import AutoTokenizer, AutoModel
def get_sentence_embeddings(sentences, model_name='sentence-transformers/all-MiniLM-L6-v2'):
"""Generate normalized embeddings for a list of sentences."""
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)
inputs = tokenizer(sentences, padding=True, truncation=True, return_tensors='pt')
with torch.no_grad():
output = model(**inputs)
embeddings = output.last_hidden_state[:, 0, :] # [CLS] token
embeddings = torch.nn.functional.normalize(embeddings, p=2, dim=1)
return embeddings.cpu().numpy()
# 1. Prepare Data
documents = [
"The sky is blue during the day.",
"Python is a popular programming language.",
"Machine learning models require large datasets.",
"The ocean is vast and deep."
]
# 2. Generate Document Embeddings
doc_embeddings = get_sentence_embeddings(documents)
doc_embeddings = np.float32(doc_embeddings)
# 3. Build FAISS Index (Inner Product)
dimension = doc_embeddings.shape[1]
index = faiss.IndexFlatIP(dimension)
index.add(doc_embeddings)
# 4. Perform Search
query = "What is the weather like outside?"
query_embedding = get_sentence_embeddings([query])
query_embedding = np.float32(query_embedding)
# Search for top 2 relevant documents
k = 2
distances, indices = index.search(query_embedding, k)
for i, doc_idx in enumerate(indices[0]):
print(f"Score: {distances[0][i]:.4f} | Doc: {documents[doc_idx]}")
بهترین روشها برای سیستمهای تولیدی
- استراتژی تکهبندی (Chunking): اسناد بزرگ را به تکههای کوچکتر و از نظر زمینه کامل (مثلاً ۱۰۰ تا ۵۰۰ توکن) تقسیم کنید تا دقت Embedding بهبود یابد.
- جستجوی ترکیبی (Hybrid Search): جستجوی معنایی را با BM25 (جستجوی کلمه کلیدی) ترکیب کنید تا بهترین نتایج از هر دو جهان را دریافت کنید. این کار اطمینان میدهد که اسامی خاص نادر یا کدهای خاص همچنان قابل بازیابی هستند.
- رتبهبندی مجدد (Re-ranking): از یک مدل کراس-انکودر (Cross-encoder) برای رتبهبندی مجدد $N$ کاندیدای برتر برگشتی از جستجوی برداری برای بهبود دقت نهایی استفاده کنید.
نتیجهگیری
جستجوی معنایی پل ارتباطی بین دادههای ساختارنیافته و کاربردهای هوش مصنوعی هوشمند است. با بهرهگیری از پایگاههای داده برداری و مدلهای Embedding قوی، میتوانید عملکرد خط لولههای RAG را به طور قابل توجهی بهبود دهید و اطمینان حاصل کنید که LLMهای شما به مرتبطترین زمینه ممکن دسترسی دارند. با FAISS شروع کنید، اما با افزایش حجم دادهها، به فکر مقیاسپذیری به پایگاههای داده برداری تخصصی مانند Pinecone، Weaviate یا Milvus باشید.