本页目录
L05 — 记忆:让 Agent 记住上下文
本课目标:搞懂 Agent 的记忆机制,学会处理上下文窗口限制。前 4 课的 Agent 每次调用都是独立的,不记得前面说过什么。这课让 Agent 能多轮对话——"我刚才说的那个数,再乘以 2"。
这是从"一次性工具"到"对话助手"的关键一步。
1. 短期记忆:对话历史就是上下文
其实你前面课已经在用"记忆"了——messages 列表就是 Agent 的短期记忆。
messages = [
{"role": "user", "content": "我叫张三"}, # 第1轮用户说的话
{"role": "assistant", "content": "你好张三"}, # 第1轮Agent的回答
{"role": "user", "content": "我叫什么名字?"}, # 第2轮用户问
{"role": "assistant", "content": "你叫张三"}, # Agent能答对,因为历史在messages里
]
关键认知:大模型本身是"无状态"的——它没有记忆,每次调用都是全新的。所谓的"记住对话",完全靠你把历史消息塞进 messages 每次都传给它。
🎯 核心认知:模型自己不记东西。你传多少历史,它就"记得"多少;你不传,它就全忘了。记忆 = messages 列表的管理。
2. 上下文窗口限制:记忆不是无限的
问题来了:如果对话很长,messages 越来越多,会发生什么?
上下文窗口(Context Window) 是模型单次能处理的最大 token 数。GLM-4 是 12.8 万 token(很大),但: - 越长越贵(按 token 计费) - 越长越慢 - 即使没超限,太长的历史也会让模型"注意力分散",回答质量下降
[系统提示] [第1轮] [第2轮] [第3轮] ... [第100轮] [新问题]
↑
累计可能超过窗口限制,或成本爆炸
三种应对策略
| 策略 | 做法 | 优点 | 缺点 |
|---|---|---|---|
| 全保留 | 所有历史都传 | 信息最全 | 长对话会超限/贵/慢 |
| 截断/滑动窗口 | 只保留最近 N 轮 | 简单有效 | 丢掉早期信息(可能重要) |
| 摘要压缩 | 用模型把旧历史压缩成摘要 | 保留关键信息 | 有压缩损失、额外成本 |
3. 策略详解
截断(滑动窗口)
最简单:只保留最近 N 条消息。
def truncate(messages, keep_last=10):
"""只保留最近 keep_last 条消息(加上系统提示)。"""
system = [m for m in messages if m["role"] == "system"]
others = [m for m in messages if m["role"] != "system"]
return system + others[-keep_last:]
好处:简单、立竿见影。坏处:如果第 1 轮说了"我叫张三",截断后就忘了。
摘要压缩
更聪明:让模型把"旧的对话"压缩成一段摘要,放进 messages。
原始历史(20轮):
用户: 我叫张三
Agent: 你好张三
用户: 我喜欢蓝色
Agent: 好的,蓝色...
... (还有17轮)
↓ 压缩成 ↓
摘要消息:
"[之前的对话摘要] 用户叫张三,喜欢蓝色,之前问过天气和计算问题..."
好处:保留了关键信息(名字、偏好),又控制了长度。坏处:压缩有信息损失,且要额外调一次模型。
💡 实际工程中:常见做法是"摘要 + 滑动窗口"结合——旧历史压缩成摘要,最近几轮原样保留。
4. 长期记忆:跨会话记住(与 RAG 的关系)
短期记忆(messages)只在单次会话内有效——程序一关就没了。长期记忆要跨会话记住用户信息。
怎么做?本质上是对"过去的对话"做 RAG: 1. 把每次对话存进数据库/文件 2. 新会话开始时,检索相关的历史对话 3. 把检索到的历史作为上下文传给模型
长期记忆 = 对历史对话建索引 + 检索相关历史 + 注入当前对话
(这就是 RAG 的思路!只不过检索的是"对话历史"而不是"文档")
🎯 认知闭环:你已经学过 RAG 了。长期记忆本质就是"对自己的对话历史做 RAG"。RAG 课程的知识在这里直接复用。
5. 本课代码会做什么
code.py 实现一个带记忆的多轮对话 Agent,演示三种窗口管理:
① 交互式多轮对话
一个 REPL,你能和 Agent 连续对话,它会记住前面说过的话(比如你告诉它名字,后面问它还记得)。
② 三种窗口管理对比
模拟一个长对话,分别用"全保留 / 截断 / 摘要"三种策略,看: - 全保留:messages 越来越长(打印 token 估算) - 截断:只留最近几轮,但忘了早期信息 - 摘要:旧历史被压缩,保留了关键信息
③ 演示"忘记"的后果
用截断策略时,故意问一个早期才提过的信息,看 Agent"失忆"的表现。
6. 跑起来
python agent-lessons/05_memory/code.py
程序有两个模式:
- 演示模式(默认):自动模拟长对话 + 三策略对比
- 交互模式:在 main() 里改成 interactive_mode(client) 可自己聊天
下一课 L06 — 规划与任务分解 会讲:复杂任务怎么拆解。