Gainstop-RAG:我们试图教会小模型"知道自己不知道"
失败实验系列 · 第一篇
做 RAG 系统的人大多遇到过这种情况:明明相关文档都找到了,答案却还是错的。我们花了相当长时间想把这个问题做成一个系统,最后发现问题本身的解法走错了方向。这篇是完整的复盘。
一个被所有 RAG 系统忽视的假设
所有的 RAG 系统,无论架构多复杂,底层都有一个从未被明说的假设:
语义上相关的内容,就是回答问题需要的内容。
这个假设在大多数场景下成立,所以没有人质疑它。但在实验里,我们反复观察到一个奇怪的现象:
Gold 文档覆盖率 = 100% # 所有需要的文档都找到了
答案正确率 = 0% # 答案还是错的
这说明一件事:相关 ≠ 足够。
找到了文档,不代表找到了"足以回答问题"的文档组合。RAG 的失败不只是检索召回率的问题,还有一个更深层的问题:模型不知道自己什么时候已经收集到足够的信息。
这就是 Gainstop-RAG / SQCS 项目的起点。
SQCS:让模型自己判断"够了没有"
SQCS(Sufficiency-based Query Completion Signal)的核心想法很简单——
传统 RAG:
检索 N 轮(固定轮次)→ 把所有文档塞给模型 → 生成答案
SQCS 的想法:
检索一轮 → 模型判断"信息够了吗?"
→ 够了就停止
→ 不够就继续检索,直到够为止
这个设计直觉上有几个优势:它解决了"相关 ≠ 足够"的问题;简单问题一轮就停,节省计算;也符合人类查资料的认知方式——人在查资料时也会判断"知道的够不够了"。
项目有一个核心约束:零训练 + 弱模型(≤7B) + 可以在 CPU 上运行。这个约束来自工程可行性考虑——真实部署里,不是每家公司都有 GPU,也不是每个场景都允许调用昂贵的强模型 API。
这个约束后来证明是整个项目的命门。
实验:弱模型做不了这个判断
我们设计了最小化实验来验证核心假设:给弱模型一个具体的单跳子问题和一篇文档,让它判断"这篇文档回答了这个子问题吗"。
三种场景的结果:
| 场景 | 任务 | 准确率 |
|---|---|---|
| 场景1 | 相关文档,答案直接在文档里 | ~60% |
| 场景2 | 相关文档,答案需要推理得出 | ~45% |
| 场景3 | 不相关文档(应判断"不够") | ~50% |
结论是决定性的:弱模型的判断准确率接近随机水平。
它不是"做得不够好",而是根本无法完成这个任务。场景3几乎等同于抛硬币。
三次设计迭代,三次碰壁
我们没有在第一次失败后就放弃,而是尝试了几种变体。
迭代1:把问题拆得更细
不让模型判断"信息够不够",而是让它判断更具体的问题:"文档里有没有提到 X 实体?"
结果:实体存在性的判断准确率有所提升,但引入了新问题——如何确定"X 实体"是什么?这需要另一个推理步骤,又回到了原来的问题。
迭代2:用打分代替二分类
不让模型判断"够/不够",而是让它给文档相关性打分,设置阈值。
结果:打分的分布极度不稳定。同一篇文档在不同轮次得分差异可以很大。弱模型对"信息充分性"没有稳定的内部表示,打分结果近乎随机。
迭代3:用树状结构替代单一判断
把多跳问题分解成子问题树,判断"这个叶子节点解决了吗"比判断"整体够不够"更容易。
结果:叶子节点的判断确实稍微容易一些,但本质上还是同一个任务。而且构建子问题树本身也需要推理能力,弱模型同样做不好。
为什么这是一个根本性障碍
在尝试各种变体之后,我们意识到这不是工程问题,而是能力边界问题:
让弱模型判断"我知道的够不够了",本质上是让它做元认知。这个能力在 7B 以下的模型里系统性地缺失,不是通过 prompt 优化能解决的。
这个结论在文献里也有佐证。FLARE、Self-RAG、IRCoT 这些做"自适应停止"的工作,都需要强模型(13B 以上,或者微调过的模型)。没有任何一篇用 ≤7B 零训练模型做这件事的工作有可靠的结果。
我们撞到了一堵有充分理由存在的墙。
失败之后的关键转折
放弃 SQCS 之后,我们重新审视了失败的根本原因:
| 旧思路 | 新思路 | |
|---|---|---|
| 谁来判断 | 弱模型在线判断 | 强模型离线预判 |
| 什么时候 | 每次查询时 | 提前一次性完成 |
| 能不能做 | 做不到 | 可以做到 |
这个转折有一种事后看来很显然、当时却不容易想到的简洁性:
SQCS 想解决的问题(检索什么时候够了)是真实存在的。但解决它的方式不一定是"让弱模型在线判断"——也可以是"让强模型提前告诉弱模型路径"。后者绕开了弱模型的能力瓶颈。这就是 PRIOR-RAG 的起点。
这个项目教会了我们什么
元认知是弱模型的硬边界。 判断"我知道的够不够"、"这步推理完成了吗"——这类任务系统性地需要大模型。用弱模型做元认知判断是一个方向性错误,不是工程问题。
"相关 ≠ 足够"是 RAG 真正的核心问题。 这个洞察本身是正确的,只是 SQCS 选错了解决路径。后续 PRIOR-RAG 验证了:通过预计算关键实体,可以从另一个角度解决这个问题。
能力约束要在设计阶段就验证。 我们在设计 SQCS 时假设弱模型能做元认知判断,没有提前验证这个假设。如果先跑一个最小化实验,可以早两周知道方向不对。这个教训很便宜,但只有在踩过坑之后才真正记住。
对于想在这个方向继续做的人:如果你有强模型或者愿意做微调,自适应停止机制是一个真实有价值的问题;如果约束和我们一样(弱模型+零训练),建议直接跳过,去做检索路径规划而不是停止判断。