长上下文能取代检索吗
上下文窗口从几千涨到百万级之后,"RAG 是不是可以不要了"每隔一段时间就会重新争论一轮。诚实的结论是:对一部分场景可以,对大多数生产场景还不行——但真正的分界线不是窗口大小,而是另外四个变量。
这篇文章给一套可执行的判断顺序,以及两种做法各自的失败模式。判断依据以你自己的语料和任务为准,不引用任何"某某模型在某基准上赢了"作为裁决。
1. 两种做法差在哪
检索是"先选,再答"。 语料在外面,按问题挑出若干切片塞进提示词,提示词通常在几千 token 量级。
长上下文是"不选,全塞"。 把整个相关语料直接放进上下文,让注意力机制自己去找。
很多人以为差别在准确率,其实更关键的差别在你知不知道答案是从哪来的。检索系统知道它给了哪几个切片,所以引用是系统的属性,是结构性的;长上下文里模型同时看到了全部内容,引用只能靠模型自述——它说它参考了哪一段,你无法从系统侧验证。凡是要对外部用户负责出处的场景(客服答复、合规问答、医疗与法律),这一条比准确率更早成为决定因素,详见《答案要能追溯到出处》那一篇的取舍。
2. 四个变量决定选哪个
2.1 语料有界还是无界
有界——一份合同、一个模块的代码、一份已定稿的规格:两种都行。无界——全量工单、整个文档站、开放的网页:只能检索,任何窗口都装不下。
这条是硬约束,没有讨论空间。
2.2 任务要"通读全文"还是"找到那一段"
需要通读的:总结一份 200 页文档、审计一份长合同、找出两份协议之间的冲突。这类问题的答案可能依赖文本里相距很远的两处之间的关系——而这种关系恰恰最容易被切片切断(见《切片决定检索上限》)。检索擅长找"相关段落",但有些问题根本没有单独的相关段落。
只需要定位的:"欧盟用户的退货政策是什么"。一段排好序的切片,效果通常好过让模型在 20 万 token 里扫一遍。
2.3 更新频率
数据经常变(库存、工单队列、价格),检索赢:索引可以增量更新,每次查询都能看到新数据。长上下文每次都要重新组装整个载荷,语料一变就得重来。
数据稳定(定稿合同、冻结的规格、一篇论文),长上下文没问题,进上下文的成本每会话只付一次。
一条好记的规则:数据变化的速度快过你愿意重建上下文的速度,就检索。
2.4 单次成本与延迟
这是最容易被低估的一项,因为它是乘法。用一份 15 万 token 的语料回答 1000 个问题:
- 长上下文:每次为约 15 万输入 token 付费,合计 1.5 亿输入 token,还没算输出
- 检索:每次取回约 4K 相关 token,合计 400 万,外加一次廉价的向量检索
差了一个数量级以上。单次问答"长上下文反正也不贵"是对的,但它是按次计价的,量一大就换了个量级。
3. 各自的失败模式
检索的失败模式都在生成之前,且互不相似:
- 召回漏:正确答案不在 top-k 里,模型只能凭空答,还答得很自信
- 切片切断:表格、跨段落的条款被切开,两边都读不懂
- 重排错序:相关的切片排到了后面,被截断(这一点《重排修不了召回》展开过)
长上下文的失败模式都不在"找不到",而在"找到了也没用好":
- 中间丢失:相关内容放在超长上下文的中间位置,模型对它的注意力显著低于首尾
- 噪声稀释:50 万 token 的无关内容,让那 500 个真正相关的 token 更难被注意到
- 成本失控:一次意外的超长输入就能吃掉预算
- 调试不透明:答错了,你无法定位它是从上下文的哪一段得出这个结论的
注意这两组失败模式不构成互补:检索不会修好中间丢失,长上下文也不会修好召回漏。选一个,就是接受那一组的失败模式。
4. 标称窗口不等于可用窗口
这是实践里最常踩的一处。厂商标称 100 万 token,不代表这 100 万都能被同等质量地使用。检索类任务(大海捞针)的表现随上下文长度下降,越接近标称上限下降越明显。
所以正确的做法是自己测一条可用窗口曲线:把一份答案放在语料的不同位置、不同总长度下,看召回率在什么长度开始塌。你得到的那个数字,才是设计时的真实约束。拿标称值做容量规划,等于拿硬盘标称容量当可用容量。
5. 混合是多数团队的落点
公开讨论里混合模式被讲得很玄,其实就一句话:让检索负责"把候选从很大缩到可控",让长上下文负责"在这批候选上做合成"。
落到管道上,是三个具体改动:
宽候选,然后重排,不要早截断。 经典 RAG 的问题是取得太少——三个紧切片,答案只要跨边界就没了。先取宽一点,靠重排把顺序排对。
总量按实测可用窗口封顶,不按标称窗口。 第 4 节那条曲线量出来的数字,是这里的上限。
切片可以切大一点。 激进切分本来就是小窗口时代的权宜之计。既然有空间,就保留段落之间的关系——这正是长上下文相对检索的优势所在。
混合的代价是管道更复杂:检索那一半仍然要好。一张撒得太宽的网里全是干扰项,比内容为空还糟,因为模型会把干扰项也读进去。
6. 缓存改变了成本那一项
第 2.4 节的成本对比有个前提:每次都重新算一遍前缀。如果前缀稳定,提示缓存能让第二次起大幅降价——折扣按厂商和模型而定(Anthropic 读取约 0.1 倍、OpenAI 较新模型 90% off、Gemini 约 75% off,详见《提示缓存怎么才命中》),"一份长文档服务很多请求"因此变得划算,长上下文的成本劣势会被显著削平。
反过来,请求稀疏(间隔超过缓存有效期)或者前缀常变,缓存写入比省下的还多,那这个折扣就不存在。具体怎么算、哪些行为会打掉缓存,见《提示缓存怎么才命中》。
一句话:缓存能让长上下文变得可负担,但只在"重复读同一段"的流量形态下。
7. 别拿别人的基准当结论
公开评测的结果是混的:有研究称长上下文在问答类基准上普遍优于 RAG,也有结果称 RAG 在对话类与通用查询上更好。这类结论互相矛盾不是因为谁做错了,而是因为结论高度依赖语料规模、切片方式与查询分布。
所以它们唯一的用途,是提醒你"该在自己数据上测一遍"。拿同一批真实问题,分别跑检索构造的提示词和长上下文构造的提示词,比成本、延迟、质量三项差值——这个结果才对你有效。
8. 一个可执行的判断顺序
按顺序问,遇到"是"就停:
- 语料装不装得进实测可用窗口? 装不进 → 检索
- 数据是不是经常变? 常变 → 检索(增量更新的做法见《知识库的重灌与切换》)
- 任务是不是必须通读全文才能答? 是 → 长上下文
- 量大之后成本能不能接受? 不能 → 检索
- 需要精确到段落的引用吗? 需要 → 检索
五问都走完还拿不定,就上混合:粗召回缩到可控规模,重排保序,交给长上下文合成。
9. 两个默认值都是错的
一类团队把 RAG 当默认值,语境里所有问题都先建索引;另一类把"反正能塞进去"当默认值,把所有东西都堆进上下文。两者都是默认值思维,区别只是默认值选了哪一边。
真正该做的是把它当成一个选项:按语料规模、更新频率、任务类型、成本四项来选,并且留一个开关——因为这四个变量里至少有三个会随时间变化。今天选长上下文的方案,两年后语料涨十倍就该换回检索;反过来,一个为小窗口做过激进切分的系统,在窗口变大之后反而应该把切片放大。
这条和《RAG 链路与失败模式》里说的是同一件事:先想清楚失败模式是什么,再选架构。