【LangGraph框架入门级】12. 人机交互:interrupt 中断与 Command 恢复

人机交互:interrupt 中断与 Command 恢复

完全自动化虽好,但在「发邮件、转账、删除数据」这类高风险操作前,我们希望 AI 先停下来,等人确认或修改后再继续。

本篇讲持久化落地的第二大能力------人机交互(human-in-the-loop,人在回路中) ,核心是 interrupt(中断) 和 Command(指令恢复)。

目录

  1. 为什么需要人机交互
  2. 核心机制:interrupt 中断
  3. 用 Command 恢复执行
  4. 黄金法则(重要)
  5. 四种典型应用模式
  6. 本篇小结

1. 为什么需要人机交互

LLM 不是 100% 可靠,可能误判、误操作。在关键节点引入人工把关,能大幅降低风险:

  • 发邮件前先给人看一眼内容;
  • 转账、下单前确认金额和对象;
  • 工具参数不确定时让人补全或修正。

人机交互就是让图能在指定位置暂停 ,把控制权交给人,处理完再恢复。


2. 核心机制:interrupt 中断

在节点(或工具)里调用 interrupt(要展示给人的信息),图会在这里立即暂停,并把传入的信息抛给外部等待人工处理:

python 复制代码
from langgraph.types import interrupt, Command
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.graph import StateGraph, START, END
from typing_extensions import TypedDict

class State(TypedDict):
    messages: list

def human_feedback(state: State):
    # interrupt:暂停,并把问题抛给人
    answer = interrupt("你想继续吗?")
    # 恢复后,answer 就是人传回的值
    return {"messages": [f"用户的回答是:{answer}"]}

builder = StateGraph(State)
builder.add_node("human_feedback", human_feedback)
builder.add_edge(START, "human_feedback")
builder.add_edge("human_feedback", END)

# 必须配置 checkpointer,中断状态才能保存
graph = builder.compile(checkpointer=InMemorySaver())

第一次 invoke 会在 interrupt 处暂停,返回中断信息:

python 复制代码
config = {"configurable": {"thread_id": "1"}}
result = graph.invoke({"messages": []}, config)
print(result)   # __interrupt__: (Interrupt(value='你想继续吗?', ...))

此时图的状态已被保存,程序可以退出,人可以过很久再回来。


3. 用 Command 恢复执行

人处理完后,用 Command(resume=人的输入) 恢复,interrupt() 的返回值就是这个输入:

python 复制代码
from langgraph.types import Command

for event in graph.stream(Command(resume="继续"), config=config):
    print(event)

也可以用 invoke(Command(resume=...), config)。恢复后图从中断点继续往下走。


4. 黄金法则(重要)

interrupt 有一条必须牢记的行为:

当图恢复执行时,整个节点(或工具)会从头重新执行,interrupt() 这一次直接返回人传入的值,不会再次暂停。

为什么这么设计:暂停期间程序可能已经退出,恢复时 LangGraph 是重跑整个节点,而不是从暂停的那一行「接着跑」。

由此带来的关键坑点:

  • interrupt 之前的副作用会被重复执行!
    比如节点里在 interrupt 之前先调了一次外部 API、写了一次数据库,恢复时节点重跑,这个 API / 写库会再执行一遍。

正确做法------把 interrupt 放在节点最前面,让有副作用的操作都在 interrupt 之后:

python 复制代码
def bad_node(state):
    send_email()                 # ❌ 恢复时会再发一次邮件!
    confirm = interrupt("确认发送?")
    ...

def good_node(state):
    confirm = interrupt("确认发送?")   # ✅ 先暂停
    if confirm == "yes":
        send_email()                   # 副作用在中断之后,只执行一次

记忆点:interrupt 尽量放节点开头;中断前不要写有副作用的代码。


5. 四种典型应用模式

5.1 模式一:批准 / 拒绝(Approval)

执行高风险操作前暂停,人选择同意或拒绝:

python 复制代码
def sensitive_tool_node(state):
    decision = interrupt({"action": "删除文件", "file": "data.csv"})
    if decision == "approve":
        return {"messages": ["已删除"]}
    return {"messages": ["已取消"]}

5.2 模式二:编辑状态 / 参数(Edit State)

人在恢复时直接修改要执行的内容或参数:

python 复制代码
def email_node(state):
    draft = "您好,感谢购买..."
    edited = interrupt({"draft": draft})   # 人可以改邮件正文
    # edited 里带回修改后的内容
    send_email(edited)
    return {"messages": ["邮件已发送"]}

5.3 模式三:补充输入(Review Inputs)

信息不全时暂停,等人补全后再继续(如补一个地址、选一个选项)。

5.4 模式四:多代理 / 多环节协同中的人工评审

在「评估器-优化器」里,把质量评估这一环交给人:生成内容后 interrupt 暂停,人给评分和修改意见,再带着反馈重新生成。

这正好对应前面工作流模式里说的「人机交互式评估」。


6. 本篇小结

  1. 人机交互让图在关键步骤暂停、等人处理后恢复,用于高风险操作把关。
  2. interrupt(信息) 让图暂停并抛出信息;必须配 checkpointer 才能保存中断状态。
  3. 用 Command(resume=人的输入) 恢复,interrupt() 的返回值即人的输入。
  4. 黄金法则 :恢复时整个节点从头重跑,interrupt 直接返回值;所以 interrupt 前的副作用会重复执行------把 interrupt 放节点最前面,副作用放后面。
  5. 四种模式:批准/拒绝、编辑状态/参数、补充输入、人工评审(评估器)。

下一篇讲持久化落地的第三大能力------时间旅行(Time Travel):回到任意历史检查点,修改输入或状态后重新执行,是调试复杂 Agent 的利器。

相关推荐
Solara1 小时前
一个标志位挂了 18 天不落地:它等的重启,2 天 14 小时后就完成了
人工智能·程序员·ai编程
开开心心就好1 小时前
打印机卡住打不了?一键清理卡死打印队列
服务器·开发语言·算法·pdf·ocr·idea·visual studio code
龙腾AI白云1 小时前
世界模型与智能体协同推理逻辑
大数据·数据库·知识图谱·pygame
把我格子衫拿来1 小时前
四元数为什么突然变号?旋转表示、SLERP 与位姿插值避坑
python·机器人·坐标变换·四元数·slerp
David猪大卫1 小时前
【C++修炼】STL容器—模板进阶:非类型模板参数、模板特化、模板分离编译
c语言·开发语言·c++·经验分享·笔记·学习·面试
SkyWalking中文站1 小时前
从模型输入到文件变更:追踪 AgentCore 上的 LangGraph Agent
langchain·aigc·ai编程
牛战士coding1 小时前
Java 对象写入 Redis 后类型变了?Jackson 多态序列化问题复盘
java·开发语言·redis
ben9518chen1 小时前
数据库系统概述
数据库