知识块 · 版本 1块链接查看来源查看知识状态待读取
01

正文

如果你的语料不到 20 万 token,不要建检索系统——这是 Anthropic 自己给的口径:直接整库塞进 prompt。如果它远超窗口,你也没得选,只能检索。真正需要判据的是这两条线之间的地带;而记忆层压根不在这条轴上——它回答的不是"装不装得下",是"下一次会话还认不认识你"。

这三条路线常被并排放在一张选型 PPT 里,好像是三个可以互换的方案。它们不是。把它们放到同一个坐标系里只有一种正确方式:它们是同一个问题的三种供给方式——"这一轮窗口里该放哪些 token,这组 token 从哪来、什么时候来、由谁决定"。 长上下文是"全部预先放进去",检索是"按当前查询临时取",记忆是"按身份长期携带"。目标函数是同一个,就是最小充分上下文:在满足任务所需信息的前提下,让进入窗口的高信号 token 集合最小。三条路线的区别只在实现这个目标的机制、时机和代价结构。

下面把每条分界线连同它的实测数字摆出来,最后收成一张可以照着做的判断表。

知识块 · 版本 1块链接查看来源查看知识状态待读取
02

一、先量语料的 token 数:20 万以下,建检索系统是自找麻烦

这是最硬也最容易被跳过的一条线。Anthropic 在 Contextual Retrieval 那篇里写得很直白:知识库小于 20 万 token(约 500 页)时不要建检索系统,直接把整个知识库放进 prompt。这句话出自一篇专门推销检索技术的文章,反而更可信——它是在划自己方法的适用下界。

为什么这条线值得当成硬约束?因为检索系统的成本不在推理侧,在工程侧。你一旦建索引,就同时买下了:切块策略(块大小和 top-k 要一起调)、索引期改写(要不要给每个 chunk 补语境前缀)、双通道召回与融合(向量和 BM25 的失败集合不重叠,所以默认两个都要)、重排、以及一整套回归评测。这些每一项都有自己的失败模式和调参空间。Anthropic 自己那组数据显示,把这套做全的收益是 top-20 检索失败率从 5.7% 降到 1.9%——但前提是你的语料大到"不检索就没法工作"。语料只有几十万字的时候,你花几个月做的这一切,替代的是一个 cat *.md 就能完成的动作。

反过来说,这条线也划出了另一侧的强制区:语料远超窗口时,检索不是选项之一,是唯一选项。这时候要讨论的不再是"要不要检索",而是"用哪种检索"——这属于检索质量自己的问题域,和本文讨论的路线选择是两层。

需要提醒的是,20 万这个数字是 Anthropic 在它的模型与价格下给的口径,不是物理常数。它的正确用法是把它当成一个可以用你自己的价格重算的公式:建索引的一次性工程成本 + 长期维护成本,除以你的查询频次,和"每次全量塞入多付的 token 费"比大小。token 单价下降会把这条线往右推,你用自托管小窗口模型会把它往左推。

知识块 · 版本 1块链接查看来源查看知识状态待读取
03

二、63% 的查询上两条路线答案相同——差距集中在你不知道是哪些的少数查询里

跨过 20 万那条线之后,"装得下但很贵"的中间地带才是真正的决策区。这里最有价值的一组实测来自 Li 等的 EMNLP 2024 Industry Track 论文,他们在 LongBench 的 7 个数据集加 ∞Bench 的 2 个(10 万 token 以上)上,把 RAG 和长上下文直塞放在同一批查询上对打(300 词分块、默认 top-k=5):

RAG(top-k 进 prompt)长上下文直塞
Gemini-1.5-Pro 九数据集均分37.3349.70
GPT-4o 九数据集均分32.6048.67

单看这张表,结论似乎是"有钱就直塞"。但同一篇论文里还有另外两个数字,它们才是决策依据:63% 的查询上两者的预测完全相同,70% 的查询上分差小于 10 分。

这两个数字改变了问题的性质。12 分的均分差距不是均匀摊在所有查询上的,而是集中在少数查询上。也就是说,你为长上下文多付的钱,在大多数查询上买不到任何东西——你付的是一份保险费,保的是那少数几个 RAG 会答错的查询。

由此产生的第三条路是 Self-Route:先让 RAG 跑,同时允许模型自我判断"给的材料够不够答";答不了才回退到长上下文。实测代价是:

  • Gemini-1.5-Pro:只用长上下文 38.39% 的 token,成本降 65%,均分 46.41(对 49.70);
  • GPT-4o:用 61.40% 的 token,成本降 39%,均分 48.89——反而略高于直塞的 48.67;
  • GPT-3.5-Turbo:用 38.85% 的 token,均分 35.32,同样高于直塞的 32.07。

GPT-4o 那一行值得盯着看几秒:更便宜,而且不更差。这不是运气,而是最小充分上下文的直接后果——干扰项是有边际成本的,Chroma 的对照实验测出即使单个干扰项也会相对基线降低性能,4 个则叠加恶化。塞得少一点,有时准确率反而上去。

这一节的可操作结论是:在中间地带,默认答案不是二选一,是路由。 而路由的设计判据就是那个 63%——先用便宜通道跑,只为那 37% 付升级费。

知识块 · 版本 1块链接查看来源查看知识状态待读取
04

三、记忆系统在准确率上打不过"全塞进去",它卖的是延迟和成本

现在把记忆层放进来,先说最反直觉的那条:在同一批数据上,记忆系统的准确率打不过"把全部对话历史塞进上下文"这个基线。

Mem0 论文在 LOCOMO 上把各路方案放在同一张表里测(LLM-as-judge 总分):

方案总分
全量上下文基线72.90
Mem0-g(图记忆)68.44
Mem0(向量记忆)66.88
Zep65.99
RAG(各 chunk/k 配置,F1)在 5.00–49.56 之间剧烈波动

最准的是那个最笨的方法。这一点必须写在任何记忆选型讨论的第一行,因为市面上"记忆让 agent 更聪明"的叙述几乎全都省略了对照组是什么——如果对照的是裸模型,记忆当然赢;如果对照的是全量上下文,记忆是在赔准确率。

那记忆卖的是什么?同一张表给了答案:

  • 总延迟 p95:全量上下文 17.117s,Mem0 1.440s(降约 91%);
  • 每对话 token:全量对话约 26,000,Mem0 约 7,000。

记忆层是一次明码标价的交易:用 6 个百分点的准确率,换一个数量级的延迟和 token。 这笔交易在什么时候划算,是可以直接算的——如果你的场景是交互式对话,17 秒的 p95 本身就不可接受,那准确率差多少都得换;如果是离线批处理,没人在乎 17 秒,那就别上记忆。

还有一个常被忽略的对照:最佳 RAG 配置(k=2、256 token chunk)的搜索延迟 p50 是 0.255s / p95 0.699s,和 Mem0 的 0.148s / 0.200s 在同一量级。也就是说,在效率这个卖点上,记忆并不比检索更强。记忆真正不可替代的地方在别处——表达时序与个体归属。LOCOMO 的 temporal 题型上,做了时序建模的系统(Mem0-g 58.13、Mem0 55.51)对没做的(OpenAI Memory 21.71、LangMem 23.43)是两倍多的差距。"用户三月前住北京、之后住上海"这种东西,检索语料表达不了,长上下文只能靠把两段对话都塞进去让模型自己推。

顺带按掉另一个流行直觉:图记忆并不在多跳上更强。同一张表里,multi-hop 题型 Mem0(向量)51.15 高于 Mem0-g(图)47.19,而图变体的代价是约 2 倍 token、约 3.2 倍搜索延迟。图稳赢的只有 temporal 一项。所以"要多跳所以上图谱"这个推理链在实测里是断的——真正该问的是你有没有大量"什么时候变的"类查询。

知识块 · 版本 1块链接查看来源查看知识状态待读取
05

四、真正把三条路线分开的不是规模,是状态性

前三节都在谈规模和成本,但它们只是表层。三条路线在架构上不可互换的根本原因是状态性不同,这一层决定了它们的更新语义、安全面和失败方式。

长上下文检索记忆
状态归属无状态,每次请求重建外部只读,agent 不写可写,agent 自己写
更新方式下次把新内容塞进去即可重跑管道、重建索引被一条更新的断言推翻
时间语义无(窗口内即"现在")通常无,文档"永远为真"核心维度,需要有效期
冲突处理不需要(内容由调用方决定)不需要(语料不自相矛盾)必须有,否则矛盾条目同时被召回
归属隔离天然按请求隔离全局共享按用户/会话/项目隔离
攻击面单轮提示注入,会话结束即消失语料投毒,离线可审运行时可写,攻击者只需当普通用户

有一个一句话判据可以直接用在任何一条信息上:"这条信息如果变了,我该重新塞一遍、该重建索引、还是该让一条更新的断言把它推翻?" 三个答案分别对应三条路线,而且这个判断和语料规模无关。

这条判据能挡掉记忆系统最常见的架构错误:把外部文档当记忆写。产品手册、API 文档、法规条文——这些东西 agent 没有参与产生、也不该改写,它们变了是发布流程的事,归检索。你把它们抄进记忆库,得到的是一份会过期的语料副本,而且没有任何机制知道它过期了。这就是记忆过期的标准触发方式:曾经为真的快照被永久保存,读回来时和刚写下时一样确定,agent 甚至会用它反驳你当场给的正确信息。

反过来,"可写"这条性质也不是免费的。检索的语料投毒需要攻击者能改你的离线语料;记忆的投毒只需要攻击者当一个普通用户——MINJA 的威胁模型就是"不能改受害者查询、不能直接访问记忆库,只能发正常查询看输出",在这个前提下达到约 98% 的注入成功率,并且注入内容绕过了输入输出审核,因为它在上下文里读起来完全合理。AgentPoison 的数字同样刺眼:投毒率 <0.1% 时攻击成功率 >80%,而不含 trigger 的正常指令性能影响 <1%——整体指标监控看不出来。

顺着状态性还有一层需要分清:即使决定了上记忆,也不是上"一个记忆库"。记忆分类里那四类(工作/情景/语义/程序)的写入时机完全不同:工作记忆每 token 都在变;情景记忆随事件发生自动 append;语义记忆需要一次显式的抽取动作才产生;程序记忆只该在规则被违反或被纠正时才改。用同一套写入策略统管四类,结果就是把"今天调试用了 grep"和"本项目禁止 push"塞进同一个池子——四分法的价值不在于分四个库,在于分别定义写入策略和有效期。

知识块 · 版本 1块链接查看来源查看知识状态待读取
06

五、三份账单不可互相抵扣:token 成本、索引成本、维护成本

三条路线的成本模型不是"贵一点/便宜一点"的差别,而是压在不同科目上、增长曲线完全不同的三份账单,彼此不能折算,也不能互相抵扣。

长上下文 = token 成本,每次查询全额支付,随语料规模线性增长。 它的账最好算,也最容易失控。但它有一笔隐藏支出:你付了 token 费,不保证那些 token 被读到。Lost in the Middle 在 20 文档设定下给的数字是:正确文档在第 1 篇时准确率 75.8%,第 20 篇 63.2%,第 10 篇(中段)53.8%——而同模型闭卷(一篇都不给)是 56.1%。中段那一行低于闭卷基线,意味着在那个位置上,你花钱建的检索/塞入系统净贡献为负。而且换更大窗口的模型不解决这一点,论文明确报告扩展窗口变体没有改善位置效应。同一现象在长度维上叫上下文腐烂,Chroma 用 LongMemEval 的对照是:约 300 token 的聚焦片段稳定优于约 113k token 的完整历史,在 18 个受测模型上一致成立。所以长上下文的真实成本是"token 费 + 一个随长度上升的准确率折扣"。

检索 = 索引成本,一次性 + 增量支付,与查询频次无关。 Contextual Retrieval 给出的口径是 $1.02 / 百万文档 token 的一次性索引改写成本,查询期零额外延迟。这类成本的关键性质是它由语料变动频率决定,不由查询量决定——语料稳定、查询频繁,索引成本被摊到接近零;语料每天大改,同一笔钱要反复重付,索引期方案就变成负债。判据不是"哪个效果好",是语料变动频率与查询频率之比。

记忆 = 维护成本,持续支付,而且随库龄单调上升。 这是三份账单里最容易被漏算的一份,因为它不出现在任何 API 账单上。它至少包含四项:

  1. 记忆过期:快照类事实(版本号、路径、端口、"当前有 3 个服务")的半衰期以天计,而记忆库默认永久有效。唯一的根治手段是写入侧纪律——记方法不记快照,以及给条目带时间戳。
  2. 无界膨胀:只有 ADD 没有 UPDATE/DELETE 的库必然线性膨胀,膨胀之后记忆挤占的正是最小充分上下文要保护的注意力预算,于是加记忆反而让 agent 变笨。Mem0 论文里同一份对话的表示开销差异是最好的警示:Mem0 约 7,000 token,Mem0-g 约 14,000,而 Zep 超过 600,000——差近百倍,论文归因于表示冗余而非信息量。
  3. 投毒清理:上一节那些数字意味着一旦被投毒,你需要的是溯源与批量作废能力,而不是"再训练一遍"。
  4. 人的注意力:上面三项都不能靠加机器解决,只能靠周期性审查和 harness 强制的上限。

关于第 4 项有一条被反复验证的规律:记忆纪律必须由 harness 强制,写进提示词的"请精简"不管用。Claude Code 给 MEMORY.md 设 200 行 / 25KB 硬上限,超限时写入仍成功但返回错误要求重写索引(因为超出部分下次加载会被直接丢弃,你以为记住了其实没有);Letta 给 memory block 设 2000 字符上限并把用量渲染进 prompt;MemGPT 在 70% 上下文占用时注入内存压力警告、100% 时冲刷约 50%。三处独立设计指向同一个信念。

知识块 · 版本 1块链接查看来源查看知识状态待读取
07

六、判断表:五个维度定位,越界了换什么

前五节的结论收成下表。用法是:五个维度各查一行,取最保守的那个结论(任何一个维度把你推向记忆或检索,就不能只靠长上下文)。最后一列写的是越过这条边界后该换什么,以及换的时候会出现的第一个信号。

维度档位选什么越界信号 → 换成什么
语料规模< 20 万 token长上下文直塞,不建索引整库塞入的 token 费开始超过建索引的摊薄成本 → 建检索
装得下窗口但很贵路由(Self-Route 式):RAG 先跑,不够再升级回退率长期 >50%,路由本身在赔钱 → 直接改直塞
远超窗口必须检索,没得选单次检索命中不了(答案分散在几十个来源)→ 上 agentic 检索,预算按约 15× token 计
更新频率语料几乎不变索引期方案吃满(语境改写、预生成摘要)—
每天有增量检索 + 增量索引;避免全库改写型方案重建索引的时间超过更新窗口 → 改查询期方案或直塞
每轮交互都在变不能靠索引,只能长上下文或记忆变化需要跨会话保留 → 记忆;只在本轮有效 → 上下文
跨会话不需要只用上下文 + 检索,别上记忆层—
需要,但可由用户重新提供会话摘要即可,仍不必建记忆库用户开始抱怨"每次都要重说一遍" → 上记忆
需要,且含"什么时候变的"记忆,且必须做时序建模时序题型准确率停在 20% 档(对照 OpenAI Memory 的 21.71)→ 加有效期字段或图记忆
延迟要求离线/批处理,秒级无所谓全量上下文最准(LOCOMO 72.90),不必上记忆—
交互式,p95 需 < 2s记忆(Mem0 p95 1.440s vs 全量 17.117s)记忆搜索 p95 自己就超标(参照 LangMem 的 59.82s)→ 换更轻的记忆表示
高 QPS 线上问答预计算索引,毫秒级有人提议上 agentic 检索 → 拒绝,它是秒到分钟级
可容忍的错误类型宁可漏答不可错答检索 + 高门槛,材料不足就拒答拒答率过高 → 加通道(BM25 与向量失败集合不重叠)而不是换 embedding 模型
宁可多说不可漏说长上下文,但警惕中段材料净贡献为负位置扫描出现 U 形 → 压 k + 首尾折叠,不是加 k
绝不能说过时的事检索(只读、可审),不要用记忆业务上必须记 → 记忆条目只存指针,真值现场取
绝不能被外部内容操纵检索(离线可审),记忆写入路径必须设信任边界工具返回值/网页内容进了持久层 → 降级为带来源的观察,不许升格成语义或程序记忆

表里有两行值得单独强调,因为它们最常被反着做——而且都属于"选完路线之后,检索质量本身怎么提"的问题:

  • "宁可漏答不可错答"那一行的越界处置是加通道,不是换模型。 LIMIT 的数据是:同一个语义上极简单的检索任务上,BM25 的 recall@100 是 85.7%,而六个不同厂商不同规模的单向量模型全落在 3.3%–18.9%。换更大的 embedding 模型不在解空间里——这是 embedding 维度的可证明上界决定的。
  • "位置扫描出现 U 形"那一行的处置是压 k,不是加 k。 多塞的文档会把正确文档往中段推,而中段的边际价值可能为负。

一条通用规律:检索质量的增益顺序是"改文本 > 加通道 > 改排序 > 改模型",而多数团队的动作顺序恰好倒过来。 Anthropic 同一组实验里,索引期改写文本把 top-20 失败率从 5.7% 降到 3.7%,加词法通道到 2.9%,再加重排到 1.9%;而换 embedding 模型这个最贵、最常被首先尝试的动作,在 LIMIT 的数据里回报最低。路线选对了但按错误顺序调检索质量,一样会白烧几个月。

知识块 · 版本 1块链接查看来源查看知识状态待读取
08

七、真实系统都是混用的,三种组合各有各的死法

生产系统里几乎不存在纯粹的单路线架构。Anthropic 自己的表述也是"用即时上下文策略增强既有检索系统",而非替代。下面三种组合覆盖了绝大多数实际形态,每种都有一个特定的失效模式。

组合一:检索 + 长上下文路由(Self-Route 形态)。 便宜通道先跑,模型自评材料是否充分,不足才升级到直塞。这是第二节那组数字直接推出来的架构。

它的失效模式是自评不可靠:模型在材料不足时倾向硬答而不是回退,尤其是被 prompt 暗示"你应该能回答"的时候。所以这套架构必须单独埋一个指标——回退率,并且定期人工抽查"没回退但答错"的样本。第二个失效模式是路由判据不会自动重新校准:你按当时的语料分布调好了阈值,半年后语料漂移,路由还在按老阈值走,而这件事不会有任何报警。

组合二:记忆存指针 + 检索取内容(即时上下文形态)。 记忆里只放"这个用户关心 X、相关文档在 path Y、上次结论见 commit Z"这类轻量标识符,内容现场取回。这是避开记忆库变成语料陈旧副本的标准做法,收益也是可量的:Anthropic 那组代码执行调 MCP 的实测里,把工具定义全量前置加载需约 150,000 token,改成文件系统按需读取后降到约 2,000 token,省 98.7%。

它的失效模式是指针失效变成静默失败:文件改名、文档下线、commit 被 rebase 掉,记忆说"有",取回来是空。危险之处在于这是静默的——agent 不会说"我的记忆坏了",它会当作"这件事不存在"继续往下走。处置很具体:把"按指针取不到"当成一个失效信号回写记忆,而不是当成一次普通的空结果。另一个前提条件是标识符本身必须可读——如果指针是 UUID 这种不可读串,agent 无法从标识符判断该不该拉取,这套组合就退化成盲目试探。

组合三:会话内长上下文 + 跨会话记忆摘要。 单次会话内不裁剪,结束时压成摘要写进记忆,下次会话加载摘要。这是最省事、也最常见的做法。

它的失效模式是有损压缩的错误会跨会话固化。摘要天然丢掉精确计数和清单——"改了哪 7 个文件""还剩哪 3 项没做"这类信息压完就没了,而且模型不知道自己丢了什么。更麻烦的是这个损失不可逆:下一轮基于错误摘要产生的新摘要会把错误继承下去,变成一条谁也追不回源头的记忆过期。处置是把精确状态外置成结构化笔记,不要指望摘要保住它;并且给摘要留一条回原始记录的指针。

三者全上的平台还有一个合成失效模式值得单列。 当程序记忆常驻(CLAUDE.md 之类)、agentic 检索按需注入、会话内长上下文自然增长这三条通道同时向窗口灌内容时,典型情况是每条通道单看都没超预算,合起来超了,而且没有任何一层知道总预算是多少。这是上下文腐烂在混合系统里最常见的入口。唯一有效的处置是把"窗口预算"当成一个显式的、被 harness 度量的量——Claude Code 的 /context 按来源拆分占比就是为了这个;记忆侧的处置则是分层加载,索引常驻、细节按需(注意 @path 导入只帮助组织,不减少上下文,被导入文件启动时一样全量加载)。

知识块 · 版本 1块链接查看来源查看知识状态待读取
09

八、这套判断在什么条件下不成立,以及你下一步该量什么

先说不成立的条件。

  • 20 万 token 那条线是价格函数,不是常数。 它反映的是 Anthropic 当时的模型与定价。正确用法是代入你自己的数字重算:建索引的工程 + 维护成本 ÷ 查询频次,对比每次全量塞入多付的 token 费。
  • LOCOMO 上"全量上下文最准"有一个前提:装得进窗口。 超过窗口,这个基线根本不存在,拿它当参照就没有意义。同理,那 72.90 分是特定模型在特定数据集上的结果,你的场景要自己复现这个基线,而不是引用它。
  • 63% 重合率是配置相关的。 它测于 LongBench 7 个 + ∞Bench 2 个数据集、300 词分块、top-k=5。如果你的语料是精确标识符密集型(错误码、SKU、函数名),那么检索通道的选择比"检索 vs 长上下文"这个问题更早决定成败——LIMIT 那组 85.7% vs 3.3%–18.9% 的差距远大于本文讨论的任何路线差异。
  • 需要完整审计轨迹的场景里,"最小充分"本身不是目标。 合规审查、事故复盘这类任务中"上下文完整"就是目标之一,裁剪会破坏可追溯性。这时该做的是把全量留在窗口外可取,而不是不留。
  • 合规约束可以直接推翻性能结论。 记忆是运行时可写状态,会落到"用户要求删除个人数据"的射程内;检索语料只读、离线可审。有些场景里这一条直接决定路线,和延迟成本都无关。

再说你下一步该量什么。 按顺序,每一步都能在一天内做完:

  1. 量语料的 token 数,和 20 万比。这一步就能决定要不要往下走。
  2. 量 BM25 的 recall@50,再决定要不要引入向量库。很多团队跳过这一步直接上向量,然后花几个月调 embedding 模型去追一个十行代码就能到的水位。
  3. 做位置扫描:固定问题和材料,把正确文档从第 1 位移到最后一位,画准确率对位置的曲线。U 形就说明你在为不会被读到的 token 付钱,处置是压 k + 首尾折叠。曲线平坦说明问题在别处。
  4. 做 focused / full 对照:同一批问题,A 版只给约 300 token 相关片段,B 版给全量历史。A 显著优于 B 就是上下文腐烂,不是模型不行。
  5. 记忆上线前,先把全量上下文基线量出来。 记忆必须在延迟或成本上明确赢过它,否则你只是在无谓地赔准确率。这是整篇文章里最容易执行、也最容易被跳过的一条纪律。
  6. 记忆上线后,常态化量三个数:启动时记忆占窗口的比例(有 /context 就直接看)、召回 top-k 里的重复条目比例、条目时间戳与对应代码/配置最后修改时间的差值。这三个数分别对应膨胀、去重失效和记忆过期。

最后回到那句判据。当你拿不准某条信息该走哪条路线时,不要问"哪个技术更先进",问:**这条信息如果变了,我该重新塞一遍、该重建索引,还是该让一条更新的断言把它推翻?**三个答案就是三条路线,而且这个问题你不需要跑任何实验就能回答。


出处

来源与依据