正在加载,请稍候…

Vector Embeddings and Semantic Search: From Theory to Production

Deep dive into vector embeddings for semantic search and recommendation systems. Learn embedding models, Qdrant, FAISS, and ANN algorithms.

Vector Embeddings and Semantic Search

Generating Embeddings

from sentence_transformers import SentenceTransformer
import numpy as np

model = SentenceTransformer('BAAI/bge-m3')  # 1024 dims, multilingual

sentences = [
    "The quick brown fox jumps over the lazy dog",
    "A fast orange fox leaped above a sleepy canine",
    "Python is a programming language",
]
embeddings = model.encode(sentences, normalize_embeddings=True)

# Cosine similarity via dot product (normalized vectors)
print(np.dot(embeddings[0], embeddings[1]))  # ~0.92 - semantically similar
print(np.dot(embeddings[0], embeddings[2]))  # ~0.15 - different topic

Qdrant Vector Database

from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
import uuid

client = QdrantClient(host="localhost", port=6333)
client.create_collection("docs", vectors_config=VectorParams(size=1024, distance=Distance.COSINE))

def index(documents):
    texts = [d["text"] for d in documents]
    embs = model.encode(texts, normalize_embeddings=True, show_progress_bar=True)
    points = [PointStruct(id=str(uuid.uuid4()), vector=e.tolist(), payload=d)
              for d, e in zip(documents, embs)]
    client.upload_points("docs", points=points, batch_size=100)

def search(query, limit=10):
    q = model.encode([query], normalize_embeddings=True)[0]
    results = client.search("docs", query_vector=q.tolist(), limit=limit, score_threshold=0.7)
    return [{"text": r.payload["text"], "score": r.score} for r in results]

Hybrid Search (Dense + Sparse via RRF)

# Qdrant RRF fusion of dense and sparse search
results = client.query_points(
    "hybrid_docs",
    prefetch=[
        models.Prefetch(query=dense_emb.tolist(), using="dense", limit=20),
        models.Prefetch(query=sparse_vec, using="sparse", limit=20),
    ],
    query=models.FusionQuery(fusion=models.Fusion.RRF),
    limit=10,
)

FAISS ANN Index

import faiss

class FAISSIndex:
    def __init__(self, dims=1024):
        quantizer = faiss.IndexFlatIP(dims)
        self.index = faiss.IndexIVFFlat(quantizer, dims, 1024)
        self.index.nprobe = 32

    def build(self, embeddings):
        self.index.train(embeddings)
        self.index.add(embeddings)

    def search(self, query, k=10):
        return self.index.search(query.reshape(1, -1), k)

Embedding-Based Recommendations

from sklearn.metrics.pairwise import cosine_similarity

class RecommendationEngine:
    def fit(self, items):
        texts = [f"{i['title']} {i['description']}" for i in items]
        self.embeddings = model.encode(texts, normalize_embeddings=True)
        self.ids = [i["id"] for i in items]

    def recommend(self, user_history, n=10):
        idx = [self.ids.index(id) for id in user_history if id in self.ids]
        user_emb = self.embeddings[idx].mean(axis=0)
        user_emb /= np.linalg.norm(user_emb)
        scores = cosine_similarity([user_emb], self.embeddings)[0]
        ranked = np.argsort(scores)[::-1]
        return [self.ids[i] for i in ranked if self.ids[i] not in user_history][:n]

Production Tips

Issue Solution
Index freshness Queue-based real-time updates
Cold start Content-based fallback
Latency ANN + L1 cache
Quality A/B test embedding models