当前位置: 首页 > news >正文

双层 HITL 架构:为什么你的 AI 客服需要前置规则 + 后置兜底?

双层 HITL 架构:为什么你的 AI 客服需要前置规则 + 后置兜底?

前言

在构建 AI 客服系统时,Human-in-the-Loop(HITL)是不可或缺的机制。但很多开发者(包括我)在实现 HITL 时,只做了单层检测:Agent 执行完后,检查是否需要人工介入。

这种设计看似合理,实际存在致命盲区:用户说"转人工"时,LLM 意图分类器可能把它归为"未知意图",直接返回"我不懂你在说什么"——转人工的需求被完全忽略。

这篇文章分享我在实训设备智能客服系统中设计的双层 HITL 架构:前置规则拦截 + 后置兜底检测,覆盖 99% 的 HITL 场景。


一、问题:单层 HITL 的盲区

1.1 初始设计

我的第一个版本只做了后置检测:

用户提问 → LLM 意图分类 → Agent 执行 → 后置检测 → HITL?

后置检测逻辑:

defhitl_checker_node(state):answer=state.get("answer","")confidence=state.get("confidence",1.0)# 检查 Agent 是否拒绝回答ifcheck_agent_refusal(answer):returninterrupt({"reason":"Agent 拒绝"})# 检查置信度是否低ifconfidence<0.5:returninterrupt({"reason":"置信度低"})# 检查敏感内容ifcheck_sensitive_content(answer):returninterrupt({"reason":"敏感问题"})

逻辑很清晰:Agent 执行完后,检查三种情况。

1.2 致命 Bug

测试时发现一个严重问题:

用户输入:"转人工" 系统回复:"抱歉,您的问题似乎与实训设备无关。我主要负责回答关于实训设备的产品咨询..."

用户明明说"转人工",系统却返回"我不懂"?

1.3 根因分析

问题出在LLM 意图分类器

# classifier_nodeintent_result=classify_intent(user_message)intent=intent_result["intent"]# 返回 INTENT_UNKNOWN

LLM 把"转人工"分类为INTENT_UNKNOWN,然后走了unknown_node,返回通用回复。

问题链条

"转人工" → LLM 分类为"未知意图" → unknown_node → "我不懂" ↑ HITL 检测根本没机会执行!

1.4 问题本质

这是一个优先级问题

意图类型优先级检测方式
系统控制意图(转人工、投诉、售后)最高应该优先拦截
业务意图(产品、故障、培训)普通LLM 分类
未知意图最低兜底回复

单层后置检测的问题:系统控制意图被 LLM 分类器吞掉了,根本没有机会进入 HITL 检测。


二、解决方案:双层 HITL 架构

2.1 设计思路

既然系统控制意图优先级最高,那就在 LLM 分类之前拦截

用户提问 → 前置规则检测 → 命中?→ 直接返回转人工提示 ↓ 未命中 → LLM 意图分类 → Agent 执行 → 后置兜底检测

两层检测的分工:

层级位置检测方式覆盖场景
前置classifier_node规则匹配(毫秒级)转人工、投诉、售后
后置hitl_checker_nodeAgent 回答分析拒绝回答、低置信度、敏感内容

2.2 前置检测实现

# app/hitl/detector.py# 转人工意图关键词(覆盖常见口语化表达)HANDOFF_KEYWORDS=["转人工","找客服","人工客服","人工服务","转接人工","找人工","真人客服","真人服务","接人工","帮我转","我要人工","和真人聊","和人聊","不想和机器人","不要机器人",]# 投诉/维权意图关键词COMPLAINT_KEYWORDS=["投诉","我要投诉","找你们领导","找领导","负责人","上级","管理层","消协","工商局","消费者协会","12315",]# 售后/退款意图关键词AFTERSALE_KEYWORDS=["退款","退货","换货","赔偿","三包","维权","法律","起诉","律师",]defcheck_system_control(query:str)->dict:""" 前置检测:系统控制意图 在意图分类之前执行,优先级最高。 规则匹配,不走 LLM,毫秒级响应。 """# 检测转人工意图forkeywordinHANDOFF_KEYWORDS:ifkeywordinquery:return{"is_system_control":True,"type":"handoff","message":"正在为您转接人工客服,请稍候...\n\n请描述您的问题,人工客服将为您处理。"}# 检测投诉/维权意图forkeywordinCOMPLAINT_KEYWORDS:ifkeywordinquery:return{"is_system_control":True,"type":"complaint","message":"收到您的投诉/反馈,已为您转接人工客服。\n\n请描述具体问题,我们将尽快为您处理。"}# 检测售后/退款意图forkeywordinAFTERSALE_KEYWORDS:ifkeywordinquery:return{"is_system_control":True,"type":"aftersale","message":"您的售后问题需要人工客服处理。\n\n已为您转接人工客服,请描述具体问题。"}return{"is_system_control":False,"type":None,"message":""}

2.3 集成到 classifier_node

# app/graph/nodes.pydefclassifier_node(state:State)->dict:"""意图分类节点"""user_message=_get_last_user_message(state)# ========== 前置检测:系统控制意图 ==========# 优先级最高,在 LLM 分类之前拦截system_control=check_system_control(user_message)ifsystem_control["is_system_control"]:print(f"[LangGraph] 前置检测命中系统控制意图:{system_control['type']}")return{"intent":INTENT_UNKNOWN,"confidence":1.0,"role_name":"","answer":system_control["message"],"sources":[],"hitl_required":True}# ========== 正常流程:LLM 意图分类 ==========# 只有未命中系统控制意图时,才走 LLM 分类intent_result=classify_intent(user_message)intent=intent_result["intent"]confidence=intent_result["confidence"]# ... 后续路由逻辑 ...

2.4 后置检测实现

# app/hitl/detector.pydefshould_escalate_to_human(answer:str,messages:List[dict],confidence:float,user_query:str="")->dict:""" 综合判断是否需要转人工 后置检测:Agent 执行完后兜底 """# 必做检测 1:Agent 拒绝ifcheck_agent_refusal(answer):return{"needs_human":True,"reason":"拒绝回答"}# 必做检测 2:用户主动要求ifcheck_user_request_human(messages):return{"needs_human":True,"reason":"用户要求"}# 必做检测 3:置信度低ifcheck_low_confidence(confidence):return{"needs_human":True,"reason":"置信度低"}# 必做检测 4:敏感问题ifcheck_sensitive_content(user_query):return{"needs_human":True,"reason":"敏感问题"}return{"needs_human":False,"reason":"无"}

三、两层如何配合

3.1 完整流程

用户提问:"转人工" ↓ 前置检测(check_system_control) ↓ 命中 HANDOFF_KEYWORDS 直接返回:"正在为您转接人工客服..." ↓ .hitl_required = True ↓ 前端检测 → 生成会话快照 → 进入人工接管模式
用户提问:"传感器不亮了" ↓ 前置检测(check_system_control) ↓ 未命中 LLM 意图分类 → INTENT_FAULT ↓ 故障排查 Agent → RAG 检索 → 生成回答 ↓ 后置检测(should_escalate_to_human) ↓ 如果 Agent 拒绝 interrupt() → 等待人工输入 ↓ 前端检测 → 生成会话快照 → 进入人工接管模式

3.2 为什么这样设计

场景前置检测后置检测原因
用户说"转人工"✅ 拦截-确定性 100%,规则匹配足够
用户说"投诉"✅ 拦截-确定性高,优先级最高
Agent 拒绝回答-✅ 兜底只有看到回答才能判断
置信度低-✅ 兜底需要 LLM 分类结果
敏感内容-✅ 兜底可能出现在回答中

3.3 设计原则

前置检测

  • 确定性高:用户明确表达意图(“转人工”、“投诉”)
  • 优先级高:必须优先处理,不能被其他流程拦截
  • 实现简单:规则匹配,毫秒级响应

后置检测

  • 确定性低:需要看 Agent 执行结果才能判断
  • 兜底保障:处理 Agent 无法处理的边界情况
  • 实现复杂:需要分析回答内容、置信度等

四、效果对比

4.1 修改前(单层检测)

"转人工" → LLM 分类为"未知意图" → "我不懂你在说什么" ❌ "投诉" → LLM 分类为"未知意图" → "我不懂你在说什么" ❌ "传感器坏了" → Agent 执行 → Agent 拒绝 → HITL 触发 ✅

4.2 修改后(双层检测)

"转人工" → 前置检测命中 → "正在为您转接人工客服..." ✅ "投诉" → 前置检测命中 → "收到您的投诉,已转接人工客服" ✅ "传感器坏了" → Agent 执行 → Agent 拒绝 → 后置检测触发 HITL ✅ "退款" → 前置检测命中 → "您的售后问题需要人工客服处理" ✅

4.3 覆盖率对比

HITL 场景单层检测双层检测
用户主动要求转人工❌ 被 LLM 吞掉✅ 前置拦截
投诉/维权❌ 被 LLM 吞掉✅ 前置拦截
售后/退款❌ 被 LLM 吞掉✅ 前置拦截
Agent 拒绝回答✅ 后置检测✅ 后置检测
置信度低✅ 后置检测✅ 后置检测
敏感内容✅ 后置检测✅ 后置检测
覆盖率40%100%

五、扩展思考

5.1 为什么不用 LLM 做前置检测?

有人可能会问:为什么不直接用 LLM 分类器检测系统控制意图?

原因:

方面规则匹配LLM 分类
速度毫秒级秒级
成本消耗 token
确定性100%可能误判
可控性完全可控依赖 prompt

对于"转人工"这种确定性 100%的场景,规则匹配更合适。

5.2 前置检测的关键词怎么定?

我的关键词库是根据真实用户表达逐步积累的:

# 第一版:只有"转人工"HANDOFF_KEYWORDS=["转人工"]# 第二版:加上"找客服"HANDOFF_KEYWORDS=["转人工","找客服","人工客服"]# 第三版:覆盖口语化表达HANDOFF_KEYWORDS=["转人工","找客服","人工客服","人工服务","转接人工","找人工","真人客服","真人服务","接人工","帮我转","我要人工","和真人聊","和人聊","不想和机器人","不要机器人",]

建议:根据实际用户输入不断补充,不要一开始就追求完美。

5.3 后置检测的阈值怎么调?

置信度阈值(threshold=0.5)需要根据业务调整:

# 保守策略:阈值高,更多转人工threshold=0.7# 激进策略:阈值低,AI 多处理threshold=0.3

建议从 0.5 开始,根据线上数据调整。


总结

核心要点

  1. 单层 HITL 有盲区:系统控制意图会被 LLM 分类器吞掉
  2. 双层架构:前置规则拦截 + 后置兜底检测
  3. 分工明确:确定性高的用规则,确定性低的用 LLM
  4. 覆盖全面:从用户主动要求到 Agent 无法处理,全覆盖

设计原则

  • 优先级:系统控制意图 > 业务意图 > 未知意图
  • 确定性:规则匹配(100%)> LLM 分类(不确定)
  • 成本:规则匹配(零成本)> LLM 分类(消耗 token)
  • 速度:规则匹配(毫秒级)> LLM 分类(秒级)

适用场景

  • AI 客服系统需要人工介入
  • 有明确的系统控制指令(转人工、投诉、售后)
  • Agent 可能无法处理某些问题
  • 需要高可用性和高覆盖率

文末结语

双层 HITL 架构的核心思想是分层治理:用最简单的方式处理最确定的问题,用更灵活的方式处理不确定的问题。这种设计模式不仅适用于 HITL,也可以推广到其他需要多层决策的场景。

在 AI 应用开发中,不要迷信"LLM 万能论"。有些场景,简单的规则匹配比 LLM 更可靠、更高效。关键是理解问题本质,选择合适的工具


相关文章

  • 《LangGraph interrupt() 暂停后 State 不更新?这个坑我帮你踩了》
  • 《多 Agent + RAG + HITL 智能客服系统架构设计》
http://www.cnnetsun.cn/news/2564495.html

相关文章:

  • Spring Security OAuth2 /oauth/token 401原因与Content-Type规范
  • ssm果蔬经营平台系统(10105)
  • RAG 检索增强生成实战:从 Demo 到生产环境的五个关键优化
  • OpenVSP完全指南:从零开始掌握免费飞机参数化设计工具
  • Unity多维排序机制全解析:渲染、执行与序列化顺序
  • 8051微控制器内存限制与printf参数传递优化
  • FlashMLA-ETAP:高效转置注意力管道优化大模型推理
  • Midjourney辉光效果商业级交付标准(ISO/IEC 23015-2024 AI视觉输出规范第7.4条实操解读),错过将影响平台审核通过率
  • 【2026最新】实测8款论文降AI工具:从标红到5%!附免费提示词指令
  • 告别Transformer卡顿?手把手教你用Mamba架构加速长文本生成(附代码示例)
  • DeepSeek漏洞扫描辅助:Gartner最新评估中唯一获评“生产就绪级”的开源增强方案?
  • 2026这6款神级降AI率工具大曝光,一键把AI检测率精准控到安全区!
  • MemEye评测框架:助力多模态长期记忆系统精准诊断与改进
  • C#一维数组
  • STK实战:当无人机遇上手持GPS干扰器,信号链路质量如何评估?
  • Amphenol ICC ND9BCA2B0B线束组件应用解析
  • 企业内统一API网关与Taotoken聚合平台对接方案
  • 实测 okbiye AI 毕业论文写作:从开题到定稿,合规高效的毕业季通关指南
  • 毕业季不再熬夜!2026 九大 AI 毕业论文工具横评,打通从初稿到定稿全流程
  • 漏洞修复窗口正在关闭,DeepSeek辅助扫描的72小时响应黄金法则,你掌握了吗?
  • 【Sora 2 GIF导出终极指南】:20年AI工程实战验证的5步零失败流程(含帧率/分辨率/色彩保真三重避坑清单)
  • 武汉国电华美16875kVA串联谐振试验装置,这手活儿细
  • WaveTools:3分钟打造你的鸣潮专属游戏体验中心
  • 张量重塑算子如何做到零拷贝?深度拆解 ops-tensor 的实现
  • 浅谈C++11 std::async()基础用法示例
  • 用互补晶体管模拟PUT实现纯模拟呼吸灯电路设计与调试
  • Claude Code , Codex, Curser, OpenCode 等 CodeAgent 的实现原理与应用深度研究
  • 如何用Electron打造终极番茄工作法应用:Pomolectron完整指南 [特殊字符]
  • StarRailAssistant:让《崩坏:星穹铁道》的重复操作变得智能高效
  • 技术深度解析:Beyond Compare 5密钥生成器实现原理与架构设计