跳到主要内容

23 篇博文 含有标签「memory」

查看所有标签

抹除后续问题所需上下文的对话记忆修剪启发法

· 阅读需 10 分钟
Tian Pan
Software Engineer

一个用户打开你的长会话智能体(agent),在第 3 轮对话时说:“我是素食主义者,而且预算有限。”对话继续进行。11 轮之后,裁剪器(pruner)开始运行。它计算 Token 数量,发现第 3 轮内容既陈旧又短小,于是为了将窗口维持在预算范围内,将其丢弃了。第 14 轮用户问:“我今晚该做点什么菜?”模型查看一个约束条件已不存在的窗口,推荐了一份 40 美元的肋眼牛排。用户觉得智能体变得越来越难用,打开满意度调查,给这次会话打了一个 2 分。

!["https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E6%8A%B9%E6%8E%89%E4%B8%8B%E4%B8%80%E8%BD%AE%E9%97%AE%E9%A2%98%E6%89%80%E9%9C%80%E4%B8%8A%E4%B8%8B%E6%96%87%E7%9A%84%E5%AF%B9%E8%AF%9D%E8%AE%B0%E5%BF%86%E8%A3%81%E5%89%AA%E5%90%AF%E5%8F%91%E6%B3%95"]辨

你的技术栈中没有任何环节会报告记忆失败。Token 预算仪表盘会显示窗口健康地维持在上限之下。延迟仪表盘会显示绿色。评估套件——将单轮回答与预留集进行对比评分——会报告没有退化。唯一能体现智能体能力下降的信号是一个差评,而你的产品团队会将其归咎于“模型方差”。但这并不是模型方差,而是裁剪启发法在错误的目标上,精准地执行了它被调优后该做的任务。

会话摘要抹掉了用户授予你的同意标志

· 阅读需 12 分钟
Tian Pan
Software Engineer

在第 3 轮,你的用户点击了“不要保留我的代码”。在第 7 轮,他们关闭了“使用我的对话来改进模型”。在第 12 轮,他们选择了退出跨会话记忆。到第 40 轮时,你的上下文预算耗尽了。压缩过程将第 1-30 轮折叠成一个简洁的 200 token 摘要,读起来非常顺畅:它捕捉了用户的提问、你的智能体做了什么以及结果如何。在第 41 轮,你的智能体——带着那份摘要和最近的 10 轮对话——自信地将用户的代码写入了一个用户在第 7 轮就已经选择退出的存储库中。

你的审计日志现在包含一个在 t=3 时的授权事件,一个在 t=41 时的违规操作,而两者之间是一段没有任何字段说明为什么该操作被允许的文本。摘要生成器经过训练是为了压缩对话,而不是为了转发控制状态。没有人告诉它那个授权开关是承重的(load-bearing)。也没人能告诉它,因为授权信息并不在对话中——它存在于对话旁的一个结构化字段里,而这个结构化字段没能熬过摘要化的过程。

那些悄悄共享长期记忆的智能体 A/B 测试变体

· 阅读需 12 分钟
Tian Pan
Software Engineer

你运行了职业生涯中最干净的一次 A/B 测试。流量分配是 50/50,哈希函数看起来没问题,指标流水线没有造假,留存样本(holdout)得到了保留,经过三周的分析,得出了一个明确的胜者:变体 B 将任务完成率提升了 4 个点,统计团队对 p 值也没有异议。你将其 100% 发布了。发布两周后,你启动时所依据的核心指标却漂回了基准线,而且没人能解释原因。

这就是那个花了一些时间才看清的部分。两个变体都在向同一个长期记忆库写入并从中读取。变体 A 中的用户写入了一条记忆,比如 “该客户更喜欢直截了当的总结”,第二天,当同一个用户恰好处于变体 B 时,变体 B 的 Agent 加载了该记忆并将其读入其提示词(prompt)中。反向的情况也在另一个方向发生。实验并不是在比较提示词 A 与提示词 B。它是在比较 “读取提示词 B 形状记忆的提示词 A” 与 “读取提示词 A 形状记忆的提示词 B”。结果是受污染的联合分布的平均值,而发布则是回归到了同一曲面上的另一个点。

记住你 Bug 的智能体:为什么修复 Bug 是一次内存失效事件

· 阅读需 11 分钟
Tian Pan
Software Engineer

几个月前,你的一个下游 API 返回了一个格式错误的时间戳——在应当显示毫秒的地方返回了秒,或者在 Schema 承诺返回字符串的地方返回了 null。你的智能体(agent)遇到了这个问题,分析了故障原因,并制定了一个修复方案:乘以 1000,或者回退到默认值,或者使用不同的端点重试。它解决了眼前的麻烦。然后,它做了一件产生深远影响的事:它记下了这个变通方案(workaround)。

也许它在长期记忆中保存了一条笔记:“计费 API 返回的时间戳单位是秒;使用前需转换。” 也许这次交互被卷入了一个微调(fine-tuning)数据集,于是这个变通方案变成了一个习得的反射行为。无论哪种方式,智能体现在都对世界产生了一种认知。而就在上周,API 团队发布了一个修复补丁。现在时间戳正确了。但没人告诉这个智能体。

为什么你的智能体需要只读副本:智能体记忆的读写分离

· 阅读需 11 分钟
Tian Pan
Software Engineer

大多数 Agent 内存都是一个无差别的存储库。循环在每一步开始时从中读取以组装上下文,并在每次动作后向其写入 —— 新的观察结果、运行摘要、暂存器编辑。同样的存储,同样的访问路径,没有分离。它在演示中运行良好,但一旦 Agent 运行时间足够长、存储库变大,它就开始腐烂。

它腐烂的原因对于任何扩展过数据库的人来说都很熟悉。一个同时提供读写服务的单一存储库就像是一个没有副本的单主数据库,它继承了该拓扑结构在负载下的每一个问题:写入与读取竞争,更新中途读取到写了一半的记录,且易失性工作集与持久记录之间没有隔离。几十年前,我们就通过读写分离解决了数据库的这个问题。Agent 内存也理应得到同样的对待。

解决方法不是更大的向量索引或更智能的嵌入模型。这是一个架构上的解决方法 —— 认识到 “内存” 是冠以同一名称的两种不同工作负载,并为每种负载提供其真正需要的存储规约。

那个记得你撤回了什么的智能体:将删除作为一等公民的记忆操作

· 阅读需 11 分钟
Tian Pan
Software Engineer

三月,一位用户告诉你的智能体停止推荐有室外座位的餐厅——他们搬到了一个带宝宝的公寓,深夜外出已经结束了。九月,智能体为他们的周年纪念建议了一家屋顶酒吧。用户感到恼火,而你感到困惑,因为你亲眼看着三月份的纠正生效了。它被写入了记忆。它仍然在那儿。问题在于它与最初的偏好并排存在,而最初的偏好也还在那里,检索算法浮现了旧的那个,因为它对“周年纪念晚餐”的向量嵌入(embedding)匹配度稍高一点。

这是没有人针对其设计的失败模式。团队在记忆写入上花费数周时间——提取、摘要、嵌入、命名空间——而将删除视为以后再解决的问题。长期记忆使得添加一个事实几乎是零成本的,因此事实不断堆积。但记忆库不是日记。日记允许包含过去真实的事情。智能体读取并据此做出决策的记忆库则不然,因为智能体无法区分事实与过时的残余。

Agent 记忆是一个没有失效策略的缓存

· 阅读需 10 分钟
Tian Pan
Software Engineer

现在每个智能体 (agent) 框架都将“长期记忆”作为核心功能发布,每个团队都将其视为百利而无一害的好事。智能体记住了用户的偏好、之前的决策、项目上下文以及上周收到的修正,因此每次会话的起始状态都比上一次更“热”。演示效果令人难以抗拒:用户说一句“按照我的喜好设置项目”,智能体就照办了。没有人问那个显而易见的问题,因为这一功能的叙事框架在刻意回避它。

问题是:这一切何时会变得不再准确?

记忆存储本质上是一个缓存。它保存着关于一个并非静止不变的世界的事实。智能体在 8 个月前记录了“用户偏好 Postgres”,但团队此后已迁移到了另一个数据库。智能体记得“用户在增长团队”,而用户在 3 月份已经调岗了。智能体存储了一个简洁的对话总结,但该对话的前提在两条消息后就被修正了。记忆层在提取这些信息时,其自信程度和新鲜感与今早刚写下的事实完全一致。我们花了 50 年的时间才意识到,没有失效策略的缓存就是一个正确性漏洞 (correctness bug)。然后我们构建了智能体记忆,并在没有这种策略的情况下将其发布了。

智能体记忆是合规层面:你从未打算构建的记录管理系统

· 阅读需 13 分钟
Tian Pan
Software Engineer

针对你的智能体记忆层的第一次合规升级,几乎从不以监管机构信函的形式出现。它往往是以你企业级销售工程师发来的一张 Jira 工单的形式出现的,上面写着:“客户的隐私团队正在阻碍合同签署——他们想知道在你的系统中‘忘记我的用户’到底是什么意思,并且他们要求在周五前给出书面答复。”这张工单通常在记忆层发布 6 到 12 个月后送达,而构建该功能的工程团队在读完问题的那一刻就会发现,他们不小心构建了一个没有任何记录管理系统(records-management system)应有原语的记录管理系统。

这是智能体产品中长期记忆的结构性问题。构建它的团队通常会针对记忆功能的卖点进行优化——检索质量、延迟、存储成本,以及让助手感觉很懂用户的个性化体验。在设计评审中,没有人会去估算同时被构建出来的那个并行系统的代价:一个按用户、按租户、跨区域的数据存储,它带有保留义务、删除语义、审计导出要求,而且从第一个用户数据进入其中的那一刻起,监管机构的倒计时就开始了。记忆并不是一个功能。它是每个隐私制度、每份企业采购调查问卷以及每个被遗忘权(right-to-erasure)请求最终都会找上的运营界面(operational surface)。

智能体内存驱逐:为什么 LRU 在模型升级中屹立不倒,而显著性评分却不行

· 阅读需 11 分钟
Tian Pan
Software Engineer

那些发布了带有显著性加权内存驱逐(salience-weighted memory eviction)功能智能体的团队,在不知不觉中,已经为每一次模型升级预订了一个内存迁移项目。驱逐策略表面上看起来是一个质量杠杆——选择最聪明的评分方法,获得最好的召回——但它实际上是一个隐秘的版本契约。当评分模型发生变化时,智能体实际上的“过去”也会随之改变。现有的围绕提示词和评估(evals)构建的工具链都无法捕捉到这一点,因为发生漂移的产物既不是提示词也不是评估,而是几个月前由一个已经不存在的模型做出的一系列关于“该忘记什么”的决定。

LRU(最近最少使用)和 LFU(最不经常使用)没有这个问题。它们是确定性的、与模型无关的,并且可以干净利落地在升级中幸存。但它们也会丢弃掉那些审慎的裁判模型会保留的信息。这是大多数团队在第一天——当 Demo 的召回率指标是衡量一切的唯一标准时——会做出的妥协。然而,这种妥协在智能体余下的生命周期里,每季度都会反噬你一次。

跨渠道记忆:当你的智能体遗忘邮件上下文时

· 阅读需 11 分钟
Tian Pan
Software Engineer

周一,一位客户在 Slack 上询问你的助手如何启用某项功能,得到了清晰的回答,然后继续工作。到了周五,他们发邮件要求确认之前的决定,而运行在不同会话存储上的助手——完全不知道周一的聊天发生过——给出了截然相反的建议。客户不会针对两个产品提交两张工单,他们会针对你的 AI 提交一张工单,而且他们是对的。对他们来说,只有一个助手。你写了三个助手并将它们粘在三个特定渠道的会话存储上,这本该是你不该泄露的实现细节。

!["https://opengraph-image.blockeden.xyz/api/og-tianpan-co?title=%E8%B7%A8%E6%B8%A0%E9%81%93%E8%AE%B0%E5%BF%86%EF%BC%9A%E5%BD%93%E4%BD%A0%E7%9A%84%E6%99%BA%E8%83%BD%E4%BD%93%E5%BF%98%E8%AE%B0%E9%82%AE%E4%BB%B6%E5%BE%80%E6%9D%A5%E6%97%B6"]

这就是跨渠道记忆问题,它处于两个被团队低估的因素的交汇点:用户对连续性的假设有多强烈,以及渠道团队为了快速交付而编写各自会话存储的行为有多普遍。最近的行业数据清晰地揭示了这一差距——只有 13% 的组织成功实现了全渠道的完整对话上下文衔接。碎片化多渠道支持的 CSAT(客户满意度)仅为 28%,而真正的全渠道支持则为 67%。这 39 个百分点的差距并不是模型质量的差距,而是记忆架构的差距。

会话边界问题:计费、评估和记忆的对话终点在哪里

· 阅读需 12 分钟
Tian Pan
Software Engineer

三个团队正在查看同一个事件流,每个团队都有一个名为 session_id 的列,但每个团队对什么是“会话”都有不同的定义。计费(Billing)继承了来自认证库的 30 分钟空闲窗口。评估(Eval)从聊天机器人框架中继承了“直到用户说‘再见’或停止打字 10 分钟为止”的定义。记忆(Memory)则使用 UI 在用户点击“开启新聊天”时生成的线程 ID —— 而大多数用户从不点击这个按钮。三列数据,三种语义,一个汇总仪表盘,以及三个共用一个根因但互不相关的 Bug。

这就是会话边界问题(session boundary problem)。它看起来像是一个埋点琐事,但实际上是一个披着基础设施外衣的产品问题:一段对话在哪里结束?坦诚的回答是没有单一的标准答案 —— 计费会话、评估会话和记忆会话并不是同一种对象 —— 如果一个团队选择了一个默认定义并让另外两个团队继承它,那么他们交付的就是具有相同根因的计费纠纷、评估偏见和内存泄漏。

总结税:当压缩消耗的 Token 超过了它节省的量

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个长时间运行的 Agent 每 12 轮就会达到其压缩阈值。每一次压缩的成本都相当于一次规模等同于当前运行窗口的 LLM 调用——首先是 8K tokens,然后是 14K,接着是 22K——因为被总结的内容跨度随着每次触发而增长。到了第 60 轮,用户在观察 Agent 自我总结上花费的 token,已经超过了在实际推理上花费的 token。成本仪表盘将“用户推理成本”显示为一个单一数字,完全没有意识到其中一半是为用户永远不会再看的上下文压缩而付费的。

这就是“总结税”:一类随着对话长度增加而增长的开销,在用户回合之间悄然触发,并作为一个单一项目出现,将用户付费的工作与系统为自我管理而进行的内务处理混为一谈。这是现代 Agent 架构中最接近“垃圾回收停顿时间(garbage-collection pause time)”的东西——而大多数团队在生产环境中运行时都关闭了 -verbose:gc