向量数据库与Embedding
Embedding 是让 LLM "理解"语义的核心技术,而向量数据库是存储和检索这些理解的基础设施。RAG、语义搜索、推荐系统都建立在它们之上。
Embedding 全景
graph TB
A[原始内容] --> B[Embedding 模型]
B --> C[向量表示]
C --> D[向量数据库]
E[查询] --> F[Embedding 模型]
F --> G[查询向量]
G --> H[相似度搜索]
D --> H
H --> I[Top-K 结果]
style B fill:#fff9c4,stroke:#f9a825,stroke-width:2px
style D fill:#e3f2fd,stroke:#1565c0,stroke-width:2px
style H fill:#c8e6c9,stroke:#43a047,stroke-width:2px
Embedding 基础
from dataclasses import dataclass
import math
@dataclass
class SimpleEmbedding:
"""简化的 Embedding 演示"""
text: str
vector: list[float]
@property
def dimension(self) -> int:
return len(self.vector)
@property
def magnitude(self) -> float:
return math.sqrt(sum(x**2 for x in self.vector))
def cosine_similarity(a: list[float], b: list[float]) -> float:
"""余弦相似度"""
if len(a) != len(b):
raise ValueError("向量维度不匹配")
dot_product = sum(x * y for x, y in zip(a, b))
magnitude_a = math.sqrt(sum(x**2 for x in a))
magnitude_b = math.sqrt(sum(x**2 for x in b))
if magnitude_a == 0 or magnitude_b == 0:
return 0.0
return dot_product / (magnitude_a * magnitude_b)
# 概念演示:语义相似的文本,向量应该接近
embeddings = [
SimpleEmbedding("猫在沙发上睡觉", [0.8, 0.2, 0.1, 0.9]),
SimpleEmbedding("小猫躺在椅子上", [0.75, 0.25, 0.15, 0.85]),
SimpleEmbedding("Python 编程入门", [0.1, 0.9, 0.8, 0.2]),
SimpleEmbedding("学习 JavaScript", [0.15, 0.85, 0.75, 0.25]),
]
# 查询相似度
query = embeddings[0].vector # "猫在沙发上睡觉"
print("与 '猫在沙发上睡觉' 的相似度:")
for e in embeddings[1:]:
sim = cosine_similarity(query, e.vector)
print(f" '{e.text}': {sim:.4f}")
向量数据库简易实现
from dataclasses import dataclass, field
@dataclass
class VectorDocument:
doc_id: str
text: str
vector: list[float]
metadata: dict = field(default_factory=dict)
class SimpleVectorStore:
"""简易向量存储"""
def __init__(self):
self.documents: list[VectorDocument] = []
def add(self, doc: VectorDocument) -> None:
self.documents.append(doc)
def add_batch(self, docs: list[VectorDocument]) -> int:
self.documents.extend(docs)
return len(docs)
def search(
self, query_vector: list[float], top_k: int = 5
) -> list[tuple[VectorDocument, float]]:
"""暴力搜索最相似的 top-K 文档"""
results = []
for doc in self.documents:
sim = cosine_similarity(query_vector, doc.vector)
results.append((doc, sim))
results.sort(key=lambda x: x[1], reverse=True)
return results[:top_k]
def delete(self, doc_id: str) -> bool:
original_count = len(self.documents)
self.documents = [d for d in self.documents if d.doc_id != doc_id]
return len(self.documents) < original_count
@property
def count(self) -> int:
return len(self.documents)
向量数据库对比
| 数据库 | 类型 | 最大向量数 | 查询速度 | 适合场景 | 开源 |
|---|---|---|---|---|---|
| ChromaDB | 嵌入式 | 100万 | 快 | 本地开发/小规模 | ✅ |
| FAISS | 库 | 10亿+ | 极快 | 大规模离线搜索 | ✅ |
| Pinecone | 云 | 无限 | 快 | 生产级托管 | ❌ |
| Weaviate | 自托管/云 | 1亿+ | 快 | 多模态 | ✅ |
| Milvus | 自托管 | 10亿+ | 极快 | 大规模生产 | ✅ |
| Qdrant | 自托管/云 | 1亿+ | 快 | Rust 高性能 | ✅ |
Embedding 模型选型
| 模型 | 维度 | 中文 | 英文 | 价格 | 推荐场景 |
|---|---|---|---|---|---|
| OpenAI text-embedding-3-small | 1536 | 良好 | 优秀 | $0.02/1M tokens | 通用 |
| OpenAI text-embedding-3-large | 3072 | 良好 | 优秀 | $0.13/1M tokens | 高精度 |
| BGE-large-zh | 1024 | 优秀 | 良好 | 免费 | 中文首选 |
| GTE-large | 1024 | 优秀 | 优秀 | 免费 | 多语言 |
| Cohere embed-v3 | 1024 | 良好 | 优秀 | $0.10/1M tokens | 多语言 |
本章小结
- Embedding 把文本变向量——语义相似的文本在向量空间中距离更近
- 余弦相似度——最常用的相似度度量,范围 [-1, 1]
- 向量数据库选型——小规模用 ChromaDB,生产用 Milvus/Qdrant
- 中文推荐 BGE——专门为中文优化的开源 Embedding 模型
- 维度不是越大越好——1024 维对大多数场景足够
下一章:RAG 入门