通用方法 · 深入

问了一百遍的问题,该写成函数

记忆的形态决定了它能回答什么问题
面向个人状态的 agent 有个反复出现的失败:你问「去年出差一共花了多少」,它把检索到的几段历史丢进窗口,然后自己算 —— 算错、算漏、还会给你一个看起来很确定的数。这条路线把用户状态编译成带类型的代码对象与规则函数,聚合类问题直接调用函数而不是让模型跨段落做算术:同一批 100 个聚合用例上 99%,而纯检索方案分别是 43% 与 6%。但代价同样明确:在「你上次说了什么」这类纯召回任务上,它输给文本检索(78.8% 对 91.69%)⇒ 它不是替代检索,是补上检索做不好的那一类。这一页讲三件事:什么时候值得编译成代码 · 编译本身的两阶段怎么保真 · 以及什么情况下别这么干。
方法 · 一图看懂
1
先分清两类问题 — 聚合 / 规则 / 矛盾消解 ⇒ 代码;纯召回「上次说了什么」⇒ 老老实实检索
2
两阶段保真 — append-only 日志留住每一条原始观察,周期性 checkpoint 才把它编译成代码
3
规则写成谓词 — 药物过敏、饮食禁忌、排期约束这类硬规则,变成决策时必然触发的函数而非可选上下文
4
矛盾显式化 — 偏好会变,checkpoint 把冲突写成 if / elif 仲裁,而不是让「哪一版会浮上来」听天由命
5
划出不适用区 — 召回为主、schema 频繁变动、或受监管的决策支持,别用它
为什么「调函数」比「检索 + 算术」可靠
检索把多段材料丢进上下文,剩下的活交给模型的算术与归并 —— 这正是模型最容易悄悄失手的地方:它不会报错,只会给你一个错的数。换成函数调用,聚合被交给一段确定性代码:`sum(t.cost for t in trips if t.year == 2024)`。作者自己给的解释很干净:提升不来自「检索得更准」,而来自把「模型做不稳的归并」换成了「模型执行得稳的函数调用」。日志还保住了聚合真正需要的东西 —— 时间顺序;一个会把过去压扁的检索系统,会把顺序丢掉。
两阶段:日志管安全,checkpoint 管性能
append-only 日志是安全属性:每条观察逐字保留,矛盾因此始终可见,checkpoint 才有材料去写仲裁规则,而不是把历史丢掉。checkpoint 是性能属性:模型把日志改写成带类型的 Python —— 实体用 dataclass(Trip / Contact / MedicalVisit),集合用带类型的 list,不变量用规则函数;编完之后 agent 通过 REPL 调用这些对象,而不是在检索到的文本上推理。这个分工解决了一个容易忽略的点:如果只留编译结果,你会在出问题时再也找不到原始证据;如果只留日志,每次问答都要重新编译一次。
什么时候它会反咬你一口
作者列了四种:① 召回为主的工作负载 —— 任务本身是「找出过去那条相关的消息」,这时文本检索确实更好,而代码生成的成本收不回来;② schema 频繁变动的早期产品 —— 当 checkpoint 周期短于两次 schema 变更的间隔,每次 checkpoint 都在过拟合当下、或重写 schema,把下游依赖的规则函数弄坏;③ 弱代码生成模型 —— 小模型写出的 dataclass 带静默类型错误,只在 agent 查询时才炸,而坏掉的一次 checkpoint 产出零条事实,不像噪声嵌入至少还能返回点像样的东西;④ 受监管的决策支持(临床 / 财务核算 / 医疗器械软件)—— 合规见过检索索引,还没见过「由模型撰写的 Python 来判定什么算药物过敏冲突」。
原理 · 为什么有效
这条路线背后是一个形态判断,不是一次技术选型:同一份用户状态,用不同的形态存,能回答的问题完全不同。文本切片的强项是「找出相关的那一段」—— 它是相似度问题;代码对象的强项是「跨全部记录算一个值 / 判一条规则 / 消一个矛盾」—— 它是确定性计算问题。把两者混为一谈,就会得到一种很常见的挫败:检索明明命中了正确的段落,答案却还是错的。更值得记住的是作者那句反直觉的收尾:「不是更好的检索」 —— 结构化检索在全记录规模上和「把全部内容塞进窗口」的上限打平,提升完全来自把不可靠的聚合换成了可靠的函数调用。
适用场景
适用:你要长期跟同一个 agent 打交道,且反复问的是跨记录的计算问题(本月订阅一共多少 / 这条规则有没有被违反 / 上次的偏好现在还成立吗);或者你需要硬规则在决策时刻必然生效(过敏、禁忌、审批阈值),不能容忍它被当成「可选的上下文」而被忽略。
⛔ 不适用:你的用法主要是「帮我找找之前聊过的那件事」(那是召回);或者你的数据结构每周都在变。
⚠️ 前提:愿意维护一份 append-only 的原始日志 —— 跳过它,你就同时失去了可审计性与仲裁材料。
自测 · 5 问
我最近三次问 agent 的问题,属于聚合 / 规则 / 矛盾,还是属于召回?
有没有哪一次,它检索到了正确材料,却给出了错的数字?
我的规则类需求(禁忌 / 阈值 / 审批)现在是写在提示词里,还是决策时会必然触发?
如果同一件事我在不同时间说过两个版本,现在的系统会不会随机浮上来一个?
我有没有保留逐字的原始记录,还是只剩下了历次摘要的结果?
怎么上手 · 验证步骤
别一次上全量。只挑一类你反复要问的聚合问题(推荐从「这个月/这一年的订阅与固定支出」开始 —— 边界清楚、能立刻验证)。三步:① 先建append-only 的原始记录(每条带时间戳,逐字,不改不删);② 用一个 checkpoint 把日志编译成带类型的对象 + 一个聚合函数;③ 拿十个你以前问过、且知道答案的问题去跑,逐个对答案。跑完之后做一件容易被跳过的事:故意问一个只有召回能答的问题(「我上周随口提的那家店叫什么」),看它是不是真的不如检索 —— 如果是,说明你的分工是对的。
自检动作:写下这次编译前后的三个数 —— 聚合问题答对了几 / 10、单个问题回答耗时、以及「需要人工复核」的次数。三个数都写不出来,说明你还在凭感觉评估「它好像变准了」。
[C级]Agent Patterns《Executable Memory: User State as Code for Personalized Agents》(把用户记忆编译成带类型的代码对象 + 规则函数,聚合类问题调函数而非检索;100 个聚合用例 99% vs MemMachine 43% / Mem0 6%,纯召回基准 LOCOMO 上 78.8% 低于 MemMachine 91.69%) [C级]尧图《推理也会过期:一只 AI Agent 的遗忘修行》(引 arXiv:2609.29875——删一段推理的判据不是它写了什么,而是其中要紧的结论有没有被搬出去) [C级]尧图《当 LLM 遇见大文档:主流开源项目如何处理上下文超限》(七种策略坐标:硬截断 / 结构化摘要 / 动态剪枝 / 外化按需检索 / 替换为引用 / 分块延迟回填 / 上下文重置) 同类:让AI记住你:跨会话不丢背景 · 上下文不是越摘越短,是越养越准
继续往下读
同级:上下文不是越摘越短,是越养越准 随机一篇