Agent Engineering 课程阅读
首页/课程二 · Agent 手写/记忆:让 Agent 记住上下文

在 GitHub 查看原文

本页目录

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 — 规划与任务分解 会讲:复杂任务怎么拆解。