LangGraph 人机交互实战:Interrupt、人工审批与工作流恢复

一、为什么需要 Human-in-the-loop?

LLM 可以自动规划并调用工具,但转账、发送邮件、删除数据、发布内容等操作不能完全交给模型。LangGraph 的 Human-in-the-loop 机制允许工作流在关键节点暂停,等待人工批准、拒绝或修改参数,再继续执行。

基于 HumanReviewExperience 下的 6 个示例,其核心组合是:

interrupt() + checkpointer + thread_id + Command(resume=...)

二、示例1:暂停与恢复工作流

示例1:节点通过 interrupt() 暂停:

python 复制代码
def review_node(state: State):
    decision = interrupt("是否继续?")

    if decision == "yes":
        return {"output": "继续执行"}

    return {"output": "人工终止"}

图必须配置 checkpointer

graph = builder.compile(checkpointer=InMemorySaver())

第一次执行触发中断:

python 复制代码
config = {"configurable": {"thread_id": "111"}}
result = graph.invoke(
    {"input": "hi", "output": ""},
    config=config,
)

print(result["__interrupt__"][0].value)

获得人工输入后,使用相同的 thread_id 恢复:

python 复制代码
result = graph.invoke(
    Command(resume="yes"),
    config=config,
)

resume 中的数据会成为 interrupt() 的返回值。

三、示例2:人工审批与条件分支

示例2展示了转账审批:

python 复制代码
def approval_node(state: ApprovalState):
    decision = interrupt({
        "question": "是否批准此操作?",
        "details": state["action_details"],
        "options": ["批准", "拒绝"],
    })

    return {
        "status": "批准" if decision == "批准" else "取消"
    }

审批完成后使用条件边分流:

python 复制代码
def route_by_status(state: ApprovalState):
    if state["status"] == "批准":
        return "proceed_node"
    return "cancel_node"

流程为:

提交转账 -> 人工审批 -> 批准执行 / 拒绝取消

四、示例3:使用 Command 动态跳转

示例3使用 Command 同时更新状态和指定下一个节点:

python 复制代码
if decision == "批准":
    return Command(
        goto="proceed_node",
        update={"status": "批准"},
    )

return Command(
    goto="cancel_node",
    update={"status": "取消"},
)

条件边适合固定且清晰的业务分支;Command(goto, update) 更适合节点内部需要动态决定跳转的场景。

五、示例4:人工编辑内容

示例4展示了把待审核内容交给人工修改:

python 复制代码
def review_node(state: State):
    updated = interrupt({
        "instruction": "查看并编辑内容",
        "content": state["text"],
    })

    if updated["success"]:
        return {}

    return {"text": updated["content"]}

恢复时可以传入结构化数据:

python 复制代码
Command(resume={
    "success": False,
    "content": "人工修改后的文章",
})

原代码漏掉了节点注册,需要补充:

builder.add_node("review_node", review_node)

同时建议使用布尔值 True、False,不要使用字符串 "true"、"false"。

六、示例5:在工具执行前增加人工审核

示例5把 interrupt() 放在邮件工具内部:

python 复制代码
@tool
def send_email(to: str, subject: str, body: str):
    review = interrupt({
        "action": "send_email",
        "to": to,
        "subject": subject,
        "body": body,
        "message": "是否同意发送邮件?",
    })

    if review["decision"] == "cancel":
        return "用户取消发送邮件"

    final_to = review.get("to", to)
    final_subject = review.get("subject", subject)
    final_body = review.get("body", body)

    return send_email_to_provider(
        final_to,
        final_subject,
        final_body,
    )

人工可以批准、取消,也可以修改模型生成的收件人、主题和正文。

原代码用 "不同意,需要修改主题" 与 "不同意" 比较,两者并不相等。建议设计稳定的审批协议:

json 复制代码
{
    "decision": "edit",
    "changes": {
        "subject": "修改后的主题"
    }
}

七、示例6:循环获取合法输入

示例6演示了不断请求用户输入,直到年龄合法:

python 复制代码
def get_age_node(state: State):
    prompt = "请输入年龄:"

    while True:
        age = interrupt(prompt)

        if isinstance(age, int) and age > 0:
            return {"age": age}

        prompt = "请输入有效年龄:必须是大于 0 的整数"

原代码虽然更新了 prompt,但调用的始终是固定文本 interrupt("请输入年龄:"),所以错误提示不会生效。

八、中断节点必须具备幂等性

恢复工作流时,包含 interrupt() 的节点会从头重新执行,因此中断前的代码可能执行多次。

错误写法:

python 复制代码
charge_credit_card()
approved = interrupt("是否批准?")

恢复时可能重复扣款。

正确写法:

python 复制代码
approved = interrupt("是否批准扣款?")

if approved:
    charge_credit_card()

邮件发送、扣款、写数据库等副作用应放在中断之后,并增加业务幂等键。

九、生产环境建议

使用 PostgreSQL 等持久化 checkpointer,不能依赖 InMemorySaver。

用订单号、任务 ID 或 UUID 作为稳定的 thread_id。

使用结构化审批数据,避免解析自然语言决定。

保存审批人、时间、原始参数、修改参数和审批结论。

校验审批人是否有权恢复对应工作流。

防止同一个审批请求被重复恢复。

为循环输入和多轮审核设置最大次数。

权限判断和金额阈值必须由业务代码控制,不能交给模型。

十、总结

LangGraph 人机交互并不是简单调用一次 input(),而是一套可暂停、可持久化、可恢复、可审计的工作流机制。补上持久化、权限、幂等和审计后,它就能用于真正的生产级人机协作系统。

相关推荐
cocoafei1 小时前
GPT-5.6 后,别再混淆 ChatGPT 和 Codex 额度了
前端·人工智能·chatgpt
范闲1 小时前
第二章:Octo v0.1.1:从「能用」到「好用」——终端 AI 聊天体验的全面升级
人工智能·后端
念雨思1 小时前
每日穿搭助手:鸿蒙AI应用开发实战——AI衣橱,每日穿搭不再愁
人工智能·华为·powerpoint·harmonyos·鸿蒙
yangdaxiageo1 小时前
算法时代的“心智置顶“:《功夫女足》如何构建GEO正向飞轮
人工智能·科技·算法·aigc
用户6369790981431 小时前
RFM客群细分AI:从数据到策略的自动化
人工智能
workflower1 小时前
人形机器人全身运动控制能力大幅提升
人工智能·深度学习·机器学习·设计模式·机器人·自动化
YMWM_1 小时前
python-venv虚拟环境
linux·开发语言·python
何时梦醒1 小时前
一文搞懂 RAG(检索增强生成):从 LLM 幻觉到智能检索,手把手带你理解核心原理与代码实现
人工智能
l134062082351 小时前
鸿蒙实战:从 rawfile 加载 AI 模型资源
人工智能·华为·harmonyos