RAG 进阶:混合检索、重排与评估
一句话定位:给朴素 RAG 打四层补丁——切块谱系、查询优化、混合检索、重排,再用评估证明补丁真的有效。前置:RAG:检索增强生成——先跑通过骨架,这里的每个补丁才有对照物。
补丁要一层层打,还要验收
朴素 RAG 的三类失效你已经知道:召回不到、排序错、答案无据。
市面上每个 RAG 教程都会甩出一堆进阶名词——混合检索、HyDE、rerank、RAGAS——但很少有人说清两件事:每个补丁对应哪类失效,以及打了补丁之后怎么证明它有效。
不对应失效的优化是装饰,没有评估的优化是赌博。这篇按「失效 → 补丁 → 验收」的线索,把进阶版图拼完整。
图:补丁地图——左下角是三类失效与各自对应的层,评估环守在最后验收一切
渐进拆解:五层各管一件事
索引侧:切块不是剪刀,是语义单元的划定
朴素管线的「每 500 字切一刀」只是切块谱系里最粗糙的一档。谱系往下走,每一档都在回答同一个问题:一块的边界画在哪,才能让「一个块 = 一个完整的意思单元」?
- 固定长度:简单便宜,起点档;主题混杂是代价。
- 段落 / 标题切块:尊重作者划好的边界——Markdown 标题、段落空行是现成的语义信号。
- 语义切块:按句间相似度找「话题转折点」下刀,贵一点但边界更准。
- 代码 AST 切块:代码不能按字数砍——按语法树沿函数、类的边界切,函数永远完整。给代码库建 RAG 的标配。
- 元数据附加:切块时顺手挂上来源文件、章节、日期、权限标签——检索之后过滤全靠它。
各档都要配 overlap(相邻块重合几十个字,沿用上一篇 500/50 的做法),防关键句被边界斩断。
查询侧:先把问题修好,再拿去检索
用户的问题天然是「口语的、省略的、模糊的」,检索库却是「书面、完整、术语化」的——五个手段按需用:
- 改写:把「钱怎么回来」改写成「退款流程」——对齐资料的语言。
- 分解:把「A 和 B 哪个方案好」拆成两个子问题分别检索。
- 澄清:歧义太大时反问用户而不是硬猜。
- HyDE:先让模型凭空写一个假想答案,拿假想答案的向量去检索——答案和文档的语言风格更接近,命中率常优于用问题本身检索。
- 多轮改写:把「那第二种呢」这类指代补全成完整问题——多轮对话的必需品。
召回侧:向量与关键词,双保险
向量检索管「意思接近」,BM25(基于词频的经典字面匹配算法,Elasticsearch 的看家本领)管「字面精确」——Embedding 与向量化说过「E-4021 被 embed 后可能和 E-4022 靠得很近」,BM25 就编号匹配而言几乎不会认错它们。
图:混合检索——同一个问题分走向量与 BM25 两路,RRF 把两路排名融合成一份结果
两路并行检索、结果融合(常用 RRF,倒数排名融合:一个文档在两路里都靠前就排最前),就是混合检索。向量路补「字面岔开但意思仍近」的那一端,BM25 补「编号必须精确」的那一端——两个极端,一路守一个。
排序侧:两段式,先广撒网再精挑
混合检索找回了候选(比如 20 段),但谁最相关还得精挑细选。这就是重排(rerank)的舞台,两种架构的取舍是本层核心:
- 双塔(bi-encoder):问题与文档各自编码成向量再算距离——文档可离线编码,检索飞快;但两段文字没有交互,「细粒度的相关性」判断不了。适合从百万级粗筛到百级。
- 交叉编码器(cross-encoder):问题与文档拼在一起送进模型,逐对输出相关性分数——每一对都做深度交互,精度显著更高;代价是每对都要跑一次模型,慢且贵。适合从百级精选到个位数。
生产标配是两段式:双塔(或向量+BM25)召回 top-20 → 交叉编码器重排 → 取 top-3 进提示词。 rerank 模型有现成的(开源 reranker 系列与商用 rerank API 都是即插即用),不必自训。
图:检索漏斗——三层收窄;交叉编码器只对几十个候选逐对打分,精度与延迟各得其所
取舍的量级感受一下:双塔编码一条文档是毫秒级,而且可以离线批量做——建库时就算好,查询时零成本;交叉编码器每一对都要跑一次完整的模型前向,几十毫秒起步,30 个候选就是秒级的追加延迟。这就是精排只对几十个候选做的原因:精度买得起的范围,以候选数量为界——想给精排多喂几个候选,先想想用户愿不愿意多等一秒。
大白话:RAG 进阶就是招聘流程——切块决定简历库质量,查询优化是把岗位要求写清楚,混合检索是海选(快但粗),rerank 是面试官(慢但准),评估是试用期考核。五个环节都过硬,才招得到对的人。
技术定义:现代 RAG 在朴素管线上叠加四层:索引层按内容形态选择切块策略(文本按段落/语义,代码按 AST,全量附加元数据);召回层用混合检索(向量 + BM25/ES,RRF 融合);查询层做改写、分解与 HyDE 等前置优化;排序层用交叉编码器对召回候选精排。整条链路用检索指标(召回率、命中率)与生成指标(答案正确率、幻觉率、引用准确率)分层度量。
动手:两段式检索 + 一份不骗人的评估集
这就是补丁地图最下方的评估环——前四层补丁打完,靠它验收:
# 示意接口:rewrite / vector_search / bm25_search / rrf / cross_encoder
def retrieve(question, top_k=3):
q = rewrite(question) # 查询侧:改写后进向量路
candidates = rrf( # 混合召回:两路各取 top-20 融合
vector_search(q, top_k=20),
bm25_search(question, top_k=20), # 字面路用原始问句
)
scored = cross_encoder.rerank(question, candidates) # 精排
return scored[:top_k]
# 评估集(golden set):先于功能开发。每条 = 问题 + 应命中的块 id + 标准答案要点
golden = [
{"q": "过了七天还能退吗", "hit": ["chunk_42"], "answer_must": ["特殊商品除外"]},
{"q": "E-4021 怎么解决", "hit": ["chunk_108"], "answer_must": ["网络超时"]},
]
# 检索指标:hit 是否出现在召回结果里(命中率/召回率)
# 生成指标:答案是否含 answer_must 要点、是否带引用、编造了几处
# 生成端还有一层引用校验:答案里的每个关键断言,能否定位到某条引用原文——定位不到即视为无据
评估集从 20 条起步就能拦住大半回退:每次改切块、换检索、调 k,跑一遍看命中率与幻觉率的变化——变好的证据必须是数字,不是体感。评估环节也可以借助 RAGAS 这类开源评估框架跑自动化指标。
边界与取舍:别把 RAG 做成补丁堆
失效驱动打补丁
你的失效若只是「编号搜不到」,加 BM25 一层就够,HyDE 与语义切块可以先不上——每层都有延迟与维护成本。上补丁前先拿 20 条真实问题复现失效,确认打在哪层;这同一批题随后就是评估基线——先当探针,再当考卷,一鱼两吃。
评估先行
先建 20 条评估集再动手改系统——没有基线的优化无法证明有效,甚至无法发现退化。评估集的题目要来自真实用户问题(而不是开发自己编的),覆盖典型与边界两类。
评估时把两类失败分开记账,混在一起算总账,永远不知道该修哪一层:
- 「该找到的没找到」是检索的锅——回去补召回与排序。
- 「找到了答错」是生成的锅——回去补提示词约束与引用校验。
检索天花板
召回、排序都做对之后,剩下的失效往往在生成端(模型无视资料、综合过度)——那是引用校验与提示词约束的领地,继续堆检索层是无效内卷。
前沿钩子
- Agentic RAG:把检索做成 Agent 的一个工具,由模型自己决定「要不要查、查什么、查完够不够」。
- 代码库 RAG:AST 切块保住函数完整性、检索结果带行号引用,让模型「按行号读代码」。
后者在Codebase Agent 实战展开;前者涉及 Agent 与工具的编排方式,读完MCP:协议与工具接入会更好理解。
自测
合上文章先自己答,再展开对照:
纯向量检索的三个盲区分别被 BM25、Rerank、Query 改写中的哪个补上?
盲区一「术语体系岔开」(用户说「钱怎么回来」,资料写「退款流程」)——由 Query 改写补:检索前先把问题改写成资料的语言,或在多轮对话里补全指代。盲区二「字面精确场景失效」(E-4021 和 E-4022 被向量认为很近)——由 BM25 补:混合检索里关键词那一路就编号匹配而言分得清编号,两路结果用 RRF 融合。盲区三「意思近不等于最相关」(正确段落排在候选末位)——由 Rerank 补:交叉编码器对召回候选逐对精排,把真正相关的顶到前面。三者作用在不同环节:改写修问题、BM25 修召回、Rerank 修排序。
RAG 评估怎么做才不是自欺?
三个原则。其一,评估集先于优化:动手改系统前先建评估集(20 条起步),否则没有基线,一切「感觉变好了」都不可证。其二,题目来自真实用户问题,覆盖典型与边界两类——用开发自己编的题评估,等于照着答案出卷。其三,分层度量:检索层看命中率与召回率(该找到的找到了没),生成层看答案正确率、幻觉率与引用准确率(找到之后答得对不对、有没有出处)——混在一起看会互相掩盖。工具上可用 RAGAS 这类开源评估框架跑自动化指标,但题目与验收标准必须自己定。最后,每次改动跑同一份评估集对比数字——变好的证据是数字,不是体感。
参考与延伸
- RAGAS(开源 LLM 应用评估框架,RAG 评估为核心场景,Apache-2.0):客观指标与测试集自动生成 — github.com/explodinggradients/ragas
- Qwen3-Reranker(与 Qwen3-Embedding 同系的开源重排模型):交叉编码器精排的即插即用实现 — github.com/QwenLM/Qwen3-Embedding
下一站:MCP:协议与工具接入——检索之外,模型接入外部世界的另一种标准化方式。