记忆是 AI 智能体架构的重要组成部分。它把上下文从一次交互延续到下一次,支持多轮对话与适应性行为。没有记忆,大多数智能体都处于无状态模式。本课深入介绍短期与长期记忆、实际实现模式,以及 Mem0 记忆层等方法,帮助你构建能够持续保持上下文的智能体。
记忆在推理中的作用
记忆让智能体在对话或任务中持续传递信息,保留此前交互、引用早先事实,并完成更复杂的推理。例如,用户在先前查询中说明了个人喜好,智能体可以在后续回答中使用。主要功能包括:
- 连续性:让多轮回答围绕同一主题,并与已有内容保持一致。
- 学习与适应:保存用户纠正或新信息,减少重复错误,逐渐适应用户需求。对话中的这种变化可以理解为 in-context learning。
- 支持推理:保存中间结果与决定,在后续步骤使用,支持多步骤推理。
- 个性化:记住姓名、兴趣和过去问题等相关细节,使后续交互更符合具体用户的上下文。
记忆让无状态的 LLM 成为能够持续对话的有状态智能体,提高交互效率与自然程度。
短期记忆与长期记忆
短期记忆是当前会话或任务中的工作上下文,通常为对话历史和最近产生的状态,在循环中持续提供给 LLM。它以 thread 为范围,属于特定对话或会话。本课实战将实现这一机制。聊天应用中的最近几轮用户与助手消息就是例子。
长期记忆跨会话保存信息,当前对话结束后仍可读取,包括用户资料、历史对话事实或积累的领域知识。它可以跨不同对话线程使用;需要时也可以按系统设计与访问权限在不同用户之间共享。
两者的主要区别:
- 范围:短期记忆属于当前会话和活动上下文;长期记忆通过持久存储跨会话保留。
- 存储方式:短期通常是传给模型的最近消息或状态变量;长期位于数据库、文件或向量索引中,独立于单次会话运行时间。
- 读取与更新:短期通常直接加入每轮提示词,也可省略不相关状态,随着交互追加消息或替换状态。长期记忆需要按需检索,可在智能体主动保存重要信息时更新,也可在会话结束后批量提取关键内容。
- 容量限制:短期受模型上下文窗口限制,长历史可能超限或降低性能。长期可以利用大规模外部存储扩展,难点在于需要时准确找到应加入上下文的信息。
短期记忆提供当前聊天历史,长期记忆提供跨会话知识连续性。下面以 LangGraph 为例介绍实现。
实现短期记忆
最常见方式是保留对话历史。每次收到用户消息,将它与一定数量的先前消息,包括助手回答,一起提供给 LLM。框架通常能够管理消息列表。LangGraph 将短期历史放在状态中,每条消息具有角色与内容,并通过 checkpointer 在调用之间保存状态。开发时可以使用内存保存器,生产时使用数据库保存器,本课示例采用 PostgreSQL:
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import StateGraph
checkpointer = InMemorySaver() # 在内存中暂存状态
workflow = StateGraph(...)
graph = workflow.compile(checkpointer=checkpointer)
# 图将按 thread 保存并加载对话状态
这里的 StateGraph(...) 表示已定义状态和节点的应用图。InMemorySaver 将状态保存在进程内存中。真实部署通常使用 PostgresSaver 等持久保存器,让服务重启或稍后恢复对话时仍可取得短期历史。调用时,在配置中提供 thread_id,告诉 checkpointer 加载或更新哪段对话,从而分别维护不同用户或会话状态。
每次运行时,应用将最新用户问题和助手回答加入状态的消息列表,checkpointer 按 thread ID 保存。下一轮用户输入到来后,加载历史并提供给 LLM,让模型知道此前说过什么。
无限累积消息也有问题。模型窗口有限,提示词过长时可能忽略重要信息,并增加延迟和费用。因此,需要管理保留、删除与压缩:
- 截断旧消息:仅保留最近 N 条,超过限制就移除更早内容。方法简单,但旧的重要信息如果未另存,可能丢失。
- 摘要:用简洁文字替代较长历史。例如,50 条消息后生成摘要,再结合最近消息继续,压缩同时保留重点。
- 消息过滤:省略或压缩与当前查询关系较小的内容。可以使用启发式规则或模型相关性评分决定。
- 保存后重置:一个主题结束时,先提取重要事实写入长期记忆,再清理短期状态,开始新主题。
选择取决于应用。客服系统可能在问题解决后概括旧对话;讲故事的智能体可能需要保持全部叙事上下文直到故事结束。LangGraph 中,状态包含 messages 并配置 checkpointer 后,可以利用框架处理保存、读取与更新。开发者更应关注消息中放入什么,例如 system 提示词,以及何时摘要或裁剪。这是 LangGraph 对基础流程管理的价值。
长期记忆与检索模式
长期记忆为智能体提供跨会话知识库,从用户事实到大量文档或历史事件都可以保存。常见实现是数据库或索引,按需要检索相关内容,再加入提示词。
其核心是支持写入、读取和搜索的持久文档存储。条目可以是 JSON 文档或文本,表示需要记住的信息。如何接入推理循环,是重要设计决策。
生成前检索:每次新问题或对话轮次开始时,先搜索长期存储。查询可以直接使用用户消息,或提取关键词。匹配记忆作为 system 内容或额外上下文加入提示词。例如,用户问“我叫什么名字?”,检索 name 或“名字是”等相关内容。若此前保存“用户名为 Aurimas”,就可以把该事实放入上下文,让模型准确回答。
按需工具调用:更动态的智能体可在推理中自行决定何时查询记忆。此前把向量数据库封装成工具,就是类似做法。LangGraph 可以提供 search_memory 工具节点或子图,模型发现当前上下文不足时调用。需要通过提示词清楚说明工具存在及适用时机。
回答后写入记忆:生成响应或完成任务后,提取新事实和结果,供将来使用。可以同步执行,也可以异步处理。例如,用户说“我叫 Aurimas,请记住”,应用可在回答前立即保存;也可以由后台程序读取对话日志,提取重要内容,以免延迟用户响应。同步写入能够立即更新,代价是增加响应时间;后台写入更快返回,但新信息可能尚未及时可用。
概括与整理:长期存储逐渐增大后,也需要合并与概括。例如,100 条用户行为记录可以形成更高层的资料,或每天夜间把当日聊天整理为关键事实。
长期记忆还可以进一步分类:
长期记忆:
- 情景记忆(Episodic):保存过去交互与智能体行动。操作完成后,应用写入持久存储,需要时再读取。例如,通过向量数据库保存交互的语义表示。
- 语义记忆(Semantic):智能体可用的外部信息,以及关于自身的知识。可以理解为 RAG 中的知识上下文,包括内部资料,或从互联网资料中选择的相关依据。
- 程序性记忆(Procedural):System Prompt 结构、可用工具、安全限制等系统性信息,通常保存在 Git、提示词注册中心或工具注册中心。
短期记忆:
- 任务需要时,应用从长期记忆取得信息,暂存在当前工作环境。
- 当前本地信息与检索到的长期信息共同组成短期或工作记忆,再组织为提示词交给 LLM,模型由此决定后续行动。
Mem0 与记忆服务层
前面介绍由应用自行管理记忆,例如 LangGraph 状态。另一方向是将记忆作为独立服务层。Mem0 是面向 AI 智能体的开源模块化记忆层。
它将长期记忆封装为可接入不同 LLM 应用的服务。无论采用 LangGraph、LangChain 还是直接 API 调用,都可以通过 Mem0 保存和读取记忆,并使用自动压缩、语义关联和个性化上下文管理等能力。Mem0 将自身描述为能够持续改进的记忆层,后续课程还将进一步介绍。
主要特点包括:
- 框架无关的集成:可以与 OpenAI API、LangGraph、CrewAI 等结合。作为中间层补充提示词上下文,或处理输出、更新记忆,减少对现有智能体代码的大幅修改。
- 压缩与效率:自动把聊天历史整理为优化摘要或向量表示,减少 token 使用,同时保留重要上下文。Mem0 提供方报告,部分场景可减少最高 80% 的提示词 token;这一结果取决于具体条件,实际应用需测量。只发送整理后的记忆,有机会降低成本并加快响应。
- 动态上下文读取:记忆持续更新,关联不同交互中的实体,优先考虑近期和相关事实,例如用户最新提及的信息或纠正,并降低过时内容的影响。
- 多类型记忆:结合事实和知识的语义记忆,以及事件轨迹的情景记忆。例如,同时保存用户资料与近期对话记录,通过重复交互改进对用户需求的理解和保存内容。
- 服务层抽象:提供托管选择,应用通过 API 获取上下文和保存新信息,由 Mem0 管理表示、索引和压缩。模块化接口可以加快开发,也便于在未来替换记忆系统。
其他项目,例如 MemoryBank、Ret-LLM 和 HippoRAG,也在研究长期记忆,包括遗忘曲线和受神经系统启发的记忆模型。开发者使用 Mem0 可能减少自定义代码,无需自行实现完整存储与检索逻辑;同时,封装也减少了对内部实现的直接控制。