2.langchain上下文与记忆之短期记忆

        短期记忆 = 让应用在单个 thread(会话)内记住先前的交互。官方实现路径只有一句话:创建 agent 时指定一个 checkpointer,再通过 thread_id 区分会话。本节先讲基于内存的 InMemorySaver

五条官方关键事实(务必记牢):

  • 必须显式指定 checkpointer,否则没有 thread 级持久化;
  • 短期记忆是 agent state 的一部分,存在图的 state 里;
  • 同一 thread 能访问完整上下文,不同 thread 之间保持隔离
  • state 通过 checkpointer 持久化,thread 可以随时恢复
  • 记忆更新时机:agent 被调用时、或某个 step(如工具调用)完成时;读取时机:每个 step 开始时。

2.1 基于内存的持久化器(InMemorySaver)

InMemorySaver 把 state 存在进程的内存字典里。官方定位很明确:适用于开发与示例,生产请用数据库支持的 checkpointer

2.1.1 举例 1:没有记忆

对照组——不传 checkpointer,即使传了 thread_id 也没用:

from langchain.agents import create_agent

def get_user_info() -> str:
    """Look up information about the current user."""
    return "No user profile on file."

agent = create_agent(
    model="google_genai:gemini-3.6-flash",
    tools=[get_user_info],
    # ← 没有 checkpointer,短期记忆未启用
)

thread_config = {"configurable": {"thread_id": "1"}}  # 传了也没用

r1 = agent.invoke(
    {"messages": [{"role": "user", "content": "Hi! My name is Bob."}]},
    thread_config,
)
print(r1["messages"][-1].content)
# Hi Bob! Nice to see you here. How are you doing?

r2 = agent.invoke(
    {"messages": [{"role": "user", "content": "What's my name?"}]},
    thread_config,
)
print(r2["messages"][-1].content)
# I'm not sure what your name is — you haven't told me yet!   ← 忘了

2.1.2 举例 2:拥有记忆

实验组——只多传一个 checkpointer,其余代码一模一样:

from langchain.agents import create_agent
from langgraph.checkpoint.memory import InMemorySaver


def get_user_info() -> str:
    """Look up information about the current user."""
    return "No user profile on file."

agent = create_agent(
    model="google_genai:gemini-3.6-flash",
    tools=[get_user_info],
    checkpointer=InMemorySaver(),   # ← 唯一的变化:启用短期记忆
)

thread_config = {"configurable": {"thread_id": "1"}}

r1 = agent.invoke(
    {"messages": [{"role": "user", "content": "Hi! My name is Bob."}]},
    thread_config,
)
print(r1["messages"][-1].content)
# Hi Bob! Nice to see you here. How are you doing?

r2 = agent.invoke(
    {"messages": [{"role": "user", "content": "What's my name?"}]},
    thread_config,
)
print(r2["messages"][-1].content)
# You are Bob!   ← 记住了

结论:两个例子的差别只有一行——checkpointer=InMemorySaver()。这就是短期记忆的全部开关。

2.1.3 关键步骤说明

# 用户 A 的会话
cfg_a = {"configurable": {"thread_id": "user-A"}}
agent.invoke({"messages": "我叫小明,喜欢极简风格"}, cfg_a)

# 用户 B 的会话(完全独立的记忆空间)
cfg_b = {"configurable": {"thread_id": "user-B"}}
agent.invoke({"messages": "我叫小红,喜欢详细解释"}, cfg_b)

agent.invoke({"messages": "我叫什么?"}, cfg_a)   # → 小明
agent.invoke({"messages": "我叫什么?"}, cfg_b)   # → 小红
# 永不串台:thread 之间天然隔离

2.1.4 工作原理

为什么要"逐步落盘"?因为这样才有断点恢复能力:如果第 3 个 step 崩了,重启后从 checkpoint#2 继续即可,前面已经花掉的 token 不浪费。这也是 HumanInTheLoop 中断、时间旅行(回到某个历史 state)能工作的底层原因——它们复用的都是同一套 checkpoint 机制。

2.1.5 常见问题

现象 根因 解决
传了 thread_id 却还是记不住 创建 agent 时没传 checkpointer 两个条件必须同时满足:checkpointer= + thread_id
程序重启后记忆全没了 用了 InMemorySaver,数据在内存里,进程退出即销毁 换 SqliteSaver / PostgresSaver(见 2.2)
两个用户互相看到对方对话 所有用户共用了同一个 thread_id thread_id 用 user_id + session_id 组合,保证唯一
想把 user_id 存进 state 让工具读 默认 AgentState 只有 messages 继承 AgentState 加字段 + state_schema=(见 2.5)
RemoveMessage 删不掉消息 对应 state key 没有 add_messages reducer 默认 AgentState 已提供;自定义 key 要显式加 Annotated[list, add_messages]</
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值