AI Agent 的记忆系统:短期记忆、长期记忆与工作记忆
一、为什么 AI Agent 需要记忆?
想象一下这个场景:你让一个 AI 助手帮你规划一次旅行。它推荐了北京的故宫,你回复说"我腿脚不太方便,需要少走路"。结果它下一句推荐你去爬长城。你会有什么感觉?——“它根本没记住我刚才说了什么。”
这就是没有记忆的 AI Agent 的典型表现。每一次对话都是"初次见面",每一次请求都从零开始。这种体验在简单的单轮问答中勉强可以接受,但对于需要多步推理、持续协作的复杂任务,记忆是 Agent 从"工具"升级为"伙伴"的关键拼图。
从认知科学借鉴,AI Agent 的记忆系统通常划分为三层:
| 记忆类型 | 人类类比 | AI Agent 实现 | 典型容量 | 生命周期 |
|---|---|---|---|---|
| 短期记忆 | 当前对话中记住的上下文 | 滑动窗口、对话历史 | 4K-128K tokens | 单次会话 |
| 长期记忆 | 你记得上周学了什么 | 向量数据库 + RAG | 百万级向量 | 跨会话持久 |
| 工作记忆 | 做菜时"下一步放盐" | 结构化 planning + scratchpad | 有限槽位 | 单任务周期 |
本文将深入每一层的设计原理、实现方案和工程优化,并给出可直接运行的 Python 代码示例。
二、短期记忆:对话窗口内的上下文管理
2.1 核心问题
大语言模型(LLM)的上下文窗口是有限的。即使在 2026 年,128K token 的窗口已很常见,长对话仍然会超出窗口。更关键的是:并非窗口内的所有信息都同等重要。将 30 轮对话全部塞入 prompt,不仅浪费 token,还会稀释关键信息——这就是著名的“Lost in the Middle”现象。
2.2 常见策略
策略一:滑动窗口(Naive Sliding Window)
最简单粗暴的方式——只保留最近 N 轮对话。
fromcollectionsimportdequeclassSlidingWindowMemory:"""最简单的短期记忆实现——滑动窗口"""def__init__(self,max_turns:int=10):self.messages=deque(maxlen=max_turns*2)# 每轮 user+assistantdefadd_user_message(self,content:str):self.messages.append({"role":"user","content":content})defadd_assistant_message(self,content:str):self.messages.append({"role":"assistant","content":content})defget_messages(self):returnlist(self.messages)# 使用示例memory=SlidingWindowMemory(max_turns=5)memory.add_user_message("帮我分析这份代码的性能问题")memory.add_assistant_message("我发现第 23 行的循环可以向量化...")# ... 多轮对话后,旧消息自动淘汰滑动窗口的问题是关键信息可能在窗口外——比如用户在对话开头提到的特定约束条件。
策略二:摘要压缩(Conversation Summarization)
用 LLM 定期将旧对话压缩为摘要,释放 token 空间:
importopenaifromtypingimportOptionalclassSummarizationMemory:"""摘要压缩记忆:定期将旧对话压缩为摘要"""def__init__(self,client:openai.OpenAI,summary_interval:int=8):self.client=client self.summary_interval=summary_interval self.messages:list[dict]=[]self.summary:Optional[str]=Nonedefadd_and_compact(self,role:str,content:str)->list[dict]:self.messages.append({"role":role,"content":content})# 超过阈值时触发压缩iflen(self.messages)>=self.summary_interval:self._summarize()# 返回当前有效上下文:摘要 + 最近消息context=[]ifself.summary:context.append({"role":"system","content":f"【历史对话摘要】{self.summary}"})context.extend(self.messages)returncontextdef_summarize(self):old_messages=self.messages[:self.summary_interval//2]self.messages=self.messages[self.summary_interval//2:]response=self.client.chat.completions.create(model="gpt-4o-mini",messages=[{"role":"system","content":"将以下对话压缩为一段简洁摘要,保留关键信息。"},{"role":"user","content":str(old_messages)}])self.summary=response.choices[0].message.content摘要压缩的局限性在于信息会逐渐失真——类似于传话游戏,每一次压缩都是一次有损转换。
策略三:混合方案(推荐)
实际生产中最常用的是混合方案:关键信息提取 + 滑动窗口。将用户偏好、约束条件等关键信息单独存储(类似长期记忆),而对话流本身用滑动窗口管理。
classHybridShortTermMemory:"""混合短期记忆:关键信息持久 + 对话流滑动"""def__init__(self,max_turns:int=10):self.key_info:dict[str,str]={}# 关键信息(持久)self.dialogue=deque(maxlen=max_turns*2)# 对话流(滑动)defadd_exchange(self,user_msg:str,assistant_msg:str):self.dialogue.append({"role":