第7课:管理长期记忆的关键架构决策 - 学习笔记_7

第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更懂你"的目标

❓ 思考题

  1. 为什么生产环境中thread_id不能写死?

    • 答:因为每个用户都应该有独立的会话。如果写死thread_id,所有用户会共享同一个会话,导致消息混乱。thread_id应该像session_id一样,每次新建会话时动态生成。
  2. 如何实现跨会话的用户偏好?

    • 答:使用长期记忆(Store),将用户偏好存储到数据库中,基于user_id而不是thread_id。这样无论用户开启多少个新会话,都能通过user_id检索到之前存储的偏好信息。
  3. store.put()和store.search()的区别是什么?

    • 答:store.put()用于存储用户偏好到长期记忆,需要提供user_id和数据;store.search()用于从长期记忆中检索用户偏好,根据user_id检索,返回该用户的所有偏好信息。
  4. 短期记忆和长期记忆在标识上的区别?

    • 答:短期记忆使用thread_id(线程ID)区分不同会话,每个会话都有独立的thread_id;长期记忆使用user_id(用户ID)区分不同用户,同一个用户的所有会话共享同一个user_id。
  5. 如何让AI更懂用户?

    • 答:通过长期记忆存储用户的偏好和历史行为,在每次对话时检索这些信息,让AI能够根据用户的个性化需求提供服务,实现"让AI更懂你"的目标。

📌 本节课重点回顾

生产环境注意: thread_id必须动态生成,不能写死,每个会话都应该有独立的标识

长期记忆存储: 使用store.put()存储用户偏好,基于user_id,可以存储多条记录

长期记忆检索: 使用store.search()检索用户偏好,根据user_id检索,返回该用户的所有偏好

跨会话特性: 长期记忆可以在不同会话之间共享,实现个性化的用户体验

架构决策: thread_id用于短期记忆,user_id用于长期记忆,两者配合使用


笔记整理时间:2024年
建议:理解thread_id和user_id的区别是构建生产级AI系统的关键,需要通过实际代码演示加深理解

相关推荐
码智社34 分钟前
AES加密原理详解及Java实现加解密实战
java·开发语言
克里斯蒂亚诺更新42 分钟前
ruoyi角色权限的对应关系
笔记
萧瑟余晖2 小时前
JDK 26 新特性详解
java·开发语言
马优晨2 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
a1117763 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
我的xiaodoujiao4 小时前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest
维天说5 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json
破碎的南瓜5 小时前
sqli--sql注入过关笔记(1,2,3,4,5,9)
数据库·笔记·sql
Zane19945 小时前
并发 vs 并行:别再傻傻分不清了,一文讲透 Java 并发编程的第一课
java·后端
你想知道什么?5 小时前
线性回归-学习笔记
笔记·学习·线性回归