当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > RAG 混合检索融合关键词与向量结果

RAG 混合检索融合关键词与向量结果

来源:17golang原创 2026-10-10 13:01:02 0浏览 收藏

RAG 同时接入关键词检索和向量检索后,真正棘手的通常不是“查两次”,而是如何把两份结果合成一份可信的候选列表。关键词检索擅长命中产品名、错误码和专有术语,向量检索更容易找到同义改写与语义相近内容。一个实用起点是让两路检索各自排序,再用 Reciprocal Rank Fusion(RRF)按名次融合,最后把统一的 Top-K 文档交给大模型。

先划清这个小项目的边界

本文只实现融合层:输入是两份已经排好序的候选,输出是去重后的统一列表。BM25、嵌入生成、向量索引和大模型调用都留在融合器外面。这样做的好处是可以独立检查融合逻辑,也便于以后替换 Elasticsearch、OpenSearch、Milvus、pgvector 或其他检索后端。

Elastic 的混合搜索文档把全文检索和向量检索组合为一份排名结果,并推荐用 RRF 合并两类排名。RRF 不直接比较不同检索器的原始分数,而是根据文档在每份结果中的名次贡献分数,因此很适合处理 BM25 分数与向量相似度不在同一量纲的问题。

为什么不能直接相加原始分数

假设关键词检索返回 12.8、9.4、7.1,向量检索返回 0.92、0.86、0.81。数值范围不同,相加后谁占主导取决于评分模型,而不是文档是否真的更相关。即使先做归一化,也要决定采用 min-max、z-score 还是按查询动态校准,线上数据分布一变,规则就可能漂移。

RRF 只看名次。对于文档 d,它在每份排名中的贡献为 1 / (k + rank),其中 rank 从 1 开始,k 是平滑常数。文档同时出现在两路前排时会获得两次贡献,只在一路出现也不会被直接丢弃。

同一查询进入关键词检索和向量检索并形成两份独立候选排名的原创结构图
图1:RAG 混合检索的两路候选结构,图片为原创说明图。

准备统一的候选数据结构

两路检索必须共享稳定的 doc_id。标题或正文不适合作为去重键,因为内容更新、分段策略或空格差异都会制造重复项。融合层还应保留来源、原始分数和元数据,便于日志分析,但排序只使用名次。

from dataclasses import dataclass
from typing import Iterable

@dataclass(frozen=True)
class Hit:
    # doc_id 必须能跨检索器唯一标识同一文档
    doc_id: str
    title: str
    source: str
    raw_score: float


# 下面两组数据代表检索器已返回的有序结果
keyword_ranked = [
    Hit("d1", "RRF 融合算法", "keyword", 12.8),
    Hit("d2", "RAG 检索调优", "keyword", 9.4),
    Hit("d4", "BM25 字段权重", "keyword", 7.1),
]

vector_ranked = [
    Hit("d2", "RAG 检索调优", "vector", 0.92),
    Hit("d3", "语义召回实践", "vector", 0.86),
    Hit("d1", "RRF 融合算法", "vector", 0.81),
]

把公式落成一个最小 Python 融合器

实现时遍历每份排名,以 doc_id 为键累计贡献。为了让相同分数的结果稳定,示例额外记录文档出现过的最好名次,并用 doc_id 作为最终兜底排序键。真实项目还可以把更新时间、权威级别或业务优先级放进明确的二级排序规则。

def rrf_fuse(
    ranked_lists: Iterable[list[Hit]],
    *,
    rank_constant: int = 60,
    top_k: int = 5,
) -> list[dict]:
    if rank_constant 

按照这组示例输入,d1 和 d2 都在两路结果中出现,会获得两次贡献;d3 与 d4 只获得一路贡献。这里不需要比较 12.8 与 0.92 谁更大,融合器只关心它们各自在所属列表里的位置。

关键词排名和向量排名按文档编号去重并累计RRF分数的原创数据结构图
图2:RRF 融合器的数据结构与输出关系,图片为原创说明图。

接入真实 RAG 链路时放在哪里

一次完整请求可以拆成六个动作:先接收用户查询,再并行执行关键词检索和向量检索;把两路结果映射成统一 Hit;调用融合器;按融合后的 doc_id 读取正文片段;最后控制上下文长度并交给生成模型。融合前的检索可以并行,融合后的正文读取则应严格按照新排名进行。

过滤条件要保持一致。例如租户、文档状态、语言和权限最好在两路检索前都应用;如果只对一路过滤,融合结果可能出现另一条路径带回的越权文档。融合之后仍应做一次权限兜底,但不能把它当作唯一的访问控制。

三个参数分别控制什么

  • 候选深度:每路取多少条参与融合。窗口越大,召回机会越多,但查询、传输和去重成本也越高。
  • rank_constant:控制头部名次与后部名次贡献的差距。数值越大,靠后候选之间的差异越平缓。Elastic 官方 RRF 文档当前给出的默认值是 60。
  • top_k:融合后最终保留多少条。它应与分段长度和模型上下文预算一起确定,而不是简单复制候选深度。

不要一开始就为两个检索器添加大量权重。先用等权 RRF 建立可解释基线,再根据带标注的查询集观察精确术语、同义改写、长查询和冷门主题的表现。需要偏置时,可以把每路贡献改为 weight / (k + rank),但权重应来自评测,而不是凭感觉。

本地验收时检查这五点

  1. 输入包含错误码或产品全名时,关键词路线的高位结果能够进入最终列表。
  2. 输入改写为同义表达时,向量路线仍能补回语义相关文档。
  3. 同一个 doc_id 同时出现于两路时,最终只保留一条且分数累加。
  4. 原始分数范围发生变化时,融合排序不会因为量纲不同而直接失真。
  5. 相同输入重复融合时,二级排序规则保证输出顺序稳定。

从最小实现走向生产环境

生产系统还需要补上超时、空列表、日志和评测。某一路超时时,可以降级为另一份排名;两路都为空时,不应让模型凭空回答。日志至少记录查询标识、两路候选 doc_id、各自名次、融合分数和最终入选项,方便定位“召回不到”还是“融合丢失”。

如果搜索引擎已经原生支持 RRF,可以把融合放到引擎端,减少应用层传输和重复代码;如果两路来自不同系统,本文这个小型融合器更容易统一接入。无论采用哪种方式,核心原则都相同:先保留每种检索信号的独立排序,再用可解释的融合规则生成最终上下文。

参考资料:Elastic Hybrid search、Elastic Reciprocal rank fusion。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
iter.Pull 未关闭造成 goroutine 残留的定位iter.Pull 未关闭造成 goroutine 残留的定位
上一篇
iter.Pull 未关闭造成 goroutine 残留的定位
iter.Seq 连接多个数据源时的停止协议
下一篇
iter.Seq 连接多个数据源时的停止协议
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    402次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    478次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    488次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    435次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    262次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码