13 · 记忆、暂停与进度:checkpointer、interrupt 与 stream
开头的现象
小林用手搓的图做出了 agent 循环,但老板连环三问:- “它能记住每个用户聊到哪吗?重启不丢?” —— 需要 checkpointer
- “转账、删数据之前,能不能先停下来等我确认?” —— 需要 interrupt
- “转三个工具,能不能一步步展示进度?” —— 需要 stream
第五幕:checkpointer——让记忆变成”图的一部分”
老板的需求终于来了:“让机器人记住每个用户聊到哪了,重启不丢。” 小林本来想用第 4 篇的手写历史,但他现在知道:LangGraph 内置了记忆——checkpointer(检查点保存器)。 他用 SQLite 存状态:session_id 和这里的 thread_id 对上了:“同一个概念——thread_id 区分会话,checkpointer 把状态(包括历史)存进 SQLite。第 10 篇我手写的 InMemoryChatMessageHistory,LangGraph 用 checkpointer 全内置了,还能持久化到磁盘。”
他叹了口气:“我第 4 篇手写的滚雪球、第 10 篇手写的会话隔离——LangGraph 全都有,还带持久化。早用 LangGraph 是不是能少走一半弯路?” 他想了想,又摇头:“不手写一遍,我根本看不懂 checkpointer 在干嘛。”
想验证”重启不丢”吗?跑11_langgraph.py第四部分——SQLite 文件存了检查点,第 1 轮自我介绍、第 2 轮同 thread 问”我叫什么”它记得。你把thread_id换成新的,它立刻失忆——隔离就是这么来的。
第六幕:interrupt——让图”暂停”等老板点头(人审)
小林做完 checkpointer 的记忆版,老板又提新需求:“机器人要转账、要删数据之前,先停下来问我一句,我确认了它才能动手。” 小林第一反应:“那我写个 if 判断?用户输入’确认’才继续?” 他写着写着发现不对劲:模型调用是异步的、状态是分散的,你要”在模型调用前停住”,得手动控制整个流程——这跟第 10 篇手写 agent 循环一样,又丑又容易错。 他翻 LangGraph 文档,看到interrupt_before——“让图在指定节点之前停下来,等你确认后从断点继续。”
app.get_state(config).next 那行,悟了:“interrupt 就是给图加了一个’闸门’——interrupt_before=["chat"] 意味着’在 chat 节点前必须等我放行’。checkpointer 记住断点位置,Command(resume=...) 就是’放行指令’。老板确认 → resume → 模型才继续干活。”
他立刻想到了实际场景:“转账工具调用前 interrupt → 等用户输’确认’ → resume → 工具才真的转账。这就是’人审’(human-in-the-loop)——机器提议,人拍板。”
interrupt 的两种暂停方式:
interrupt_before=["节点"]:在指定节点前停(做事前审核,如转账前)interrupt_after=["节点"]:在指定节点后停(做事后检查,如转账后看结果)
想验证”闸门”吗?跑上面的代码——第一次invoke后get_state().next显示('chat',)(暂停),模型没回复;Command(resume=...)后才出现回复,next变空。这就是”人审”的完整闭环。
第七幕:stream——让图”边跑边报进度”
小林做完人审,又想要”进度感”:机器人转 3 个工具 + 1 次回答,能不能一步步展示给用户看? 而不是闷头转半天最后”啪”一下出结果。 LangGraph 的stream() 提供了三种”看进度”的模式(实测):
小林给机器人接上了
updates 模式,用户能看到:“正在查天气 → 正在算数 → 正在汇总……”——进度感有了,体验上一个台阶。
想验证吗?用假模型(不调 API)跑app.stream(input, stream_mode="updates")——每次吐['chat'](节点名);换stream_mode="values"——每次都吐完整状态列表。两种模式肉眼可见的区别。
🔧 技术细节:这一章涉及的关键类和签名
④SqliteSaver——checkpointer(持久化记忆)
interrupt——人审暂停(第六幕)
stream()——三种进度模式(第七幕)
想验证吗?app.get_state(config).next在 interrupt 后显示('chat',);Command(resume=...)后变空。app.stream(input, stream_mode="values")每次都吐完整状态。
结论(小林用两天换来的)
LangGraph 三大进阶能力:checkpointer + thread_id(持久化记忆,重启不丢)、interrupt + Command(resume)(人审暂停,机器提议人拍板)、stream() 三种模式(边跑边报进度)。这三样就是”生产级 Agent”的标配——能记住、能等人、能给进度。复现信号:什么时候你会想起这一章
- 想让记忆”持久化、重启不丢”——checkpointer + thread_id。
- 想”中途插一手”(人审确认后再执行)——
compile(interrupt_before=[...])+Command(resume=...)。 - 想”边跑边报进度”——
app.stream(input, stream_mode=...)(updates/values/messages 三种粒度)。