目的
理解Embedding模型的重要性以及现有Emebdding模型的优劣以及选型的指标。
Embedding是RAG的"心脏"
RAG系统工作流程与Embedding的作用
处理阶段 核心任务 Embedding的角色 输入→输出转换 文档处理 知识库准备 将文档切片转换为向量 文本 → 数字向量 检索阶段 查找相关信息 计算查询与文档的语义相似度 问题向量 vs 文档向量 增强阶段 构建提示词 基于语义相关度筛选最佳上下文 相关文档 + 原始问题 生成阶段 生成答案 为LLM提供精准的上下文信息 增强提示 → 最终答案
Embedding在RAG中的核心价值
价值维度 传统关键词搜索 基于Embedding的语义搜索 优势说明 语义理解 仅匹配字面词项 理解同义词、相关概念 “汽车"也能匹配"车辆”、“机动车” 多语言支持 需要语言特定配置 跨语言语义映射 中文问题可检索英文相关内容 长尾查询 对生僻查询效果差 基于概念相似性工作 即使查询词不常见也能找到相关内容 上下文感知 忽略词语上下文 考虑词语在上下文中的含义 "苹果公司"vs"水果苹果"区分明确
什么是Embedding?从文字到向量的魔法
Embedding技术基础概念
概念 定义 直观比喻 技术实现 Embedding向量 文本的数值表示 文字的"数字指纹" 浮点数数组,如[0.1, -0.5, 0.8, …] 向量空间 所有向量存在的数学空间 “语义宇宙” 高维坐标系(通常256-1536维) 语义相似度 向量间的距离关系 “语义距离” 余弦相似度、欧氏距离等 维度 向量的长度 “指纹的复杂程度” 模型输出固定长度的向量
文本到向量的转换示例
文本内容 可能的向量表示(简化) 语义相近文本 相似度计算 “我喜欢机器学习” [0.2, 0.7, -0.1, 0.5, …] “我热爱人工智能” 余弦相似度: 0.89 “今天天气很好” [0.1, 0.3, 0.9, -0.2, …] “阳光明媚的一天” 余弦相似度: 0.85 “编程很难学” [-0.5, 0.6, 0.2, 0.4, …] “写代码有挑战” 余弦相似度: 0.82 “苹果很好吃” [0.3, -0.2, 0.1, 0.8, …] “水果很美味” 余弦相似度: 0.78
Embedding模型选型的关键考量因素
选择Embedding模型时,需要从多个维度进行权衡:
1. 性能指标
检索准确率:模型找到相关文档的能力 排序质量:相关文档在结果中的排名位置 泛化能力:在未见过的数据上的表现
2. 技术参数
上下文长度:单次能处理的文本长度(512 tokens? 8K? 32K?) 向量维度:输出向量的尺寸(384维? 768维? 1536维?) 推理速度:生成向量的快慢
3. 资源成本
计算资源:模型运行需要的GPU/CPU资源 存储成本:向量数据库的存储需求 部署复杂度:本地部署还是使用API服务
4. 业务适配
语言支持:是否支持你的业务语言 领域适配:在专业领域(医疗、法律等)的表现 数据隐私:是否需要本地化部署
如何选择Embedding模型
模型介绍
模型系列 代表模型 主要语言 上下文长度 向量维度 关键优势 OpenAI text-embedding-3-large 多语言 8192 3072(可调整) 多语言、通用质量高,API支持,无需本地部署 QWen3 QWen3-8B 中英文 32K 可配置 8B 型号在 MTEB 多语言榜单排名第一 BGE系列 bge-large-zh 中文优化 512 1024 中文SOTA表现 E5系列 e5-large-v2 多语言 514 1024 平衡性能与效率 M3E系列 m3e-base 中文 512 768 中文社区优化 GTE系列 gte-large 多语言 8192 1024 长文本支持 Sentence-BERT all-MiniLM-L6 英文 256 384 轻量快速
如何选择
评估指标详细说明
指标 数学公式 代码实现关键点 适用场景 Hit Rate @ K
H
R
@
K
=
命中查询数
总查询数
HR@K = \frac{\text{命中查询数}}{\text{总查询数}}
H R @ K = 总查询数 命中查询数 any(doc_id in relevant_docs for doc_id in top_k_results)快速评估模型是否能在前K个结果中找到相关文档 MRR @ K
M
R
R
@
K
=
1
N
∑
i
=
1
N
1
rank
i
MRR@K = \frac{1}{N}\sum_{i=1}^N \frac{1}{\text{rank}_i}
MRR @ K = N 1 i = 1 ∑ N rank i 1 找到第一个相关文档的排名,计算其倒数 关注第一个相关文档的排名质量 NDCG @ K
N
D
C
G
@
K
=
D
C
G
@
K
I
D
C
G
@
K
NDCG@K = \frac{DCG@K}{IDCG@K}
N D CG @ K = I D CG @ K D CG @ K
D
C
G
@
K
=
∑
i
=
1
K
r
e
l
i
log
2
(
i
+
1
)
DCG@K = \sum_{i=1}^K \frac{rel_i}{\log_2(i+1)}
D CG @ K = i = 1 ∑ K log 2 ( i + 1 ) re l i 计算实际排序和理想排序的折扣累积增益比 考虑多级相关性和排序位置的综合评估
Hit Rate @ K:前K个结果中至少包含一个相关文档的概率
def hit_rate_at_k ( search_results: List[ List[ str ] ] ,
ground_truth: List[ List[ str ] ] ,
k: int ) - > float :
"""
计算Hit Rate @ K
Args:
search_results: 模型返回的排序结果列表,每个子列表包含文档ID
ground_truth: 真实相关文档列表,每个子列表包含相关文档ID
k: 考虑的前K个结果
Returns:
hit_rate: Hit Rate @ K 值
"""
hits = 0
total_queries = len ( search_results)
for i in range ( total_queries) :
top_k_results = search_results[ i] [ : k]
relevant_docs = set ( ground_truth[ i] )
if any ( doc_id in relevant_docs for doc_id in top_k_results) :
hits += 1
return hits / total_queries if total_queries > 0 else 0.0
Mean Reciprocal Rank (MRR) @ K:衡量第一个相关文档的排名质量def mean_reciprocal_rank_at_k ( search_results: List[ List[ str ] ] ,
ground_truth: List[ List[ str ] ] ,
k: int ) - > float :
"""
计算Mean Reciprocal Rank @ K
Args:
search_results: 模型返回的排序结果列表
ground_truth: 真实相关文档列表
k: 考虑的前K个结果
Returns:
mrr: Mean Reciprocal Rank @ K 值
"""
reciprocal_ranks = [ ]
for i in range ( len ( search_results) ) :
top_k_results = search_results[ i] [ : k]
relevant_docs = set ( ground_truth[ i] )
first_relevant_rank = None
for rank, doc_id in enumerate ( top_k_results, 1 ) :
if doc_id in relevant_docs:
first_relevant_rank = rank
break
if first_relevant_rank is not None :
reciprocal_ranks. append( 1.0 / first_relevant_rank)
else :
reciprocal_ranks. append( 0.0 )
return np. mean( reciprocal_ranks) if reciprocal_ranks else 0.0
Normalized Discounted Cumulative Gain (NDCG) @ K:考虑排序位置的综合指标def ndcg_at_k ( search_results: List[ List[ str ] ] ,
ground_truth: List[ List[ str ] ] ,
k: int ,
relevance_scores: Dict[ str , float ] = None ) - > float :
"""
计算Normalized Discounted Cumulative Gain @ K
Args:
search_results: 模型返回的排序结果列表
ground_truth: 真实相关文档列表
k: 考虑的前K个结果
relevance_scores: 文档相关性得分字典,如果不提供则使用二值相关性
Returns:
ndcg: Normalized Discounted Cumulative Gain @ K 值
"""
ndcg_scores = [ ]
for i in range ( len ( search_results) ) :
top_k_results = search_results[ i] [ : k]
relevant_docs = set ( ground_truth[ i] )
dcg = 0.0
for rank, doc_id in enumerate ( top_k_results, 1 ) :
if relevance_scores and doc_id in relevance_scores:
rel = relevance_scores[ doc_id]
else :
rel = 1.0 if doc_id in relevant_docs else 0.0
dcg += rel / math. log2( rank + 1 )
ideal_relevance = [ ]
for doc_id in relevant_docs:
if relevance_scores and doc_id in relevance_scores:
ideal_relevance. append( relevance_scores[ doc_id] )
else :
ideal_relevance. append( 1.0 )
ideal_relevance. sort( reverse= True )
ideal_relevance = ideal_relevance[ : k]
idcg = 0.0
for rank, rel in enumerate ( ideal_relevance, 1 ) :
idcg += rel / math. log2( rank + 1 )
if idcg > 0 :
ndcg_scores. append( dcg / idcg)
else :
ndcg_scores. append( 0.0 )
return np. mean( ndcg_scores) if ndcg_scores else 0.0
总结
为RAG系统选择合适的Embedding模型至关重要,它直接决定了检索质量,进而影响生成答案的准确性。我在验证RAG的稳定性时经常使用两种以上的模型进行调试,如Qwen3、BAAI等开源模型系列。最后,希望大家在落地RAG的时候都能为RAG找到合适的"心脏"。
参考资料
RAG系统嵌入模型怎么选?选型策略和踩坑指南 从 Word2Vec 到 LLM2Vec:如何为 RAG 选择合适的嵌入模型 Embedding模型本地部署及其作用解析 A comprehensive benchmark of single-cell Hi-C embedding tools 阿里开源通义千问3向量模型