第6课:如何管理短期记忆和长期记忆 - 学习笔记
📚 课程核心主题
本节课详细讲解如何在实际项目中管理短期记忆和长期记忆,包括实现步骤、检索机制、存储方案选择等核心内容。
🎯 第一部分:短期记忆的管理实现
短期记忆实现的三个步骤
步骤1:开启短期记忆能力
是什么:
- 使用 Checkpointer(检查点) 机制
- 通过
PostgresSaver或RedisSaver来创建检查点实例
代码示例:
python
from langgraph.checkpoint.postgres import PostgresSaver
# 创建checkpointer实例
checkpointer = PostgresSaver.from_conn_string(connection_string)
# 绑定到Agent
agent = create_agent(checkpointer=checkpointer)
关键点:
- Checkpointer是短期记忆的基础设施
- 它会自动创建数据库表结构
- 不需要手动创建表
步骤2:每次对话加载历史信息
是什么:
- 每轮对话开始时,系统会自动从存储中加载历史信息
- 这些历史信息是当前线程(thread_id)的所有对话记录
工作流程:
用户输入新消息
↓
系统从数据库加载该thread_id的所有历史消息
↓
将历史消息放入上下文(Context)
↓
AI模型利用上下文生成回复
关键点:
- 加载是自动的,不需要手动调用
- 只加载当前thread_id的消息
- 不同线程之间的消息是隔离的
步骤3:放入上下文(对话窗口)
是什么:
- 将加载的历史消息放入**上下文(Context)**中
- 上下文就是AI模型能看到的所有信息
- AI利用这些上下文信息来回答问题
作用:
- ✅ 保持对话的连贯性
- ✅ AI知道之前说了什么
- ✅ 能够根据历史信息做出合适的回复
类比理解:
- 就像你和朋友聊天,你们都能看到之前的聊天记录
- 这样对话才不会"乱",才能保持连贯
关键问题:如何从大量历史信息中找到有用的信息?
问题背景
挑战:
- 随着对话增加,历史消息会越来越多
- 不可能把所有消息都放入上下文
- 需要智能选择哪些信息是有用的
解决方案:
方案1:语义检索(Semantic Search)
是什么:
- 通过语义理解来检索相关信息
- 使用向量化存储(Vector Storage)
- 只检索与当前查询(query)相关的信息
工作原理:
用户输入:"预订酒店"
↓
将历史消息向量化
↓
计算与"预订酒店"的语义相似度
↓
只检索相似度高的消息
↓
放入上下文
优势:
- ✅ 只获取相关的信息
- ✅ 缩小检索范围
- ✅ 提高效率
例子理解:
- 就像图书馆找书,不是把所有书都拿出来
- 而是根据"关键词"找到相关的书
- 语义检索就是根据"语义相似度"找到相关的对话
方案2:历史信息压缩(Compression)
是什么:
- 对历史信息进行压缩和总结
- 将多条消息压缩成更短的摘要
- 减少Token消耗
工作原理:
多条历史消息
↓
使用AI模型进行总结
↓
生成压缩后的摘要
↓
用摘要替代原始消息
优势:
- ✅ 减少Token数量
- ✅ 保留关键信息
- ✅ 提高处理效率
💾 第二部分:长期记忆的管理实现
为什么需要长期记忆?
实际需求场景
场景:用户偏好设置
用户说:
"我要预订酒店,需要有窗户,有WIFI"
需求:
- 这是用户的个人偏好
- 希望以后每次预订酒店时,都能自动应用这个偏好
- 即使过了几天、几个月,也要记住这个偏好
问题:
- ❌ 用短期记忆无法实现
- ❌ 短期记忆只在当前会话有效
- ❌ 关闭会话后,偏好就丢失了
解决方案: 使用长期记忆
长期记忆的实现步骤
步骤1:存储用户偏好
是什么:
- 将用户的偏好信息存储到长期记忆中
- 使用 Store 类(不是Saver类)
- 基于 user_id 存储,不是thread_id
代码结构:
python
from langgraph.checkpoint.postgres import PostgresStore
# 创建长期记忆存储实例
store = PostgresStore.from_conn_string(connection_string)
# 存储用户偏好
user_preferences = {
"住宿偏好": "有窗户,有WIFI"
}
store.put(
user_id="1",
data=user_preferences
)
关键点:
- 使用
PostgresStore(不是PostgresSaver) - 存储时使用
user_id,不是thread_id - 可以存储任意结构的数据
步骤2:检索用户偏好
是什么:
- 在需要时,从长期记忆中检索用户偏好
- 使用
store.search()方法 - 根据
user_id检索
代码示例:
python
# 检索用户偏好
preferences = store.search(
user_id="1"
)
# 使用检索到的偏好
if preferences:
# 应用用户偏好到当前任务
apply_preferences(preferences)
实际应用场景:
- 用户说:"帮我预订酒店"
- 系统先检索用户的长期记忆
- 找到偏好:"有窗户,有WIFI"
- 在预订时自动应用这些偏好
短期记忆和长期记忆的配合使用
两个存储实例
在实际项目中,需要同时使用两个存储:
-
Checkpointer(短期记忆)
pythoncheckpointer = PostgresSaver.from_conn_string(connection_string)- 存储:当前线程的对话历史
- 区分标识:thread_id
-
Store(长期记忆)
pythonstore = PostgresStore.from_conn_string(connection_string)- 存储:用户偏好、跨会话信息
- 区分标识:user_id
关键区别:
| 特性 | Checkpointer(短期) | Store(长期) |
|---|---|---|
| 类名 | PostgresSaver | PostgresStore |
| 存储内容 | 对话历史 | 用户偏好 |
| 区分标识 | thread_id | user_id |
| 作用范围 | 当前会话 | 跨所有会话 |
🔧 第三部分:存储方案的选择
PostgreSQL vs Redis
PostgreSQL(关系型数据库)
特点:
- ✅ 适合一般场景
- ✅ 数据持久化可靠
- ✅ 适合中小型应用
- ✅ 自动创建表结构
适用场景:
- 一般的企业应用
- 对并发要求不是特别高
- 需要可靠的数据持久化
Redis(内存数据库)
特点:
- ✅ 高并发场景推荐
- ✅ 每秒10万级以上的高吞吐
- ✅ 支持数据过期设置(TTL)
- ✅ 可以设置哪些信息过期,哪些永不过期
适用场景:
- 并发量特别大的场景
- 对吞吐要求非常高
- 需要灵活的数据过期策略
数据过期功能:
- 用户偏好:可以设置为永不过期
- 临时信息:可以设置过期时间(如7天后过期)
- 这在PostgreSQL中很难实现,但在Redis中很简单
存储方案的组合使用
可以分开使用
方案1:短期用PostgreSQL,长期用Redis
python
# 短期记忆用PostgreSQL
checkpointer = PostgresSaver.from_conn_string(postgres_conn)
# 长期记忆用Redis
store = RedisStore.from_conn_string(redis_conn)
方案2:都用Redis
python
# 短期和长期都用Redis
checkpointer = RedisSaver.from_conn_string(redis_conn)
store = RedisStore.from_conn_string(redis_conn)
方案3:都用PostgreSQL
python
# 短期和长期都用PostgreSQL
checkpointer = PostgresSaver.from_conn_string(postgres_conn)
store = PostgresStore.from_conn_string(postgres_conn)
选择建议:
- 如果并发量特别大,建议用Redis
- 一般情况用PostgreSQL也可以
- 可以根据实际需求灵活组合
📊 第四部分:实际应用流程
完整的工作流程
场景:用户预订酒店(应用长期记忆)
步骤1:用户首次设置偏好
用户:"我要预订酒店,需要有窗户,有WIFI"
↓
系统提取偏好信息
↓
存储到长期记忆(store.put)
↓
数据库中的store表新增记录
步骤2:用户再次预订酒店(新会话)
用户:"帮我预订酒店"
↓
系统检索长期记忆(store.search)
↓
找到用户偏好:"有窗户,有WIFI"
↓
应用偏好到预订任务
↓
AI回复:"已成功为您预订了汉庭酒店,并确保房间有窗户和WIFI"
关键点:
- ✅ 即使切换了线程(thread_id不同),也能检索到偏好
- ✅ 因为长期记忆是基于user_id的
- ✅ 实现了"让AI更懂你"的目标
💡 关键概念总结
| 概念 | 简单理解 |
|---|---|
| Checkpointer | 短期记忆存储,使用Saver类,基于thread_id |
| Store | 长期记忆存储,使用Store类,基于user_id |
| 语义检索 | 通过语义相似度检索相关信息,使用向量化存储 |
| 历史信息压缩 | 将多条消息压缩成摘要,减少Token消耗 |
| PostgreSQL | 关系型数据库,适合一般场景 |
| Redis | 内存数据库,适合高并发,支持数据过期 |
| user_id | 用户标识,用于长期记忆的区分 |
| thread_id | 线程标识,用于短期记忆的区分 |
❓ 思考题
-
短期记忆实现的三个步骤是什么?
- 答:①开启短期记忆能力(使用Checkpointer);②每次对话加载历史信息(自动从存储中加载);③放入上下文(将历史消息放入对话窗口,供AI使用)
-
如何从大量历史信息中找到有用的信息?
- 答:有两种方案:①语义检索:通过向量化存储,计算语义相似度,只检索相关的信息;②历史信息压缩:将多条消息压缩成摘要,减少Token消耗
-
短期记忆和长期记忆在存储上有什么区别?
- 答:短期记忆使用Checkpointer(PostgresSaver类),基于thread_id存储对话历史;长期记忆使用Store(PostgresStore类),基于user_id存储用户偏好。两者可以分开使用不同的存储方案。
-
为什么高并发场景推荐使用Redis?
- 答:Redis可以做到每秒10万级以上的高吞吐,性能远超PostgreSQL。另外,Redis支持数据过期设置(TTL),可以灵活设置哪些信息过期、哪些永不过期,这在PostgreSQL中很难实现。
-
如何实现跨会话的用户偏好?
- 答:使用长期记忆(Store),将用户偏好存储到数据库中,基于user_id而不是thread_id。这样无论用户开启多少个新会话,都能通过user_id检索到之前存储的偏好信息。
📌 本节课重点回顾
✅ 短期记忆管理: 开启能力 → 加载历史 → 放入上下文,三个步骤缺一不可
✅ 智能检索机制: 通过语义检索和历史信息压缩,从大量信息中找到有用的部分
✅ 长期记忆管理: 使用Store类存储用户偏好,基于user_id实现跨会话记忆
✅ 存储方案选择: PostgreSQL适合一般场景,Redis适合高并发,可以灵活组合使用
✅ 实际应用: 短期记忆和长期记忆配合使用,实现智能化的用户体验
笔记整理时间:2024年
建议:理解短期记忆和长期记忆的管理机制是构建生产级AI系统的关键,需要掌握存储方案的选择和组合使用