目录
-
[SQLite 持久化:SqlitePersistence](#SQLite 持久化:SqlitePersistence)
-
[Agent 多轮对话持久化:AgentPersistence](#Agent 多轮对话持久化:AgentPersistence)
-
[get_state 与 get_state_history 详解](#get_state 与 get_state_history 详解)
1. 什么是状态持久化?
LangGraph 默认情况下,每次 invoke() 执行完毕后,State 就销毁了。但很多场景需要跨调用保留状态:
| 场景 | 需求 |
|---|---|
| 多轮对话 | AI 记住上一轮聊了什么 |
| 工作流断点续跑 | 某步骤失败后,从失败点继续 |
| 状态审计 | 查看每一步的中间状态 |
| 回滚/分支 | 回到历史状态重新执行 |
LangGraph 通过 Checkpointer(检查点保存器) 实现状态持久化。核心 API:
# 编译时指定 checkpointer
app = graph.compile(checkpointer=InMemorySaver())
# 配置 thread_id(会话 ID)
config = {"configurable": {"thread_id": "user-001"}}
# 同 thread_id 多次 invoke,状态自动恢复
result1 = app.invoke({"messages": []}, config) # 第1次
result2 = app.invoke({"messages": []}, config) # 第2次(从第1次结果继续)
Checkpoint 的工作原理
第1次 invoke()
│
├── 创建 checkpoint_1(开始前状态)
├── 执行节点,创建 checkpoint_2(中间状态)
├── 执行完成,创建 checkpoint_3(最终状态)
│
▼ 持久化存储(内存 / SQLite / Postgres)
第2次 invoke()(同 thread_id)
│
├── 从存储加载 checkpoint_3 作为初始状态
├── 创建 checkpoint_4(开始前状态)
└── ...
2. 持久化方案对比
| 方案 | 后端 | 数据生命周期 | 安装要求 | 适用场景 |
|---|---|---|---|---|
| InMemorySaver | 内存 | 程序关闭即丢失 | 内置,无需安装 | 开发调试、单次 session |
| SqliteSaver | SQLite 文件 | 持久化到文件 | pip install langgraph-checkpoint-sqlite |
本地实验、单机部署 |
| PostgresSaver | PostgreSQL | 持久化到数据库 | pip install langgraph-checkpoint-postgres |
生产环境、多实例共享 |
3. 内存持久化:MemoryPersistence
3.1 文件:MemoryPersistence.py
三步工作流 step_one → step_two → step_three,配合 InMemorySaver 演示状态的保存和读取。
3.2 核心代码
from langgraph.checkpoint.memory import InMemorySaver
# 编译图时传入 checkpointer
app = graph.compile(checkpointer=InMemorySaver())
# 每个 thread_id 独立存储状态
config = {"configurable": {"thread_id": "user_13811112222"}}
# 第1次执行
result = app.invoke({"messages": ["开始执行"], "step_count": 0}, config)
3.3 测试输出
首次执行结果:
{'messages': ['开始执行', '执行了步骤 1', '执行了步骤 2', '执行了步骤 3'],
'step_count': 3}
检查存储的状态:
{'messages': ['开始执行', '执行了步骤 1', '执行了步骤 2', '执行了步骤 3'],
'step_count': 3}
执行历史(从最新到最旧,共 6 个 checkpoint):
checkpoint_1: {'messages': ['开始执行', ...'步骤 1', '步骤 2', '步骤 3']} ← 最终
checkpoint_2: {'messages': ['开始执行', ...'步骤 1', '步骤 2']} ← step_two 后
checkpoint_3: {'messages': ['开始执行', ...'步骤 1']} ← step_one 后
checkpoint_4: {'messages': ['开始执行']} ← 初始
checkpoint_5: {'messages': []} ← 系统内部
3.4 关键行为
持久化的核心是 thread_id:
-
同一个
thread_id多次invoke()→ 状态自动叠加(相当于"继续对话") -
不同
thread_id→ 完全隔离
恢复执行:
# 如果图已完成,invoke(None) 直接返回已有结果(不重新执行)
result2 = app.invoke(None, config)
4. SQLite 持久化:SqlitePersistence
4.1 文件:SqlitePersistence.py
与内存持久化功能相同,但数据存储在 SQLite 文件中,程序重启后数据不丢失。
4.2 安装依赖
pip install langgraph-checkpoint-sqlite
4.3 核心代码
import sqlite3
from langgraph.checkpoint.sqlite import SqliteSaver
# 1. 建立 SQLite 连接
conn = sqlite3.connect(
database="D:/hermes-project/project/sqlite_data.db",
check_same_thread=False
)
# 2. 创建 SqliteSaver
sqliteDB = SqliteSaver(conn=conn)
# 3. 编译图时传入
graph = builder.compile(checkpointer=sqliteDB)
# 4. 执行(同 thread_id 自动持久化)
config = {"configurable": {"thread_id": "user-001"}}
result = graph.invoke({"messages": []}, config)
4.4 数据库结构
执行后 SQLite 文件中有两个核心表:
checkpoints 表: 每个状态变更的完整快照
| thread_id | checkpoint_id | parent_checkpoint_id | checkpoint (BLOB) |
|---|---|---|---|
| user-001 | uuid-1 | None | 初始状态(空 messages) |
| user-001 | uuid-2 | uuid-1 | 开始执行 |
| user-001 | uuid-3 | uuid-2 | node_1 执行后(['abc','def']) |
writes 表: 每个节点的写入明细
| thread_id | checkpoint_id | channel | value |
|---|---|---|---|
| user-001 | uuid-1 | messages | [](初始) |
| user-001 | uuid-3 | messages | ['abc','def'] |
4.5 连续执行的 Checkpoint 链
第1次执行: invoke({messages:[]})
checkpoint_1 (开始, messages=[])
↓
checkpoint_2 (node_1运行中)
↓
checkpoint_3 (完成, messages=['abc','def'])
第2次执行: invoke({messages:[]}) ← 从 checkpoint_3 继续
checkpoint_4 (开始, 恢复 ['abc','def'])
↓
checkpoint_5 (node_1运行中)
↓
checkpoint_6 (完成, ['abc','def','abc','def'])
每次 invoke() 生成 3 个 checkpoint (开始→中间→完成),通过 parent_checkpoint_id 串联。
4.6 查看 SQLite 数据库
import sqlite3
conn = sqlite3.connect("D:/hermes-project/project/sqlite_data.db")
# 列出所有表
cur = conn.execute("SELECT name FROM sqlite_master WHERE type='table'")
for t in cur.fetchall():
print(t[0])
# 查看 checkpoints
rows = conn.execute(
"SELECT thread_id, checkpoint_id, parent_checkpoint_id "
"FROM checkpoints ORDER BY checkpoint_id"
).fetchall()
5. Agent 多轮对话持久化:AgentPersistence
5.1 文件:AgentPersistence.py
将 Checkpoint 与 LangChain 的 create_agent() 高级 API 结合,实现带记忆的多轮对话。
5.2 核心代码
from langchain.agents import create_agent
from langgraph.checkpoint.memory import InMemorySaver
llm = init_chat_model(model="qwen-plus", ...)
checkpointer = InMemorySaver()
agent = create_agent(model=llm, checkpointer=checkpointer)
config = {"configurable": {"thread_id": "user-001"}}
# 第一轮:自我介绍
msg1 = agent.invoke(
{"messages": [("user", "你好,我叫张三,喜欢足球")]},
config
)
# 第二轮:AI 记得上轮信息
msg2 = agent.invoke(
{"messages": [("user", "我叫什么?我喜欢做什么?")]},
config
)
# AI 回复:你叫张三,喜欢足球 ⚽
5.3 测试输出
AI: 你好张三!很高兴认识你,同为球迷——足球的魅力在于团队精神与激情活动!
AI: 你叫张三,喜欢足球!
关键: 第二轮 AI 准确回答了"张三"和"足球"------这是 InMemorySaver 在 agent 层面自动持久化了对话历史。
5.4 AgentPersistence 的技术要点
| 要点 | 说明 |
|---|---|
create_agent 中的 checkpointer |
LangChain 1.2+ 的 Agent 高级 API 原生支持 checkpointer |
| 消息自动累加 | messages 字段使用 add_messages reducer,新消息追加到历史 |
| thread_id 隔离 | 不同 thread_id 的对话历史互不干扰 |
| 可替换后端 | InMemorySaver → SqliteSaver/PostgresSaver 无需改业务代码 |
6. get_state 与 get_state_history 详解
6.1 get_state:获取当前状态
# 获取指定 thread 的当前状态
saved_state = app.get_state(config)
print(saved_state.values) # 状态字典
print(saved_state.next) # 下一步要执行的节点(空=已完成)
输出:
{'messages': ['开始执行', '步骤1', '步骤2', '步骤3'], 'step_count': 3}
() ← 空元组表示图已执行完毕
6.2 get_state_history:获取完整执行历史
# 获取指定 thread 的所有历史 checkpoint
history = app.get_state_history(config)
for checkpoint in history:
print(checkpoint.values)
print(checkpoint.next)
print(checkpoint.config['configurable']['checkpoint_id'])
print("---")
输出按从最新到最旧排列:
# 最新(最终状态)
当前状态: {'messages': ['开始执行', '步骤1', '步骤2', '步骤3'], 'step_count': 3}
---
当前状态: {'messages': ['开始执行', '步骤1', '步骤2'], 'step_count': 2}
---
当前状态: {'messages': ['开始执行', '步骤1'], 'step_count': 1}
---
当前状态: {'messages': ['开始执行'], 'step_count': 0}
---
当前状态: {'messages': [], 'step_count': 0} ← 初始状态
6.3 checkpoint 的返回结构
class StateSnapshot:
values: dict # 该时刻的完整 State
next: tuple # 下一步要执行的节点(空=已完成)
config: dict # 包含 checkpoint_id 等配置
metadata: dict # source, step 等信息
created_at: datetime # 创建时间
parent_config: dict # 上一个 checkpoint 的配置
tasks: tuple # 待执行的任务
7. 总结对比
7.1 三个文件的定位
| 文件 | 后端 | 用途 | 核心 API |
|---|---|---|---|
| MemoryPersistence.py | InMemorySaver | 基础演示:状态保存、历史查看 | compile(checkpointer=), get_state(), get_state_history() |
| SqlitePersistence.py | SqliteSaver | 文件级持久化:程序重启不丢失 | sqlite3.connect(), SqliteSaver(conn) |
| AgentPersistence.py | InMemorySaver | Agent 多轮对话记忆 | create_agent(checkpointer=), 多次 invoke() |
7.2 核心 API 速查
| 操作 | API |
|---|---|
| 内存持久化 | compile(checkpointer=InMemorySaver()) |
| SQLite持久化 | compile(checkpointer=SqliteSaver(conn)) |
| 配置线程 | config = {"configurable": {"thread_id": "xxx"}} |
| 获取当前状态 | app.get_state(config) |
| 获取历史状态 | app.get_state_history(config) |
| 更新状态 | app.update_state(config, values={...}) |
| Agent 持久化 | create_agent(model=llm, checkpointer=...) |
7.3 学习路线
1. MemoryPersistence.py → 理解 checkpoint 是什么、get_state 怎么用
│
▼
2. SqlitePersistence.py → 数据持久化到文件,查看数据库结构
│
▼
3. AgentPersistence.py → 实战:多轮对话 AI 助手