短期记忆和长期记忆都存 MySQL

两者都存 MySQL 且都跨重启不丢,但它们的 语义层级 完全不同:

短期记忆 (Checkpointer) 绑定 thread_id,存的是一次会话的完整消息流水账------每轮对话的 HumanMessage、AIMessage、ToolMessage 全部 append。换了 thread_id 就是全新的会话,对之前的事一无所知。

长期记忆 (Store) 绑定 namespace(通常是 user_id),存的是跨会话的结构化知识点------用户的偏好、档案、历史行为。同一个用户在不同 thread 里都能访问到。

Thread 1 存偏好 → Thread 2(新 thread_id)仍然能查出来

result3 = memory_agent.invoke(

{"messages": {"role": "user", "content": "我喜欢什么颜色?"}},

config={"configurable": {"thread_id": "thread2"}}, # ← 不同线程

context=UserContext(user_id="current_user") # ← 相同用户

)

短期记忆保证你重启后同一场对话能继续聊下去;长期记忆保证你换一场对话(不同 thread_id)还能认出这个人是谁。

State(状态)--- 数据的"载体"

short_memory/04_custom_state.py:34-37

class CustomState(AgentState): # 继承内置 AgentState

user_id: str # ← 你定义的业务字段

hobby: str

other_info: dict

messages 字段是 AgentState 自带的,不用声明

State 是一个内存中的字典容器,包含两部分:

  • messages(AgentState 内置):HumanMessage、AIMessage、ToolMessage 的完整列表

  • 自定义字段:你通过 state_schema 添加的任何业务数据

State 本身不负责持久化,它只是数据格式的定义。


短期记忆(Checkpointer)--- State 的"存档机制"

Checkpointer 做的事:每一次 Super-Step 结束后,把整个 State 快照保存到存储。

Step 1: 用户说"我叫张三" → State{messages:HumanMsg, AIMsg} → 📸 Checkpointer 拍照存 MySQL

Step 2: 用户说"北京天气" → State{messages:..., HumanMsg, AIMsg, ToolMsg, AIMsg} → 📸 再拍

Step 3: 用户说"我叫什么" → Agent 从 MySQL 恢复 State,看到 Step1 里说过"我叫张三"

关键性质:绑死 thread_id。同一个 thread 内,State 会累积增长(消息越来越长)。换 thread_id → 读不到任何之前的 State。

short_memory/03_short_memory_indb.py:42-49

config = {"configurable":{"thread_id":"session001"}} # ← 钥匙

resp1 = agent.invoke({"messages":{"role":"user","content":"你好,我叫张三"}}, config=config)

resp2 = agent.invoke({"messages":{"role":"user","content":"你知道我的信息吗?"}}, config=config)

第二轮能记住"张三",因为同一个 thread_id 下 Checkpointer 把 State 恢复了


长期记忆(Store)--- 独立于会话的"知识库"

Store 不关心你当前在哪个 thread、聊到哪一步。它用 namespace + key → value 组织数据:

long_memory/04_modify_long_memory_intool.py:43-55

namespace = (user_id, "preferences") # namespace 标识"谁的什么类型的数据"

memory_id = str(uuid.uuid4()) # key 是每条记忆的唯一 ID

runtime.store.put(namespace, memory_id, {"category": "color", "preference": "蓝色"})

同一用户在 thread1 存的偏好,切换到 thread2 照样能查到:

Thread 1 存 → Thread 2 查,跨 session 共享

result3 = memory_agent.invoke(

...,

config={"configurable": {"thread_id": "thread2"}}, # ← 不同线程

context=UserContext(user_id="current_user") # ← 相同用户,同一 namespace

)


三者关系总结

┌─────────────────────────────────┐

│ State (数据容器) │

│ messages + user_id + hobby ... │

└──────────┬──────────────────────┘

│

┌────────────────┼────────────────┐

▼ ▼ ▼

┌─────────────────┐ ┌─────────────┐ ┌─────────────────┐

│ 每次 step 后 │ │ 工具中读取 │ │ 中间件中读写 │

│ Checkpointer │ │ runtime.state│ │ state"xxx" │

│ 自动快照 State │ │ Command 更新 │ │ return dict │

└────────┬────────┘ └──────────────┘ └─────────────────┘

│

▼

┌─────────────────┐ ┌─────────────────────────┐

│ 短期记忆 │ │ 长期记忆 (Store) │

│ = State 的 │ │ 独立于图执行的知识库 │

│ 持久化快照 │ │ namespace + key → value │

│ 绑 thread_id │ │ 跨 thread、跨 session │

└─────────────────┘ └─────────────────────────┘

相关推荐
rannn_1111 分钟前
【Java面试题】高频面试题1|Java 后端、MySQL、Redis 与 RAG 面试整理
java·jvm·数据库·后端·面试
写后端的胖头鱼4 分钟前
一文详解Spring 事务失效场景
java·spring·事务·transactional·事务传播机制
Q26433650239 分钟前
【有源码】基于Spring Boot和Vue的在线考试与交流系统-教育信息化背景下在线考试与交流一体化平台
java·vue.js·spring boot·mysql·spring·毕业设计·课程设计
Chen_harmony11 分钟前
一、C++入门基础
开发语言·c++
事圆则缓12 分钟前
Kotlin Flow、StateFlow、SharedFlow 全解析:冷流、热流与 Android 状态管理
android·kotlin·php
学逆向的15 分钟前
远程线程注入
开发语言·jvm·网络安全·win32
应用市场18 分钟前
把旧 Pixel 变成相册备份中转站(上):Mac 到安卓的照片传输工具设计——流式上传、sha256 校验、adb forward 与 Bonjour
android·macos·adb·kotlin·swift
Mikko719 分钟前
JVM 线上排查实战(七):jps 看不到进程、jstack 报不允许的操作怎么办?attach 失败的六种情况实测
java·运维·jvm·后端
jianjinwssy20 分钟前
MyBatis-Plus 从入门到实战:常用功能与核心原理
java·mybatis
会编程的吕洞宾28 分钟前
Spring AI 2.0 会话记忆实战,让 AI 助手记住每一次对话
java·人工智能·spring