9.4.3 短期记忆

- 理解短期记忆和长期记忆的区别
- 理解为什么不能把整段历史无限塞给模型
- 掌握对话窗口、运行态状态、摘要记忆三种常见短期记忆方式
- 看懂一个简单的短期记忆管理器
- 知道短期记忆最常见的失效方式
短期记忆到底是什么?
Section titled “短期记忆到底是什么?”短期记忆可以先理解成:
系统为了完成当前这轮任务,暂时保留的上下文和中间状态。
它通常包括:
- 最近几轮对话
- 当前任务目标
- 已执行步骤
- 临时中间结果
和长期记忆有什么不同?
Section titled “和长期记忆有什么不同?”| 类型 | 关注什么 |
|---|---|
| 短期记忆 | 当前这次任务要用的信息 |
| 长期记忆 | 跨任务、跨会话仍然有价值的信息 |
例如:
- “用户上一句说想查退款政策” -> 短期记忆
- “这个用户喜欢简洁回答” -> 更像长期记忆
为什么不能把所有历史都一直塞给模型?
Section titled “为什么不能把所有历史都一直塞给模型?”因为上下文窗口不是无限的
Section titled “因为上下文窗口不是无限的”模型能看的上下文长度有限。 如果你把所有历史都不断塞进去,会遇到:
- token 成本越来越高
- 响应越来越慢
- 重要信息被淹没
信息越多,不一定越好
Section titled “信息越多,不一定越好”很多新人会觉得:
“多给模型一点历史,总不会错吧?”
其实不一定。
因为如果上下文里混了太多无关内容,模型反而更容易:
- 抓错重点
- 复读旧信息
- 忘掉当前真正要做的事
所以短期记忆真正要解决的不是“记得越多越好”,而是:
在有限预算里,保留当前最有用的信息。
短期记忆最常见的三种形态
Section titled “短期记忆最常见的三种形态”对话窗口(sliding window)
Section titled “对话窗口(sliding window)”最简单的方式:
- 只保留最近 N 轮消息
优点:
- 简单
- 实现成本低
缺点:
- 太久之前的重要信息会被挤掉
运行态状态(task state)
Section titled “运行态状态(task state)”不是只记聊天文本,而是明确记:
- 当前任务目标
- 已经查过什么
- 下一步该做什么
这类状态对 Agent 特别重要。
摘要记忆(summary memory)
Section titled “摘要记忆(summary memory)”当历史太长时,不是全丢掉,而是先压缩成摘要。
例如:
- 保留最近 4 轮原文
- 更早的内容压成一段总结
这是一种很常见的折中方式。
一个最简单的短期记忆:滑动窗口
Section titled “一个最简单的短期记忆:滑动窗口”messages = [ {"role": "user", "content": "你好"}, {"role": "assistant", "content": "你好,我可以帮你做什么?"}, {"role": "user", "content": "我想了解退款政策"}, {"role": "assistant", "content": "你是想了解时间范围,还是具体条件?"}, {"role": "user", "content": "主要看时间范围"},]
window_size = 3short_term_memory = messages[-window_size:]
for msg in short_term_memory: print(msg)预期输出:
{'role': 'user', 'content': '我想了解退款政策'}{'role': 'assistant', 'content': '你是想了解时间范围,还是具体条件?'}{'role': 'user', 'content': '主要看时间范围'}这段代码虽然简单,但已经很重要
Section titled “这段代码虽然简单,但已经很重要”它教你一件最本质的事:
短期记忆最先是一个“保留哪些消息”的选择问题。
不是所有历史都值得继续带着走。
但仅靠消息窗口还不够
Section titled “但仅靠消息窗口还不够”为什么不够?
Section titled “为什么不够?”看这组对话:
- 用户说“我想查退款政策”
- 后面又连续问了几轮别的细节
- 到第 10 轮又问“那我这种情况能退吗?”
如果你只保留最近 3 轮,系统可能已经忘了:
- 当前任务其实一直围绕“退款”
所以 Agent 还要有结构化状态
Section titled “所以 Agent 还要有结构化状态”例如:
task_state = { "goal": "帮助用户判断退款条件", "last_tool": "search_policy", "latest_policy_result": "购买后 7 天内且学习进度低于 20% 可退款"}
print(task_state)预期输出:
{'goal': '帮助用户判断退款条件', 'last_tool': 'search_policy', 'latest_policy_result': '购买后 7 天内且学习进度低于 20% 可退款'}这类状态和原始聊天记录不同,它更像:
系统正在干什么的工作区。
一个更有教学意义的短期记忆管理器
Section titled “一个更有教学意义的短期记忆管理器”下面这个例子同时管理:
- 最近几轮消息
- 当前任务状态
class ShortTermMemory: def __init__(self, max_messages=4): self.max_messages = max_messages self.messages = [] self.state = {}
def add_message(self, role, content): self.messages.append({"role": role, "content": content}) self.messages = self.messages[-self.max_messages:]
def update_state(self, **kwargs): self.state.update(kwargs)
def snapshot(self): return { "messages": self.messages, "state": self.state }
memory = ShortTermMemory(max_messages=3)memory.add_message("user", "我想查退款政策")memory.add_message("assistant", "你更关心时间范围还是条件?")memory.add_message("user", "先看时间范围")memory.update_state(goal="判断退款资格", topic="退款政策")
print(memory.snapshot())预期输出:
{'messages': [{'role': 'user', 'content': '我想查退款政策'}, {'role': 'assistant', 'content': '你更关心时间范围还是条件?'}, {'role': 'user', 'content': '先看时间范围'}], 'state': {'goal': '判断退款资格', 'topic': '退款政策'}}
这个例子真正比“只存历史消息”强在哪里?
Section titled “这个例子真正比“只存历史消息”强在哪里?”因为它把短期记忆拆成了两层:
- 文本上下文
- 结构化状态
这在 Agent 系统里非常重要。
摘要记忆:当消息越来越长怎么办?
Section titled “摘要记忆:当消息越来越长怎么办?”一种常见策略
Section titled “一种常见策略”真实系统很常见这种做法:
- 最近几轮消息原样保留
- 更早历史压缩成摘要
一个简化版示例
Section titled “一个简化版示例”old_messages = [ "用户先问了退款政策", "之后问了证书要求", "最后又回到退款条件"]
summary = "用户本轮主要目标是判断自己是否满足退款条件,中间顺带问过证书。"
recent_messages = [ {"role": "user", "content": "那我学习进度 30% 还能退吗?"}]
memory_package = { "summary": summary, "recent_messages": recent_messages}
print(memory_package)预期输出:
{'summary': '用户本轮主要目标是判断自己是否满足退款条件,中间顺带问过证书。', 'recent_messages': [{'role': 'user', 'content': '那我学习进度 30% 还能退吗?'}]}这就是最基本的“摘要 + 最近窗口”的思路。
短期记忆在 Agent 里到底解决什么?
Section titled “短期记忆在 Agent 里到底解决什么?”它主要解决三件事:
保持当前任务连贯性
Section titled “保持当前任务连贯性”系统不能每一步都像第一次见到用户那样重新开始。
让多步执行不丢状态
Section titled “让多步执行不丢状态”例如:
- 已经调用了哪个工具
- 已经查到了什么
- 还差哪一步
控制上下文成本
Section titled “控制上下文成本”短期记忆不是只为“记住”,也是为了:
- 少塞无关内容
- 降低 token 成本
- 提高响应稳定性
短期记忆最常见的失效方式
Section titled “短期记忆最常见的失效方式”表现:
- 系统突然忘了刚才正在说什么
表现:
- 上下文又长又乱
- 回答跑偏
- 成本变高
只存消息,不存状态
Section titled “只存消息,不存状态”表现:
- 多步任务容易掉链子
- 工具调用前后状态衔接差
只存状态,不存对话原文
Section titled “只存状态,不存对话原文”表现:
- 容易丢掉用户原始表达
- 语气、约束和细节缺失
所以短期记忆通常不是“只选一种”,而是组合设计。
初学者最常踩的坑
Section titled “初学者最常踩的坑”把短期记忆和长期记忆混在一起
Section titled “把短期记忆和长期记忆混在一起”短期记忆解决的是当前任务,不是用户画像全集。
以为消息窗口越大越稳
Section titled “以为消息窗口越大越稳”窗口太大也会带来噪声和成本。
忽略结构化状态
Section titled “忽略结构化状态”这会让 Agent 一到多步任务就开始发飘。
学完这一页,至少保留这张证据卡:
- 记忆类型
- 短期、长期、情景或程序性
- 写入规则
- 在内存创建或更新时
- 检索规则
- 查询、相关性、时效性和权限检查
- 失败检查
- 过时记忆、隐私泄漏、矛盾或过度检索
- 清理动作
- 总结、合并、过期、删除或请求确认
这一节最重要的不是记住“窗口”“摘要”这些词,而是抓住这条主线:
短期记忆的目标,不是无限保留历史,而是在有限上下文里维持当前任务的连贯性。
真正设计得好的短期记忆,通常既包含最近消息,也包含任务状态,有时还会加一层摘要压缩。
- 把本节的
ShortTermMemory扩展成支持summary字段。 - 把最大消息窗口从 3 改成 5,观察
snapshot()输出怎样变化。 - 想一想:如果一个 Agent 经常忘掉“当前已经调过哪个工具”,你会优先补消息窗口,还是补结构化状态?
- 用自己的话解释:为什么说短期记忆解决的是“当前任务连贯性”,而不是“长期用户画像”?
参考实现与讲解
summary字段可以把较早轮次压缩成当前任务摘要,而原始 message window 继续保留最近细节。- 把窗口从 3 改成 5 后,
snapshot()会保留更多最近消息,可能提升连贯性,但也会增加噪声和 token 成本。 - 如果 Agent 忘记已经调用过哪些工具,应优先加 structured state。单纯扩大 message window 更弱,也更贵。
- 短期记忆解决的是当前任务连贯性:目标、约束、最近修正、工具结果和下一步动作。它不应该变成永久用户画像。