实现 短期记忆(Short-term Memory) 的核心方案——基于内存的 Checkpointer(持久化器):InMemorySaver,让 Agent 在同一线程(Thread)内具备记忆历史对话的能力。
| 要素 | 说明 |
|---|
| State | 存储当前会话内的历史消息列表(messages),由 LangGraph 的状态图管理 |
| Checkpointer | 对 State 在某一时刻的快照进行持久化存储(类比 RPG 游戏的"自动存档") |
| thread_id | 区分不同会话线程的标识符,同一 thread_id 内部共享记忆,不同 thread_id 之间隔离 |
- 将记忆数据存储在进程内存中。
- 同进程内有效,进程结束或重启后数据丢失。
- 适用于开发测试阶段,生产环境需改用外部存储介质(SQLite / PostgreSQL)。
| 步骤 | 操作 |
|---|
| Step 1 | 创建 InMemorySaver 实例 |
| Step 2 | 在创建 Agent 时将 InMemorySaver 作为 checkpointer 参数传入 |
| Step 3 | 构建 config 字典,指定 thread_id(字符串类型) |
| Step 4 | 调用 invoke 时传入 config 参数,同一 thread_id 的调用共享记忆 |
【无记忆 — 两次独立 invoke】
invoke({"messages": [HumanMessage("我叫张三")]}) → State: [Human:我叫张三, AI:你好张三]
invoke({"messages": [HumanMessage("我叫什么?")]}) → State: [Human:我叫什么?, AI:不知道] ❌ 不共享
【有记忆 — 同一 thread_id】
invoke({"messages": [HumanMessage("我叫张三")]}, config=config) → State: [Human:我叫张三, AI:你好张三]
invoke({"messages": [HumanMessage("我叫什么?")]}, config=config) → State: [..., Human:我叫什么?, AI:你叫张三] ✅ 共享
thread_id = "1" 的消息列表:
┌──────────────────────────────────────────────┐
│ [Human: 我叫张三] │
│ [AI: 你好张三!] │
│ [Human: 我叫什么?] ← 第2次 invoke 追加 │
│ [AI: 你叫张三] ← AI 回复追加 │
│ [Human: 我刚才问了什么?] ← 第3次 invoke 追加 │
│ [AI: 你刚才问了你叫什么名字] ← AI 回复追加 │
└──────────────────────────────────────────────┘
thread_id = "2" 的消息列表:
┌──────────────────────────────────────────────┐
│ [Human: 我叫什么?] │
│ [AI: 我还不知道你叫什么] ← 与 thread_id=1 隔离 │
└──────────────────────────────────────────────┘
- 读取当前
thread_id 对应的历史 messages 列表 - 将新的用户消息追加到列表末尾
- 将完整消息列表发送给大模型
- 大模型返回响应(AI Message)
- 将 AI 响应也追加到消息列表中(State 更新)
from langgraph.checkpoint.memory import InMemorySaver
from langchain_core.messages import HumanMessage
from rich import print as rprint
checkpointer = InMemorySaver()
agent = create_react_agent(
model=model,
tools=[],
checkpointer=checkpointer
)
config = {"configurable": {"thread_id": "1"}}
response1 = agent.invoke(
{"messages": [HumanMessage(content="我叫张三")]},
config=config
)
print(response1["messages"][-1].content)
response2 = agent.invoke(
{"messages": [HumanMessage(content="我叫什么?")]},
config=config
)
print(response2["messages"][-1].content)
response3 = agent.invoke(
{"messages": [HumanMessage(content="我刚才问了什么问题?")]},
config=config
)
print(response3["messages"][-1].content)
state = agent.get_state(config)
rprint(state.values["messages"])
config2 = {"configurable": {"thread_id": "2"}}
state2 = agent.get_state(config2)
rprint(state2.values["messages"])
config2 = {"configurable": {"thread_id": "2"}}
response4 = agent.invoke(
{"messages": [HumanMessage(content="我叫什么?")]},
config=config2
)
print(response4["messages"][-1].content)
| 问题 | 原因 | 解决方案 |
|---|
| Agent 不记得之前信息 | 未创建 InMemorySaver 或未传入 checkpointer 参数 | 确认 create_react_agent(..., checkpointer=...) |
| Agent 不记得之前信息 | invoke 时未传 config | 确保 invoke(..., config=config) |
| Agent 不记得之前信息 | 两次 invoke 使用了不同的 thread_id | 确保同一对话使用相同的 thread_id |
get_state 返回空 | 该 thread_id 下还未执行过任何 invoke | 先执行一次 invoke 再调用 get_state |
- 短期记忆的核心是"线程隔离 + State 持久化",
InMemorySaver 是理解这一机制的最简入口。 thread_id 的设计非常灵活:可用于多用户聊天(每个用户独立 thread)、同一用户的多任务隔离(编码任务 vs 写作任务)。InMemorySaver 仅适合开发测试——进程重启数据丢失。下一节将介绍基于 SQLite / PostgreSQL 的外部存储 Checkpointer,实现真正的持久化短期记忆。- 获取 State 的能力(
agent.get_state(config))不仅是调试利器,也是实现"查看历史"等功能的 API 基础。