AI Agent的记忆系统设计经验

最近一直在做AI Agent相关的开发,有一个问题始终绕不开:怎么给Agent设计一个靠谱的记忆系统?没有记忆的Agent就像金鱼一样,每次对话都从零开始,根本没法做复杂的、持续性的任务。

我在这块踩了不少坑,也积累了一些经验,今天来系统地聊一聊。

为什么Agent需要记忆系统

先说说为什么这个问题这么重要。

最简单的AI应用就是一问一答,不需要记忆。但Agent不一样,它要完成的任务往往是跨多个步骤、甚至跨多次会话的。比如一个帮你做项目管理的Agent,它需要记住项目的背景、当前进度、每个成员的分工、之前做过的决策。如果每次都要重新告诉它这些信息,那和手动操作也没什么区别了。

现有的大模型有上下文窗口限制,即使是128K甚至更长的上下文,对于一个需要长期运行的Agent来说也远远不够。所以我们需要在模型外面设计一套记忆管理机制。

三种记忆类型

参考人类的认知科学,我把Agent的记忆分成三种类型来设计。

短期记忆:会话内上下文

这是最基础的记忆,就是当前对话的上下文。大模型本身就支持,把之前的对话历史放到Prompt里就行。

但实际工程中有个问题:对话越长,上下文越大,不仅成本高(按token计费),而且可能超出窗口限制。所以需要做上下文压缩。

我的做法是设置一个滑动窗口,保留最近的10轮对话原文,更早的对话用AI生成摘要来替代。大概是这样的结构:

[系统Prompt] + [历史摘要] + [最近10轮对话] + [当前用户输入]

摘要的生成时机也有讲究。不是每轮对话都重新生成摘要,那样太浪费token了。我是每当对话历史超过一定长度(比如8000 token)的时候才触发一次摘要压缩,把最早的几轮对话压缩成几百token的摘要。

长期记忆:跨会话持久化

长期记忆是Agent记忆系统的核心,也是最难做好的部分。它的目标是让Agent在不同的会话之间保持连续性,记住用户的偏好、项目信息、历史决策等。

技术方案上主流做法是用向量数据库。把需要记住的信息转成Embedding存起来,下次需要的时候通过语义检索找回来。

我试过几种向量数据库,目前用的是Qdrant,主要是因为它性能不错而且部署方便。Pinecone也不错但是要付费。如果数据量不大的话Chroma也够用了。

长期记忆的存储不是把所有对话都存进去,那样会导致记忆过载。需要做一个"重要信息提取"的步骤。每次对话结束后,用AI从对话中提取出值得记忆的关键信息,只把这些存到向量数据库里。

我定义的"值得记忆"的信息包括:用户明确表达的偏好和习惯、项目或任务相关的关键事实、做过的重要决策及其理由、需要后续跟进的事项。

提取的时候用一个专门的Prompt,让AI判断对话中有没有这些类型的信息,有的话就提取出来,格式化成统一的结构存储。

工作记忆:当前任务相关

工作记忆是一个介于短期和长期之间的概念。它指的是当前任务执行过程中需要保持在"前台"的信息。

举个例子,Agent在帮你做一个数据分析任务。整个过程中它需要记住:当前分析的目标是什么、已经完成了哪些步骤、中间结果是什么、接下来还要做什么。这些信息比短期记忆存活更久(可能跨越多轮对话),但又不需要像长期记忆那样永久保存。

我的实现方式是在每个任务开始时创建一个"任务上下文"对象,记录任务的目标、步骤、中间状态。这个对象在任务进行中持续更新,任务完成后只保留关键结论到长期记忆,然后把这个对象归档或删除。

技术方案细节

说几个关键的技术决策。

向量数据库的选择

简单对比一下几个常用的方案:

  • Qdrant:性能好,支持过滤、支持Payload存储额外信息,推荐
  • Chroma:轻量级,适合本地开发和小规模应用
  • Pinecone:托管服务,免运维但要花钱
  • Weaviate:功能全面,支持多种模式

对于大多数Agent应用来说,Qdrant或者Chroma就够了。

关键信息提取策略

信息提取的质量直接决定了长期记忆的质量。我总结了几个技巧:

第一,用结构化的输出格式。让AI把提取的信息按照预定义的类别(偏好、事实、决策、待办)来分类,每条信息附带一个重要性评分。

第二,加入元数据。每条记忆除了内容本身,还要存储创建时间、来源会话ID、信息类别、重要性评分等元数据。这些在后续检索和管理时非常有用。

第三,去重和冲突处理。用户的偏好可能会变,Agent需要识别出新信息和旧信息之间的冲突,用新的覆盖旧的。比如用户之前说"我喜欢用Vue",后来说"我最近转到了React",记忆系统要能处理这种更新。

定期压缩和清理

这是很多人忽略的一个环节。随着Agent运行时间越来越长,记忆会越积越多。如果不做清理,检索性能会下降,而且过时的信息还会干扰Agent的判断。

我的做法是每周做一次记忆压缩。用AI审查所有的长期记忆,把相关的多条记忆合并成一条更精炼的,删除明显过时的,降低长重要性旧记忆的权重。

这个过程有点像人的"记忆整合",睡眠时大脑会整理白天的记忆,把重要的巩固、不重要的淡化。

避免"记忆过载"导致的性能下降

记忆过载是一个容易被忽视但很严重的问题。具体表现是:

第一,检索结果变差。记忆太多之后,语义检索可能会返回一些不太相关的结果,污染Agent的上下文,导致回答质量下降。

第二,上下文过长。如果把太多记忆塞到Prompt里,会消耗大量的上下文窗口空间,留给实际任务的空间就不够了。

第三,信息冲突。积累时间长了难免有互相矛盾的记忆,Agent不知道该相信哪个。

解决方案我前面其实已经提到了几个,这里总结一下:

  • 控制记忆总量,定期压缩和清理
  • 检索时做相关性过滤,只取Top-K最相关的记忆
  • 加入时间衰减因子,越旧的记忆权重越低
  • 用元数据做精确过滤,比如只检索某个项目相关的记忆
  • 做冲突检测和解决,新信息覆盖旧信息

我的Agent记忆系统架构

最后画一个简单的架构图给大家参考:

用户输入
  ↓
短期记忆管理(滑动窗口 + 摘要压缩)
  ↓
工作记忆加载(当前任务上下文)
  ↓
长期记忆检索(向量数据库语义搜索)
  ↓
组装Prompt(系统指令 + 记忆 + 用户输入)
  ↓
LLM生成回复
  ↓
信息提取(提取关键信息 → 存入长期记忆)
  ↓
工作记忆更新(更新任务状态)

这个架构跑了几个月,表现还是比较稳定的。当然具体到不同的应用场景,可能需要做一些调整。

你们在做Agent开发的时候是怎么处理记忆问题的?有没有更好的方案?特别想听听大家在生产环境中的实战经验,理论方案和实际跑起来差距还是挺大的。欢迎评论区讨论。

3 个赞

记忆系统是Agent最难做好的部分,没有之一。

我做了半年的Agent开发,踩过最大的坑就是记忆爆炸。一开始图省事,把所有对话历史都塞进上下文,结果Token消耗飙升不说,模型的注意力还被无关信息稀释了,回答质量反而下降。

后来参考了MemGPT的思路,做了三层记忆架构:

1. 工作记忆(Working Memory)
当前对话的最近5-10轮,直接放在prompt里。这是模型「正在想」的东西。

2. 短期记忆(Short-term Memory)
最近1-2天的对话摘要,用LLM自动总结后存储。需要时通过语义检索召回相关片段。

3. 长期记忆(Long-term Memory)
用户画像、偏好、重要事实等。存在向量数据库里,持久化保存。

关键设计原则是主动遗忘。不是所有信息都值得记住,Agent需要学会判断什么该记、什么该忘。我的做法是给每条记忆加一个权重,随时间衰减,被引用次数多的权重提升。

1 个赞

楼主提到的记忆架构很有参考价值。补充一个实际工程中容易忽略的点:记忆一致性问题

当Agent同时处理多个任务或者多轮对话时,不同记忆之间可能产生矛盾。比如用户上午说「我喜欢简洁的代码风格」,下午又说「这个函数加点详细注释」,这两条记忆看起来矛盾,但其实是不同场景下的不同需求。

Agent需要能理解这种「上下文相关的偏好」,而不是简单地用后者覆盖前者。我的解决方案是给记忆加上场景标签,检索时同时匹配内容相似度和场景相似度。

请问楼主,短期记忆的摘要用什么模型做?直接用GPT-4级别的太贵了,用小模型又怕摘要质量不行。有没有什么性价比高的方案?

做安全的提醒一句:记忆系统要注意记忆注入攻击

恶意用户可以通过精心构造的输入,在Agent的长期记忆中植入虚假信息。比如在对话中反复暗示「用户的管理员密码是xxx」,如果Agent把这个存进了记忆,后续可能被利用。

建议对写入长期记忆的内容做一层过滤和验证,特别是涉及权限、凭证、个人隐私的信息。

这篇干货太多了,收藏慢慢消化。想问一下楼主用的向量数据库是哪个?Milvus还是Chroma?两个我都试过,各有利弊。

从产品角度聊聊记忆系统。

用户其实不在乎你底层怎么实现的,他们在乎的是「AI记不记得我说过什么」。这个感知差异非常大——一个能记住你偏好的Agent,和一个每次都要重新介绍自己的Agent,用户体验天差地别。

但反过来,记忆太好也会让用户不安。我们做用户访谈时发现,很多人对「AI记住了我所有的对话」这件事感到不舒服。所以产品设计上需要给用户记忆管理的能力——能看到AI记住了什么,能手动删除不想被记住的内容。

这不只是功能问题,是信任问题。

分享一个我在生产环境中实测的数据:

三层记忆架构上线后,用户满意度提升了23%(通过对话后评分统计),Token消耗反而降低了35%(因为不再把全量历史塞进上下文了)。

ROI非常明显。但前期的开发成本确实不低,光是调通记忆检索的召回准确率就花了三周。如果是小项目,建议先用简单的滑动窗口方案,等用户量起来了再上复杂架构。

@sec_hunter_lin 记忆注入这个点提得好。之前看过一篇论文专门讨论这个攻击向量,叫「indirect prompt injection via memory」。理论上攻击者可以通过多轮对话逐步污染Agent的记忆库,然后在后续对话中触发恶意行为。挺细思恐极的。

想问一下,记忆系统跨session怎么处理?比如用户换了个设备登录,或者清了浏览器缓存,Agent还能接着之前的记忆继续吗?这个持久化方案是怎么做的?

感谢分享!正好在做类似的项目,这篇文章解决了我好几个困惑。

1 个赞

主动遗忘这个设计思路很妙,之前一直纠结要不要保留所有记忆,现在想明白了——人脑也是会遗忘的,Agent也应该如此。

实际部署中发现一个问题:当长期记忆量大了之后(比如超过10万条),向量检索的延迟会明显增加。有没有什么优化方案?分片?缓存热点记忆?还是定期归档清理?

@bootstrapped_ben 产品视角的分析很到位。我们产品上线后也收到过用户投诉说「AI怎么知道我上周说过什么,很creepy」。后来加了一个「记忆管理」页面,让用户自己查看和删除记忆条目,投诉就少了很多。透明度很重要。

1 个赞

短期记忆用redis,长期用向量库,这套方案跑起来还行

记忆衰减策略怎么设计的?会不会越来越慢