RAG中的混合检索(Hybrid Search):稀疏检索与稠密检索的强强联合

目录

引言

什么是混合检索?

混合检索的核心思想

稀疏检索(BM25)与稠密检索的对比

稀疏检索(BM25)

稠密检索(向量检索)

为什么需要混合检索?

[1. 医疗领域](#1. 医疗领域)

[2. 法律领域](#2. 法律领域)

[3. 技术文档](#3. 技术文档)

混合检索的实现方式

[1. 结果融合(Score Fusion)](#1. 结果融合(Score Fusion))

[2. 重排序(Reranking)](#2. 重排序(Reranking))

[3. 使用支持混合检索的向量数据库](#3. 使用支持混合检索的向量数据库)

权重优化:从静态到动态

静态权重的局限

动态权重调整

方法一:基于LLM的动态权重调优

方法二:基于信息熵的动态加权

混合检索的最佳实践

[1. 根据场景选择权重](#1. 根据场景选择权重)

[2. 结合重排序提升效果](#2. 结合重排序提升效果)

[3. 使用专业工具和平台](#3. 使用专业工具和平台)

[4. 持续评估和优化](#4. 持续评估和优化)

总结


引言

在构建RAG(检索增强生成)系统时,检索质量直接决定了生成内容的上限。如果检索阶段无法召回相关文档,即使大模型能力再强,也难以生成准确的答案。

然而,单一检索方法总有局限:稠密向量检索 擅长理解语义,却可能忽略精确的关键词匹配;**稀疏检索(如BM25)**能精准命中关键词,却难以理解同义词和上下文语义。那么,有没有办法让两者优势互补?

答案是肯定的------这就是本文要介绍的混合检索(Hybrid Search)

什么是混合检索?

混合检索是一种结合多种检索技术(通常是稀疏检索和稠密检索)的查询方法,旨在融合不同检索方式的优势,提升整体检索效果。

在RAG系统中,混合检索通常发生在检索阶段,通过聚合多个信息流,为后续的生成提供更准确、更丰富的上下文。

混合检索的核心思想

传统的RAG方案中,检索到的多个文档往往只是简单拼接后输入给大模型。而混合检索则采用更专业的机制,跨多个检索结果组合相关信息:

  • 在检索后增强:对多个检索结果应用重排序、过滤或合并

  • 在生成中融合:让大模型独立处理每个检索结果,再融合生成

稀疏检索(BM25)与稠密检索的对比

要理解混合检索的价值,首先需要了解这两种检索方式的优缺点。

稀疏检索(BM25)

BM25(Best Matching 25)是基于关键词匹配的传统信息检索算法,它通过计算查询词与文档的词频(TF)和逆文档频率(IDF)来评估相关性。

优点

  • 精准匹配:能精确命中特定术语、编号、名称等

  • 可解释性强:清楚知道为什么匹配(因为包含某些关键词)

  • 无需训练:直接基于统计计算,无需模型训练

缺点

  • 语义盲区:无法理解同义词(如"汽车"和"车辆")

  • 词汇鸿沟:如果文档用词与查询不同,即使语义相关也无法召回

  • 无法处理复杂语义:对意图理解能力有限

稠密检索(向量检索)

稠密检索通过神经网络将文本映射到高维语义空间,用向量表示语义,通过计算向量相似度进行检索。

优点

  • 语义理解:能理解同义词、上下文和隐含意图

  • 跨语言检索:支持不同语言的语义匹配

  • 容错性强:对查询中的拼写错误有一定容忍度

缺点

  • 可能引入噪音:语义相近但不相关的内容可能被误召回

  • 可解释性差:难以解释为什么匹配

  • 依赖训练数据:对长尾或专业领域术语可能效果不佳

为什么需要混合检索?

单一检索方法在实际应用中往往力不从心,尤其是在以下场景:

1. 医疗领域

医生搜索"2型糖尿病 儿童患者 病例",纯向量检索可能召回一堆1型糖尿病的资料------语义相近,但与需求不符。

2. 法律领域

用户查询"XX场景下的连带责任",纯向量检索可能返回大量"XX场景补充责任"的文书------仅两字之差,法律含义却天差地别。

3. 技术文档

搜索"Oracle JDBC驱动配置",纯关键词搜索可能错过用"Java数据库连接"表述的文档,纯语义搜索可能召回过于泛化的内容。

混合检索的价值 正是在于:既能理解整体语义,又能匹配精确术语,弥补单一方法的不足

混合检索的实现方式

1. 结果融合(Score Fusion)

最常用的混合检索方式是分别执行稀疏检索和稠密检索,然后将两个结果集按一定权重融合。

python 复制代码
def hybrid_search(query, dense_retriever, sparse_retriever, alpha=0.5, top_k=10):
    """
    混合检索:融合稠密检索和稀疏检索的结果
    
    Args:
        query: 查询文本
        dense_retriever: 稠密检索器
        sparse_retriever: 稀疏检索器(BM25)
        alpha: 稠密检索权重 (0-1),稀疏检索权重为 1-alpha
        top_k: 返回结果数量
    
    Returns:
        融合后的检索结果
    """
    # 执行稠密检索
    dense_results = dense_retriever.retrieve(query, top_k=top_k*2)
    
    # 执行稀疏检索
    sparse_results = sparse_retriever.retrieve(query, top_k=top_k*2)
    
    # 融合分数
    combined_scores = {}
    
    # 归一化分数并加权融合
    for doc_id, score in normalize_scores(dense_results):
        combined_scores[doc_id] = alpha * score
    
    for doc_id, score in normalize_scores(sparse_results):
        if doc_id in combined_scores:
            combined_scores[doc_id] += (1 - alpha) * score
        else:
            combined_scores[doc_id] = (1 - alpha) * score
    
    # 按融合分数排序,返回top_k
    sorted_results = sorted(combined_scores.items(), 
                           key=lambda x: x[1], reverse=True)[:top_k]
    
    return sorted_results

def normalize_scores(results):
    """分数归一化"""
    if not results:
        return []
    
    scores = [score for _, score in results]
    max_score = max(scores)
    min_score = min(scores)
    
    if max_score == min_score:
        return [(doc_id, 1.0) for doc_id, _ in results]
    
    return [(doc_id, (score - min_score) / (max_score - min_score)) 
            for doc_id, score in results]

2. 重排序(Reranking)

更精细的方式是先分别检索出较多候选结果,然后用一个更强大的模型(如交叉编码器)进行重排序

python 复制代码
def hybrid_search_with_rerank(query, dense_retriever, sparse_retriever, 
                               reranker, initial_k=20, final_k=10):
    """
    混合检索 + 重排序
    """
    # 分别检索更多候选
    dense_results = dense_retriever.retrieve(query, top_k=initial_k)
    sparse_results = sparse_retriever.retrieve(query, top_k=initial_k)
    
    # 合并候选文档(去重)
    candidate_docs = merge_deduplicate(dense_results, sparse_results)
    
    # 使用重排序模型重新打分
    reranked = reranker.rerank(query, candidate_docs)
    
    return reranked[:final_k]

3. 使用支持混合检索的向量数据库

现代向量数据库如**Milvus 2.5+**已原生支持混合检索,内置BM25算法,可以自动从文本字段生成稀疏向量。

python 复制代码
from pymilvus import MilvusClient, DataType, Function, FunctionType

# 创建支持混合检索的集合
schema = MilvusClient.create_schema()

# 添加文本字段(启用分析器)
schema.add_field(
    field_name="text", 
    datatype=DataType.VARCHAR, 
    max_length=65535, 
    enable_analyzer=True,
    analyzer_params={"type": "chinese"}  # 中文分析器
)

# 添加稠密向量字段
schema.add_field(
    field_name="dense", 
    datatype=DataType.FLOAT_VECTOR, 
    dim=768
)

# 添加稀疏向量字段(将由BM25函数自动生成)
schema.add_field(
    field_name="sparse_bm25", 
    datatype=DataType.SPARSE_FLOAT_VECTOR
)

# 定义BM25函数:自动从text字段生成稀疏向量
bm25_function = Function(
    name="bm25",
    function_type=FunctionType.BM25,
    input_field_names=["text"],
    output_field_names="sparse_bm25",
)
schema.add_function(bm25_function)

# 创建集合
client.create_collection(
    collection_name="hybrid_collection",
    schema=schema
)

# 混合检索:同时使用稠密向量和稀疏向量
hybrid_results = client.hybrid_search(
    collection_name="hybrid_collection",
    reqs=[
        # 稠密检索请求
        {
            "vector": query_dense_embedding,
            "anns_field": "dense",
            "param": {"metric_type": "IP"},
            "limit": 10
        },
        # 稀疏检索请求
        {
            "vector": query_text,  # 自动转换为BM25稀疏向量
            "anns_field": "sparse_bm25",
            "param": {"metric_type": "BM25"},
            "limit": 10
        }
    ],
    rerank={"strategy": "rrf"},  # 使用倒数秩融合
    limit=10
)

权重优化:从静态到动态

混合检索的核心挑战之一是如何确定稠密检索和稀疏检索的权重 (即前述代码中的alpha值)。

静态权重的局限

传统的固定权重方案(如始终alpha=0.5)无法适应不同查询的特性------有些查询更需要语义理解,有些则更需要关键词精确匹配。

动态权重调整

最新研究提出了动态权重调整方案,让系统根据查询特性自适应地调整融合权重。

方法一:基于LLM的动态权重调优

**DAT(Dynamic Alpha Tuning)**框架利用大语言模型评估两种检索方法的效果,动态校准最优权重:

python 复制代码
def dynamic_alpha_tuning(query, dense_retriever, sparse_retriever, llm):
    """
    使用LLM动态调整混合检索权重
    """
    # 分别获取两种检索的top-1结果
    dense_top1 = dense_retriever.retrieve(query, top_k=1)[0]
    sparse_top1 = sparse_retriever.retrieve(query, top_k=1)[0]
    
    # 让LLM评估两个结果的有效性
    prompt = f"""
    查询:{query}
    
    结果A(稠密检索):{dense_top1.text}
    结果B(稀疏检索):{sparse_top1.text}
    
    请评估这两个结果与查询的相关性,分别给出0-10的分数。
    只返回两个数字,格式:A分数, B分数
    """
    
    response = llm.generate(prompt)
    dense_score, sparse_score = parse_scores(response)
    
    # 归一化作为权重
    total = dense_score + sparse_score
    alpha = dense_score / total if total > 0 else 0.5
    
    return alpha

实验表明,DAT方法在各种评估指标上显著优于固定权重混合检索。

方法二:基于信息熵的动态加权

另一种前沿方法是使用归一化香农熵作为检索置信度的代理,迭代优化稀疏和稠密分数的线性组合:

python 复制代码
def entropy_based_weighting(query, dense_retriever, sparse_retriever, 
                            max_iterations=5, epsilon=0.1):
    """
    基于熵的动态权重调整
    """
    # 初始化权重
    w_dense, w_sparse = 0.5, 0.5
    
    for iteration in range(max_iterations):
        # 执行混合检索
        results = hybrid_search(query, dense_retriever, sparse_retriever,
                               alpha=w_dense, top_k=20)
        
        # 计算检索结果的熵(衡量不确定性)
        scores = [score for _, score in results]
        entropy = calculate_entropy(scores)
        
        # 熵归一化
        norm_entropy = entropy / max_entropy
        
        # 更新权重:熵越高,越偏向稀疏检索(更精确)
        w_dense = 1 - norm_entropy
        w_sparse = norm_entropy
        
        # 检查收敛
        if abs(w_dense - prev_w_dense) < epsilon:
            break
    
    return hybrid_search(query, dense_retriever, sparse_retriever,
                        alpha=w_dense, top_k=10)

这种方法在HotPotQA和TriviaQA等数据集上显著优于固定权重基线。

混合检索的最佳实践

1. 根据场景选择权重

  • 技术文档/法律条文:提高稀疏检索权重(alpha较小),确保术语精准匹配

  • 开放域问答/对话:提高稠密检索权重(alpha较大),强调语义理解

  • 混合场景:从0.5开始,根据实际效果微调

2. 结合重排序提升效果

混合检索后,可以使用交叉编码器等重排序模型对结果进行精排,进一步提升相关性。

3. 使用专业工具和平台

  • Milvus/Zilliz Cloud:原生支持混合检索,提供完整的工具链

  • Oracle Database 23ai:同时支持向量搜索和全文搜索,内置混合检索能力

  • RAGFlow框架:集成混合检索模块,简化开发流程

4. 持续评估和优化

建立评估指标,持续监控检索效果:

  • Precision@K:检索结果的相关性

  • Recall@K:相关文档的召回率

  • MRR:首个相关结果的排名

总结

混合检索通过结合稀疏检索和稠密检索的优势,显著提升了RAG系统的检索质量:

  • 稀疏检索(BM25):确保关键词精准匹配,可解释性强

  • 稠密检索(向量):捕捉语义相似性,理解深层意图

  • 混合检索:两者优势互补,应对复杂查询场景

随着向量数据库技术的进步(如Milvus 2.5+的原生混合检索能力)和动态权重优化算法的成熟(如DAT、基于熵的调整),混合检索正变得越来越易用和高效。

在实际应用中,建议从简单的加权融合开始,根据具体场景调整权重,逐步引入重排序和动态优化策略,打造最适合自己业务需求的RAG系统。

相关推荐
橙露1 小时前
Python 办公自动化:批量处理 Excel/Word/PPT 实战教程
python·word·excel
咚咚王者2 小时前
人工智能之视觉领域 计算机视觉 第十三章 视频背景减除
人工智能·计算机视觉·音视频
你的论文学长2 小时前
对抗知网的 N-Gram 算法:基于语义解耦的【文本重构】与【事实性核验】架构设计
人工智能·算法·重构
WW_千谷山4_sch2 小时前
MYOJ_7788:(洛谷P3387)【模板】缩点(有关强连通分量)
c++·算法·深度优先·动态规划·图论·拓扑学
Java_慈祥2 小时前
My First AI智能体!!!
python·agent·coze
一水鉴天2 小时前
关于“整体设计定稿” 的高阶表述 20260222
人工智能·架构
小O的算法实验室2 小时前
2026年IEEE TCYB SCI1区TOP,少即是多:一种用于大规模优化的小规模学习粒子群算法,深度解析+性能实测
算法·论文复现·智能算法·智能算法改进
美酒没故事°2 小时前
mac电脑安装OpenClaw步骤
人工智能·macos
用户3521802454752 小时前
RAG 做不好?可能是你的 PDF 在"捣乱" 😅
后端·python·ai编程