跳转到主要内容

聊天历史是数据库。别再把它当成滚动回溯了。

阅读需 1 分钟Tian PanTian Pan

针对 Agent 类产品,生产环境下最常见的投诉通常是某种形式的“它忘记了我们刚才说的话”。这种投诉往往出现在第 8 轮、第 15 轮或第 30 轮——绝不会在第 2 轮出现。团队的第一反应往往如出一辙:扩大上下文窗口。但这其实是错误的直觉,因为 Bug 不在模型本身,而在于团队将对话历史视为了终端的滚动回放(scrollback)——追加一行、渲染尾部、满了就截断。实际上,他们不知不觉中构建的是一个读多写少的数据库,具有仅追加写入、热工作集、隐藏在截断规则中的淘汰策略,以及取决于所提问题类型的查询模式。一旦你接受了这一点,整个问题的本质就改变了。

滚动回放模式之所以如此诱人,是因为聊天界面看起来就像一份对话记录。消息向下流动,用户自上而下阅读,而喂给模型的自然方式就是将最新的 N 轮对话拼接到提示词中。这种数据结构感觉是“免费”的:没有 Schema,没有索引,没有查询——只需追加、渲染、重复。在最初的几轮对话中,任何架构都表现良好。模型拥有完整的上下文,费用低廉,演示效果极佳。

然后,产品进入了实际生产环境。一个用户进行了长时间的支持会话;另一个用户第二天回来,期望对话能保持连贯;第三个用户要求 Agent 总结一个已经持续了两小时的线程。突然间,Agent 开始自相矛盾,丢掉了用户在 6 轮前设定的约束,或者仅仅在历史记录上就耗尽了上下文预算,导致回答实际问题时无以为继。团队提高了截断限制,导致成本激增,有人指出,即使在按 Token 线性计费的供应商那里,将上下文长度翻倍也会使注意力计算量增加四倍——而且模型在上下文中间部分使用 Token 的能力衰减得很快,以至于更多的字节并不等同于更多的记忆。

没人会在白板上画出的成本模型

滚动回放模式掩盖的第一件事是你的 Token 到底买到了什么。在长对话中,账单上的主要支出项不是模型的输出,甚至不是系统提示词,而是对话历史。由于 API 是无状态的,客户端不断将相同的对话轮次重复拼接到提示词中,导致每一轮都要全量重新发送。

在没有提示词缓存的情况下,成本大致随对话长度呈平方级增长。到第 30 轮时,早期的消息已经被重新发送给供应商 30 次了。缓存降低了常数——例如 Claude 的提示词缓存和 OpenAI 的自动提示词缓存——但它并没有改变成本增长的曲线,因为只有当前缀完全稳定时,缓存才会生效。任何工具调用的结果、检索到的文档或注入到提示词中的时间戳都会使后续内容失效,并迫使缓存重新预热。没有量化过这一点的团队往往认为他们的 Token 账单随输出量增长。事实并非如此。它随对话长度的积分增长,而历史记录的重复读取通常占总量的三分之二。

这一点至关重要,因为它反转了优化目标。最便宜的 Token 是你没有放入提示词中的那个。本文后续部分的所有架构选择,从根本上说都是在讨论:应该在何时、以何种保真度加载过去的哪一部分片段?而“每一轮都全量加载”这种暴力方案,只有在对话很短时才可行。

当你称其为数据库时,一切都变了

一旦你不再称其为记录,而是称其为数据库,问题的空间就会围绕你已经知道如何解决的问题重新排列。数据库有索引、查询计划、物化视图、淘汰策略和一致性模型。这些概念在对话历史中都有对应物,但在任何“仅追加和渲染”的系统中,这些概念都被隐式地处理了——而且通常处理得很糟。

轮次索引(turn index)是你首先要构建的东西。它不需要很复杂:每轮一个整数 ID、一个时间戳、角色、由小型分类器生成的意图标签(如 questioncorrectioninstructiontool_resultchitchat)以及内容哈希就足够开始了。有了这个索引,你就可以编写类似“给我用户发出指令的最后三轮对话”之类的查询,而无需扫描整个日志。大多数 Agent 从不编写此类查询,因为其数据结构不支持——它们只是按顺序获取尾部,而不考虑相关性。

意图层面的总结变成了基于索引的物化视图。你不需要重播每一轮对话,而是携带一个运行中的压缩表示:用户正在寻找航班,指定了周二出发,排除了红眼航班,对价格敏感但对航空公司要求灵活。这种总结是对底层日志的反规范化处理,按照应用程序控制的计划进行异步刷新。与任何物化视图一样,它可能会与源数据失去同步——下文提到的评估规范就是为了让你正视这种偏移。

会员专享

余下内容仅对会员开放。

会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。

  • 完整文章,包含未公开存档的部分
  • 可落地的工作框架,附带权衡与决策依据
  • 新文章抢先看,先于公开发布

随时取消 · 一次订阅,畅读全部

参考资料

保持联系,关注我获取更多内容

阅读需 10 分钟

在写第一个 Prompt 之前,先设计好你的 Agent 状态机

先写 Prompt 再拼接逻辑的直觉,会导致 agent 在简单测试中正常运行,却在生产环境中神秘失败。先设计状态机,会改变一切。

insider
ai-engineering
阅读需 10 分钟

对话历史是信任边界,而非文本块

对话历史是多源反馈流,而非仅可追加的状态。为每一轮对话的来源打上标签,使用 HMAC 锚定用户回合,并将工具输出封装在信任区内 —— 否则你的 Agent 攻击面将随对话轮数线性增长。

insider
ai-security
阅读需 9 分钟

环境 AI 一致性问题:当每个功能都由 AI 驱动,整个产品却失去了统一感

在搜索、摘要、对话和推荐中同时部署 AI,会产生跨功能矛盾,其对用户信任的损害远超任何单一的错误答案。本文介绍如何构建让用户感受到统一产品体验的系统。

insider
ai-engineering
阅读需 9 分钟

脚手架审计:每一次模型发布都让你的部分开发框架变成累赘

重试机制编排、JSON 修复解析器以及强制思维链,都是为你不再运行的模型而构建的。这是一套在每次模型升级时,对过时的 LLM 脚手架进行标记、消融和删除的实用规范。

insider
ai-engineering
阅读需 9 分钟

你的智能体内存需要垃圾回收机制

持久化智能体内存默认会单调增长,因此过时的事实会污染之后检索它们的每一次运行。本文将探讨为什么仅靠 TTL 是不够的,以及过时评分、替代链、溯源和写入时门控如何将内存从简单的日志转变为一套生命周期管理系统。

insider
ai-agents