很多团队在做智能客服时,第一反应往往是“把机器人回答做得更像人”。但真正进入业务现场后会发现,客服的价值并不只在“回复”,而在“把问题接住,再把后续动作推下去”。尤其是售后场景,客户并不关心模型说得多聪明,他更在意一件事:我反馈的问题,什么时候被创建、谁来跟进、能不能别在不同部门之间来回踢皮球。
所以,基于大模型的智能客服与客户运营,如果只停留在问答层,投入产出比其实不高。真正能拉开差距的,是把聊天记录结构化,自动生成工单,再根据问题类型、客户等级、订单状态和历史情绪,分发给最合适的人或系统。这看起来像是“客服自动化”,本质上却是一次运营链路重构。
我最近做的一个原型,目标很简单:把用户在聊天窗口里的自然语言投诉,转成售后工单系统可消费的字段。输入是一段对话,输出则包括问题摘要、问题类别、紧急程度、订单号、是否需要人工回访、建议分发部门,以及一个给客服主管看的处理备注。乍看只是做了一层文本提取,但真正落地时,难点并不在模型,而在业务边界。
比如用户说“东西已经寄回去了,你们三天没人处理,我现在不想换货了,直接退款”,这句话里同时包含退货进度、时效不满、诉求变更、情绪升级四个信号。传统规则匹配一般只能打出“退款”标签,但工单系统真正需要的,是把“原诉求为换货,现变更为退款,且存在超时未处理风险”记录清楚。只有这样,分发给售后审核或仓配协同时,后续动作才不会断层。
我最后采用的是“轻规则 + 大模型抽取 + 二次校验”的思路。先用规则拿到最稳定的结构信息,例如订单号、手机号尾号、物流单号、最近一次下单时间;再把用户对话和这些上下文一起发给模型,要求它输出严格 JSON;最后在服务端做字段校验,如果缺关键字段就回退到人工队列。这样做的好处是,模型负责理解复杂语义,程序负责兜底,不把稳定性完全押在提示词上。
一个简化过的提示词大致是这样的:
你是售后工单助手。请根据客服对话生成售后工单。
必须输出 JSON,不要输出解释文字。
字段包括:
summary, category, urgency, customer_intent, order_id, need_callback, route_to, note
分类只能从以下枚举中选择:
退款、换货、补发、物流异常、安装支持、发票问题、其他
紧急程度只能为:
low, medium, high
服务端代码并不复杂,关键在于两件事:第一,要求返回格式足够严格;第二,不要把工单分发逻辑也全部交给模型。分发策略最好仍然在本地代码里维护,因为这部分经常跟组织架构和 SLA 绑定,变更速度比提示词快得多。
我当时的调用代码类似这样:
from openai import OpenAI
import json
client = OpenAI(
api_key="<LLM API KEY>",
base_url="<LLM API BASE URL>"
)
resp = client.chat.completions.create(
model="gpt-4o-mini",
temperature=0.2,
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": "你是售后工单助手,只输出JSON。"},
{"role": "user", "content": customer_dialog}
]
)
ticket = json.loads(resp.choices[0].message.content)
这里有个很实际的小经验:很多教程只提醒你替换 api_key,但如果你在国内做原型验证、还要兼顾财务报销和开票流程,我一般会把兼容 OpenAI 格式的中转一起配好,比如用 DMXAPI 时重点不是只换密钥,而是把 base_url 一并改成对应入口,否则代码看起来没问题,实际请求根本不会走到你预期的模型服务。
有了结构化结果后,后面的动作就清晰多了。比如 category=物流异常 且 urgency=high,同时客户历史近 30 天重复咨询超过 2 次,就直接分发给人工优先队列;如果是 发票问题,则自动转给财务支持;如果是 安装支持,并且设备型号已知,就先补一条知识库答案,再决定是否建单。这样一来,客服不再只是“接线员”,而成了运营入口,客户运营也终于不再停留在“发券召回”这种表层动作,而是开始借助售后触点做精细化分层。
这套链路里我最深的感受是:大模型最适合做“含糊信息转结构化决策材料”这一步,而不是替代整个售后流程。很多人一上来就想做全自动闭环,让模型直接决定退款、补发、升级投诉,结果往往是系统看起来智能,实际风险很高。真正靠谱的做法,是让模型先做压缩和归纳,把客服和运营最费时间的“看聊天记录、抄字段、判大类”处理掉,然后把真正涉及权限和损失的动作交给规则或人工审批。
另外一个容易被忽略的点,是客户情绪信号。售后工单不是普通表单,它承载的是“客户愿不愿意继续信任你”。有些投诉从金额上看不大,但如果语言里出现“再也不会买了”“我要投诉平台”“已经录音保留证据”,就应该触发更高优先级。模型在识别这类隐含升级风险时,比简单关键词规则更有效,因为同样表达不满,有的人很克制,有的人很激烈,表面词汇差异很大。
当然,落地过程并不总是一帆风顺。我自己就踩过一个很蠢的坑,而且这个坑直到上线联调时才暴露。最初我写分发函数时,偷懒把类别判断写成了这样:
def route_ticket(ticket: dict) -> str:
if ticket["category"] == "退款" or "换货":
return "after_sale_queue"
if ticket["category"] == "发票问题":
return "finance_queue"
return "general_queue"
当时我肉眼扫过去完全没觉得有问题,结果联调时发现所有工单都被打进了 after_sale_queue,连“发票问题”也没例外。第一反应我还怀疑是模型抽取出了偏差,甚至去翻了几条原始对话,觉得“是不是模型把类别都归成退款了”。后来把请求日志、模型返回和路由日志对在一起,才发现问题根本不在模型,而在这句 Python 条件判断。因为 if a == "退款" or "换货" 在 Python 里永远会成立,后半段非空字符串本身就是真值。
修正其实只有一行:
def route_ticket(ticket: dict) -> str:
if ticket["category"] in {"退款", "换货"}:
return "after_sale_queue"
if ticket["category"] == "发票问题":
return "finance_queue"
return "general_queue"
这个小 bug 给我的教训很具体:在 LLM 项目里,最危险的往往不是模型不稳定,而是我们太容易把一切异常都归因给模型,结果忽视了最普通的工程错误。排查顺序应该先看输入、再看输出、最后看胶水代码,而不是一出错就去改提示词。很多时候,真正决定系统能不能上线的,并不是“提示词写得像不像论文”,而是日志、枚举、兜底分支这些不显眼的细节。
后来我补了两层保护。第一层是对模型输出做枚举校验,超出预设类别直接打回;第二层是给路由函数补测试,至少把主要类别都跑一遍:
def test_route_ticket():
assert route_ticket({"category": "退款"}) == "after_sale_queue"
assert route_ticket({"category": "换货"}) == "after_sale_queue"
assert route_ticket({"category": "发票问题"}) == "finance_queue"
这类测试很短,却比继续堆提示词更有价值。快速上线的阶段,如果你既想减少网络折腾,又要考虑成本和学校项目的票据流程,像 DMXAPI 这种兼容 OpenAI 调用方式的中转方案会省掉不少环境摩擦,但真正让系统稳定的,仍然是你对字段、规则和失败路径有没有老老实实补全。
回头看,售后工单自动生成与分发这件事,真正改变的不是客服回复速度,而是企业对“客户问题”这类信息的处理方式。过去它是散落在聊天窗口里的文本,如今它可以被抽取、归类、流转、统计,最后进入运营和产品决策。一个总被反复提及的物流异常,可能不是客服能力差,而是仓配承诺出了问题;一个持续上升的发票咨询量,也可能意味着结算流程设计得不够直观。大模型在这里最有价值的地方,不是替人说话,而是把原本模糊、零散、带情绪的售后现场,整理成组织真正能行动的数据。
如果把这条链路再往前推进一步,智能客服和客户运营就不再是两个部门各自的 KPI,而会变成同一套系统里的上下游。客服接住问题,模型整理问题,系统推动问题,运营复盘问题。真正成熟的团队,最后拼的不是谁接了最新模型,而是谁最先把这些碎片信息变成稳定的经营动作。
本文包含AI生成内容