news 2026/9/9 18:16:45

AI Agent实战:如何把转人工从默认出口改为最后出口

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI Agent实战:如何把转人工从默认出口改为最后出口

这次我们聊一个 AI Agent 实战里绕不开的问题:Agent 一遇到不懂的、不确定的、报错的情况,就直接把会话转给人工,这样到底行不行?

先说结论:在很多团队里,这个动作不是“兜底”,而是“甩锅”。用户感知是“这个 AI 像个摆设”,运营感知是“人工工单量根本没降下来”,技术感知是“Agent 好像做了,又好像没做”。真正合格的 Agent 实战,不是避免所有失败,而是建立一套“先自救、再降级、最后才转人工”的分层决策机制。

这篇文章会用一个具体的客服订单查询场景展开,讲清楚 AI Agent 为什么不能一遇到问题就转人工、在哪几个节点最容易误转、如何设计分级兜底策略、如何用代码实现自校验和降级链路,以及转人工时怎样做到“带着上下文转”而不是“干转”。

如果你正在做 AI Agent 落地,尤其是客服、售后、内部工单这类项目,这篇文章可以直接收藏。

1. 核心问题:转人工为什么成了 Agent 的“默认出口”

从实战看,Agent 转人工本身不是问题,问题是转得太早、太频繁、太无脑。常见的触发方式有三种:

  • 意图识别置信度低于阈值,直接转人工。
  • Tool 调用抛异常,直接转人工。
  • 大模型回答内容为空或校验不通过,直接转人工。

这三种方式看起来都有道理,但实际效果往往很差。原因在于:大多数“失败”并不是真的无法处理,而是 Agent 只尝试了一条路径,没有尝试第二条路径。

举一个真实的处理逻辑对比。一个订单查询 Agent,用户问“我前天买的那个东西怎么还没到”。如果走“意图识别失败转人工”的路线,结果就是用户被转走。但如果 Agent 具备以下能力,情况完全不同:

  1. 识别出这是“物流查询”意图,但置信度只有 0.6。
  2. 先用模糊查询把用户最近 30 天订单拉出来。
  3. 再筛选出状态为“已发货”且“物流未更新”的订单。
  4. 如果只有一条匹配,直接展示物流信息。
  5. 如果有多条匹配,反问用户确认订单编号。

这个过程看起来很简单,但覆盖了意图识别、工具调用、结果筛选、多轮澄清四个环节。任何一个环节设计不到位,Agent 都会倾向于“转人工”。

所以,这篇文章的核心观点是:转人工应该是一个 Agent 经过多级自救后的最终出口,而不是异常分支的默认出口。

2. 适用场景与使用边界

这个思路适用于以下场景:

  • 客服问答 Agent,包括电商、金融、企业服务等垂直领域。
  • 内部工单系统,比如 IT 支持、HR 咨询、财务报销。
  • 知识库问答场景,尤其是文档检索结果不理想时。
  • 需要调用多个外部工具的 Agent,比如查订单、查库存、查物流。

同样,也存在不适合硬扛的场景:

  • 涉及账号安全、资金操作、法律条款确认等高风险操作,人工介入必须前置。
  • 用户情绪激烈、多次表达不满时,继续让 Agent 尝试反而会放大负面体验。
  • 监管明确要求必须人工处理的流程,Agent 不能越权。

这里需要特别强调的是,安全边界比技术能力更重要。在任何线上系统中,人工永远不能被彻底移除,Agent 的“不转人工”不是把人工通道关掉,而是让转人工变得更有价值、更少发生、更精准。

从版权、隐私和合规角度来看,Agent 在处理用户订单、个人信息、聊天记录时,必须遵守最小化原则,只取解决当前问题所需的数据,不能把用户数据用于训练,也不能在无授权的情况下跨系统调用敏感接口。

3. 实战前置:一套可复用的分支决策结构

在写代码之前,我们先约定一套通用的 Agent 分支决策结构。后面所有示例都会围绕这套结构展开。

普通 Agent 的处理流程通常是一条直线:

接收用户消息 -> 意图识别 -> 调用工具 -> 返回结果

这套流程缺少三个关键节点:识别校验、结果校验、兜底策略。

改造后的决策链路应该是这样:

接收用户消息 -> 意图识别 -> 置信度判断 -> 工具调用 -> 结果校验 -> 生成回答 -> 质量校验 -> 返回结果 | | | | v v v v 澄清会话 失败重试 结果修正 降级回答

也就是说,Agent 在每一个关键节点都要回答一个问题:“当前结果能不能直接交给用户?”如果不能,是重新尝试、换一种方式,还是确认信息后继续。

下面用订单查询这个场景,逐步实现这套结构。

4. 环境准备与工程目录设计

这个实战案例不需要特定的一键部署工具,你可以基于现有的 Agent 框架来改,比如 LangChain、Spring AI、Dify 自定义工具流程,或者直接用 OpenAI/国产大模型的 Function Calling 接口。

建议的最小环境:

  • Python 3.10 或以上。
  • 一个可用的 LLM API,支持 Function Calling 或 Tool Use。
  • 一个测试用的模拟订单数据库,可以用 SQLite 或内存 JSON。
  • 日志系统,至少使用标准 logging。

目录结构可以参考:

agent_project/ ├── agent/ │ ├── __init__.py │ ├── core.py # Agent 主流程 │ ├── intent.py # 意图识别与置信度判断 │ ├── tools.py # 订单查询、物流查询工具 │ ├── validators.py # 结果校验器 │ └── fallback.py # 降级与转人工策略 ├── data/ │ └── orders.json # 模拟订单数据 ├── logs/ │ └── agent.log └── main.py # 入口脚本

这里有一个容易被忽略的点:目录分层决定排查效率。如果所有逻辑都写在一个文件里,出现问题后你很难判断到底是意图识别错了、工具返回错了,还是最终回答生成错了。

5. 核心逻辑一:意图识别不能只看置信度

很多团队做意图识别时,只保留一个最终标签和一个置信度分数,然后设定一个固定阈值,比如低于 0.7 就转人工。

这个做法的问题很明显:置信度的含义取决于模型训练数据分布。如果训练集里“查订单”的样本特别多,那么任何和订单沾边的输入都可能被分到这一类;如果训练数据很少,真正的订单查询也可能只有 0.5 的置信度。

更务实的做法是给意图识别加两个辅助信号:

  • 可澄清性:如果用户意图模糊,Agent 能不能通过反问来缩小范围。
  • 可替代工具:当前意图不能用,有没有其他工具可以完成相近目标。

代码示例:

# agent/intent.py def parse_intent(user_message: str) -> dict: # 实际项目中这里调用 LLM 或分类模型 # 返回结果包含 intent、confidence、status return { "intent": "query_logistics", "confidence": 0.62, "status": "ambiguous" } def should_clarify(intent_result: dict) -> bool: # 只有当结果不可靠,且意图可澄清时,才进入澄清流程 if intent_result["confidence"] < 0.7 and intent_result["status"] == "ambiguous": return True return False def clarify_message(original_message: str) -> str: # 返回澄清问题,由 Agent 发送给用户 return "您是想查询订单物流状态,还是想申请售后处理?"

这里的关键是:不是一低于阈值就转人工,而是先判断“这个模糊能不能通过对话消除”。绝大多数意图模糊,用一句反问就能解决。

6. 核心逻辑二:工具调用失败要有重试和替代路径

工具调用是 Agent 实战中出现问题最多的环节。失败原因通常包括:

  • 参数缺失,比如用户没有提供订单号。
  • 外部接口超时或暂时不可用。
  • 数据格式变化,解析失败。
  • 权限不足,Agent 没有访问某个系统的资格。
  • 查询结果为空。

针对这些失败,降级顺序应该是:

  1. 检查参数是否完整,不完整则反问用户补齐。
  2. 检查同一工具能否用其他参数重试。
  3. 尝试替代工具,比如物流查询失败时,用订单详情的物流字段代替。
  4. 如果前三步都失败了,才进入转人工流程。

代码示例:

# agent/fallback.py def call_with_fallback(user_info: dict, order_id: str = None): # 第一步:参数缺失时澄清 if not order_id: return {"action": "ask_user", "message": "请提供订单号或收件人手机号后四位"} # 第二步:主工具调用 result = query_order(user_id=user_info["id"], order_id=order_id) if result["status"] == "success": return {"action": "reply", "data": result} # 第三步:日志记录失败原因,并尝试替代工具 logger.warning(f"query_order failed: {result['error']}") alt_result = query_order_by_phone(user_id=user_info["id"], phone_tail=user_info.get("phone_tail")) if alt_result["status"] == "success": return {"action": "reply", "data": alt_result} # 第四步:保留结构化上下文,转人工 return { "action": "transfer_human", "reason": "主工具与替代工具均查询失败", "debug_info": { "order_id": order_id, "primary_error": result["error"], "alt_error": alt_result.get("error") } }

注意第四步:转人工时,一定要携带上下文。用户不需要对人工客服重复一遍自己的问题,人工客服也不需要从零开始排查。这就是“结构化转人工”和“干转”的核心区别。

7. 核心逻辑三:回答生成后必须经过质量校验

还有一个转人工高发节点是:大模型返回内容为空、内容与工具结果不一致、或者生成了模型自己编造的订单信息。

要解决这个问题,可以在回答前加一个校验器:

# agent/validators.py def validate_response(response_text: str, tool_data: dict | None) -> dict: # 情况一:内容为空 if not response_text or len(response_text.strip()) < 5: return {"valid": False, "reason": "empty_response"} # 情况二:工具数据存在,但回答中缺少关键字段 if tool_data: expected_fields = tool_data.get("required_fields", []) missing = [f for f in expected_fields if f not in response_text] if missing: return {"valid": False, "reason": "missing_fields", "missing": missing} # 情况三:回答中包含明确的错误断言,比如“订单不存在”但实际查询到了订单 if tool_data and tool_data.get("order_exists") and "订单不存在" in response_text: return {"valid": False, "reason": "contradiction"} return {"valid": True}

有了这个校验器,Agent 在把回答发送给用户之前,可以多一步判断。如果回答不合法,宁可重新调用一次生成模型,也不要直接把错误内容发出去。

这一点对于客服场景尤其重要。用户可能无法分辨 AI 回答错在哪里,但一定会因为错误信息产生投诉。转人工之前先自检,是最便宜的纠错手段。

8. 完整实战:一个订单查询 Agent 的程序主流程

下面把上面的模块串起来,形成一个完整的、带分级兜底策略的 Agent 主流程。

# agent/core.py class OrderAgent: def __init__(self, user_info: dict): self.user_info = user_info self.max_retries = 2 self.conversation_history = [] def handle(self, user_message: str) -> dict: self.conversation_history.append({"role": "user", "content": user_message}) # 1. 意图识别 intent = parse_intent(user_message) # 2. 意图可澄清时优先澄清 if should_clarify(intent): return self._ask_user(parse_intent.none) # 实际会调用 LLM 生成澄清问题 # 3. 调用工具,带失败重试 tool_result = None for attempt in range(self.max_retries): tool_result = call_with_fallback(self.user_info, extract_order_id(user_message)) if tool_result["action"] != "ask_user": break logger.info(f"tool call attempt {attempt + 1} finished") if tool_result["action"] == "transfer_human": return self._transfer_human(tool_result) # 4. 生成回答 response_text = self._generate_response(user_message, tool_result) # 5. 回答质量校验 validation = validate_response(response_text, tool_result.get("data")) if not validation["valid"]: logger.warning(f"validation failed: {validation['reason']}") response_text = self._generate_response(user_message, tool_result, retry=True) self.conversation_history.append({"role": "assistant", "content": response_text}) return {"action": "reply", "message": response_text} def _transfer_human(self, reason_info: dict) -> dict: # 结构化转人工 return { "action": "transfer_human", "message": "我来为您转接人工客服", "context": { "user_id": self.user_info["id"], "reason": reason_info["reason"], "debug_info": reason_info.get("debug_info"), "history": self.conversation_history[-6:] } }

这个流程的核心变化在于:每一步都有“返回起点重新尝试”的能力,而不是直接进入人工通道。人工转接被放在最后,且自带完整的上下文信息。

9. 功能测试与效果验证

写完了逻辑,下一步就是验证。建议从以下几个维度测试这类 Agent。

9.1 模糊意图测试

输入:“我买的东西呢?”

预期结果:Agent 不是直接转人工,而是反问用户“您是想查物流、申请退款,还是咨询售后政策?”

判断标准:只要能进入澄清流程,就说明意图识别模块的降级策略生效。

9.2 工具参数缺失测试

输入:“帮我查一下订单”

预期结果:Agent 获取不到订单号,应该要求用户补充。

失败情况:如果 Agent 直接说“查询失败转人工”,说明参数缺失的兜底逻辑没有生效。

9.3 工具失败重试测试

模拟主查询工具返回超时。

预期结果:Agent 自动记录日志,并改用替代工具查询。用户无感知。

判断标准:日志中能看到primary_erroralt_result

9.4 回答质量校验测试

构造一个场景,让第一轮生成回答不包含订单号,或者回答内容与工具返回矛盾。

预期结果:校验器拦截错误回答,触发重新生成。

判断标准:日志中出现validation failed记录,且用户最终收到的是修正后的回答。

9.5 转人工质量测试

当所有兜底策略都失败时,人工客服收到工单里应该包含:

  • 用户 ID。
  • 用户原始问题。
  • Agent 尝试过的动作。
  • 具体失败原因。
  • 最近的对话历史。

人工客服不需要重新询问用户基础信息,这是判断转人工设计是否合格的最重要指标。

10. 资源占用与性能观察

如果你使用的是云端大模型 API,性能观察的重点不在显存,而在调用次数、时延和 token 消耗。

建议在日志里记录以下指标:

  • 每个用户会话的意图识别耗时。
  • 工具调用重试次数。
  • 回答校验拦截次数。
  • 转人工次数与转人工原因分布。
  • 平均每次会话消耗 token 数。

如果是本地部署模型,比如用 vLLM 或 Ollama 跑开源模型,则需要额外观察:

  • 显存占用是否在请求高峰时溢出。
  • 模型推理延迟是否影响用户体验。
  • 长上下文输入是否导致首 token 延迟明显增加。

一个实操建议:为不同节点设置独立的日志字段,而不是全部塞进一条 message。结构化的日志字段可以直接接入 Prometheus 或 Elasticsearch,方便后续做监控告警。

11. 常见问题排查与解决方案

问题现象可能原因排查方式解决方案
Agent 频繁转人工意图识别阈值设置过高,且缺少澄清策略查看日志中转人工前置信度和状态增加澄清节点,降低阈值前先做对话澄清
工具调用失败后直接结束会话没有实现重试和替代工具检查工具调用分支逻辑加入参数补齐、重试、替代工具三级降级
回答内容与工具返回数据不一致生成环节没有把工具结果注入提示词,或注入后被截断对比工具返回数据和最终回答文案在生成前拼接工具结果,并用校验器检查关键字段
转人工工单信息量少转人工时只传了当前消息检查转人工函数上下文参数统一结构化工单格式,携带历史会话、调试信息
模型生成内容为空输出 token 限制太小查看 API 返回内容增加 max_tokens,并加入空内容重试
用户重复表达不满Agent 没有识别情绪状态检查是否有情绪识别或敏感词检测节点高风险情绪下,主动转人工而不是继续尝试

12. 最佳实践与合规建议

最后给出一套工程化建议,能帮你减少无效转人工,同时保证用户体验。

第一,不要全局只用一个提示词模板。订单查询和售后投诉的处理方式完全不同。建议按意图拆分提示词,并在系统 Prompt 中明确告诉模型:“当工具返回结果为 None 时,不要摘引不存在的字段。”

第二,所有工具调用必须有超时限制。外部接口一旦超时,要立即进入降级逻辑,不能在等待中无限阻塞用户会话。

第三,转人工不等于结束会话。转人工后,原始会话内容必须持久化,并在人工端显示完整上下文。这里可以使用 Redis 缓存会话状态,避免 Agent 进程重启导致上下文丢失。

第四,批量排查 Agent 问题时,不要用真实用户数据。建议准备一套脱敏的模拟数据集,把容易触发失败的输入整理成回归测试用例。

第五,涉及人脸、声音、订单数据、个人隐私时,必须遵循最小化访问原则。Agent 只允许读取完成当前任务所需的数据,不能跨权限调用接口,也不能将读取到的用户数据用于后续非授权场景。

第六,人工客服的角色不是“帮 AI 收拾烂摊子”,而是“处理 AI 确认无法处理的事情”。这个定位差别会在工单流转、绩效评估、系统设计上带来完全不同的方案。

13. 总结与下一步

AI Agent 转人工这个话题,本质上比拼的不是模型聪明不聪明,而是工程链路完不完整。一个遇到问题就转人工的 Agent,只是给人工客服增加负担;一个具备“澄清、重试、校验、降级”能力的 Agent,才能真正把人工工单量降下来,同时保证用户体验。

这篇文章的核心观点,简单概括为三条:

  • 意图识别不准时,先澄清再判断,不要直接转人工。
  • 工具调用失败时,先补齐参数、重试、换工具,再做最后兜底。
  • 转人工时必须携带上下文和调试信息,让人工客服能无缝接手。

你可以先从“工具失败重试”和“回答质量校验”这两个节点入手改造。这两个节点改造成本最低,收益最明显。改完之后再看日志里的转人工分布,会明显看到原因从“unknown”变成具体可排查的错误类型。

后续可以继续扩展的方向包括:多轮对话中的上下文裁剪策略、人工工单的自动分类与优先级判断、以及基于历史会话的 Agent 效果评估体系。方向很多,核心是一件:把转人工从“默认出口”改成“最后出口”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 18:16:07

Java入门术语全解析:从JDK到Lambda的人话翻译

能把人从"入门"劝退到"放弃"的&#xff0c;往往不是Java语法有多难&#xff0c;而是满屏的黑话&#xff1a;JDK、JVM、JRE、多态、泛型、Lambda、序列化……每个词单独看都认识&#xff0c;连在一起就集体装死。我当年学Java踩过的坑&#xff0c;至少有一半…

作者头像 李华
网站建设 2026/9/9 18:15:58

大数据可视化核心技术拆解:从架构设计到实时渲染的实战指南

1. 项目背景与核心痛点的重新认识做数据可视化这个方向这么多年&#xff0c;我越来越觉得&#xff0c;大数据领域里的“可视化”和传统意义上的“画图表”完全是两码事。刚入行那会儿&#xff0c;我以为掌握几个图表库、调整一下配色、把折线图柱状图堆到一张大屏上&#xff0c…

作者头像 李华
网站建设 2026/9/9 18:14:13

三步拿到八大网盘直链:网盘直链下载助手新手使用指南

三步拿到八大网盘直链&#xff1a;网盘直链下载助手新手使用指南 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云…

作者头像 李华
网站建设 2026/9/9 18:11:46

用 QtScrcpy 在电脑上显示与控制安卓:连接、键鼠映射与组控指南

用 QtScrcpy 在电脑上显示与控制安卓&#xff1a;连接、键鼠映射与组控指南 【免费下载链接】QtScrcpy Android real-time display control software 项目地址: https://gitcode.com/GitHub_Trending/qt/QtScrcpy QtScrcpy 是一款基于 Qt 框架的开源安卓投屏与控制工具&…

作者头像 李华
网站建设 2026/9/9 18:11:27

C#异步方法命名冲突引发支付重复扣款:事故复盘与五条防冲突规范

1. 一次支付重复事故的全过程复盘1.1 当天晚上的现象&#xff1a;对账报表先拉响警报那天是周四晚上十一点多&#xff0c;我正在改一个定时任务&#xff0c;群里突然被对账组拉了个语音会议。财务说&#xff0c;当天有四十多笔订单在支付渠道侧被扣了两次款&#xff0c;金额从几…

作者头像 李华
网站建设 2026/9/9 18:09:40

论文提交前的检查工具怎么配齐?查重、AIGC、格式、终检四环节

论文被打回返工&#xff0c;大多不是写的问题&#xff0c;而是提交前检查漏了项&#xff1a;查重超标、AI 率过高、格式不符&#xff0c;任一环节出错都可能在送审时被拦。把查重、AIGC、格式、终检四环节的工具配齐&#xff0c;比临时补救省时&#xff1b;文末附免费权益入口。…

作者头像 李华