前三篇我们已经解决了:
- LangGraph 为什么需要 Graph
- State 如何在 Node 之间流转
- Conditional Edge 如何控制动态流程
但是还有一个问题:
一次 Graph 执行结束之后,State 去哪里了?
这就是 LangGraph 的 Memory。
1. Agent 为什么需要记忆?
先看普通函数:
javascript
function chat(input) {
return "你好";
}
每次调用:
第一次:
用户:我叫小明
第二次:
用户:我叫什么?
函数本身不知道第一次发生了什么。
因为两次调用之间没有共享数据。
但是聊天 Agent:
用户:
我叫小明
Agent:
好的,我记住了
用户:
我叫什么?
Agent:
你叫小明
说明 Agent 必须保存一些信息:
历史消息
用户信息
任务状态
工具结果
这些数据就是 State。
2. 最简单的方案:自己维护对象
很多人第一反应:
ini
const memory = {};
例如:
arduino
const sessions = {
"user1": {
name: "小明"
}
};
看起来没问题。
实际上这就是一个简单的 Memory。
但是随着 Agent 复杂,会出现问题。
问题一:多用户隔离
如果只有一个用户:
ini
let state = {};
没有问题。
但是:
css
用户A:
我的名字是小明
用户B:
我的名字是小红
需要:
css
用户A
State A
用户B
State B
而不是:
所有用户
共享一个 State
所以需要一个唯一标识:
thread_id
表示:
这一份 State 属于哪个会话。
3. thread_id 是什么?
thread 可以理解成:
一条独立的对话线程。
例如:
vbnet
thread_id: "xiaoming-chat"
对应:
css
{
messages:[
"我叫小明"
]
}
另一个:
vbnet
thread_id:"xiaohong-chat"
对应:
css
{
messages:[
"我叫小红"
]
}
两个会话互不影响。
4. LangGraph 如何保存 State?
LangGraph 提供:
Checkpointer
它负责保存 Graph 执行过程中的 State。
结构:
thread_id
↓
State
类似:
css
{
"user-a": {
messages:[]
},
"user-b": {
messages:[]
}
}
5. MemorySaver 是什么?
LangGraph 提供了一个简单实现:
ini
const checkpointer = new MemorySaver();
MemorySaver:
就是:
存储在内存中的 Checkpointer。
例如:
css
MemorySaver
{
"xiaoming": {
visitCount:3
},
"xiaohong": {
visitCount:5
}
}
注意:
MemorySaver 只是开发学习阶段使用。
因为它存在:
服务关闭
↓
数据消失
生产环境通常会使用:
- Redis
- PostgreSQL
- MongoDB
等持久化存储。
6. Checkpointer 如何参与 Graph?
之前:
ini
const app = graph.compile();
表示:
创建一个普通可执行 Graph。
加入:
ini
const app = graph.compile({
checkpointer
});
表示:
这个 Graph 执行时,需要保存状态。
执行时:
arduino
const config = {
configurable:{
thread_id:"user-1"
}
};
await app.invoke(
{},
config
);
这里:
thread_id
告诉 LangGraph:
使用 user-1 这份状态。
7. 一个访问次数 Demo
State:
javascript
const StateAnnotation = Annotation.Root({
visitCount: Annotation({
reducer:(prev,next)=>next,
default:()=>0
})
});
节点:
javascript
function recordVisit(state){
return {
visitCount:state.visitCount + 1
};
}
流程:
sql
START
↓
recordVisit
↓
END
第一次:
css
await app.invoke(
{},
{
configurable:{
thread_id:"xiaoming"
}
}
);
执行:
0
↓
1
保存:
makefile
xiaoming
visitCount:1
第二次:
还是:
vbnet
thread_id:"xiaoming"
LangGraph 会找到之前状态:
makefile
visitCount:1
继续执行:
1
↓
2
8. Memory 和 State 的关系
这里容易混淆:
State:
当前 Graph 执行中的数据。
Memory:
保存这些 State 的机制。
关系:
Graph运行
↓
产生State
↓
Checkpointer保存
↓
下一次恢复State
9. LangGraph Memory 的完整模型
最终:
markdown
thread_id
↓
Checkpointer
↓
State
↓
Node → Edge → Node
总结
LangGraph 的 Memory 本质上解决的是:
如何让一次 Graph 执行结束后的 State,在下一次执行时继续存在。
核心概念:
| 概念 | 作用 |
|---|---|
| State | 保存 Agent 当前数据 |
| thread_id | 区分不同会话 |
| Checkpointer | 保存和恢复 State |
| MemorySaver | 内存版 Checkpointer |
一句话:
Checkpointer 是 LangGraph 的状态保存机制,通过 thread_id 管理不同会话的 State,让 Agent 可以拥有连续的上下文。