LangChain1.0智能体开发:人机协作

智能体能自主决策任务的执行,但有时人工介入是必要的。LangChain提供了人工协作中间件支持智能体的人工介入功能。阅读本文您将获得:

  • LangChain人工协作中断支持的决策类型
  • LangChain人工协作如何配置中断
  • LangChain人工协作如何响应中断
  • LangChain人工协作的执行生命周期
  • LangChain自定义人工协作逻辑

LangChain提供了人工协作HumanInTheLoopMiddleware中间件。 人工协作(Human-in-the-Loop,简称 HITL)中间件可让你在【智能体工具调用过程中】加入人工监督环节。当模型提出可能需要审核的操作(例如写入文件或执行SQL语句)时,该中间件能够暂停执行流程,等待人工决策。 其实现原理是通过可配置策略对每一次工具调用进行检查。若需要人工介入,中间件会触发【中断信号】以终止当前执行。此时,图状态会通过LangGraph的持久化层保存,确保执行流程可安全暂停,并在后续重新启动。 之后,人工决策将决定后续操作方向:该行动可按原计划批准执行("批准")、修改后再运行("编辑"),或结合反馈意见予以拒绝("拒绝")。

1、中断决策类型

人工协作中间件定义了三种内置的人工响应中断的方式:

决策类型 说明 示例场景
✅ 批准(approve) 行动按原样获批并直接执行,无需修改 完全按照撰写内容发送邮件草稿
✏️ 编辑(edit) 工具调用经修改后执行 发送邮件前修改收件人
❌ 拒绝(reject) 工具调用被拒绝,且需在对话中添加拒绝说明 拒绝某封邮件草稿,并说明应如何重写

每种工具可用的决策类型,取决于你在 "interrupt_on"(中断触发条件)中配置的策略。当多个工具调用同时处于暂停状态时,每个行动都需要单独决策。决策的提供顺序必须与中断请求中行动的显示顺序一致。在编辑工具参数时,应谨慎修改。对原始参数进行大幅调整,可能会导致模型重新评估其执行思路,进而可能出现工具被多次执行或触发意外操作的情况。

2、配置中断

若要使用人工协作(HITL)功能,需在创建智能体时,将该中间件添加到智能体的中间件列表中。 你需要通过一种 "工具操作 - 决策类型" 映射关系来配置该中间件:为每种工具操作指定允许的决策类型。当某次工具调用与映射关系中的某一操作匹配时,中间件就会中断执行流程。

python 复制代码
from langchain.agents import create_agent
from langchain.agents.middleware import HumanInTheLoopMiddleware 
from langgraph.checkpoint.memory import InMemorySaver 

agent = create_agent(
    model="gpt-4o",
    tools=[write_file_tool, execute_sql_tool, read_data_tool],
    middleware=[
        HumanInTheLoopMiddleware( 
            interrupt_on={
                "write_file": True,  # All decisions (approve, edit, reject) allowed
                "execute_sql": {"allowed_decisions": ["approve", "reject"]},  # No editing allowed
                # Safe operation, no approval needed
                "read_data": False,
            },
            # Prefix for interrupt messages - combined with tool name and args to form the full message
            # e.g., "Tool execution pending approval: execute_sql with query='DELETE FROM...'"
            # Individual tools can override this by specifying a "description" in their interrupt config
            description_prefix="Tool execution pending approval",
        ),
    ],
    # Human-in-the-loop requires checkpointing to handle interrupts.
    # In production, use a persistent checkpointer like AsyncPostgresSaver.
    checkpointer=InMemorySaver(),  
)

必须配置一个检查点(checkpointer),以在中断期间持久化保存图状态(graph state)。在生产环境中,应使用具备持久化功能的检查点工具,例如AsyncPostgresSaver;若用于测试或原型开发,可使用InMemorySaver。调用智能体时,需传入包含线程ID(thread ID)的配置,使执行流程与对话线程相关联。

3、响应中断(Responding to Interrupts)

调用智能体后,智能体将持续运行,直至任务完成或触发中断。当某次工具调用与你在 "interrupt_on"(中断触发条件)中配置的策略相匹配时,中断即会被触发。在此情况下,调用结果中将包含一个 "interrupt" 字段,该字段内会列出需要审核的操作。之后,你可将这些操作呈现给审核人员,待获取决策意见后,即可恢复执行流程。

python 复制代码
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langchain.tools import tool
from langchain.agents.middleware import HumanInTheLoopMiddleware
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.types import Command
from config import api_key, api_base

def init_model():
    model = init_chat_model(
        api_key = api_key,
        base_url = api_base,
        model = "Qwen/Qwen3-8B",
        model_provider = "openai",
        temperature = 0.7,
    )
    return model

@tool
def send_email(recipient: str, content: str) -> str:
    """Send an email to the specified recipient."""
    return f"Email sent to {recipient} with content: {content}"

agent = create_agent(
            model=init_model(),
            tools=[send_email], 
            middleware=[HumanInTheLoopMiddleware(
                interrupt_on={
                    # Require approval for sensitive operations
                    "send_email": True,
                    "delete_database": True,
                    # Auto-approve safe operations
                    "search": False,
                })
                ],
            # Persist the state across interrupts
            checkpointer=InMemorySaver(),
)

# Human-in-the-loop requires a thread ID for persistence
config = {"configurable": {"thread_id": "001"}}

# Agent will pause and wait for approval before executing sensitive tools
result = agent.invoke(
    {"messages": [{"role": "user", "content": "Send an email to the team, tell them we will be back in 2 hours"}]},
    config=config
)
interrupts = result.get("__interrupt__", "No interrupt")
if interrupts != "No interrupt":
    for interrupt in interrupts:
        action_requests = interrupt.value.get("action_requests", [])
        review_configs = interrupt.value.get("review_configs", [])
        for action_request in action_requests:
            tool_name = action_request['name']
            tool_args = action_request['args']
            msg = action_request['description']
            print(msg)
            print(f"需要审批的操作: {tool_name}")
            print(f"操作参数: {tool_args}")

print("=" * 30 + "人工审批" + "=" * 40 )
human_decision = input("请输入您的审批意见(approve/reject/edit): ")

if human_decision == "approve":
    # 批准
    result = agent.invoke(
        Command(resume={"decisions": [{"type": "approve"}]}),
        config=config  # Same thread ID to resume the paused conversation
    )
    print(result['messages'])
elif human_decision == "edit":
    # 编辑
    result = agent.invoke(
        Command(resume={"decisions": [{"type": "edit", "edited_action": {
                            # Tool name to call. Will usually be the same as the original action.
                            "name": "send_email",
                            # Arguments to pass to the tool.
                            "args": {"recipient": "team@xxxx.com", "content": tool_args['content']},}
                            }]}),
        config=config  # Same thread ID to resume the paused conversation
    )
    print(result['messages'])
else:
    # 拒绝
    result = agent.invoke(
        Command(resume={"decisions": [{"type": "reject", "message": "已拒绝执行发送邮件。"}]}),
        config=config  # Same thread ID to resume the paused conversation
    )
    print(result['messages'])

4、执行生命周期(Execution Lifecycle)

人工协作中间件定义了一个模型后钩子(after_model hook),此钩子会在模型生成响应之后、任何工具调用执行之前运行,具体流程如下:

  • 智能体调用模型以生成响应。
  • 中间件检查响应中是否包含工具调用。
  • 若存在任何需要人工输入的调用,中间件会构建一个包含 "操作请求"(action_requests)和 "审核配置"(review_configs)的 HITL 请求(HITLRequest),并触发中断。
  • 智能体等待人工决策。
  • 根据HITL响应(HITLResponse)中的决策结果,中间件执行已批准(approved)或已编辑(edited)的调用,为已拒绝(rejected)的调用生成工具消息(ToolMessage),随后恢复执行流程。

5、自定义HITL逻辑

对于更具特殊性的工作流,你可以直接借助 "中断原语"(interrupt primitive)和 "中间件抽象层"(middleware abstraction)构建自定义HITL逻辑。 请先参考上文所述的 "执行生命周期",理解如何将中断功能集成到智能体的运行流程中。

相关推荐
2501_930412272 小时前
如何添加清华源到Conda?
开发语言·python·conda
2501_930412272 小时前
如何删除Conda中的清华源配置?
开发语言·python·conda
程序猿20232 小时前
Python每日一练---第十二天:验证回文串
开发语言·python
沿着路走到底3 小时前
python 判断与循环
java·前端·python
jz_ddk4 小时前
[数学基础] 瑞利分布:数学原理、物理意义及Python实验
开发语言·python·数学·概率论·信号分析
王国强20094 小时前
LangChain智能体核心组件概述
agent
陈辛chenxin4 小时前
【大数据技术06】大数据技术
大数据·hadoop·分布式·python·信息可视化
AI大模型4 小时前
本地部署vLLM+Qwen3:高性能大模型推理引擎,比Ollama强在哪?
程序员·llm·agent