AI 编程与智能体

[AI 上下文 #6] AI 智能体的记忆设计:将信息放在上下文之外(计划文件、记忆与 RAG)

如果你一直读到这里,应该已经看出一个共同模式:尽量减少放在上下文窗口中的内容。第 3 篇的“在 /clear 前将状态写入文件”、第 4 篇的“只放指针,不放正文”,以及第 5 篇的“把过程交给子智能体,只将结论交给主智能体”,全都指向同一个方向。不过,这些文件,也就是移到上下文之外的信息,究竟要放在哪里,我们还没有认真讨论。

5 分钟阅读
[AI 上下文 #6] AI 智能体的记忆设计:将信息放在上下文之外(计划文件、记忆与 RAG) 封面图

如果你一直读到这里,应该已经看出一个共同模式:尽量减少放在上下文窗口中的内容。第 3 篇的“在 /clear 前将状态写入文件”、第 4 篇的“只放指针,不放正文”,以及第 5 篇的“把过程交给子智能体,只将结论交给主智能体”,全都指向同一个方向。不过,这些文件,也就是移到上下文之外的信息,究竟要放在哪里,我们还没有认真讨论。

本篇讨论的就是这个目的地:即使会话结束也必须保留的知识,应该放在哪里、如何放置。打个比方,上下文窗口是工作台,文件系统是仓库。工作台狭小而昂贵,会在会话结束时被清理。仓库宽敞、便宜,而且会一直保留。优秀的智能体运作,归根结底就是设计工作台与仓库之间的物流。

计划文件,长任务的生命线

最基本的外化方式是计划文件。开始任务时,让智能体创建一个类似 PLAN.md 的文件,写入目标、已确定的决策和剩余步骤,并随着进展持续更新。

只靠这一个文件,就能同时解决多个问题。首先,它能在会话重置后继续存在。无论是上下文已满而执行 /clear,还是合上笔记本、第二天开启新会话,只要读取计划文件,就能继续工作。这不同于第 3 篇提到的 auto-compact 所生成的不确定摘要:它是一份由你直接控制保留内容的准确记录。

它还有一个副作用。如果智能体在每一步都更新并重新读取计划文件,整体目标就会反复出现在上下文的末尾附近。正如第 2 篇所见,模型的注意力会强烈集中在上下文末端;我们可以反过来利用这一特性,让“刚才正在做什么”始终保持在视野中。当任务包含几十个步骤时,这就是防止智能体中途忘记原始目标、转而跑题的解决办法。实际上,处理长任务的智能体产品也会采用这种模式:把待办列表放在文件中,并不断重写。

记忆:跨会话积累的知识

如果计划文件延长了单个任务的寿命,那么记忆就会在整个项目中积累知识。包括 Claude Code 在内的智能体都支持记忆目录功能,原理很简单:把了解到的事实逐条写入文件,只始终加载摘要索引,并在相关任务需要时读取正文。第 4 篇的指针原则在这里同样适用。

关键在于存储标准。什么都记,记忆很快就会变成垃圾场。标准是“无法从其他地方推导出的信息”。代码结构可以通过阅读代码得知,因此不应记录;过去的提交历史由 git 记得,也不应记录。相反,“这个项目的 dev 服务器必须始终从 main 工作树启动”这类运行规则,“用户希望使用正式语气”这类偏好,以及经过反复踩坑才发现的环境特有陷阱,都值得写入记忆。因为这些内容没有记录在其他地方。

过时记忆的问题也必须纳入计划。半年前记录的事实,不一定现在仍然正确。记忆的读写规则中应加入“如果引用的记忆与现实不符,就更新或删除”,这样才能避免错误记忆以第 2 篇所说的上下文污染形式卷土重来。

先移出去,需要时再取回来。计划文件、记忆与 RAG 的共同原则
先移出去,需要时再取回来。计划文件、记忆与 RAG 的共同原则

RAG:当仓库大到图书馆规模时

计划文件和记忆讨论的是几十个文件的规模。但如果仓库大到图书馆那么大呢?公司内部 Wiki 数千页、论文数万篇、客户咨询记录数十万条。你确定需要的信息就在其中某处,但不可能把全部内容加载到上下文中。

这时使用的技术就是 RAG(Retrieval-Augmented Generation,检索增强生成)。收到问题后,先从仓库中搜索相关片段,再只把找到的几个片段放入上下文来生成答案。搜索通常使用 embedding 技术。将文本转换为语义空间中的坐标后,“退款规定”这个问题和“支付取消政策”这份文档,即使表述不同,也可能位于相近的坐标,因此即使关键词没有重叠,也能找到它们。

有一段时间,RAG 被认为是处理长文档的唯一正确答案,但在编程智能体领域出现了有趣的反转。人们发现,能够使用工具的智能体即使不进行 embedding 搜索,也能通过反复使用 grep 和探索文件,较好地找到所需代码。因此,如今的实际做法是混合式的。对于具有精确标识符的代码,智能体直接探索更有优势;对于表述各异的自然语言文档集合,embedding 搜索更有优势。无论哪一种,原则都相同:“不要全部加载,只在查询时加载相关部分。”

即使会话结束也能保留的记录,是长任务的生命线
即使会话结束也能保留的记录,是长任务的生命线

总结

  • 上下文是工作台,文件是仓库。会话结束后仍需保留的知识,基本原则是移入文件,而不是留在上下文中。
  • 计划文件能让长任务在会话重置后继续,并反复将目标暴露在上下文的最近位置,防止偏离。
  • 记忆中只记录无法从其他地方推导的信息,始终加载索引,并通过更新和删除规则管理过时条目。
  • 仓库非常大时,使用 RAG 在查询时只加载相关片段。代码适合直接探索,自然语言文档集合则适合 embedding 搜索。

现在只剩系列的最后一篇了。到目前为止,我们为了质量管理上下文;最后一篇要谈钱。内容包括提示缓存的原理:即使是相同的上下文,构建方式不同也可能让 API 成本相差数倍;以及为什么不能随意修改上下文的前半部分。

延伸阅读