最近给自用的客服软件接了大模型自动回复。软件是个 Electron 桌面程序,同时管抖店和微信小店的客服,之前只有关键词自动回复,这次加了「AI 智能回复」。

做下来最大的感受:把接口调通只花了半天,剩下几天全在解决「怎么让它别乱说话、也别把客户晾着」。

不是配一个 API Key 就完事

一开始想得很简单:填个 Base URL、Key、模型名,把客户问题丢过去,拿回答发出去。真做起来发现要处理的事一大堆:

  • 客户可能问的是退款、纠纷,这种不能让 AI 直接回,得转人工并强提醒;
  • 客户在砍价,AI 不能跟着降价,也不能承诺;这个和「纠纷」是两回事,要分开处理;
  • AI 超时或者报错,不能干等着,得回落到关键词话术;
  • 排队久了客户会走,所以我做了个「超过 10 秒先说『稍等,我查一下』,AI 好了再补发答案」的机制。

这些都不是模型能力问题,是产品问题。

提供商五花八门,就别把字段写死

市面上大一统的「OpenAI 兼容」接口其实并不完全统一。我最后支持了两种协议:

  • OpenAI 协议:Authorization: Bearer,走 /v1/chat/completions;
  • Claude(Anthropic)协议:x-api-key + anthropic-version 头,走 /v1/messages,返回是 content[] 数组而不是 choices[]。

界面上做成一个协议下拉,选哪个就走哪套。模型列表也是点「连接」按钮去拉 /v1/models 填进下拉框,而不是让用户手打模型名——手打太容易错。

思考强度:能力判断不能靠猜

现在很多模型有「思考强度」这个参数(reasoning effort),能调低/中/高。问题是:不同模型支持的档位不一样,有的支持 low/medium/high,有的只有「开/关」,有的根本不支持。

直观想法是问接口「你支持哪些档位」,但实测大部分 OpenAI 兼容接口的 /v1/models 只返回模型 id,不返回能力字段。只有 OpenRouter 这类聚合网关会返回。

所以我的做法是:内置一份模型能力表(从公开的模型目录整理),按模型名查它支持的真实档位;查不到的,才退回按名字推断。

更关键的是一个兜底:滑块永远能拖,拖到模型不支持的档,自动降到最近的档;发请求时如果接口因为参数不认而报错,就自动去掉参数重试一次。

宁可「思考强度没生效」,也不能「因为一个可选参数导致整条回复失败」。客服场景里,能回上话永远比回得完美重要。

另外每个带思考强度的滑块旁边我都标了提示:思考越强越慢越贵,客服场景建议保持「不开启」——推理过度容易「想太多」,编出商品没有的信息(幻觉)。

关键词规则:| 和 + 这种需求躲不开

老的关键词回复逻辑很简单:一条规则一堆关键词,要么「命中任意一个」要么「全部命中」。

但真实的话术表经常是这样写的:

发|寄+邮政|中通|顺丰|快递

意思是「发或寄」且「邮政或中通或顺丰或快递」——分组布尔逻辑,不是单纯的「全是或」或「全是与」。硬拆成多条规则会破坏「一行一条」的结构,优先级也会乱。

所以给规则加了个「布尔表达式」字段:+ 是和、| 是或、# 和逗号是关键词分隔。一行 Excel 就能精确还原成一条规则。

顺带把匹配优先级也理清了,现在是这样判:

  1. 「必须全部命中」(含 +)永远优先于「命中任意一个」;
  2. 同为全部命中,命中的关键词越多越优先(3 个词全中 > 2 个词全中 > 1 个词全中);
  3. 再按用户设的优先级数值。

这样「快递」和「快递+投诉」两条规则同时命中时,只会发后者那条。

写软件这几年的几条固定习惯

除了这次 AI 接入,最近修 bug 也攒了点经验,一起记下来。

第一,判断「是不是同一条消息」,只用消息唯一 ID,不用时间。

我踩过最惨的坑,就是用「几分钟内算新消息」来判断要不要回复。结果客户上午问、客服下午才上线,消息「过期」了,永远不回复。服务端给了消息唯一 ID,就该用 ID 比,ID 相同才是同一条,内容一模一样但 ID 不同就是两条新消息。时间只能用来清理内存,不能用来做业务判断。

第二,接口返回能拿到的字段,绝不靠猜。

模型能力、消息角色、连接状态——凡是接口/页面明确给的确定性事实,就只用它。绝不用「长度比例」「模糊相似度」「某个中间子串包含」这些自己算出来的近似值去替代。近似值一定会有时灵时不灵。

第三,备用方案不能掩盖主流程的错。

「拿不到就用默认值」听起来很稳,但如果默认值是错的,它会悄悄把问题盖住,等出事了才发现主流程一直没走通。宁可让它明显报错。

第四,改之前先读代码,别信记忆。

会话可能有半截、代码可能被别人改过。每次动手前先 read 一遍当前实际内容,而不是照着脑子里的旧版本改。

小结

接大模型这事,技术上不难,难的是把「对话」这种模糊的东西,塞进「客服」这种要求确定性的场景里。我的原则就一条:AI 是加分项,不是必需项。AI 挂了有兜底,AI 乱说有人工强提醒,用户永远能得到回应。

剩下的,就是把这些兜底一条条测出来。