RAG从入门到精通-RAG系统核心引擎Embedding模型

目的

理解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模型

模型介绍

模型系列代表模型主要语言上下文长度向量维度关键优势
OpenAItext-embedding-3-large多语言81923072(可调整)多语言、通用质量高,API支持,无需本地部署
QWen3QWen3-8B中英文32K可配置8B 型号在 MTEB 多语言榜单排名第一
BGE系列bge-large-zh中文优化5121024中文SOTA表现
E5系列e5-large-v2多语言5141024平衡性能与效率
M3E系列m3e-base中文512768中文社区优化
GTE系列gte-large多语言81921024长文本支持
Sentence-BERTall-MiniLM-L6英文256384轻量快速

如何选择

评估指标详细说明

指标数学公式代码实现关键点适用场景
Hit Rate @ K H R @ K = 命中查询数 总查询数 HR@K = \frac{\text{命中查询数}}{\text{总查询数}} HR@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=N1i=1Nranki1找到第一个相关文档的排名,计算其倒数关注第一个相关文档的排名质量
NDCG @ K N D C G @ K = D C G @ K I D C G @ K NDCG@K = \frac{DCG@K}{IDCG@K} NDCG@K=IDCG@KDCG@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)} DCG@K=i=1Klog2(i+1)reli
计算实际排序和理想排序的折扣累积增益比考虑多级相关性和排序位置的综合评估
  1. 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):
            # 获取前K个结果
            top_k_results = search_results[i][:k]
            # 获取真实相关文档
            relevant_docs = set(ground_truth[i])
            
            # 检查前K个结果中是否有至少一个相关文档
            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
  1. 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
             
             # 计算 Reciprocal Rank
             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
    
  2. 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
             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:
                     # 二值相关性:相关为1,不相关为0
                     rel = 1.0 if doc_id in relevant_docs else 0.0
                 
                 dcg += rel / math.log2(rank + 1)  # 使用 log2(rank + 1) 作为折扣因子
             
             # 计算 IDCG (理想排序的DCG)
             # 构建理想排序:所有相关文档排在前面
             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]  # 只取前K个
             
             idcg = 0.0
             for rank, rel in enumerate(ideal_relevance, 1):
                 idcg += rel / math.log2(rank + 1)
             
             # 计算 NDCG
             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找到合适的"心脏"。

参考资料

  1. RAG系统嵌入模型怎么选?选型策略和踩坑指南
  2. 从 Word2Vec 到 LLM2Vec:如何为 RAG 选择合适的嵌入模型
  3. Embedding模型本地部署及其作用解析
  4. A comprehensive benchmark of single-cell Hi-C embedding tools
  5. 阿里开源通义千问3向量模型
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值