Embedding:向量检索的基础
在RAG系统中,Embedding模型的质量直接决定了检索质量的上限。一个好的Embedding模型能让语义相关的文档在向量空间中靠近,不相关的远离。选错了Embedding模型,后面再多优化也白费。
主流Embedding模型
通用模型
BGE系列(智源)
- bge-large-zh-v1.5:中文最强之一
- bge-m3:多语言、多功能(稠密+稀疏+多向量)
- 维度:768/1024
- 优势:中文效果好、支持指令微调
E5系列(微软)
- multilingual-e5-large:多语言
- E5-large-v2:英文
- 维度:1024
- 优势:多语言一致性好
GTE系列(阿里)
- gte-large-zh:中文优化
- gte-multilingual:多语言
- 维度:1024
- 优势:长文本效果好
OpenAI text-embedding-3-large
- 维度:3072(可降维)
- 优势:API调用方便
- 劣势:中文效果不如国产模型
开源vs商用对比
| 模型 | 类型 | 中文MTEB | 速度 | 部署 |
|---|---|---|---|---|
| bge-m3 | 开源 | 66.3 | 快 | 自部署 |
| gte-large-zh | 开源 | 64.1 | 中 | 自部署 |
| text-embedding-3 | API | 62.5 | 快 | API |
| jina-embeddings-v3 | 开源 | 63.8 | 中 | 自部署 |
模型选型维度
1. 语言支持
- 纯中文场景:bge-large-zh、gte-large-zh
- 中英混合:bge-m3、multilingual-e5
- 多语言:bge-m3、E5-multilingual
2. 向量维度
维度越高,表达能力越强,但存储和检索成本也越高:
| 维度 | 1M文档存储 | 检索延迟 | 表达能力 |
|---|---|---|---|
| 384 | 1.5GB | 低 | 基准 |
| 768 | 3GB | 中 | 好 |
| 1024 | 4GB | 中 | 很好 |
| 3072 | 12GB | 高 | 最好 |
实践建议:768维是性价比最高的选择。
3. 最大输入长度
- 512 tokens:标准长度,适合短文档分块
- 8192 tokens:长文档,适合全文索引
- bge-m3支持8192,适合长文档场景
4. 指令感知
部分模型支持instruction prefix:
query: "What is AI?" → instruction="为检索相关文档生成向量"
document: "AI is..." → instruction="为文档生成向量"
指令感知模型在非对称检索(短query匹配长文档)时效果更好。
微调Embedding模型
何时需要微调
- 通用模型在你的领域表现不佳
- 有大量领域特定的query-document对
- 需要特殊语义匹配(如法律条文、医疗术语)
微调方法
对比学习微调:
# 数据格式
train_data = [
{"query": "劳动合同解除条件",
"positive": "用人单位与劳动者协商一致,可以解除劳动合同",
"negatives": ["天气晴朗", "股票上涨", "旅游攻略"]}
]
# InfoNCE损失
def info_nce_loss(q, pos, negs, temperature=0.05):
pos_sim = cos_sim(q, pos) / temperature
neg_sim = cos_sim(q, negs) / temperature
return -log(exp(pos_sim) / (exp(pos_sim) + sum(exp(neg_sim))))
数据构建策略:
- 硬负样本:与正样本相似但不够匹配的文档
- 跨编码器重排:用Cross-encoder生成训练数据
- 合成数据:用LLM生成领域query
微调效果
在法律领域实测:
- 微调前MTEB:62%
- 微调后MTEB:71%
- 提升9个百分点,检索准确率显著提升
评估指标
标准基准
MTEB(Massive Text Embedding Benchmark)
- 涵盖56个任务
- 分类、聚类、检索、重排、STS
- 最全面的Embedding评估基准
C-MTEB
- 中文版MTEB
- 35个中文任务
- 中文模型选型必看
自定义评估
def evaluate_embedding(model, test_cases):
"""
test_cases: [(query, relevant_doc, irrelevant_docs)]
"""
hits = 0
for query, relevant, irrelevant in test_cases:
q_vec = model.embed(query)
rel_vec = model.embed(relevant)
irrel_vecs = [model.embed(d) for d in irrelevant]
# 检查正样本是否比所有负样本更相似
sim_pos = cos_sim(q_vec, rel_vec)
sim_neg = max(cos_sim(q_vec, v) for v in irrel_vecs)
if sim_pos > sim_neg:
hits += 1
return hits / len(test_cases)
关键指标
- Recall@K:Top-K结果中包含正确答案的比例
- MRR:正确答案的平均倒数排名
- nDCG:考虑排序位置的归一化折损累计增益
工程优化
批量向量化
# 高效批量编码
texts = [doc.text for doc in documents]
embeddings = model.encode(texts, batch_size=256, show_progress_bar=True)
多向量索引
bge-m3支持三种向量:
- Dense向量:语义检索
- Sparse向量:关键词检索(类似BM25)
- Multi-vector:细粒度匹配
三路检索融合效果优于单一检索。
量化压缩
# 将768维float32压缩为int8
quantized = (embeddings * 128).astype(np.int8)
# 存储减少4倍,精度损失<1%
总结
Embedding模型是RAG系统"看不见但决定一切"的组件。选型不是"用最好的"而是"用最适合的"——中文场景优先考虑bge和gte系列,多语言考虑bge-m3,有特殊领域需求时做微调。最重要的是建立量化评估体系——不要用"看起来检索结果还不错"来判断,要用Recall@K等指标持续追踪。Embedding模型的每一次升级都会带来RAG系统的整体提升。