14 · 六个检索策略,只有一个活下来了(而且它也不是全面变好)
「优化 RAG」我列了六个看起来很标准的操作:Rerank、Multi-Query、Parent Document 去重、HyDE、查询路由、Self-Query。每一个在教程里都被写成「提升召回的经典手段」。
我拿 120 条评测集跑了一遍。
五个负收益。
这篇写这个结果,以及我从里面学到的那件事——它比任何一个策略本身都值钱。
一、先把数字摆出来
基线:hybrid 检索,候选池 50,返回 5,120 条评测集。
| 策略 | recall@5 | 跨文档全中率 | 对比基线 |
|---|---|---|---|
| baseline | 69.17% | 12.5% | — |
| rerank | 62.50% | 33.33% | 召回 −6.67pp,全中 +20.8pp |
| parentdedup | 66.67% | 12.5% | 召回 −2.5pp,全中 0 |
| routing | 66.67% | 12.5% | 召回 −2.5pp,全中 0 |
| selfquery | 66.67% | 8.33% | 召回 −2.5pp,全中−4.2pp |
| HyDE(10 条样本) | 50.0% | — | 召回 −20pp,成本 4× |
(数据来源:data/eval/w3d4_*.json。HyDE / Multi-Query 只在 10 条子集上跑过,样本太小不足以定论,我在手册里标注了这一点。)
只有 Rerank 在某一项上是大幅提升。但同一行里,它的整体召回是降的。
二、Rerank 这个怪结果,我盯着看了很久
Rerank 让「跨文档全中率」从 12.5% 涨到 33.33%——在 40 条难题子集上是从 12.5% 涨到37.5%。这是整个第三周唯一一个能称得上「显著提升」的数字。
但同时,整体 recall@5 从 69.17% 掉到 62.50%。
同一个策略,在一类题上是 +20.8pp,在整体上是 −6.67pp。
一开始我以为是我测错了,重新跑了一遍,数字没变。
后来我把「简单题」和「跨文档题」拆开看才明白:
- 跨文档题需要同时命中多个文档,Rerank 的重排序恰好擅长这个;
- 简单题(术语匹配、边界判断)本来 hybrid 一次就命中的,Rerank 反而把正确结果排到了后面。
损失全在简单题上。
三、我学到的那件事:均值会骗人
如果我只看recall@5这一个总数:
Rerank 让召回降了 6.67 个百分点 → 砍掉。
那我会砍掉整个第三周唯一有用的策略。
如果我只看「跨文档 +20.8pp」这个亮点:
Rerank 大幅提升 → 全量上线。
那我会上线一个让大多数题变差的策略,而大多数题才是真实流量的主体。
两个结论都错。正确的是第三个:
Rerank 只在跨文档这类题上启用。
所以我给评测脚本加了--types参数——策略必须在它对症的题型上测,而不是在全量上测完看总数。
这条纪律后来救了我一次:Multi-Query 在 10 条难题上把召回从 70% 提到 80%,看起来很漂亮,但成本 2×、p95 延迟 2×。要不是我坚持分开看题型和成本,这个策略差点就上线了。
四、为什么其它五个都不行
不是策略不好,是我的场景不匹配:
- HyDE(先用模型生成一个假答案,再拿它去检索):我的语料是 API 文档,术语精确。让模型先「编一段像答案的话」,反而把精确术语稀释成了模糊描述。召回 −20pp,成本 4 倍。
- Self-Query(让模型从问题里抽结构化条件):文档库没有强结构化的元数据可抽,抽出来的条件经常是错的,比不做还差。
- Routing / ParentDedup:在我的语料规模上,收益小到被噪声淹没。
这不是「这些策略没用」,是「这些策略在我的语料上没用」。换个语料,结论可能反过来。
我在手册里写了一句话提醒自己:参数「最佳实践」抄不来,要跑自己的语料。
五、第二个反直觉的发现
第二周我做过一次分块实验:原子感知分块 vs 固定长度分块,命中率打平(都是 87.5%)。
我当时的结论是:分块质量不影响检索命中率。
收益其实在生成端——分块合理,模型读到的上下文更完整,答案更准。
所以:别用命中率去衡量分块好坏。你用检索指标去评价一个影响生成端的改动,永远测不出来。
六、一句话
第三周最大的收获不是某个策略,是这条纪律:
看任何「提升」,先问一句:提升在哪个子集上?损失又在哪个子集上?
均值上的 +2%,可能是难题 +10%、简单题 −8%。而你的真实流量里,简单题占八成。
下一篇:15 · 我的评测端自己也错了三处