1. 什么是持久化与记忆?
┌─────────────────────────────────────────────────────────────────────┐
│ LangGraph 持久化与记忆系统 │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 记忆层次结构 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ 短期记忆 │ │ 长期记忆 │ │
│ │ (Short-Term) │ │ (Long-Term) │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ Checkpoint机制 │ │ BaseStore机制 │ │
│ │ (检查点) │ │ (存储) │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ Thread级别 │ │ Namespace级别 │ │
│ │ (会话范围) │ │ (全局范围) │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ MemorySaver │ │ InMemoryStore │ │
│ │ SqliteSaver │ │ RedisStore │ │
│ │ PostgresSaver │ │ PostgreSQLStore │ │
│ │ RedisSaver │ │ ... │ │
│ └─────────────────────┘ └─────────────────────┘ │
│ │
│ 核心概念: │
│ • 短期记忆:会话级别的状态保存,支持断点续传和时间旅行 │
│ • 长期记忆:跨会话的知识存储,支持用户画像和个性化服务 │
└─────────────────────────────────────────────────────────────────────┘
在LangGraph中,持久化 和记忆是两个密切相关但又有所区别的概念:
1.1 持久化(Persistence)
持久化是指将AI工作流的运行状态保存到存储介质中,使得状态不会因为程序重启或会话结束而丢失。持久化是实现记忆功能的底层技术基础。
核心价值:
- 容错恢复:工作流执行失败后可以从最近的检查点继续执行
- 状态保持:跨请求、跨会话保持工作流状态
- 时间旅行:可以回溯到历史状态重新执行
1.2 记忆(Memory)
记忆是指AI系统能够记住过去的信息并在未来使用的能力。记忆分为两个层次:
短期记忆:会话级别的记忆
- 范围:单个对话线程(Thread)内
- 内容:对话历史、中间状态、临时变量
- 生命周期:会话结束即失效(除非持久化)
- 实现方式:Checkpoint机制
长期记忆:跨会话的记忆
- 范围:全局范围,跨多个对话线程
- 内容:用户偏好、知识库、历史记录
- 生命周期:长期保存,可随时检索
- 实现方式:BaseStore机制
2. 短期记忆:Checkpoint机制详解
2.1 Checkpoint基本概念
┌─────────────────────────────────────────────────────────────────────┐
│ Checkpoint 工作原理 │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 工作流执行过程 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ [Start] ──▶ [Node A] ──▶ [Node B] ──▶ [Node C] ──▶ [End] │
│ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ │
│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │ CP0 │ │ CP1 │ │ CP2 │ │ CP3 │ │ CP4 │ │
│ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │
│ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Checkpoint 存储后端 │ │
│ │ ┌───────────────────────────────────────────────┐ │ │
│ │ │ Thread ID: "user_123" │ │ │
│ │ │ ┌─────────────────────────────────────────┐ │ │ │
│ │ │ │ CP0: {messages: [], step: "start"} │ │ │ │
│ │ │ │ CP1: {messages: ["Hi"], step: "greet"} │ │ │ │
│ │ │ │ CP2: {messages: [...], step: "process"} │ │ │ │
│ │ │ └─────────────────────────────────────────┘ │ │ │
│ │ └───────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ CP = Checkpoint (检查点) │
│ 每个节点执行后自动保存状态快照 │
└─────────────────────────────────────────────────────────────────────┘
2.1.1 什么是Checkpoint?
Checkpoint(检查点)是工作流在执行过程中某个时间点的完整状态快照。想象一下游戏中的存档功能:
- CP0:游戏刚开始,角色在出生点
- CP1:完成第一个任务后
- CP2:击败第一个Boss后
- CP3:获得关键道具后
每次执行一个节点后,LangGraph会自动创建一个Checkpoint,记录当前的完整状态。
2.1.2 Checkpoint的核心组成
每个Checkpoint包含以下关键信息:
-
配置信息(Config)
- Thread ID:标识这个Checkpoint属于哪个会话
- 版本号:Checkpoint的版本标识
-
元数据(Metadata)
- 创建时间戳
- 执行节点名称
- 执行耗时
- 父Checkpoint引用
-
状态值(Values)
- 完整的State对象内容
- 所有变量的当前值
- 消息历史记录
-
下一个节点(Next)
- 记录接下来要执行的节点
- 用于恢复执行时的定位
2.2 Thread(线程)概念
┌─────────────────────────────────────────────────────────────────────┐
│ Thread 隔离机制 │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 用户会话管理 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ User A │ │ User B │ │ User C │ │
│ │ Thread_1 │ │ Thread_2 │ │ Thread_3 │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Checkpoint 存储后端 │ │
│ │ ┌───────────────────────────────────────────────┐ │ │
│ │ │ Thread_1: │ │ │
│ │ │ ├─ CP0: {user: "A", messages: [...]} │ │ │
│ │ │ ├─ CP1: {user: "A", messages: [...]} │ │ │
│ │ │ └─ CP2: {user: "A", messages: [...]} │ │ │
│ │ │ │ │ │
│ │ │ Thread_2: │ │ │
│ │ │ ├─ CP0: {user: "B", messages: [...]} │ │ │
│ │ │ └─ CP1: {user: "B", messages: [...]} │ │ │
│ │ │ │ │ │
│ │ │ Thread_3: │ │ │
│ │ │ └─ CP0: {user: "C", messages: [...]} │ │ │
│ │ └───────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ 核心特性: │
│ • 每个Thread代表一个独立的会话上下文 │
│ • Thread之间完全隔离,互不干扰 │
│ • 通过Thread ID唯一标识每个会话 │
└─────────────────────────────────────────────────────────────────────┘
2.2.1 Thread的作用
Thread(线程)是LangGraph中用于隔离不同会话的核心概念。它类似于数据库中的会话(Session):
关键特性:
- 隔离性:每个Thread有独立的状态空间,互不干扰
- 唯一性:通过Thread ID唯一标识
- 持久性:Thread的状态可以跨请求保持
典型应用场景:
- Web应用:每个用户会话对应一个Thread
- 多租户系统:每个租户对应一个Thread
- 批处理任务:每个任务实例对应一个Thread
2.2.2 Thread ID的设计
Thread ID的设计非常灵活,可以是:
- 用户ID :
user_12345 - 会话ID :
session_abc123 - 任务ID :
task_workflow_001 - 组合键 :
user_123_task_456
最佳实践:
- 使用有意义的命名,便于调试和监控
- 保持一致性,避免重复或冲突
- 考虑可扩展性,支持未来的需求变化
2.3 Checkpoint存储后端
┌─────────────────────────────────────────────────────────────────────┐
│ Checkpoint 存储后端对比 │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 存储后端类型 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ MemorySaver │ │ SqliteSaver │ │ PostgresSaver │ │
│ │ (内存存储) │ │ (SQLite存储) │ │ (PostgreSQL存储)│ │
│ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 开发/测试 │ │ 本地开发 │ │ 生产环境 │ │
│ │ 快速原型 │ │ 小型应用 │ │ 高并发 │ │
│ │ 临时存储 │ │ 单机部署 │ │ 分布式系统 │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
│ │ │ │ │
│ │ │ │ │
│ ┌────────▼────────┐ ┌────────▼────────┐ ┌────────▼────────┐ │
│ │ 优点: │ │ 优点: │ │ 优点: │ │
│ │ • 极快 │ │ • 持久化 │ │ • 高性能 │ │
│ │ • 简单 │ │ • 单文件 │ │ • 高可用 │ │
│ │ • 无需配置 │ │ • 无需服务 │ │ • 事务支持 │ │
│ │ │ │ • 轻量级 │ │ • 扩展性强 │ │
│ │ 缺点: │ │ │ │ │ │
│ │ • 重启丢失 │ │ 缺点: │ │ 缺点: │ │
│ │ • 不持久 │ │ • 性能有限 │ │ • 配置复杂 │ │
│ │ • 单进程 │ │ • 并发能力弱 │ │ • 需要维护 │ │
│ └─────────────────┘ │ • 单机限制 │ └─────────────────┘ │
│ └─────────────────┘ │
│ │
│ ┌─────────────────┐ │
│ │ RedisSaver │ │
│ │ (Redis存储) │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ 高性能缓存 │ │
│ │ 分布式部署 │ │
│ │ 会话共享 │ │
│ └─────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ 优点: │ │
│ │ • 超高性能 │ │
│ │ • 内存存储 │ │
│ │ • 分布式支持 │ │
│ │ │ │
│ │ 缺点: │ │
│ │ • 需要持久化 │ │
│ │ • 数据可能丢失 │ │
│ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
2.3.1 MemorySaver(内存存储)
**适用场景:**开发调试、快速原型、测试环境
工作原理:
- 使用Python的
defaultdict在内存中存储Checkpoint - 数据结构简单,访问速度极快
- 无需外部依赖,开箱即用
限制:
- 进程重启丢失:Python进程结束,所有数据消失
- 单进程限制:无法在多进程间共享
- 内存限制:大量数据可能导致内存溢出
**类比:**就像游戏的临时存档,关机后就没了
2.3.2 SqliteSaver(SQLite存储)
**适用场景:**本地开发、小型应用、单机部署
工作原理:
- 使用SQLite数据库持久化存储Checkpoint
- 单文件数据库,无需独立服务
- 支持ACID事务,数据可靠性高
优势:
- 持久化:数据保存在磁盘,重启不丢失
- 轻量级:单文件,易于部署和备份
- 标准SQL:支持复杂查询和索引
限制:
- 并发能力有限:不适合高并发场景
- 单机限制:无法跨机器共享
**类比:**就像单机游戏的存档文件,可以随时读取
2.3.3 PostgresSaver(PostgreSQL存储)
**适用场景:**生产环境、高并发、分布式系统
工作原理:
- 使用PostgreSQL数据库存储Checkpoint
- 支持连接池、事务、复制等企业级特性
- 可以水平扩展,支持集群部署
优势:
- 高性能:优化的查询和索引
- 高可用:支持主从复制、故障转移
- 扩展性强:支持分区、分片等
- 企业级:完善的监控、备份、恢复机制
限制:
- 配置复杂:需要数据库管理和维护
- 成本较高:需要服务器资源
**类比:**就像云端游戏存档,多设备同步,永不丢失
2.3.4 RedisSaver(Redis存储)
**适用场景:**高性能缓存、分布式会话、实时应用
工作原理:
- 使用Redis内存数据库存储Checkpoint
- 支持持久化到磁盘(RDB/AOF)
- 分布式部署,支持集群
优势:
- 超高性能:内存操作,微秒级响应
- 分布式支持:多节点共享状态
- 丰富的数据结构:支持列表、集合、哈希等
限制:
- 内存成本:大量数据需要更多内存
- 持久化配置:需要正确配置RDB/AOF
**类比:**就像游戏的云存档+本地缓存,既快又可靠
3. 长期记忆:BaseStore机制详解
3.1 BaseStore基本概念
┌─────────────────────────────────────────────────────────────────────┐
│ BaseStore 架构 │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 命名空间层次结构 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Root Namespace (根命名空间) │ │
│ │ ┌───────────────────────────────────────────────────────┐ │ │
│ │ │ users/ (用户命名空间) │ │ │
│ │ │ ├─ user_123/ │ │ │
│ │ │ │ ├─ preferences: {theme: "dark", lang: "zh"} │ │ │
│ │ │ │ ├─ history: ["query1", "query2", ...] │ │ │
│ │ │ │ └─ profile: {name: "张三", age: 25} │ │ │
│ │ │ │ │ │ │
│ │ │ ├─ user_456/ │ │ │
│ │ │ │ ├─ preferences: {...} │ │ │
│ │ │ │ └─ history: [...] │ │ │
│ │ │ │ │ │ │
│ │ │ └─ user_789/ │ │ │
│ │ │ │ │ │
│ │ │ knowledge/ (知识库命名空间) │ │ │
│ │ │ ├─ domain_finance/ │ │ │
│ │ │ │ ├─ term_001: {name: "GDP", def: "..."} │ │ │
│ │ │ │ └─ term_002: {name: "CPI", def: "..."} │ │ │
│ │ │ │ │ │ │
│ │ │ └─ domain_tech/ │ │ │
│ │ │ ├─ term_001: {name: "AI", def: "..."} │ │ │
│ │ │ └─ term_002: {name: "Blockchain", def: "..."} │ │ │
│ │ │ │ │ │
│ │ │ system/ (系统命名空间) │ │ │
│ │ │ ├─ config: {...} │ │ │
│ │ │ └─ stats: {...} │ │ │
│ │ └───────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ 核心概念: │
│ • 层次化命名空间:类似文件系统的目录结构 │
│ • 键值存储:每个命名空间下存储键值对 │
│ • 跨Thread共享:所有Thread都可以访问 │
└─────────────────────────────────────────────────────────────────────┘
3.1.1 什么是BaseStore?
BaseStore是LangGraph提供的用于长期记忆的键值存储系统。它类似于一个分布式的、层次化的数据库,用于存储跨会话的持久化数据。
核心特性:
- 层次化命名空间:使用路径式的命名空间组织数据
- 键值存储:每个命名空间下存储键值对
- 跨Thread共享:所有会话都可以访问相同的数据
- 可插拔后端:支持多种存储实现
3.1.2 命名空间(Namespace)设计
命名空间是BaseStore的核心概念,它使用类似文件系统的路径来组织数据:
命名空间格式:
namespace = ["level1", "level2", "level3", ...]
设计原则:
- 层次清晰:从通用到具体,逐层细化
- 语义明确:命名空间名称要有明确的业务含义
- 可扩展性:预留扩展空间,支持未来需求
3.2 BaseStore存储后端
┌─────────────────────────────────────────────────────────────────────┐
│ BaseStore 存储后端对比 │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 存储实现类型 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │InMemoryStore │ │ RedisStore │ │PostgreSQLStore │ │
│ │ (内存存储) │ │ (Redis存储) │ │ (PostgreSQL存储)│ │
│ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ 开发/测试 │ │ 生产环境 │ │ 企业级应用 │ │
│ │ 快速原型 │ │ 高性能 │ │ 复杂查询 │ │
│ │ 临时存储 │ │ 分布式 │ │ 事务支持 │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
│ │ │ │ │
│ │ │ │ │
│ ┌────────▼────────┐ ┌────────▼────────┐ ┌────────▼────────┐ │
│ │ 优点: │ │ 优点: │ │ 优点: │ │
│ │ • 极快 │ │ • 高性能 │ │ • 强大查询 │ │
│ │ • 简单 │ │ • 内存存储 │ │ • 关系型 │ │
│ │ • 无需配置 │ │ • 分布式 │ │ • 事务支持 │ │
│ │ │ │ • 丰富数据结构 │ │ • 完整性 │ │
│ │ 缺点: │ │ │ │ │ │
│ │ • 重启丢失 │ │ 缺点: │ │ 缺点: │ │
│ │ • 不持久 │ │ • 需配置 │ │ • 配置复杂 │ │
│ │ • 单进程 │ │ • 成本 │ │ • 性能相对较低 │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
│ │
│ ┌─────────────────┐ │
│ │ DuckDBStore │ │
│ │ (DuckDB存储) │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ 嵌入式分析 │ │
│ │ 高性能查询 │ │
│ │ 单文件部署 │ │
│ └─────────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ 优点: │ │
│ │ • 分析优化 │ │
│ │ • 列式存储 │ │
│ │ • SQL支持 │ │
│ │ │ │
│ │ 缺点: │ │
│ │ • 新兴技术 │ │
│ │ • 生态较小 │ │
│ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
3.2.1 InMemoryStore(内存存储)
**适用场景:**开发测试、快速原型、临时数据
特点:
- 纯内存存储,速度极快
- 数据结构简单,易于理解
- 重启后数据丢失
使用场景:
- 本地开发调试
- 单元测试
- 临时缓存
3.2.2 RedisStore(Redis存储)
**适用场景:**生产环境、高性能需求、分布式系统
特点:
- 基于Redis的高性能键值存储
- 支持丰富的数据结构(字符串、列表、集合、哈希等)
- 支持持久化(RDB/AOF)
- 分布式部署,支持集群
使用场景:
- 用户会话数据
- 实时推荐系统
- 缓存层
- 消息队列
3.2.3 PostgreSQLStore(PostgreSQL存储)
**适用场景:**企业级应用、复杂查询、事务处理
特点:
- 基于PostgreSQL的关系型存储
- 支持复杂的SQL查询
- 强大的事务支持(ACID)
- 数据完整性保证
使用场景:
- 用户画像系统
- 知识库管理
- 审计日志
- 复杂业务逻辑
3.2.4 DuckDBStore(DuckDB存储)
**适用场景:**嵌入式分析、高性能查询、单文件部署
特点:
- 嵌入式列式数据库
- 针对分析查询优化
- 单文件部署,无需服务
- 支持标准SQL
使用场景:
- 数据分析应用
- 报表生成
- OLAP查询
- 嵌入式系统
3.3 长期记忆的典型应用场景
┌─────────────────────────────────────────────────────────────────────┐
│ 长期记忆应用场景 │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 用户画像系统 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 用户偏好 │ │ 历史记录 │ │ 个性化设置 │ │
│ │ (Preferences) │ (History) │ │ (Settings) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Namespace: ["users", "user_id", "profile"] │ │
│ │ • theme: "dark" │ │
│ │ • language: "zh-CN" │ │
│ │ • notification: true │ │
│ │ • favorite_topics: ["tech", "finance"] │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 知识库系统 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 领域知识 │ │ 术语定义 │ │ 最佳实践 │ │
│ │ (Domain) │ │ (Terms) │ │ (BestPractices)│ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Namespace: ["knowledge", "domain", "topic"] │ │
│ │ • definition: "详细定义..." │ │
│ │ • examples: ["示例1", "示例2"] │ │
│ │ • related_topics: ["topic1", "topic2"] │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 系统配置 │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 全局配置 │ │ 业务规则 │ │ 权限策略 │ │
│ │ (Config) │ │ (Rules) │ │ (Policies) │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Namespace: ["system", "config"] │ │
│ │ • max_tokens: 4096 │ │
│ │ • temperature: 0.7 │ │
│ │ • timeout: 30 │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
3.3.1 用户画像系统
场景描述:
构建一个能够记住用户偏好的智能助手,提供个性化的服务体验。
存储内容:
- 用户偏好:主题、语言、通知设置等
- 历史记录:用户的历史查询、操作记录
- 个性化设置:自定义配置、快捷方式
3.3.2 知识库系统
场景描述:
构建一个跨会话的知识库,让AI能够记住和检索领域知识。
存储内容:
- 领域知识:各领域的专业知识和概念
- 术语定义:专业术语的详细解释
- 最佳实践:行业标准和最佳实践
Namespace: ["knowledge", "finance", "gdp"]
Key: "definition" -> "GDP(国内生产总值)..."
Key: "examples" -> ["示例1", "示例2"]
Key: "related" -> ["GNP", "CPI"]
业务价值:
- 提高回答的准确性和专业性
- 减少重复学习成本
- 支持知识的持续积累和更新