Embedding 与向量化
问题
什么是 Embedding?RAG 中如何选择 Embedding 模型?
答案
Embedding 是将文本转换为固定维度的稠密向量,使语义相似的文本在向量空间中距离更近。它是 RAG 检索的基础。
一、Embedding 工作原理
二、主流 Embedding 模型
| 模型 | 维度 | 最大 Token | 适用 | 特点 |
|---|---|---|---|---|
text-embedding-3-small | 1536 | 8191 | 通用 | OpenAI,性价比高 |
text-embedding-3-large | 3072 | 8191 | 高精度 | OpenAI,支持降维 |
bge-large-zh-v1.5 | 1024 | 512 | 中文 | 开源,BAAI |
jina-embeddings-v3 | 1024 | 8192 | 多语言 | 开源,长文本 |
voyage-3 | 1024 | 32000 | 代码+文本 | 代码检索效果好 |
cohere-embed-v3 | 1024 | 512 | 多语言 | 支持搜索/分类模式 |
三、相似度计算
余弦相似度(最常用)
import numpy as np
def cosine_similarity(a: np.ndarray, b: np.ndarray) -> float:
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
| 度量方式 | 公式特点 | 适用场景 |
|---|---|---|
| 余弦相似度 | 衡量方向,忽略幅度 | 文本检索(最常用) |
| 欧氏距离 | 衡量绝对距离 | 图像、推荐 |
| 点积 | 方向 + 幅度 | 归一化后等价余弦 |
四、Embedding 优化技巧
1. Query 和文档使用不同的前缀
一些模型(如 BGE、E5)要求为 query 和 document 添加不同前缀:
# BGE 模型需要加前缀
query_text = "query: 如何退款?"
doc_text = "passage: 退款需要在30天内提交申请..."
2. 微调 Embedding 模型
当通用模型在特定领域检索效果不好时,可以用领域数据微调:
# 构造 (query, positive_doc, negative_doc) 三元组
training_data = [
{
"query": "Python 如何读取文件",
"positive": "使用 open() 函数打开文件...",
"negative": "Java 中使用 FileReader..."
}
]
何时需要微调 Embedding
- 通用模型在你的领域 Recall@10 < 80%
- 有大量领域文档但专业术语多(医疗、法律、金融)
- 可以构造 1000+ 高质量 query-doc 对
3. 维度选择
text-embedding-3-large 支持自定义维度(降维不显著影响质量):
from openai import OpenAI
client = OpenAI()
response = client.embeddings.create(
model="text-embedding-3-large",
input="如何退款?",
dimensions=256, # 从 3072 降到 256,节省存储和计算
)
常见面试问题
Q1: 为什么不能直接用关键词匹配,要用 Embedding?
答案:
- 关键词匹配:只匹配字面相同的词,"退款"搜不到"退货退钱"
- Embedding 语义匹配:理解语义相似性,"如何退款" 能匹配 "退货流程"
- 实践中通常混合使用:BM25(关键词)+ Embedding(语义)= 混合检索
Q2: Embedding 维度越高越好吗?
答案:
不一定。高维度提供更丰富的语义表示,但也增加存储和计算成本。OpenAI 的实验表明,text-embedding-3-large 从 3072 降到 256 维,性能仅下降约 3%,但存储减少 12 倍。需根据场景在精度和效率间权衡。
Q3: 如何评估 Embedding 模型的质量?
答案:
- MTEB 排行榜:Massive Text Embedding Benchmark,涵盖检索、分类、聚类等任务
- 领域评估:构造领域 query-doc 数据集,评估 Recall@K、MRR
- A/B 测试:在实际 RAG 系统中对比端到端效果