LangGraph 提供了两种类型的记忆机制,用于在不同场景下保存和检索信息:短期记忆(Short-term Memory)和长期记忆(Long-term Memory)。
概述
- 短期记忆:通过 Checkpointer 实现,thread-scoped(线程作用域),用于跟踪单次会话中的多轮对话
- 长期记忆:通过 Store 实现,跨会话存储,用于存储用户特定或应用级别的数据
短期记忆(Short-term Memory)
短期记忆通过 Checkpointer 实现,是 thread-scoped(线程作用域)的,用于跟踪单次会话中的多轮对话。
特点
- 作用域 :限定在单个
thread_id内 - 存储内容:对话历史、状态数据、中间结果等
- 生命周期:与线程绑定,线程结束时记忆也随之结束
- 实现方式:通过 Checkpointer 在每个步骤保存状态
使用场景
- 多轮对话中保持上下文
- 在会话中记住用户之前说过的话
- 保存会话中的临时数据
基本用法
python
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import StateGraph, MessagesState
# 创建 checkpointer
checkpointer = InMemorySaver()
# 编译图时启用 checkpointer
graph = builder.compile(checkpointer=checkpointer)
# 第一次对话
config = {"configurable": {"thread_id": "user_123"}}
graph.invoke({"messages": [("user", "我叫张三")]}, config)
# 第二次对话 - 可以访问之前的消息
graph.invoke({"messages": [("user", "我刚才说我叫什么?")]}, config)
# Agent 可以回答:"你刚才说你叫张三"
短期记忆的工作原理
- 状态保存:在每个执行步骤(superstep),Checkpointer 自动保存图的状态快照
- 状态恢复:下次执行时,从保存的检查点读取状态,包括之前的对话历史
- 线程隔离 :不同的
thread_id拥有独立的状态,互不干扰
短期记忆的生产环境使用
在生产环境中,应该使用数据库支持的 Checkpointer:
python
from langgraph.checkpoint.postgres import PostgresSaver
DB_URI = "postgresql://user:password@localhost:5432/dbname"
checkpointer = PostgresSaver.from_conn_string(DB_URI)
graph = builder.compile(checkpointer=checkpointer)
长期记忆(Long-term Memory)
长期记忆通过 Store 实现,是 跨会话 的,用于存储用户特定或应用级别的数据。
长期记忆的特点
- 作用域 :跨多个
thread_id,可以在任何线程中访问 - 存储内容:用户偏好、历史信息、知识库等
- 生命周期:独立于线程,持久化存储
- 实现方式:通过 Store 在自定义 namespace 下存储
长期记忆的使用场景
- 记住用户的偏好设置
- 存储跨会话的历史信息
- 保存应用级别的知识库
长期记忆的基本用法
python
from langgraph.store.memory import InMemoryStore
store = InMemoryStore()
# 保存用户偏好(跨会话)
await store.aput(
["users", "user_123", "preferences"],
{"theme": "dark", "language": "zh-CN"}
)
# 在任何线程中都可以访问
preferences = await store.aget(["users", "user_123", "preferences"])
print(preferences) # {"theme": "dark", "language": "zh-CN"}
命名空间结构
Store 使用层次化的命名空间结构来组织数据:
python
# 用户数据
["users", "user_123", "preferences"]
["users", "user_123", "history"]
["users", "user_123", "settings"]
# 应用数据
["app", "config", "version"]
["app", "knowledge", "faq"]
# 组织数据
["orgs", "org_456", "members"]
长期记忆的生产环境使用
在生产环境中,应该使用数据库支持的 Store:
python
from langgraph.store.postgres import PostgresStore
DB_URI = "postgresql://user:password@localhost:5432/dbname"
store = PostgresStore.from_conn_string(DB_URI)
短期记忆 vs 长期记忆
| 特性 | 短期记忆 | 长期记忆 |
|---|---|---|
| 实现 | Checkpointer | Store |
| 作用域 | 单个 thread_id |
跨多个 thread_id |
| 存储内容 | 对话历史、状态数据 | 用户偏好、历史信息 |
| 生命周期 | 与线程绑定 | 持久化存储 |
| 使用场景 | 多轮对话上下文 | 跨会话信息 |
| 命名空间 | thread_id |
自定义 namespace |
结合使用
在实际应用中,可以同时使用短期记忆和长期记忆:
python
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.store.memory import InMemoryStore
checkpointer = InMemorySaver() # 短期记忆
store = InMemoryStore() # 长期记忆
graph = builder.compile(checkpointer=checkpointer, store=store)
# 在节点中使用
def my_node(state):
# 访问短期记忆(当前会话的对话历史)
messages = state["messages"]
# 访问长期记忆(用户偏好)
preferences = await store.aget(["users", user_id, "preferences"])
# 根据短期和长期记忆做出决策
if preferences.get("theme") == "dark":
# 使用深色主题
pass
return {"messages": [("assistant", "回复")]}
最佳实践
1. 选择合适的记忆类型
- 使用短期记忆:当信息只在当前会话中有用时
- 使用长期记忆:当信息需要在多个会话间共享时
2. 管理对话历史
对于长对话,考虑使用以下策略:
- 截断历史:只保留最近的 N 条消息
- 摘要历史:将旧消息总结为摘要
- 选择性保留:只保留重要的消息
3. 命名空间设计
设计清晰的命名空间结构:
python
# 好的设计
["users", user_id, "preferences"] # 用户偏好
["users", user_id, "history"] # 用户历史
["app", "config"] # 应用配置
# 避免
["data", "stuff"] # 不够清晰
["user123"] # 缺少层次结构
4. 性能考虑
- 短期记忆:Checkpointer 在每个步骤都会保存,注意性能影响
- 长期记忆:Store 操作是异步的,适合批量操作
- 缓存策略:对于频繁访问的数据,考虑使用缓存
5. 数据一致性
- 确保短期记忆和长期记忆的数据一致性
- 在更新长期记忆时,考虑事务处理
- 定期清理过期的记忆数据