拒绝“金鱼脑”:深入剖析 AI Agent 的记忆系统(短期、长期与工作记忆)

在当前的大语言模型(LLM)时代,AI Agent(人工智能代理)正在从单纯的“对话机器人”进化为能够执行复杂任务的“数字员工”。然而,只要稍微深入使用过原生的 LLM API,你都会遇到一个致命的问题:大模型是“无状态”的。

如果没有记忆,AI Agent 就像患有严重失忆症的员工,每次对话都要重新认识世界,上一秒设定的目标下一秒就忘得一干二净,更别提执行需要跨越数十步的复杂任务了。

如果说 LLM 是 Agent 的**“大脑”(负责推理和生成),那么记忆系统就是 Agent 的“海马体”**(负责信息的存储、检索和巩固)。一个真正强大的 Agent,必须具备像人类一样完善的记忆机制。

本文将带你深入剖析 AI Agent 的记忆系统,从经典的短期记忆、长期记忆,到常常被忽视却至关重要的工作记忆。我们不仅会探讨理论架构,还会结合实际的代码落地,为你揭示如何打造一个“过目不忘”的智能体。


💡 核心概念:用计算机架构类比 Agent 记忆

在深入细节之前,我们可以用经典的计算机体系结构(冯·诺依曼架构)来通俗地理解这三种记忆:

人类认知 AI Agent 记忆 计算机类比 核心作用
感觉记忆/短期记忆 Short-Term Memory CPU 寄存器 / 内存 (RAM) 缓存当前对话上下文,处理即时信息。
长期记忆 Long-Term Memory 硬盘 / 数据库 永久存储历史对话、用户偏好、外部知识。
工作记忆 Working Memory CPU 缓存 / 运行栈 当前执行复杂任务时的中间状态、计划步骤和草稿本。

理解了这个映射关系,我们就可以逐一深入探讨了。


一、 短期记忆:Agent 的“瞬时触觉”

短期记忆是 Agent 处理当前交互上下文的能力。

在底层实现上,LLM 本身的上下文窗口就是一个受限的短期记忆。当你向 ChatGPT 发送一段长达 5000 字的对话历史时,这 5000 字就构成了 Agent 的短期记忆。模型通过注意力机制在这个范围内捕捉词与词之间的关联。

1. 短期记忆的挑战

  • 容量限制: 尽管 Gemini 1.5 Pro 等模型已经将上下文窗口扩展到了 200 万 Token,但它依然是有上限的。无尽的对话必然会撑爆内存。
  • 注意力稀释: “迷失在中间”现象表明,当上下文过长时,LLM 往往会忽略中间部分的重要信息。
  • 成本问题: 每次请求都携带巨大的 Prompt 意味着高昂的 API 费用和极慢的响应速度。

2. 优化策略:滑动窗口与摘要

为了管理短期记忆,最常用的策略是滑动窗口结合自动摘要

当对话长度超过设定的阈值时,系统会提取最老的对话轮次,调用 LLM 生成一段摘要,然后将原对话从短期记忆中删除,把摘要作为系统提示词的一部分保留下来。这样既保留了上下文的“意译”,又节省了 Token。


二、 长期记忆:Agent 的“底层知识库”

如果说短期记忆是 Agent 的 RAM,那么长期记忆就是 Agent 的硬盘。它允许 Agent 跨越多个会话甚至数月的时间,记住用户的偏好、以往的事实以及学习到的经验。

在 Agent 架构中(如 LangChain 或 AutoGen),长期记忆通常依赖于向量数据库,这就是著名的 RAG(检索增强生成) 架构的核心。

1. 长期记忆的分类

借鉴认知心理学,Agent 的长期记忆也可以分为两类:

  • 语义记忆: 存储客观事实和概念。例如“巴黎是法国的首都”、“用户的生日是5月1日”。通常通过知识图谱或向量数据库实现。
  • 情景记忆: 存储过去经历的具体事件。例如“昨天我帮用户写了一篇关于 Web3 的博客”、“用户上次对该代码设计表示不满意”。通常通过保存历史对话片段或运行日志来实现。

2. 长期记忆的工作流

一个成熟的长期记忆系统包含三个核心步骤:

  1. 编码与写入: 在对话过程中,Agent 自动识别重要信息(如“我喜欢吃辣”),将其提取出来,通过 Embedding 模型转化为向量,存入向量数据库(如 Chroma, Pinecone, Milvus)。
  2. 检索: 当用户下次提问(如“推荐一家餐厅”)时,系统将提问向量化,在数据库中进行相似度搜索(KNN),召回相关的记忆片段。
  3. 融合: 将召回的历史记忆注入到 LLM 的 Prompt 中,作为短期记忆的一部分供模型参考。

三、 工作记忆:Agent 的“草稿本与运行栈”

这是大多数初学者最容易忽略,但却是构建复杂 Agent 最关键的一环。

短期记忆负责“对话”,长期记忆负责“知识”,那么工作记忆负责“行动与规划”

当 Agent 执行一个复杂任务(例如:“帮我分析这支股票,写一份报告,然后发邮件给老板”)时,它不能仅仅依赖对话历史。它需要一块“草稿本”来记录:

  • 当前的目标和总体计划。
  • 已经完成了哪些步骤?(防止死循环)
  • 当前正在使用什么工具?工具返回了什么中间结果?
  • 推理过程。

在 ReAct (Reason + Act) 模式或 Plan-and-Solve 框架中,工作记忆是 Agent 的执行上下文。它就像 CPU 里面的寄存器,随着程序的运行不断被擦写和更新。

工作记忆的实现形式

  1. 系统提示词中的变量: 在代码中维护一个字典或状态机,实时更新 Agent 的状态,并注入到 Prompt 中。
  2. Scratchpad(草稿本): 类似于 LangChain 中的 Intermediate Steps,专门用来记录思考链路和工具调用的返回结果。
  3. 结构化 JSON: 诸如 LangGraph 这样的高级框架,通过维护一个全局的 JSON State(状态图),在不同的执行节点间传递工作记忆。

四、 代码实战:构建一个三合一记忆的 AI Agent

纸上得来终觉浅。下面我们将使用 Python 和最流行的编排框架 LangChain,结合向量数据库 Chroma,从零构建一个具备三种记忆系统的 Agent。

这个 Agent 的角色是一个“技术面试助手”。它能记住你刚才说了什么(短期),能记住你过往的简历和求职偏好(长期),还能在帮你准备面试题时,记录它自己的思考步骤和当前进度(工作)。

1. 环境准备

你需要安装以下依赖:

1
pip install langchain langchain-openai langchain-chroma chromadb faiss-cpu pydantic

假设你已经配置了 OpenAI API Key 的环境变量。

2. 核心代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
import os
from typing import TypedDict, Annotated, List, Tuple
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage, BaseMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_chroma import Chroma
from langchain_core.tools import tool
from langgraph.graph import StateGraph, END

# ==========================================
# 1. 定义工作记忆
# ==========================================
# 工作记忆不仅包含消息,还包含当前的状态、计划和中间步骤
class AgentState(TypedDict):
messages: Annotated[List[BaseMessage], "对话历史(短期记忆的载体)"]
current_task: str # 当前主任务
scratchpad: List[str] # 草稿本/中间步骤 (工作记忆核心)
is_finished: bool # 状态标记:任务是否完成

# ==========================================
# 2. 初始化长期记忆
# ==========================================
# 使用 Chroma 向量数据库作为长期语义记忆
embeddings = OpenAIEmbeddings()
vector_store = Chroma(collection_name="agent_memory", embedding_function=embeddings)

def save_to_long_term_memory(text: str):
"""将重要信息存入长期记忆"""
vector_store.add_texts([text])
print(f"[系统] 已写入长期记忆: {text[:30]}...")

def retrieve_from_long_term_memory(query: str, k=2) -> str:
"""从长期记忆中检索相关信息"""
results = vector_store.similarity_search(query, k=k)
if results:
return "\n".join([doc.page_content for doc in results])
return "无相关历史记忆。"

# ==========================================
# 3. 定义 Agent 的工具 (影响工作记忆的动作)
# ==========================================
@tool
def save_user_preference(preference: str):
"""当用户提及他的偏好、简历背景或重要信息时,调用此工具保存。"""
save_to_long_term_memory(preference)
return "已记录您的偏好。"

@tool
def finish_preparation(summary: str):
"""当面试题准备完毕,调用此工具结束任务。"""
return "任务已完成。"

tools = [save_user_preference, finish_preparation]

# ==========================================
# 4. 初始化 LLM (大脑)
# ==========================================
llm = ChatOpenAI(model="gpt-4o", temperature=0.7)
llm_with_tools = llm.bind_tools(tools)

# ==========================================
# 5. 构建控制节点 (融合三种记忆)
# ==========================================
def agent_node(state: AgentState):
# a. 获取短期记忆 (当前上下文)
short_term_memory = state["messages"]

# b. 获取长期记忆 (检索历史)
# 我们用最后一条人类消息作为 Query 去检索长期记忆
query = ""
for msg in reversed(short_term_memory):
if isinstance(msg, HumanMessage):
query = msg.content
break
long_term_memory = retrieve_from_long_term_memory(query) if query else "无"

# c. 整理工作记忆 (当前状态和草稿本)
work_memory = "\n".join(state["scratchpad"]) if state["scratchpad"] else "刚开始,暂无中间步骤。"
task_status = "已完成" if state["is_finished"] else "进行中"

# d. 组装最终的系统提示词 (将三种记忆注入大脑)
system_prompt = f"""你是一个资深的AI面试教练。

## 【长期记忆库】(用户的历史背景和偏好,你必须参考):
{long_term_memory}

## 【工作记忆区】(你当前的内部状态和草稿本,不要直接暴露给用户):
- 当前主任务: {state['current_task']}
- 任务状态: {task_status}
- 内部步骤记录:
{work_memory}

## 指令:
1. 根据【长期记忆库】了解用户的真实背景。
2. 回答用户的当前问题。
3. 如果在对话中发现了用户的个人信息/偏好,请立即调用 `save_user_preference` 工具。
4. 如果用户要求准备面试题,请在思考时更新你的内部步骤。如果准备完毕,请调用 `finish_preparation`。
"""

# 构建消息列表
messages = [SystemMessage(content=system_prompt)] + short_term_memory

# 调用大模型
response = llm_with_tools.invoke(messages)

# 更新工作记忆的草稿本 (这里简单记录一下AI的动作)
new_scratchpad = state["scratchpad"].copy()
if response.content:
new_scratchpad.append(f"AI思考/回复: {response.content[:50]}...")
if response.tool_calls:
for tc in response.tool_calls:
new_scratchpad.append(f"调用工具: {tc['name']} 参数: {tc['args']}")

return {
"messages": short_term_memory + [response],
"scratchpad": new_scratchpad
}

# ==========================================
# 6. 构建工作流图
# ==========================================
workflow = StateGraph(AgentState)

# 添加节点
workflow.add_node("agent", agent_node)

# 设置入口
workflow.set_entry_point("agent")

# 添加条件边:如果 LLM 调用了工具,我们需要一个执行工具的节点(这里为了简化,直接在内部处理)
# 如果没有工具调用,且任务完成,则结束
workflow.add_edge("agent", END)

# 编译应用
app = workflow.compile()

# ==========================================
# 7. 运行测试
# ==========================================
def chat():
print("=== 面试助手已上线 ===")
# 初始化工作记忆状态
state = {
"messages": [],
"current_task": "协助用户准备面试",
"scratchpad": [],
"is_finished": False
}

while True:
user_input = input("你: ")
if user_input.lower() in ["exit", "quit"]:
break

# 更新短期记忆
state["messages"].append(HumanMessage(content=user_input))

# 运行 Agent 图
result = app.invoke(state)

# 更新全局状态
state["messages"] = result["messages"]
state["scratchpad"] = result["scratchpad"]

# 获取最后的 AI 回复并打印
last_ai_msg = state["messages"][-1]
if isinstance(last_ai_msg, AIMessage):
print(f"AI 教练: {last_ai_msg.content}")

if __name__ == "__main__":
# 模拟一段对话
print("第一次对话...")
state1 = {
"messages": [HumanMessage(content="你好,我是一名有3年Python经验的开发者,我想准备大厂面试。")],
"current_task": "协助准备大厂Python面试",
"scratchpad": [],
"is_finished": False
}
res1 = app.invoke(state1)
print("AI 教练:", res1["messages"][-1].content)
print("-" * 30)

# 模拟第二次对话(此时短期记忆清空,但长期记忆已保存)
print("第二天,新的会话开始了...")
state2 = {
"messages": [HumanMessage(content="帮我出两道常考的算法题。")],
"current_task": "出两道算法题",
"scratchpad": [],
"is_finished": False
}
res2 = app.invoke(state2)
print("AI 教练:", res2["messages"][-1].content)

代码解析:记忆是如何流转的?

在上述代码中,我们没有使用简单的 ConversationChain,而是使用 StateGraph 精细地控制了 Agent 的内部状态。

  1. 短期记忆的体现: messages 列表负责承载当前的对话历史,LLM 能够直接看到这个列表,从而理解用户的上下文。
  2. 长期记忆的体现: 当用户在第一次对话中说出“有3年Python经验”时,Agent 调用了 save_user_preference 工具,将该信息向量化并存入了 Chroma 数据库。当第二天开启全新的会话时,messages 虽然为空,但 retrieve_from_long_term_memory 函数通过查询“算法题”,检索到了“3年Python经验”,并将其注入到了 System Prompt 中。
  3. 工作记忆的体现: 这是最精妙的部分。在 AgentState 中,我们维护了 current_taskscratchpad。即使 LLM 没有在对话中直接表现出它的规划,但在后台,系统不断地把中间工具调用、任务状态追加到 scratchpad 中,并在每一轮对话时悄悄“塞”给 LLM。这就是 Agent 暗中的“草稿本”。

五、 进阶探讨:当前记忆系统的痛点与未来方向

尽管架构看起来完美,但在实际生产环境中,AI Agent 的记忆系统仍面临巨大的挑战:

1. 主动遗忘机制

人类的记忆之所以高效,是因为我们擅长遗忘。当前基于向量数据库的长期记忆只会无限增长,导致检索出来的信息充斥着噪音。未来的 Agent 需要具备“记忆巩固”和“遗忘”机制——定期合并相似的碎片化记忆,降低不再使用的历史记忆的权重,甚至主动删除错误信息。

2. 反射性记忆

按照文中所述的架构,Agent 只能记住“事实”。但真正高级的 Agent 应该能记住“经验”。比如,AutoGPT 中曾提出一种机制:当 Agent 执行失败后,它会在后台总结“我错在哪里,下次应该怎么做”,并将这种方法论存入记忆库。这类似于人类在复盘后形成的直觉。

3. 记忆的容量与注意力分配

在单次会话中,如果短期记忆 + 检索到的长期记忆 + 工作记忆的总长度超过了 LLM 的有效处理能力(比如超过了 100k Token),模型就会产生严重的性能衰退。如何在有限的 Prompt 空间里,动态决定哪些记忆“优先级最高”,是未来系统优化的关键。

六、 总结

没有记忆的 LLM 只是一个静态的字典,而拥有了记忆系统的 Agent 才是一个能够成长、适应并执行复杂任务的“智能体”。

  • 短期记忆提供了即时上下文,让对话得以顺畅进行。
  • 长期记忆赋予了 Agent 个性化与知识积累,使其能够跨越时间维度。
  • 工作记忆则是 Agent 任务规划与执行的心智草稿本,是保证 Agent 不跑题、不死循环的关键。

从工程实现的角度来看,构建一个强大的 Agent 并不是调用某个单一的 API,而是设计一套优秀的数据流转和状态管理架构。通过像 LangChain、LangGraph 这样的框架,结合向量数据库,我们完全可以根据业务需求,定制出属于你自己的、拥有“最强大脑”的 AI Agent。

随着模型原生支持上下文长度的增加,以及记忆检索算法的优化,我们有理由相信,在不久的将来,AI Agent 将真正成为我们可靠的、拥有“数字人格”的全天候助手。