Context Selection — 为什么 RAG 召回 ≠ 答对
Context Selection — 为什么 RAG 召回 ≠ 答对
写过 RAG 都见过这个数:召回率 90%(top-k 里 90% 含正确答案),端到端答对率只有 60%。30% gap 在哪?
不是 retrieval,是 selection 没做。
Lost in the Middle — 30% 的实证缺口
2023 年 7 月 Stanford 的 Liu 等人发表 Lost in the Middle(arXiv:2307.03172),用一个实验暴露所有长 context LLM 的隐疾:
实验设计:
- multi-document QA task(20 文档 + 1 问题)
- 只有 1 个含答案,其他 19 个是 distractor(话题相关但不含答案)
- 把含答案那篇放 context 不同位置(第 1 / 5 / 10 / 15 / 20)
- 测每个位置答对率
结果:所有测试模型(GPT-3.5、Claude、LLaMA)呈 U 形曲线——答案放开头或结尾时答对率最高,放中间掉 30%+。
[] — 图见原 paper 第 3 页。
召回的 10 段,第 4 到第 7 段模型基本看不见。retrieval 100% recall,模型也用不到位置不对的部分。
不是 bug,是 transformer 注意力 + 训练数据分布——开头/结尾在训练数据里更重要(摘要、结论)。Anthropic 在 200K 模型复现,Long context tips 明确建议关键信息放结尾。
三个 root cause — 不只是位置问题
Position bias 最显眼,但 RAG 召回 ≠ 答对有三层原因:
1. Position bias — 中段失明
10 段召回 5 段相关按相关度排序——相关度第 1 不等于 attention 第 1。要主动把最关键那段塞到结尾。
2. Distractor pollution — 干扰段污染
2024 Found in the Middle(He et al.)证明:context 里 distractor 越多(话题相似但不含答案),hallucination 越高——模型把 distractor 的相关名词「拼装」成假答案。
澳洲税务 RAG 召回 10 段:3 段 GST、7 段 income tax。用户问 GST,7 段是 distractor。模型会说「GST 是 ...,还有 income tax 的 ...」——把 income tax 细节当 GST 事实。召回正确也召回相似但错的,等于污染。
3. Instruction-following degradation — 长 context 下指令服从下降
Anthropic 200K context 评估文档:context 越长,模型对 system prompt 硬规则服从率越低。50K 下要求 JSON 偶尔漏字段;200K 下漏字段率显著增加。
RAG 多召回的隐藏成本——你以为「多召回更安全」,实际是 system instruction 被冲淡。
Selection ≠ Retrieval
retrieval 找候选,selection 从候选挑真正进 context 的。
| 阶段 | 任务 | 优化目标 | 工具 |
|---|---|---|---|
| Retrieval | 全量 corpus 找 top-N 候选 | Recall | bi-encoder / BM25 / hybrid |
| Selection | 从 top-N 挑 top-K 进 context | Precision + position | rerank / filter / LLM-judge |
| Composition | 把 top-K 排序塞进 prompt | Position、token 预算 | 手工 + 模板 |
入门 RAG 教程只讲 retrieval,top-5 直接塞 prompt——90% recall 但 60% accuracy 的根因。
Selection 的三段式
第 5 章详述工具栈。整体形状:
Stage 1 — Filter(粗筛)
按硬规则去掉:
- 时效过期(2023 年文档讲 2026 年事)
- 来源黑名单(CSDN 二手抄文)
- 长度异常(< 50 或 > 5000 字)
成本极低(O(n)),扔掉 30-50% 候选。
Stage 2 — Rerank(精筛)
用 cross-encoder 重新打分:
- bi-encoder(retrieval 用)一次只看 query 或 doc,速度快但精度差
- cross-encoder 同时看 query + doc,精度高 30-50%,成本是 bi-encoder 的 50-100 倍——只对 top-50 用
主流:Cohere rerank-3 / BGE-reranker-v2 / Anthropic contextual retrieval。
Stage 3 — LLM-as-judge(终筛)
用便宜模型(Haiku 或 4o-mini)当 judge:
- Input: query + 单 doc
- Output: 真的能回答 query 吗?yes/no + 理由
成本是 rerank 的 5-10 倍,但能 catch rerank 漏掉的「话题相关但答非所问」段落。
三段:retrieval 100 → filter 50 → rerank 10 → judge 3 → 进 context 3 段。recall 不变,distractor 打到 0。
JR 真实案例:daily-jobs 的 selection pipeline
JR Academy 每天 3 个 daily-jobs routine 跑(给 ai-essentials / ai-engineer / ai-engineer-rag bootcamp 学员推荐 3 个岗位):
# tested: 2026-04-26 · routine: Daily Jobs - AI Engineer Bootcamp
Stage 0: 抓取(retrieval)
WebFetch au.linkedin.com/jobs/junior-machine-learning-jobs
WebFetch au.linkedin.com/jobs/ai-engineer-jobs
→ 抓回约 30 个 job
Stage 1: Filter(硬规则)
剔除 recruiter spam(YO IT Consulting 这类同 job 多 location 群发)
剔除 SEEK 来源(403 默认无效)
剔除发布 > 7 天
→ 剩约 18 个 job
Stage 2: Rerank(按 tier 标签)
打 3 个 tier 标签:
aspirational(理想档 — Mid-Senior + T0/T1 brand)
actionable(够得着档 — Junior/Graduate + AU Big 4)
special(特殊机会 — Intern / Graduate Program / 2026-27 Start)
→ 每 tier 留 top 3-5 候选
Stage 3: LLM-as-judge(人称代入)
以「JR Bootcamp 学员视角」给每个候选写 whyForLearners
≥ 30 字、必须具体、不允许模板填空
→ 每 tier 选 1 个最佳 → 共 3 个 final
最终 context 进 prompt:3 个 job 全文 + 3 个 whyForLearners
不是 fancy 算法——三段过滤 + 一个判断模型。出来的 3 个 job 都通过 distractor 筛选 + position 排序(tier 就是 position 信号)。
学员看到的不是「30 抓回选 3」,是「精挑 3 个对你有意义的」——selection 的产品价值。
多召少筛 vs 少召多筛 — Trade-off
| 维度 | 多召 + 弱筛 | 少召 + 强筛 |
|---|---|---|
| Recall | 高(top 50 ≥ 95%) | 中(top 10 ≈ 75-85%) |
| Selection 工程量 | 三段式 + LLM judge | 一段 rerank 即可 |
| Token 成本 | 高(50 段过 rerank) | 低(10 段直接进 prompt) |
| 延迟 | +2-5 秒 | +200ms |
| Distractor 风险 | 高,必须强筛 | 低,但漏召高 |
| 适合 | 知识库 QA(90%+ 准确率) | 实时对话(延迟敏感) |
| 不适合 | 实时聊天 | 严肃合规(漏召不能接受) |
JR 经验:对外 production RAG 走多召强筛,对内工具走少召弱筛。延迟、成本、质量要求都不一样。
一句话带走
Recall 是 retrieval 的事,accuracy 是 selection 的事。top-10 直接塞 prompt 是 toy demo;production RAG 必须分 retrieval / selection / composition 三段。中间那段是 90% recall 到 90% accuracy 之间的工程量。
引用来源
- Liu et al. (2023-07-06). Lost in the Middle. arXiv:2307.03172.
- He et al. (2024-03-08). Found in the Middle. arXiv:2403.04797.
- Anthropic. Long context tips.
- Anthropic. (2023-05-11). 100K context windows.
- Liu. GitHub: lost-in-the-middle.
Production case: JR Academy omni-report Daily Jobs — 三段 selection pipeline.
📚 相关资源
❓ 常见问题
关于本章主题最常被搜索的问题,点击展开答案
RAG 召回率 90% 但答对率只有 60%,问题在哪?
90% recall = top-k 里有正确答案但 LLM 没用上,三个原因:(1) Lost in the Middle 注意力衰减、(2) distractor 段落污染、(3) 长 context 下 instruction-following 下降。解法是加 selection 层,不是继续调 retrieval。
Selection 和 Rerank 是同一回事吗?
Rerank 是 selection 的一段,不是全部。完整 selection 三段:filter(硬规则去时效/来源/长度异常)→ rerank(cross-encoder 精筛)→ LLM-as-judge(Haiku/4o-mini 终筛)。100 候选 → 3 个真进 prompt。
什么时候不需要做 selection?
三个条件同时满足才能跳:实时聊天助手 + 召回数 ≤ 5 + 延迟敏感。否则 production RAG 必须做 selection。JR 内部规则:对外学员侧多召强筛,对内仪表盘少召弱筛。
Selection 一套上完整 pipeline 一个月成本多少?
10K query/天规模:Cohere rerank $30/月 + LLM-as-judge (Haiku) $300/月 + 向量库 Pinecone Standard $70/月 = ~$400/月。换 BGE 自托管 + Haiku 判断 = ~$120/月(不含 GPU 摊销)。比不做 selection 省下的 LLM input token 成本通常 5-10× 回本。
做企业内部知识库该不该上 selection?
该上。企业 KB 文档来源杂(Confluence / Slack / Google Doc 老版本),distractor 比公网 RAG 更严重。第一步先加 LLM-as-judge 一层,单 query $0.0005 即可把召回准确率从 60% 拉到 85%+。Filter + rerank 是后续优化。
Selection 最常见的失败模式是什么?
把 selection 做成「再排一次序」而不是「真砍掉」。100 候选 rerank 完仍塞 top-20 进 prompt = 没做 selection。正确做法:rerank 完按 score 阈值(< 0.3 直接扔)+ 硬上限 top-3 至 top-5。砍不下去就是没做。