LangChain 中间件实战:HumanInTheLoopMiddleware 实现高危操作人工审核
2026/7/31 5:12:28 网站建设 项目流程

1. 引言

在构建基于大语言模型(LLM)的智能体(Agent)时,我们常常需要让 Agent 执行一些具有潜在风险的操作,例如直接操作数据库、调用外部 API 或执行系统命令。为了确保安全性和可控性,引入人工审核环节至关重要。LangChain 提供了强大的中间件(Middleware)机制,其中HumanInTheLoopMiddleware便是实现“人在回路”(Human-in-the-loop)审核的利器。

本文将深入解析HumanInTheLoopMiddleware的工作原理,并通过一个完整的代码示例,演示如何拦截 Agent 对数据库的高危写操作(如INSERTUPDATEDELETE),在人工确认、拒绝或修改后才继续执行。

2. 核心概念与依赖

2.1 什么是中间件(Middleware)?

在 LangChain 的 Agent 执行流程中,中间件是一种可插拔的组件,它能够在 Agent 调用工具(Tool)之前之后介入,实现诸如日志记录、权限检查、结果修改或(本文重点)人工中断等功能。

2.2 HumanInTheLoopMiddleware

HumanInTheLoopMiddlewarelangchain.agents.middleware模块提供的一个中间件。它的核心功能是:根据预定义的规则(interrupt_on)在特定工具被调用时暂停 Agent 执行,等待外部(例如用户、审批系统)输入决策,然后根据决策结果恢复执行。

2.3 关键依赖安装

确保已安装以下库:

pipinstalllangchain langchain-core langgraph

本文示例还假设你有一个可用的 LLM 模型。示例中使用了一个名为get_deepseek_model的工厂函数来获取模型,你可以替换为 OpenAI、Azure OpenAI 或本地模型。

3. 代码实现详解

3.1 导入与初始化

fromlangchain.agentsimportcreate_agentfromlangchain.agents.middlewareimportHumanInTheLoopMiddleware,InterruptOnConfigfromlangchain_core.messagesimportHumanMessagefromlangchain_core.toolsimporttoolfromlanggraph.checkpoint.memoryimportInMemorySaverfromlanggraph.typesimportCommandfrommethod.model_factoryimportget_deepseek_model# 获取模型实例model=get_deepseek_model()

3.2 定义高危工具

我们定义一个模拟的数据库写操作工具。在实际应用中,这里应连接真实的数据库。

@tooldefdangerous_write(sql)->str:"""对数据库执行风险操作(插入/更新/删除)。当请求涉及数据库写操作或出现以‘SQL’开头的指令时,必须调用本工具"""returnf'[模拟执行]{sql}'

关键点:工具的description非常重要,它引导 LLM 在何时调用此工具。这里明确要求“当请求涉及数据库写操作或出现以‘SQL’开头的指令时,必须调用本工具”。

3.3 配置人工审核中间件

hitl=HumanInTheLoopMiddleware(interrupt_on={'dangerous_write':InterruptOnConfig(allowed_decisions=['approve','reject','edit'],description='请确认是否执行此高危操作')})
  • interrupt_on: 一个字典,指定哪些工具的调用需要中断。键是工具名('dangerous_write'),值是InterruptOnConfig配置对象。
  • allowed_decisions: 定义人工可以做出的决策类型。通常包括:
    • 'approve': 批准执行。
    • 'reject': 拒绝执行。
    • 'edit': 修改工具调用的参数后再执行。
  • description: 中断时显示给人工审核者的提示信息。

3.4 创建带中间件的 Agent

agent=create_agent(model=model,middleware=[hitl],# 将中间件加入执行链tools=[dangerous_write],system_prompt=""" 只用一句极短中文回答(≤20字)。 凡是涉及数据库写操作,或消息以“SQL”开头时,必须调用工具dangerous_write,不得直接回答 """,checkpointer=InMemorySaver()# 用于保存中断状态,便于恢复)CFG={'configurable':{'thread_id':'test-hitl'}}# 会话配置

system_prompt进一步强化了 LLM 的行为约束,确保其严格遵守工具调用规则。

3.5 实现中断处理逻辑

当中间件触发中断后,Agent 的invoke方法会返回一个包含"__interrupt__"键的状态。我们需要编写处理函数来获取人工决策,并使用Command(resume=...)来恢复 Agent 执行。

state={'messages':[]}defhandle_interrupt(result):"""处理HITL中断:从命令行读取决策,并用Command(resume=...)恢复。"""interrupt=result.get("__interrupt__")print(interrupt)print('开始人工干预')decision=input("请输入决策:'approve','reject','edit'\n").strip().lower()ifdecision=='approve':returnagent.invoke(Command(resume={'decisions':[{'type':'approve'}]}),config=CFG)elifdecision=='reject':returnagent.invoke(Command(resume={"decisions":[{"type":"reject","override":{"content":"[操作已被人工拒绝]"}}]}),config=CFG)elifdecision=='edit':new_sql=input("请输入您的新sql语句:")returnagent.invoke(Command(resume={"decisions":[{"type":"edit","edited_action":{"name":"dangerous_write","args":{"sql":new_sql}}}]}),config=CFG)else:print("输入的指令有问题,采用reject方案")returnagent.invoke(Command(resume={"decisions":[{"type":"reject","override":{"content":"[操作已被人工拒绝]"}}]}),config=CFG)

决策恢复机制

  • approve: 决策类型为approve,Agent 将使用原参数继续调用工具。
  • reject: 决策类型为reject,并提供一个override内容。Agent 不会调用工具,而是直接将此内容作为工具调用的结果返回给 LLM。
  • edit: 决策类型为edit,并提供edited_action指定新的工具名和参数。Agent 将使用新参数调用工具。

3.6 模拟多轮对话

conversation=['你是谁?',"SQL: INSERT INTO logs(content) VALUES ('hello');",'继续',"SQL: DELETE FROM orders WHERE created_at >= date('now','-7 days');"]fori,questioninenumerate(conversation,start=1):print(f"\n第{i}轮")print(f"Q:{question}")humanMessage=HumanMessage(content=f"{question}")state=agent.invoke({"messages":[humanMessage]},config=CFG)# 检查是否被中间件中断ifstate.get("__interrupt__"):state=handle_interrupt(state)print(type(state).__name__)print(state)answer=state['messages'][-1].contentprint(f"A:{answer}")

4. 执行流程与输出分析

运行上述代码,你将看到类似以下的交互过程:

第1轮(普通问答):

Q: 你是谁? A: [LLM的简短自我介绍,例如:“我是AI助手。”]

说明:第一轮不涉及 SQL,LLM 直接根据系统提示简短回答。

第2轮(触发中断):

Q: SQL: INSERT INTO logs(content) VALUES ('hello');

此时,LLM 识别到“SQL:”开头,决定调用dangerous_write工具。中间件检测到对该工具的调用,触发中断。控制台打印中断信息并等待输入:

开始人工干预 请输入决策:'approve','reject','edit'

假设用户输入approve,Agent 恢复执行,工具被调用,返回[模拟执行]INSERT INTO logs(content) VALUES ('hello');,LLM 最终输出该结果。

第3轮(不触发):

Q: 继续 A: [LLM的简短回答]

第4轮(再次触发中断):

Q: SQL: DELETE FROM orders WHERE created_at >= date('now','-7 days');

再次触发中断。此时用户可以尝试rejectedit决策。

  • 如果输入reject,最终回答将是[操作已被人工拒绝]
  • 如果输入edit,程序会提示输入新的 SQL,例如改为SELECT * FROM orders WHERE ...,然后 Agent 会用新 SQL 调用工具。

5. 总结与扩展

5.1 核心价值

HumanInTheLoopMiddleware为 AI Agent 系统提供了关键的安全护栏。它将自动化流程与人类判断相结合,特别适用于:

  • 数据库写操作:防止误删、误更新。
  • 金融交易:支付、转账前的二次确认。
  • 内容发布:敏感信息发布前的审核。
  • 系统控制:重启服务器、修改配置等危险命令。

5.2 扩展思路

  1. 图形化界面:将命令行输入替换为 Web 界面或聊天机器人按钮,提升用户体验。
  2. 多级审批:根据操作风险等级,设计串联多个审批节点的中间件。
  3. 超时与默认策略:为中断设置超时,超时后自动执行预设策略(如拒绝)。
  4. 审计日志:在中间件中记录所有中断事件、决策人、决策结果和时间戳,便于追溯。

通过本文的示例,你应该已经掌握了使用HumanInTheLoopMiddleware为你的 LangChain Agent 添加人工审核能力的基本方法。合理利用此机制,可以极大增强 AI 应用在真实生产环境中的安全性与可靠性。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询