☰
AI客服系统设计:避免死循环,让用户顺畅转人工
2026/9/30 10:49:48 网站建设 项目流程

消费者权益保护机构近期点名AI客服时,用户说得最多的一句话是“被客服当猴耍”。按字面能力看,AI客服已经能完成欢迎语、关键词识别、常见问题检索和自动生成回答;但按实际体验看,很多系统仍会在用户着急处理订单、投诉、退款、改地址时,给出无用的重复话术,甚至找不到人工入口。真正的问题不是大模型不会说话,而是客服系统没有设计出“知道自己不能做什么”的边界,也没有把“转人工”和“问题闭环”当成核心路由。

这篇文章不讨论具体企业案例,而是把客服投诉中最常见的问题翻译成一套工程改进思路:如何设计一个既能保留大模型自然语言能力、又不会把用户困在死循环里的AI客服系统。文章会从根因分析开始,逐步拆解能力边界、会话上下文、转人工链路、可观测性和回归测试,最后给出一个最小可运行的示例。

1. AI客服被点名:问题到底出在模型,还是出在系统设计?

1.1 用户投诉里的三类高频现象

用户对AI客服不满,通常不是因为它回答得不够“像人”,而是因为它没有解决实际问题。整理公开投诉和低分评价后,大概可以归成三类。

第一类是答非所问。用户输入“我要退货”,系统返回的是优惠券领取方法;输入“我的订单怎么还没发货”,系统返回的是“您可以点击右下角物流查询”。这属于语义理解不到位或知识库检索范围选择错误。

第二类是循环套娃。用户无论输入什么,系统都回复同一句“您可以描述更多问题哦”,或者在几个固定卡片之间来回跳转。反复几次之后,用户既没有得到答案,也没有退出路径。

第三类是转人工困难。用户已经明确输入“人工客服”“投诉”“我要找真人”,系统仍然用FAQ话术试图拦截,或者提示“当前人工繁忙”,然后让用户继续等待。这已经不是模型能力问题,而是服务流程设计问题。

这三类现象放在技术架构里,指向同一个结论:AI客服的对外表现,不是单个模型的输出决定的,而是由意图识别、知识检索、会话管理、业务接口、转人工策略共同决定的。模型只负责最后一个生成环节。

1.2 模型能力不等于客服系统能力

很多人测试大模型时会觉得它足够聪明。随便丢一句“帮我写一篇退货说明”,模型能写出完整内容,于是直接把模型接到客服后端,结果线上体验立刻变形。

原因是客服场景和创作场景完全不同。用户来客服系统的目标是办理业务,不是看模型发挥。用户期望回答能够对应到订单状态、退换货政策、账户问题、发票信息等真实数据。模型如果没有拿到订单上下文,再会写话术也回答不准确。

更麻烦的是,模型天然倾向于给出流畅、可信、完整的句子,而不是直接承认“我不知道”。在缺少知识库、缺少数据库读取权限、缺少转人工策略时,系统仍然会生成看起来正确但实际无效的内容,并让用户误以为业务已经处理完成。

客服系统设计必须补上这层缺口。要让模型在能确定的范围内回答,在不能确定时明确说不知道,知道要转人工时立刻转交,而不是继续拖延用户时间。

1.3 客服系统的责任边界

一个合格的客服系统,至少要回答清楚三个问题:能处理哪些请求,不能处理哪些请求,不能处理时怎么退出。

能处理的请求,指的是系统有对应知识页、业务流程或业务接口。比如物流查询、优惠券使用规则、售后时效、地址变更条件。这部分是AI客服的正常工作范围。

不能处理的请求,包括用户表达强烈不满、要求人工介入、遇到账号敏感操作、问题超出设定知识范围等。此时系统必须提供人工或工单出口。

退出的路径必须始终存在,并且不能把“退出”藏到三级菜单后面。很多被诟病的AI客服,不是在回答上出错,而是根本不提供有效出口。架构上应当把“退出或转人工”当作核心路由,和“大模型回复”放在同等重要的位置。

可以用一张表来罗列系统边界:

请求类型系统应做的事缺了会怎样
政策咨询用知识库检索回答,附内容来源答案看着合理,实际无依据
订单查询调用订单系统,返回真实状态模型猜测单号状态,制造假故障
地址修改核验身份再执行,并要求用户确认权限越权或误操作
投诉记录事件、转人工或创建工单用户情绪升级,无法追踪
超范围问题拒绝回答,并推荐人工模型幻觉扩大,用户走投无路

2. 构建AI客服前,先定义“服务底线”和“能力边界”

2.1 先列意图清单和动作清单

很多客服项目仓促上马,让模型自由发挥,美其名曰“智能”。但落地时应该先做两件看起来很传统的工作:定义意图,定义动作。

意图是用户这句话想解决什么问题,例如“查物流”“催发货”“申请退款”“改地址”“开发票”“投诉”。每个意图都要配一个处理策略。

动作是系统为了完成这个意图需要的操作,例如调用订单查询接口、创建售后单、推送给CRM系统。对于动作型的处理,不能只靠模型生成一句“已经帮您申请”,必须有后端真实操作作为依据。

一份最小意图-动作表可以是这样的结构:

意图动作是否需要二次确认失败兜底
查物流调用物流接口否返回接口报错,提示稍后再试或转人工
催发货创建催发货任务是转工单,通知仓储人员
申请退款进入退款引导并校验订单是若用户订单异常,转人工
修改收货地址校验订单状态,调用修改接口是拒绝并说明原因
投诉生成投诉工单否若系统不可用,马上留电话回拨

这一步可以帮助团队确认哪些功能可以做强交互闭环,哪些知识类问题只需要“检索并回复”。最怕的是把所有问题都交给一个万能Prompt,用户遇到问题时不是拿到明确结果,而是被要求重新描述。

2.2 给每个高风险动作配二次校验

客服系统里最常见的风险不是模型说错一句话,而是系统根据模型的输出直接执行了业务操作。

比如模型从用户对话中抽取了“退款金额”,然后拼成一个JSON,调用退款接口。如果抽取结果有误,或者用户说“我要退昨天买的那个”,模型没有明确关联到具体订单,退款操作就可能出错。

设计原则是:凡是涉及资金、优惠券、隐私资料、订单状态变更的动作,都必须在动作执行前加入二次确认页面或确认话术。系统可以先给用户展示“您确认要提交以下申请吗”的确认信息,等用户选择“确认”后再真正提交。

这看起来只是产品交互规则,但工程上必须做到:动作确认和动作执行之间保持状态一致性。不能出现用户已经确认,请求头还是旧参数;也不能出现用户点了一次提交,网络超时后系统自动重试导致重复创建售后单。幂等键和重试机制要在后端提前设计好。

2.3 把“转人工”当作一等路由,而不是附加功能

转人工不应该由模型自己决定心情好坏,也不应该藏在某个意图分支后面。更合理的做法是,把“用户是否要求转人工”和“系统判断自己无法处理”当成路由入口条件,放在所有逻辑的最前面。

这样做的原因很简单。用户说“转人工”时,意图已经非常明确,继续让AI拦截只会制造更多投诉。系统在处理用户输入前,可以先经过一轮规则、分类器或语义模型,命中“人工意愿”时直接进入人工队列,携带会话摘要和用户已描述的问题,而不是把之前所有上下文丢掉。

转人工还应该具备优先级。投诉、隐私泄露、资金异常、长时间未解决等场景,可以标记高优先级。普通业务咨询转人工时,可以减少排队等待。

2.4 定一个可验收标准

上线前后需要设置几个指标,让团队知道系统到底是变好了还是变差了。基础指标建议包含首答有用率、转人工成功率、人工接通率、会话重复转交率、用户重新进入率。

首答有用率指第一次回答是否解决了用户问题。这个指标不能只靠模型自己评分,需要用户在每条回答后给出“有帮助”或“没帮助”的轻量反馈,并由人工质检抽样确认。

转人工成功率和人工接通率反映的是出口质量。如果用户转人工后等待时间过长,或者转人工后要重新描述历史问题,即使AI回答正确率很高,整体体验也无法改善。

还需要监控“用户放弃率”。当用户已经开始投诉或输入明确业务诉求,却在一段时间后直接关闭会话,说明系统没能解决问题。这个信号比任何满意度问卷都真实。

3. 最小实现:支持“转人工”的大模型客服后端

3.1 技术选型和目录结构

为了把前面的设计思路落地,这里用FastAPI实现一个最小后端,重点不在于所有生产功能,而在于演示完整链路:接收用户消息、管理会话历史、判断是否转人工、调用大模型、返回结构化响应。

示例使用大模型服务提供的OpenAI兼容接口,地址通过环境变量注入。你可以把它替换成自己部署或购买的任意兼容服务;如果本地只有vLLM、Ollama、模型网关,则只需要改地址和模型名。

目录结构可以简化成:

ai-customer-service/ ├── app.py ├── requirements.txt ├── .env └── README.md

requirements.txt:

fastapi uvicorn[standard] httpx pydantic

.env应包含大模型地址、模型名称、密钥等信息。这里只列占位项,真实项目请通过密钥管理或K8s Secret加载:

LLM_BASE_URL=http://127.0.0.1:8001/v1/chat/completions LLM_API_KEY=sk-your-key LLM_MODEL=your-chat-model

如果不方便填写真实key,可以先使用本地兼容服务做联调。下面代码不做任何版本绑定,重点看逻辑结构。

3.2 会话消息管理

会话历史是避免“用户重复描述问题”的基础。最简单的方式是使用内存字典保存消息,demo里已经够用;生产系统要换成Redis或数据库,并加上过期时间。

app.py核心代码:

from typing import Optional from fastapi import FastAPI, HTTPException from pydantic import BaseModel import httpx import os app = FastAPI() MEMORY: dict[str, list[dict]] = {} MAX_HISTORY = 10 MAX_AGE_SECONDS = 60 * 30 HUMAN_WORDS = [ "转人工", "人工客服", "真人", "我要投诉", "必须要人处理", "人工", ] SYSTEM_PROMPT = """你是一个电商平台的在线客服助手。 你的工作范围包括:售前咨询、订单查询、退换货政策、发票说明、优惠活动规则。 如果用户需要人工介入,请明确告知将转接人工客服,不要重复询问用户问题。 回答时只能依据给定业务上下文,不要编造订单号和金额。 如果无法确认,请回答“当前问题需要人工协助”。""" def get_history(session_id: str) -> list[dict]: data = MEMORY.get(session_id, []) # 简单过期处理 return [item for item in data if item.get("ts", 0) + MAX_AGE_SECONDS > int(__import__("time").time())] def append_message(session_id: str, role: str, content: str) -> None: data = get_history(session_id) data.append({"_session_id": session_id, "role": role, "content": content}) if len(data) > MAX_HISTORY: data = data[-MAX_HISTORY:] MEMORY[session_id] = data def remove_sys_fields(messages: list[dict]) -> list[dict]: return [{"role": item["role"], "content": item["content"]} for item in messages]

这段代码中最容易被忽视的是两个函数:append_message负责写入,remove_sys_fields负责在调用模型前清理内部字段。不要把标记时间、会话ID等字段直接传给大模型接口,否则模型可能学到异常结构。

3.3 转人工检测与会话路由

在调用大模型之前,先做一次转人工判断。这样能让“我要投诉”这类请求立即进入人工入口,不走模型生成流程。

class ChatRequest(BaseModel): session_id: str message: str user_id: Optional[str] = None class ChatResponse(BaseModel): reply: str need_human: bool reason: str = "" def should_request_human(text: str) -> bool: t = text.strip().lower() for word in HUMAN_WORDS: if word in t: return True return False def is_obvious_failure(text: str) -> bool: failure_mark = ["系统繁忙", "查询失败", "接口异常", "无法处理"] return any(word in text for word in failure_mark) async def call_llm(session_id: str, user_message: str) -> str: url = os.getenv("LLM_BASE_URL", "http://127.0.0.1:8001/v1/chat/completions") api_key = os.getenv("LLM_API_KEY", "") model = os.getenv("LLM_MODEL", "chat-model") history = remove_sys_fields(get_history(session_id)) payload = { "model": model, "messages": [{"role": "system", "content": SYSTEM_PROMPT}] + history, "temperature": 0.2, "top_p": 0.8, "max_tokens": 600, } headers = {"Authorization": f"Bearer {api_key}"} async with httpx.AsyncClient(timeout=20) as client: resp = await client.post(url, headers=headers, json=payload) resp.raise_for_status() data = resp.json() return data["choices"][0]["message"]["content"] @app.post("/chat", response_model=ChatResponse) async def chat(req: ChatRequest): if not req.message.strip(): raise HTTPException(status_code=400, detail="消息不能为空") append_message(req.session_id, "user", req.message) if should_request_human(req.message): append_message( req.session_id, "assistant", "好的,正在为您转接人工客服,请稍候。", ) return ChatResponse( reply="好的,正在为您转接人工客服,请稍候。", need_human=True, reason="user_request_human", ) try: reply = await call_llm(req.session_id, req.message) except Exception: append_message( req.session_id, "assistant", "系统正在处理中,请留下联系方式,我们会安排人工回访。", ) return ChatResponse( reply="系统正在处理中,请留下联系方式,我们会安排人工回访。", need_human=True, reason="llm_call_failed", ) if is_obvious_failure(reply) or "需要人工协助" in reply: append_message(req.session_id, "assistant", reply) return ChatResponse( reply=reply, need_human=True, reason="llm_says_need_human", ) append_message(req.session_id, "assistant", reply) return ChatResponse(reply=reply, need_human=False, reason="")

这段代码体现了两个关键判断:用户主动要求人工时,直接路由到人工;大模型或底层接口出现异常时,不允许系统沉默,而是转人工或留电回访。

这里的转人工还不是真正的队列写入,只是返回了一个结构化标记。生产实现中,reason字段需要被下游链路解析,用来创建工单或推送到坐席工作台。

3.4 启动与本地验证

安装依赖并启动:

pip install -r requirements.txt uvicorn app:app --reload --port 8000

用两个请求验证转人工链路是否奏效:

curl -X POST http://127.0.0.1:8000/chat \ -H "Content-Type: application/json" \ -d '{"session_id":"s1001","message":"我要投诉"}'

预期返回:

{ "reply": "好的,正在为您转接人工客服,请稍候。", "need_human": true, "reason": "user_request_human" }

再试一个政策咨询请求:

curl -X POST http://127.0.0.1:8000/chat \ -H "Content-Type: application/json" \ -d '{"session_id":"s1001","message":"7天无理由退货的时限怎么算?"}'

如果大模型服务可用,会返回一段知识型话术。这里要注意:本地代码中并没有接入真正的知识库,所以线上环境还需要在SYSTEM_PROMPT里注入检索后的知识片段,或者把回答逻辑改成RAG链路。

4. 多轮对话为什么经常让用户重复描述问题?

4.1 上下文丢失的三种具体表现

客服对话最常见的一种差评是:用户在第一轮说了订单号,AI回复不相关;用户第二轮又提了一次订单号,AI还是像第一次一样问“请问您的订单号是多少”。原因通常是以下几个。

第一,后端没有保存会话历史,每一轮请求都被当成新对话。第二,有保存历史,但历史没有被拼进模型请求。第三,历史被拼进去了,但内容超过模型上下文窗口,早先的关键信息被截断。

工程上不仅要把消息保存下来,还要在每次调用前明确把当前用户的诉求、订单号、问题类型整理成结构化的状态信息,而不是只塞一堆聊天记录。

4.2 会话结构的最小模型

推荐从“消息列表”升级为“用户状态”结构。一个完整会话包含以下内容:

字段示例用途
session_ids1001会话唯一标识
user_idu881已登录用户标识
context{"order_id": "A123", "issue": "改地址"}多轮抽取的实体
history[{"role":"user","content":"..."}]原始消息
stateWAITING_CONFIRM当前会话状态
created_at2025-07-01 10:00:00创建时间
last_active_at2025-07-01 10:05:00最后活跃时间

当用户说“我要改订单A123的地址”,系统把order_id和issue存到context。下一轮用户说“改成北京朝阳区”,模型只需要结合当前上下文,就能知道用户指的是“订单A123改地址到北京朝阳区”,而不是重新询问。

所以上下文管理不只是把聊天记录拼起来,还要做字段抽取、状态更新和过期处理。

下面是简化版状态记录逻辑:

SESSION_CONTEXT: dict[str, dict] = {} def update_context(session_id: str, order_id: str = None, issue: str = None) -> None: ctx = SESSION_CONTEXT.setdefault( session_id, {"order_id": None, "issue": None, "need_confirm": False}, ) if order_id: ctx["order_id"] = order_id if issue: ctx["issue"] = issue

4.3 上下文超过长度后怎么办

模型上下文窗口再大,也扛不住客服会话长期运行。推荐两种处理方式:裁剪短期历史和生成会话摘要。

短期消息历史可以只保留最近几轮完整原文,用于理解用户刚刚的表达。再往前的消息,用一段JSON格式的摘要代替。摘要需要包含用户ID、核心诉求、已确认订单号、已提供的解决方案、未解决点。

{ "summary": "用户想修改订单A123的收货地址,要求改成北京市朝阳区", "order_id": "A123", "question_type": "modify_address", "status": "wait_confirm", "already_tried": [] }

这样既压缩了token,又保留了对坐席交接最有用的信息。

4.4 多轮确认的体验设计

当系统识别到用户有业务操作意图后,不要每次都让用户从头表达。比如先问“您要处理哪个订单”,用户回答“A123”,下一个分支直接问“是否把地址修改为北京市朝阳区?”。

这类交互本质上是在状态机里前进,每一步都把前一步结果带进下一步。和自由多轮对话不同,客服业务动作必须用确定性状态约束,避免模型自由发散的潜风险。

5. 避免大模型“一本正经胡说八道”的工程化措施

5.1 给模型画出“会”与“不会”的范围

AI客服被投诉的很大一部分原因是幻觉。用户问“我能不能全额退款”,模型直接回答“可以退款”,但实际业务规则是“仅7天内且商品未拆封才支持全额退款”。

避免幻觉的第一道关卡不是更好的幻觉检测模型,而是给模型提供结构化的知识片段。调用模型前,将和用户问题最相关的政策、订单、FAQ片段检索出来,放入context,并让模型只能基于这些片段回答。

系统提示词中应当明确写清楚:

你只能基于提供给你的知识片段回答。 如果知识片段里没有对应内容,不要推测。 回答时列出引用编号,方便用户核实。

示例注入知识片段的Prompt结构:

{ "role": "system", "content": "请基于以下知识回答用户问题。\n[1] 7天无理由退货时限:自签收次日起7日内可以申请。\n[2] 已拆封商品若影响二次销售,不在无理由退货范围。\n用户问题:我昨天拆了包装,还能申请7天无理由退货吗?" }

5.2 不要用“自由自然语言”直接执行业务动作

很多大模型应用喜欢让模型输出JSON,然后程序解析JSON去执行动作。这种方式在开发阶段很方便,但风险在于:模型输出不是稳定的程序字段,可能存在字段遗漏、动作误判、金额乱写、订单号幻觉。

更稳妥的做法是给模型提供固定的工具声明或函数列表。模型只能选择其中某个动作,并输出动作参数。

{ "function_name": "modify_delivery_address", "parameters": { "order_id": "A123", "new_address": "北京市朝阳区" } }

服务端在真正执行前需要校验三件事:

  • order_id是否存在且属于当前用户。
  • 用户是否已经完成身份认证。
  • new_address是否完整,且需用户再次确认后才能提交。

即使模型给出了JSON,服务端也不能直接拿它操作数据库,而要解析成内部结构并走正规业务校验逻辑。

5.3 外部工具调用要白名单化

如果客服系统需要调用订单、售后、发票等外部接口,建议把所有动作集中在一个工具调度层,并对每个工具定义权限、超时、失败返回。

工具可调用的角色是否高级风险失败策略
查询订单已登录用户,且只能查本人订单否返回错误并提示重试
发起退款申请已登录用户 + 二次确认是记录操作日志,转人工
修改地址已登录用户 + 订单状态校验 + 二次确认是失败保留上下文,允许重试
下发短信验证码需风控策略是频率限制,失败转人工

模型永远不能直接拥有数据库连接、文件系统或服务器命令执行权限。系统生成的工具调用,需要经过权限过滤和参数校验。

5.4 RAG检索时要设置置信下限

接入RAG方案时,很多团队把相似度阈值设置得过低,导致检索结果和当前问题完全无关,模型最后只能靠复杂话术凑出一个回答。

建议为知识库检索设置“有答案才回答”的下限。如果检索结果top1相似度低于阈值,就应承认“暂未找到相关答案”,并转人工或引导用户换一个问法。

同时要记录检索出来的知识标题和相似度分数。这样出现问题后,运营人员可以快速定位是不是知识库缺少某个主题,而不是直接怀疑大模型能力有问题。

6. 转人工链路设计:不是“排队”,而是“交接”

6.1 交接对象和交接材料

“转人工”如果只是把用户放进一个等待队列,本质上就是把问题从AI的烂摊子丢给人。更完整的做法是“交接”,而交接的前提是交接材料。

人工坐席接手时,应当看到用户的服务档案,至少包含:

  • 用户基础信息,昵称、会员等级、是否已完成实名。
  • 历史对话摘要,标题式列出用户已经说过的内容。
  • 问题类型和严重等级,例如“退款失败”“投诉物流”“政策咨询”。
  • 当前会话已尝试过的方案。
  • 系统连接的业务上下文,例如已识别的订单号。

会话摘要可以由大模型自动生成,但必须在转人工发生后立即落库。下面是交接数据示例:

{ "ticket_id": "TK20250701001", "user_id": "u881", "session_id": "s1001", "category": "complaint", "priority": "high", "reason": "user_request_human", "summary": "用户投诉物流超过3天未更新,要求客服跟进派送并说明赔付规则。", "context": { "order_id": "A123", "carrier": "示例快递" }, "callback_phone_masked": "138****1234" }

交接数据里的手机号、地址等个人信息必须做脱敏处理和权限隔离,只允许有服务权限的坐席查看。客服页面不能显示明文敏感信息。

6.2 人工入口在会话中的位置

可以这样设计聊天流程:

用户动作系统动作预期结果
输入“人工”检测到人工意图不问原因,直达人工队列
AI连续2次未能回答自动创建优先工单坐席主动回拨或在线接入
用户点击“不满意”记录失败原因作为后续质检数据
夜间无人坐席引导用户留联系方式生成次日回访任务

夜间值班是重要场景。很多用户时间因为深夜网购问题找客服,人工队列却无人接听。此时不能只显示“当前非工作时间”,而是应自动提交工单并明确告知用户回访时间,让用户感受到问题没有被丢弃。

6.3 排队过程的体验控制

如果人工确实繁忙,需要给用户排队预期。这里不应该让用户一直干等,只显示“正在排队,前面还有10人”,而应该提供三种选择:等待在线接入、选择离线留言、留下电话等回拨。

排队过程中,AI状态也需要同步给用户。不要出现用户已经转人工,AI还在按照机器人逻辑自动回复知识库内容的情况。这会让用户认为自己又被丢回了机器人循环。

7. 日志、评测与后续迭代

7.1 不要只记录问题和答案

很多客服项目上线后,日志只记录了“好”或“不好”的最终评价,缺少过程信息。要定位失误,必须记录每一次请求的完整上下文。

建议记录字段包括:

字段说明
session_id每次会话唯一标识
user_text用户原始输入
model_input发送给模型的最终消息片段
model_output模型生成的结果
retrieval_scores知识检索分数
intent_name命中的意图或分类结果
route_result是否转人工,原因是哪个
error_code接口异常或业务异常码
latency_ms响应时长
user_feedback用户对回答的有用性评价
timestamp完整时间戳

这些数据要能够按会话ID串起来,也要支持按意图、按模型版本、按时间范围做统计。

7.2 用户点“转人工”和“不满意”是最重要的标注信号

AI客服经常会遇到用户输入“你回答的根本不是我要的”然后点转人工。这类信号可以直接作为负面样本。

工程做法是把这类事件异步写回标注队列。运营人员对样本进行人工复核后,可以选择加入回归测试集或调整Prompt。不要直接让模型拿单挑样本做微调,那样容易过拟合,最好的方式是先积累一批质量稳定的评估集。

一个实用的反馈闭环是:

  1. 用户点“不满意”
  2. 系统记录当前问题、回答、上下文
  3. 运营人员分类失败原因
  4. 修复知识库或调整提示
  5. 启动回归测试
  6. 发布并观察指标变化

7.3 用历史会话做回归测试

大模型应用不能只靠上线时的一次冒烟测试。Prompt或知识库变更后,需要先跑一批历史真实会话,检查哪些会话从正确变为错误。

最小回归集可以包含100到200条会话。每条会话由运营和研发共同标注期望结果,标注内容包括:应该走人工、应该附知识链接、应该拒绝回答、应该返回订单状态等。

建立方便的工具:

test_cases = [ { "id": "case_001", "messages": ["我要退货", "我的订单是A123"], "expect": "query_refund_policy", }, { "id": "case_002", "messages": ["人工客服", "快一点"], "expect": "human_handoff", }, ]

跑回归时,用同一条Prompt和同一组测试数据在不同模型版本下对比输出,观察哪些版本更稳定。

7.4 流量峰值下的防护

客服系统可能在大促、活动日出现流量和情绪集中上升的情况。底层模型服务在被大量请求压垮时,系统不能把每个请求都发往模型,然后静默等待超时。

建议增加限流、降级和队列三层能力。高峰期可以对知识类问题启用缩减模型或快速检索回复;对高风险动作继续限制为人工处理;对模型服务超时立刻降级为常见问题和转人工入口。

用户在大促期间最需要的不是长篇大论,而是“有人接住问题,确认正在处理”。宁可给一句简短真实回复,也不让用户看见一个转圈后崩溃的页面。

8. 从“被戳脊梁骨”到“习惯性被信任”的落地清单

8.1 把常见失败模式整理成运维手册

不同团队踩过的坑大致相同。建议在项目启动时,就把下面这些常见现象写进排查手册,遇到同类问题可以按表处理。

问题现象可能原因处理建议
用户说“人工”,AI继续答FAQ人工意图没有在路由最前面命中将人工关键词检测放到LLM调用之前
转人工成功,但坐席不知道用户说过什么没有生成交接摘要在转人工时保存分类、实体、历史摘要
用户问了3次同样问题,AI仍像首次聊天会话历史未保存或未传给模型持久化历史,并检查模型请求是否包含历史
答案像真的,但业务规则是反的没有注入知识库片段引入RAG,并限制模型只能基于知识片段回答
系统偶尔读不到订单,询问两次后自己编造缺少接口错误兜底校验失败时直接声明无法处理并转人工
用户点确认却被重复扣款或重复提交缺少幂等键和状态校验接入幂等ID,动作状态做幂等控制
人工不在线,系统还是在假装解决问题没有夜间/无人值守策略非工作时间自动转工单并承诺回访时间

8.2 安全和隐私是客服系统绕不开的红线

AI客服处理的大部分是个人信息和订单数据。给模型传入user_id、order_id时要确保调用方做了身份认证;管理员接口要使用鉴权,不能让任意用户通过绑定其他人ID去查询订单。

日志里的手机号、地址、银行卡号等敏感信息要脱敏。模型服务端日志也会记录请求内容,如果不做脱敏,敏感数据会进入模型厂商日志,属于高风险行为。

客服系统还需要支持“清除会话”能力。用户可以要求删除历史对话和个人信息。系统层面应该记录数据删除请求,并能从存储和日志中移除对应内容。

8.3 上线前检查清单

在正式发布前,建议逐条核对这些点:

  • [ ] 是否给模型限定回答范围。
  • [ ] 是否设置“不知道”时的拒绝话术。
  • [ ] 是否把“用户主动转人工”放在路由最前。
  • [ ] 是否实现转人工时的会话摘要传递。
  • [ ] 是否设置夜间、无坐席、服务异常时的处理路径。
  • [ ] 是否为高风险业务动作增加二次确认和幂等控制。
  • [ ] 是否记录模型输入输出和检索分数。
  • [ ] 是否设置请求超时与降级策略。
  • [ ] 是否对日志中的个人信息脱敏。
  • [ ] 是否建立人工客服抽检的评估集。
  • [ ] 是否对模型输出做了不允许执行外部操作的隔离。
  • [ ] 是否提供会话删除和数据清除机制。

8.4 后续可以扩展的方向

当基础链路稳定后,可以继续提升两件事:第一,扩大确定性业务闭环的比例,让更多订单查询、售后申请能在AI侧完成,而不是把所有动作都丢给人工;第二,建立持续的对话质量评估闭环,把线上用户的负面反馈转化为知识库或模型版本迭代依据。

更复杂的项目可以进一步引入语音客服、异步外呼回访、多模态工单、实时坐席辅助。每个扩展都要回到同一个原则:无论技术多么先进,用户被卡住时,一定有出口,有人负责,有结果反馈。

AI客服愿意承认“不知道”,同时能让用户快速找到真人,这不是模型退步,而是客服系统真正具备了服务意识。这样的系统即使偶尔犯错,用户也会觉得它是一个可靠的入口,而不是一个被推出来敷衍人的机器人。

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

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

立即咨询