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-3API62.5API
jina-embeddings-v3开源63.8自部署

模型选型维度

1. 语言支持

  • 纯中文场景:bge-large-zh、gte-large-zh
  • 中英混合:bge-m3、multilingual-e5
  • 多语言:bge-m3、E5-multilingual

2. 向量维度

维度越高,表达能力越强,但存储和检索成本也越高:

维度1M文档存储检索延迟表达能力
3841.5GB基准
7683GB
10244GB很好
307212GB最好

实践建议: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系统的整体提升。