你现在在做的事
你是不是也在做一个“全自动”的AI客服或规划助手?把所有用户请求丢给大模型,指望它自己调用API、生成回答、完成整个流程——然后发现用户体验一团糟:用户抱怨“机器人听不懂”“订错行程”“无法处理特殊需求”。
Expedia CEO 前两天说了句大实话:端到端的AI聊天机器人目前不实用。他们两年前推出旅行规划助手Roamie,现在发现客户更想要有人类参与的协作体验。这不是AI能力不够,而是架构错了。
自动化后的效果对比
| 维度 | 全自动AI(典型) | 混合架构(本文方案) |
|---|---|---|
| 用户满意度 | 低(60%以下) | 高(85%以上,Expedia内部数据) |
| 错误率 | 高(15-20% 关键错误) | 低(<5% 需人工介入) |
| 开发成本 | 初期高,维护更高 | 中等,但可快速迭代 |
| 可解释性 | 几乎为零 | 可追溯 |
关键在于:把AI当做一个“聪明的前端路由”,而不是终点。
工具组合和流程图

核心组件:
- LangChain(编排层)——控制对话状态、调用工具、决定是否转人工
- 函数调用(工具层)——搜索航班、查询价格、预订(每个都是原子操作)
- 人工交接API(非AI节点)——使用Zendesk/Talkdesk或自定义WebSocket
- 向量检索(知识库)——FAQ、政策、常见问题
流程图(简化):
用户输入 → Intent识别 → 需要工具?→ 调用对应API → 验证结果 → 完成?→ 结束
↓ 失败/不清晰 No
人工交接 ←──────── 回到对话
关键区别:任何一次工具调用失败或置信度低于0.7,立即触发人工交接。
关键节点配置
1. 提示词设计(用LangChain的Prompt Template)
from langchain.prompts import ChatPromptTemplate
SYSTEM_PROMPT = """你是一个旅行助手,但**不是全能规划者**。你的角色是:
1. 理解用户意图,归类到以下子任务:{available_tasks}
2. 对于每个子任务,调用对应的工具函数并返回结果
3. **必须遵守的规则**:
- 如果用户需求涉及多个步骤,**只执行当前明确的一步**
- 如果用户描述模糊(比如“帮我规划去巴黎的行程”),不要自行补充细节,而是触发人工交接
- 如果任何工具返回错误或空结果,立即触发 handoff
- 每个消息回复后,判断是否需要人工跟进,如果需要返回 JSON flag
当前可用工具:{tools}
用户请求:{input}
请输出 JSON 格式:{{ "task": "工具名称或handoff", "params": {{...}}, "confidence": 0.0-1.0 }}"""
prompt = ChatPromptTemplate.from_messages([
("system", SYSTEM_PROMPT),
("human", "{input}")
])
个人观点:很多团队把系统提示写成“你是一个贴心助手,能处理任何问题”,这是灾难。要明确边界,让AI知道自己什么时候该闭嘴。
2. 人工交接触发条件
def should_handoff(state: DialogState) -> bool:
# 条件1:置信度低于阈值
if state.last_confidence < 0.7:
return True
# 条件2:连续两次工具调用失败
if state.consecutive_failures >= 2:
return True
# 条件3:用户明确要求
if "转人工" in state.last_input or "找人工客服" in state.last_input:
return True
# 条件4:涉及多步骤复杂规划
if state.require_multistep and state.step_completed == 0:
return True
return False
3. 人工交接API示例(WebSocket)
async def handoff_to_agent(user_id, context):
# 将完整对话上下文传给人工代理
await websocket.send_json({
"type": "handoff",
"user_id": user_id,
"context": {
"dialog_history": context.history[-20:],
"current_intent": context.current_intent,
"failed_attempts": context.failures,
"user_profile": await get_user_profile(user_id)
}
})
# 同时给用户推送等待消息
return {"status": "transferred", "queue_position": 1}
常见问题和调试技巧
Q1: 人工交接后用户重新解释需求,浪费客户时间
→ 必须传递完整上下文,让人工代理看到AI刚才做了什么、尝试了什么。我在项目里用“会话摘要+最后3轮对话+失败日志”传给人工,客服满意度提升30%。
Q2: 用户对AI和人工来回切换感到困惑
→ 在UI上明确标识:“AI助手处理中” vs “您正在与人工客服小明对话”。切换时发一条通知:“已将您转接给人工客服,您刚才说的XXX已记录。”
Q3: 怎么避免AI自作主张帮用户下订单?
→ 所有写操作(预订、支付、修改)必须经过人工确认或要求用户二次确认。在工具调用后加一个confirm_step,让AI先返回结果,用户说“确认”再执行。
Q4: 如何测试这种混合架构?
→ 我用模拟用户 + 覆盖率映射。写一个自动化测试,生成100条边缘案例(模糊意图、多步骤、错误场景),检查AI是否正确触发handoff。重点测试那些“AI觉得自己能处理但实际不能”的情况。
对你意味着什么
如果你正在建AI客服/规划助手,马上检查你的架构:
- 有没有明确的“我不知道”的退路? → 没有?加handoff。
- 模型是否被允许调用多个工具创建复合结果? → 禁止,一次只干一件事。
- 错误处理是不是简单返回“抱歉,请重试”? → 应该直接转人工。
Expedia的教训是:别以为大模型出现就能替代人类。真正好的AI产品是懂得自己不是万能的。

最后,送一段我调试时常用的代码片段:
# 在LangChain的AgentExecutor里加入回调
from langchain.callbacks import StdOutCallbackHandler
handler = StdOutCallbackHandler()
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
handle_parsing_errors=True,
max_iterations=3,
early_stopping_method="generate",
callbacks=[handler]
)
让每次工具调用和思考过程都打印出来,你就能发现哪些地方AI应该放弃但还在死磕。