第7课:管理长期记忆的关键架构决策 - 学习笔记
📚 课程核心主题
本节课通过实际代码演示,深入讲解管理长期记忆的关键架构决策,包括生产环境中的注意事项、thread_id的动态生成、用户偏好的存储和检索等核心实现细节。
🎯 第一部分:生产环境中的关键问题
问题1:thread_id不能写死
问题背景
演示场景:
- 代码中写死了
thread_id = 1 - 所有对话都使用同一个thread_id
- 导致所有消息都混在一起
实际生产中的问题:
- ❌ 每个用户都应该有独立的会话
- ❌ thread_id必须动态生成
- ❌ 不能所有用户共享同一个thread_id
正确的做法
是什么:
thread_id应该像 session_id 一样- 每次新建会话时,动态生成新的thread_id
- 每个会话都有唯一的标识
代码示例:
python
# ❌ 错误做法:写死thread_id
thread_id = "1" # 所有用户都用这个
# ✅ 正确做法:动态生成
import uuid
thread_id = str(uuid.uuid4()) # 每次生成新的唯一ID
# 或者
thread_id = generate_session_id() # 自定义生成函数
类比理解:
- 就像Web开发中的session_id
- 每个用户登录后,都会生成一个新的session_id
- 不同用户的session_id是不同的
- thread_id也是一样的道理
问题2:消息加载的问题
演示场景分析
场景:
- 使用写死的
thread_id = 1 - 消息累积到了17条
- 每次新对话都会加载所有17条消息
问题:
- ❌ 在实际生产中,会不会出现加载17条消息的情况?
- ❌ 如果thread_id是动态生成的,就不会有这个问题
答案:
- ✅ 会:如果thread_id写死,就会加载所有消息
- ✅ 不会:如果thread_id动态生成,新会话就是全新的,不会加载旧消息
关键理解:
- 动态生成thread_id后,每个新会话都是独立的
- 不会加载之前会话的消息
- 这是正常且正确的行为
💾 第二部分:长期记忆的存储和检索实现
存储用户偏好
步骤1:提取用户偏好信息
是什么:
- 从用户的输入中提取偏好信息
- 可以使用AI模型自动提取
- 也可以手动提取
代码示例:
python
# 从用户输入中提取偏好
user_input = "我要预订酒店,需要有窗户,有WIFI"
# 提取偏好信息
preferences = {
"住宿偏好": "有窗户,有WIFI",
"用户姓名": "KEVIN"
}
关键点:
- 偏好信息可以是结构化的数据
- 可以包含多个字段
- 需要根据业务需求设计数据结构
步骤2:存储到长期记忆
是什么:
- 使用
store.put()方法存储用户偏好 - 基于
user_id存储,不是thread_id - 存储到数据库的
store表中
代码示例:
python
from langgraph.checkpoint.postgres import PostgresStore
# 创建store实例
store = PostgresStore.from_conn_string(connection_string)
# 存储用户偏好
store.put(
user_id="1", # 用户ID,不是thread_id
data={
"住宿偏好": "有窗户,有WIFI"
}
)
数据库变化:
- 执行后,数据库中的
store表会新增记录 - 每条记录对应一个偏好项
- 可以通过
user_id查询
关键点:
- ✅ 使用
user_id,不是thread_id - ✅ 可以存储多条记录
- ✅ 每条记录都是独立的
检索用户偏好
步骤1:从长期记忆中检索
是什么:
- 使用
store.search()方法检索用户偏好 - 根据
user_id检索 - 返回该用户的所有偏好信息
代码示例:
python
# 检索用户偏好
preferences = store.search(
user_id="1" # 根据用户ID检索
)
# 返回结果可能是:
# [
# {"住宿偏好": "有窗户,有WIFI"},
# {"用户姓名": "KEVIN"}
# ]
关键点:
- 检索是基于
user_id的 - 返回的是该用户的所有偏好
- 可能返回多条记录
步骤2:应用偏好到当前任务
是什么:
- 将检索到的偏好应用到当前任务中
- 在AI生成回复时,包含偏好信息
- 让AI知道用户的个性化需求
实际流程:
用户:"帮我预订酒店"
↓
检索长期记忆(store.search)
↓
找到偏好:"有窗户,有WIFI"
↓
将偏好信息传递给AI
↓
AI生成回复:"已成功为您预订了汉庭酒店,并确保房间有窗户和WIFI"
🔄 第三部分:跨会话使用长期记忆
实际演示场景
场景设置
会话1(thread_id = 4):
- 用户:"我要预订酒店,需要有窗户,有WIFI"
- 系统提取偏好并存储到长期记忆
- 数据库中的
store表新增2条记录
会话2(thread_id = 5,新会话):
- 用户:"帮我预订酒店"
- 系统从长期记忆中检索用户偏好
- 检索到:"有窗户,有WIFI"
- AI回复:"已成功为您预订了汉庭酒店,并确保房间有窗户和WIFI"
关键验证点
验证1:thread_id不同,但能检索到偏好
- ✅ thread_id从4变成5(新会话)
- ✅ 但user_id没变(还是1)
- ✅ 仍然能检索到之前存储的偏好
验证2:长期记忆的跨会话特性
- ✅ 即使关闭了会话1
- ✅ 开启新的会话2
- ✅ 偏好信息仍然存在
验证3:让AI更懂你
- ✅ 不管什么时候预订酒店
- ✅ 都会自动应用用户的偏好
- ✅ 实现了个性化的用户体验
🎯 第四部分:架构决策的关键点
决策1:thread_id vs user_id
thread_id(线程ID):
- 用于短期记忆(Checkpointer)
- 每个会话都有独立的thread_id
- 会话关闭后,可以丢弃
user_id(用户ID):
- 用于长期记忆(Store)
- 同一个用户的所有会话共享同一个user_id
- 跨会话持久保存
关键理解:
- 短期记忆 = thread_id级别
- 长期记忆 = user_id级别
- 两者配合使用,实现完整的记忆系统
决策2:存储时机
什么时候存储长期记忆?
- ✅ 用户明确表达偏好时
- ✅ AI识别到用户偏好时
- ✅ 用户确认设置时
什么时候检索长期记忆?
- ✅ 每次对话开始时
- ✅ 需要个性化服务时
- ✅ 执行相关任务前
关键点:
- 存储和检索的时机很重要
- 需要根据业务场景设计
- 避免过度检索,影响性能
决策3:数据结构设计
用户偏好应该存储什么?
- 个人基本信息(姓名、联系方式等)
- 业务偏好(住宿偏好、出行偏好等)
- 历史行为(浏览记录、购买记录等)
数据结构示例:
python
{
"user_id": "1",
"preferences": {
"住宿偏好": "有窗户,有WIFI",
"出行偏好": "商务舱",
"饮食偏好": "素食"
},
"metadata": {
"created_at": "2024-01-01",
"updated_at": "2024-01-15"
}
}
关键点:
- 数据结构要灵活
- 支持扩展
- 便于检索和更新
💡 关键概念总结
| 概念 | 简单理解 |
|---|---|
| thread_id动态生成 | 每次新建会话时生成新的唯一ID,不能写死 |
| user_id | 用户标识,用于长期记忆的区分,跨会话使用 |
| store.put() | 存储用户偏好到长期记忆的方法 |
| store.search() | 从长期记忆中检索用户偏好的方法 |
| 跨会话特性 | 长期记忆可以在不同会话之间共享 |
| 个性化服务 | 通过长期记忆实现"让AI更懂你"的目标 |
❓ 思考题
-
为什么生产环境中thread_id不能写死?
- 答:因为每个用户都应该有独立的会话。如果写死thread_id,所有用户会共享同一个会话,导致消息混乱。thread_id应该像session_id一样,每次新建会话时动态生成。
-
如何实现跨会话的用户偏好?
- 答:使用长期记忆(Store),将用户偏好存储到数据库中,基于user_id而不是thread_id。这样无论用户开启多少个新会话,都能通过user_id检索到之前存储的偏好信息。
-
store.put()和store.search()的区别是什么?
- 答:store.put()用于存储用户偏好到长期记忆,需要提供user_id和数据;store.search()用于从长期记忆中检索用户偏好,根据user_id检索,返回该用户的所有偏好信息。
-
短期记忆和长期记忆在标识上的区别?
- 答:短期记忆使用thread_id(线程ID)区分不同会话,每个会话都有独立的thread_id;长期记忆使用user_id(用户ID)区分不同用户,同一个用户的所有会话共享同一个user_id。
-
如何让AI更懂用户?
- 答:通过长期记忆存储用户的偏好和历史行为,在每次对话时检索这些信息,让AI能够根据用户的个性化需求提供服务,实现"让AI更懂你"的目标。
📌 本节课重点回顾
✅ 生产环境注意: thread_id必须动态生成,不能写死,每个会话都应该有独立的标识
✅ 长期记忆存储: 使用store.put()存储用户偏好,基于user_id,可以存储多条记录
✅ 长期记忆检索: 使用store.search()检索用户偏好,根据user_id检索,返回该用户的所有偏好
✅ 跨会话特性: 长期记忆可以在不同会话之间共享,实现个性化的用户体验
✅ 架构决策: thread_id用于短期记忆,user_id用于长期记忆,两者配合使用
笔记整理时间:2024年
建议:理解thread_id和user_id的区别是构建生产级AI系统的关键,需要通过实际代码演示加深理解