添加内存
原文:Add Memory
一句话
LangGraph 支持两种内存类型:短期内存(thread-level persistence)用于多轮对话,长期内存用于跨会话存储用户特定或应用级数据。
什么时候翻这页
当你需要实现 Agent 的记忆功能,使其能够记住之前的对话内容或用户信息时。
核心概念
- 短期内存:作为 Agent 状态的一部分,用于多轮对话的上下文保持
- 长期内存:用于存储用户特定或应用级数据,可在不同会话间保持
- Checkpoint:检查点机制,用于保存和恢复 Agent 的状态
- StateGraph:LangGraph 中的核心图结构,用于构建 Agent 工作流
- Store:长期存储接口,用于持久化数据
怎么做
添加短期内存
短期内存通过在编译 StateGraph 时提供 checkpointer 实现:
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import StateGraph
checkpointer = InMemorySaver()
builder = StateGraph(...)
graph = builder.compile(checkpointer=checkpointer)
graph.invoke(
{"messages": [{"role": "user", "content": "hi! i am Bob"}]},
{"configurable": {"thread_id": "1"}},
)
生产环境中的短期内存
在生产环境中,使用数据库支持的 checkpointer:
from langgraph.checkpoint.postgres import PostgresSaver
DB_URI = "postgresql://postgres:postgres@localhost:5432/postgres?sslmode=disable"
with PostgresSaver.from_conn_string(DB_URI) as checkpointer:
builder = StateGraph(...)
graph = builder.compile(checkpointer=checkpointer)
添加长期内存
长期内存通过在编译 StateGraph 时提供 store 实现:
from langgraph.store.memory import InMemoryStore
from langgraph.graph import StateGraph
store = InMemoryStore()
builder = StateGraph(...)
graph = builder.compile(store=store)
在节点中访问 Store
一旦编译了带有 store 的图,LangGraph 会自动将 store 注入到节点函数中:
from dataclasses import dataclass
from langgraph.runtime import Runtime
from langgraph.graph import StateGraph, MessagesState, START
import uuid
@dataclass
class Context:
user_id: str
async def call_model(state: MessagesState, runtime: Runtime[Context]):
user_id = runtime.context.user_id
namespace = (user_id, "memories")
# 搜索相关记忆
memories = await runtime.store.asearch(
namespace, query=state["messages"][-1].content, limit=3
)
info = "\n".join([d.value["data"] for d in memories])
# 在模型调用中使用记忆
# 存储新记忆
await runtime.store.aput(
namespace, str(uuid.uuid4()), {"data": "User prefers dark mode"}
)
builder = StateGraph(MessagesState, context_schema=Context)
builder.add_node(call_model)
builder.add_edge(START, "call_model")
graph = builder.compile(store=store)
管理检查点
可以查看和删除 checkpointer 存储的信息:
# 查看线程状态
config = {
"configurable": {
"thread_id": "1",
# 可选提供特定检查点的 ID
# "checkpoint_id": "1f029ca3-1f5b-6704-8004-820c16b69a5a"
}
}
graph.get_state(config)
# 查看线程历史
list(graph.get_state_history(config))
# 删除线程的所有检查点
checkpointer.delete_thread("1")
命令 / API 速查
短期内存相关
InMemorySaver(): 内存中的检查点保存器PostgresSaver.from_conn_string(DB_URI): 从连接字符串创建 PostgreSQL 检查点保存器MongoDBSaver.from_conn_string(MONGODB_URI): 从连接字符串创建 MongoDB 检查点保存器RedisSaver.from_conn_string(DB_URI): 从连接字符串创建 Redis 检查点保存器OracleSaver.from_conn_string(DB_URI): 从连接字符串创建 Oracle 检查点保存器graph.compile(checkpointer=checkpointer): 编译图时指定检查点保存器graph.invoke(..., {"configurable": {"thread_id": "1"}}): 调用图时指定线程 ID
长期内存相关
InMemoryStore(): 内存中的存储PostgresStore.from_conn_string(DB_URI): 从连接字符串创建 PostgreSQL 存储builder.compile(store=store): 编译图时指定存储runtime.store.asearch(namespace, query, limit): 异步搜索存储中的数据runtime.store.aput(namespace, key, value): 异步存储数据graph.invoke(..., context=Context(user_id="1")): 调用图时传递上下文
检查点管理
graph.get_state(config): 获取当前状态graph.get_state_history(config): 获取状态历史checkpointer.delete_thread(thread_id): 删除线程的所有检查点
与 Hello-Agents / Claude Code 的联系
在 Hello-Agents 中,我们介绍了 LangGraph 的基本概念和简单工作流。本章节扩展了这些概念,添加了内存功能,使 Agent 能够记住之前的交互。这与 Claude Code 中的持久化概念类似,但提供了更细粒度的控制和更丰富的功能。
初学者易错点
- 忘记在调用图时提供
thread_id,导致无法正确恢复对话状态 - 混淆短期内存和长期内存的用途,错误地使用其中一种来实现另一种功能
- 在使用数据库支持的 checkpointer 或 store 时忘记调用
setup()方法 - 在节点函数中错误地访问 store,没有通过
Runtime对象 - 忽略了异步操作的需要,特别是在使用数据库存储时
相关词条
- StateGraph: LangGraph 中的核心图结构
- MessagesState: 处理消息的状态类型
- Subgraphs: 子图的使用
- Persistence: 持久化机制