设计一个智能客服系统
一句话回答
核心是意图识别 + 分流:常见问题走知识库 RAG;查订单、退款这类业务走工具调用,并且用户身份由服务端根据登录态注入,不能由模型传入;需要多项信息的业务用多轮对话收集,涉及资金的写操作走固定流程并让用户确认;识别到不满、反复解决不了或高风险的问题时转人工,并带上对话摘要。上线后用对话质检发现问题,把自助解决率、转人工率、满意度放在一起衡量效果;大促高峰提前扩容,并准备分级降级方案。
详细解析
第一步:澄清需求
- 业务范围:以电商为例,咨询(发货时间、退换货政策)、查询(订单、物流)、办理(退款、改地址)、投诉
- 渠道:网页、App、小程序,还是也有电话?电话要接入语音识别和合成
- 人工客服:要对接已有的客服工作台和工单系统,坐席数量决定了转人工的容量
- 规模:日常和大促高峰的会话量,高峰可能是平时的数倍
- 约束:政策类回答必须准确;资金操作要可审计;对话涉及个人信息,要满足隐私要求
第二步:整体架构
多渠道接入(网页、App、小程序)
▼
接入层:会话管理、用户身份(登录态 → user_id)、消息去重
▼
对话编排(流程状态机 + 大模型)
├─ 意图识别与路由
│ ├─ 政策咨询、常见问题 ──► 知识库 RAG(带出处、带生效时间)
│ ├─ 查询和办理 ──► 业务流程 + 工具:查订单、查物流、申请退款
│ ├─ 闲聊、超出范围 ──► 固定话术,引导回业务
│ └─ 转人工 ──► 客服工作台(排队、分配坐席、对话摘要)
├─ 情绪和风险识别(每一轮都做)
└─ 输入输出内容审核
▼
数据:会话日志 → 质检、指标看板、知识库缺口分析
为什么不是"一个 Agent 挂上所有工具":退款、改地址都有明确的业务规则,用流程(状态机)控制步骤、用模型负责理解和生成,更可控也更好测试。两者的取舍见工作流还是 Agent。
第三步:核心模块和数据模型
意图识别和路由:明确的表达("转人工""投诉")用规则直接命中;其余交给分类模型或大模型,输出意图、置信度和抽取到的信息(订单号、商品),用结构化输出约束格式。置信度低时反问澄清,而不是猜;一句话里有多个意图就逐个处理。
知识库问答:政策和常见问题由运营维护,每条带生效时间和负责人。和标准问题高度相似时,直接返回审核过的标准答案;其余用 RAG 生成并附上出处,资料里没有就转人工,不让模型凭自己的知识回答政策问题。知识库的设计见知识库问答系统。
工具调用和身份校验:工具拿到的用户身份来自服务端的会话,模型只能传订单号这类业务参数,工具内部校验订单是否属于当前用户(见代码示例)。未登录的用户先用手机验证码验证身份,才能查询个人信息。
多轮对话收集信息:以退款为例,需要订单、商品、原因、退款方式几项信息。状态机记录已经收集到的内容,模型从用户的自由回答里抽取,缺什么问什么;能让用户选择的地方就给卡片(比如列出最近的订单供点选),减少输入错误。提交前把完整信息展示给用户确认,调用接口时带上幂等键。
转人工:
- 触发条件:用户明确要求;连续表达不满;同一个问题几轮都没解决;投诉、法律纠纷、大额退款等高风险问题;模型的置信度持续偏低
- 交接内容:结构化摘要(问题是什么、已经做过什么、收集到的信息、用户情绪)加完整对话记录,人工坐席不用让用户从头再说一遍
- 没有空闲坐席时,告知排队位置,或者转为留言工单、约定回电
数据模型:
conversations:渠道、用户、状态(机器人接待 / 排队中 / 人工接待 / 已结束)、当前意图、已收集的信息(JSON)、满意度messages:会话 ID、发送方(用户 / 机器人 / 坐席)、内容、识别出的意图和置信度handoffs:会话 ID、转人工的原因、摘要、坐席 ID、排队和接起的时间kb_entries:标准问题、相似问法、答案、生效和失效时间、负责人、版本
第四步:关键难点
回答必须准确:客服说出的政策和承诺,用户会当成公司的正式答复。2024 年加拿大航空的一起裁决中,网站的客服机器人告诉乘客,丧亲优惠票价可以在购票后再申请退还差价,实际政策并不允许;航空公司主张不该为机器人的说法负责,裁决没有采纳,判它赔偿乘客。所以政策类问题只依据知识库回答;模型不能自行承诺补偿和折扣;涉及金额的结论由业务系统计算,而不是由模型生成。
对话质检:人工质检只能抽查一小部分对话,现在可以用模型按评分细则检查全部对话:问题是否解决、回答是否符合知识库、有没有越界承诺、语气是否得当。低分对话进入人工复核;把没解决的问题聚类,就能找到知识库的缺口。
指标要放在一起看:
| 指标 | 含义 | 注意 |
|---|---|---|
| 自助解决率 | 没有转人工、且一段时间内没有再次咨询同一问题的会话占比 | 只看"没转人工"会高估,用户可能只是放弃了 |
| 转人工率 | 转到人工的会话占比 | 不能为了压低它,让用户找不到人工入口 |
| 满意度 | 会话结束后用户的评价 | 主动评价的用户有偏差,要结合差评原因分析 |
| 重复咨询率 | 同一问题短期内再次咨询的比例 | 反映"表面上解决了,实际没解决" |
高峰扩容和降级:大促前按预估量扩容无状态服务,和模型供应商提前确认额度,或者接入多个供应商;高频问题("什么时候发货")缓存答案,并提前在入口发布公告。资源不够时分级降级:
- 换成更小、更快的模型
- 只返回知识库里的标准答案,不再实时生成
- 质检、摘要等非实时功能改为事后批量处理
- 人工排队时告知预计等待时间,并提供留言入口
第五步:扩展与优化
- 坐席辅助:人工接待时给坐席推荐回复和相关知识,由坐席确认后发送
- 主动服务:物流异常时主动通知用户,从源头减少咨询量
- 语音渠道:接入语音识别和合成,延迟和打断的处理见实时语音助手
代码示例
查询订单的工具:模型只提供订单号,用户身份由服务端注入,模型无法伪造:
const getOrderTool = {
name: 'get_order',
description: '查询当前用户的一个订单的状态和物流。用户问订单进度、物流、发货时间时使用。',
parameters: {
type: 'object',
properties: { orderId: { type: 'string', description: '订单号' } },
required: ['orderId'],
},
// ctx 来自服务端的登录会话,不经过模型
async run({ orderId }: { orderId: string }, ctx: { userId: number }) {
const order = await db.orders.findById(orderId)
// 订单不存在和不属于当前用户返回同样的提示,避免被用来探测订单号
if (!order || order.userId !== ctx.userId) return { error: '没有找到这个订单' }
// 只返回回答需要的字段,不返回收货人的完整手机号和地址
return { status: order.status, logistics: order.logisticsSummary, updatedAt: order.updatedAt }
},
}
面试官可能追问
用户说"我要退款",可以让模型直接调用退款接口吗?
不可以。模型负责理解意图和收集信息,退款按固定流程走:校验订单状态和退款规则、由业务系统计算可退金额、把信息展示给用户确认、调用接口时带幂等键。超过一定金额或不符合规则的转人工审核。模型只能"发起申请",不能决定"批准"。
怎么防止用户通过对话越权查别人的订单,或者诱导客服做出承诺?
越权靠工具层的身份校验:用户身份由服务端注入,工具内部校验数据归属,模型说什么都改变不了结果。承诺靠流程和输出约束:补偿、折扣不在模型的能力范围内,要走人工或规则;输出审核检查有没有"保证退款""一定赔偿"这类越界表述。提示注入的通用防御见提示注入。
知识库里的政策更新了,怎么保证客服不再说旧政策?
每条知识带生效时间和失效时间,检索时按当前时间过滤;更新后重建索引,清掉相关的答案缓存;维护一组政策类的评测问题,每次知识库更新后自动跑一遍,确认回答已经变化。大促期间的临时规则到期自动下线。
怎么判断用户情绪不好、该转人工了?
结合多个信号:模型对每轮用户消息做情绪分类;规则匹配"投诉""没用""找人工"等表达;行为信号,比如短时间内重复发送同一个问题、连续点踩。单一信号容易误判,可以累计一个"不满分数",超过阈值就主动询问是否转人工。
易错点
- 让模型从对话里获取或传递用户身份,导致越权查询
- 用模型自己的知识回答政策问题,而不是只依据知识库
- 只盯着转人工率:把人工入口藏起来能压低这个数字,满意度却会下降
- 资金类操作交给模型直接执行,没有确认、幂等和审计
AI 模拟面试官
用自己的话回答,AI 对照参考答案打分、指出遗漏,再追问,最多 3 轮
这道题你掌握了吗?
选一个最接近的状态,没掌握的题会出现在"我的进度 · 待复习"里。
学习记录暂存在本机浏览器。登录后自动同步到账号,换设备也能看到。