拓冰建站拓冰建站
首页 / 资讯中心 / 正文

电商客服意图识别三层混合架构:规则+小模型+LLM的工程实践

做电商客服系统的同学大概率都遇到过这个尴尬场景用户明明问的是“什么时候发货”规则引擎匹配到了“发货”关键词结果机器人给回了一段商品发货时效说明用户直接炸毛。换个场景用户问“你这衣服和那件299的有什么区别”小模型分类器纠结半天最后给了一个“其他”了事用户等了两秒收到一句“抱歉我不太明白您的意思”。这种体验放在十年前还能忍放在现在就是劝退。我接手电商客服意图识别这个项目时目标很明确在不把推理成本拉爆的前提下把客服机器人的意图识别准确率从85%提到95%以上同时把“答非所问”的比例压到最低。试了一圈方案之后最终落地了一套“规则 小模型 大语言模型LLM”三层混合架构。这条路线没有用特别炫的技术但胜在每层各司其职、能兜底、能降级、能算账。这篇文章把我的设计思路、落地细节、踩过的坑一次性讲清楚给正在做客服系统或者准备做意图识别的同学一个可复用的参考。1. 三层混合架构的整体设计与选型逻辑1.1 电商客服意图识别的业务边界与数据形态电商客服场景的意图识别和通用对话里的意图识别不太一样它有非常鲜明的行业特点。首先是意图集合相对收敛。虽然每个店铺的商品不同但用户的诉求高度集中在售前咨询、售中催促、售后处理这三类上。售前主要是问商品属性材质、尺码、颜色、库存、优惠券用法售中主要是催发货、改地址、催物流售后主要是退货、换货、退款、发票、质量问题。掰着手指头算核心意图三四十个已经算很多了真正高频的其实就十几个。其次是对话形态复杂。淘宝、京东这类平台上用户的一句话往往不是一个完整句子可能是“在吗”“”“这个能便宜点不”“那算了”这种碎片化表达。更麻烦的是多轮对话中意图会漂移用户前一句还在问尺码后一句就转到“那能发顺丰吗”。这就要求意图识别系统不能只看单句还得结合会话上下文。第三个特点是实时性要求高。用户发出消息后通常期望1秒内收到回复。如果意图识别耗时超过500毫秒客服机器人的整体响应就会明显变慢用户感知很差。这些业务特性决定了技术选型不能走极端纯靠大模型虽然语义理解强但延迟高、成本贵而且并发一高就扛不住纯靠小模型虽然快但对长尾表达和复杂上下文力不从心纯靠规则就更脆稍微换个说法就漏。1.2 三层混合架构的整体设计与选型逻辑我最终落地的架构分为三层各层按“成本从低到高、能力从弱到强”的顺序依次承担流量规则层处理高确定性、强格式化的请求比如订单号查询、链接识别、关键词触发、正则匹配的典型FAQ。小模型层处理高频、中低频但不复杂的意图比如尺码咨询、优惠咨询、退换货判断采用文本分类 序列标注的双任务模型。LLM层处理长尾、复杂、跨多轮上下文的意图以及小模型低置信度但确实属于业务范围的请求同时承担新意图发现的职责。选这套路线核心逻辑是“按难度分配算力”。规则层几乎零成本命中即返回响应在10毫秒以内小模型层用一个几十M的模型单卡GPU能撑很高的并发响应在30到80毫秒LLM层只有前两层搞不定的请求才会进来占比控制在10%到20%这样整体成本不会失控。选型阶段我也对比过“全部走LLM”的方案。当时在几个主流大模型上跑过压测单次意图识别的token消耗平均在300到500按当时的API价格一天十万级请求量光识别费用就得上千块这还没算延迟和限流。而用混合架构LLM只处理其中一两万条费用能控制在原来的五分之一以下。对于业务方来说这就不是技术选型问题了是能不能立项的问题。2. 规则层用最低成本拦截最高确定性的请求2.1 规则层处理的场景范围与边界规则层适合处理的请求有一个共同特征表达形式高度确定或者携带了明确的结构化信息。比如用户直接发订单号格式是平台统一的比如“JD123456789”或者“2024120912345678”。用户发来一个商品链接需要识别出是哪个商品并返回商品详情卡片。用户输入“人工客服”“转人工”“投诉”这类强指令词必须直接转人工绝对不能误判成别的意图。用户命中“退款”“退货”等强业务词但还没有具体描述原因时可以直接进入退款入口的引导流程。用户输入纯数字或“催单”这类明确指令直接走对应的处理逻辑。这些请求的共同点是表达简单、意图唯一、不需要理解上下文。用一个大模型去理解“我要退款”这句话技术上没错但属于杀鸡用牛刀。规则层用几行正则就能做到99%以上的准确率响应时间可以忽略不计。2.2 规则引擎的工程实现要点规则层不是简单写几个if-else就完事我建议用一个独立的规则引擎模块来管理方便后续扩展和维护。核心由三部分组成第一部分是规则定义。我用的是JSON格式存储规则每条规则包含规则ID、优先级、匹配模式、命中的意图、返回的响应模板。{ rule_id: RULE_001, priority: 90, intent: query_order_status, patterns: [ ^[A-Z]{2}\\d{9,15}$, 订单号[:]?\\s*[A-Z]{2}\\d{9,15} ], threshold: 0.99, action: call_order_api, response_template: template_order_status }第二部分是匹配引擎。我把匹配分为三类正则匹配、关键词匹配、词典匹配。正则匹配用于订单号、手机号、日期等格式化信息提取关键词匹配用于“退款”“换货”“开发票”等强业务词命中这里要注意词表和业务意图的映射关系词典匹配用于自定义的专有名词比如品牌名、商品系列名。第三部分是规则编排。规则之间要支持优先级、互斥、组合三种关系。比如用户同时提到了“退款”和“人工客服”按优先级应该走“人工客服”对应的转人工流程而不是退款引导流程。这个场景我在初期就踩过坑当时规则没有优先级设计结果“退款”规则先匹配了用户想找人工反而被机器人拦住体验很差。2.3 规则层与上层模型的置信度衔接规则层命中后返回的置信度我会直接置为0.99以上因为规则的确定性远高于模型。但这带来一个新问题规则层拦截了太多流量后小模型层会缺少足够多的训练样本。这个问题我在后面的训练数据章节会专门讲。判断规则层是否失效有一个很简单的监控指标规则层的覆盖率变化。正常情况下规则层能拦截30%到40%的流量如果覆盖率突然下降到20%以下大概率是用户表达方式变了或者平台订单号格式调整了。这种波动要及时察觉。3. 小模型层意图分类与槽位抽取的双任务设计3.1 模型选型从BERT到轻量化方案的取舍小模型层是整个架构的流量担当承担50%到60%的意图识别任务。既然叫小模型选型上就不能盲目追求大。我在实践中的选型基准如下参数量在30M到110M之间太大就失去了“小”的意义。推理延迟在CPU上不超过100毫秒GPU上不超过30毫秒。支持动态量化INT8量化后精度损失不超过1个百分点。具体模型上我最初用的是BERT-base中文效果不错但线上并发一高GPU显存吃紧。后来换了RoBERTa-wwm-ext效果略好一点点但提升有限。真正解决性能问题的是做了一步蒸馏把12层的BERT蒸馏到一个6层的TinyBERT推理速度提升了接近3倍精度只掉了0.7个百分点。如果项目从零开始我现在的选择会更偏向轻量方案。比如用6层的MiniLM或者ALBERT-tiny作为底座从头做意图分类和槽位标注效果不一定比蒸馏后的BERT差但部署体积和推理速度都能兼顾。这里有一个经验不要迷信排行榜上的模型效果要结合自己的推理环境做压测。3.2 双任务设计意图分类槽位抽取为什么必须一起做电商客服的意图识别只做意图分类是不够的。同样是“退货”意图用户说的是“衣服太大了想退货”和“收到的商品有质量问题要退货”后续的处理流程完全不同。前者要引导用户选择退货原因后者要建议用户提交照片凭证。所以识别出意图之后还必须要提取关键信息也就是槽位slot。我采用的是多任务学习框架共享一个BERT编码器上面接两个输出头一个是意图分类头输出意图标签的概率分布一个是序列标注头用BIESO标注体系给每个token打标签抽取商品名、属性、数量、订单号等关键槽位。这种设计的好处有两个。一是省资源两个任务共享一个模型线上只需要部署一个模型文件推理一次就能同时拿到意图和槽位结果。二是互相增强意图分类和槽位抽取共享底层语义信息联合训练能提升各自的效果。我在实验里对比过联合训练的意图分类F1比单独训练高了约1.2个百分点槽位抽取的F1高了约2个百分点。3.3 训练数据构造从单句到多轮上下文的演进小模型训练最关键的环节是数据。我第一次做这个项目时犯了一个典型错误用单句对话训练意图识别模型结果上线后遇到大量带有上下文指代的问题直接翻车。比如用户先问“这个裙子有红色的吗”客服回答“有的”用户接着问“那有大码吗”单看后一句是识别不出“这个裙子”这个指代对象的。改进方案是把训练数据组织成多轮对话切片。具体做法是取当前轮次和之前最多两轮内容拼成上下文窗口用特殊分隔符隔开作为模型的输入。在实际数据构造上我整理了一套相对完整的流程数据来源历史客服聊天记录、工单系统数据、公开电商客服语料。数据清洗过滤掉涉及手机号、地址、姓名等隐私信息的内容做脱敏处理。数据标注按“意图标签 槽位标签 上下文片段”三元组进行标注。类别均衡通过重采样和降采样控制各类别样本量避免出现明显的类不平衡。训练集的意图标签体系上我强烈建议加两个特殊类别一个是“闲聊”对应非业务相关的寒暄另一个是“OOS”Out-of-Scope对应不在业务意图集合内的请求。这两个类别能显著提升模型在真实环境中的鲁棒性。电商场景里用户经常会发“你好”“在吗”“谢谢”“哈哈哈”这类消息如果不做特殊类别处理模型往往会把它们强行分到某个业务意图里引发错误响应。3.4 推理链路中的置信度测算与阈值选择模型输出层得到的是各个意图的概率分布我采用的置信度是最高概率减去次高概率的差值这个差值比单纯看最高概率更能反映模型的判别信心。如果差值大于0.3说明模型很笃定如果差值小于0.1说明模型在两个意图之间犹豫这时候强行给结果是有风险的。阈值设置上我采用了两级阈值主阈值为差值大于0.25允许直接返回意图次阈值为差值大于0.15且最高概率大于0.7返回意图但标记为低置信度同时触发LLM层的复核机制。低于次阈值的一律交给LLM层处理。这里要特别提醒阈值不是一成不变的要定期用线上真实数据回测。我上线初期阈值设得比较严导致大量本应小模型处理的请求涌到了LLM层成本飙升。后来逐步放宽阈值同时配合规则层的流量拦截才把各层流量比例调到预期状态。调阈值的过程中我习惯按天观察数据每次只调整0.05观察三天确认没有明显副作用再继续调。4. LLM层兜底长尾场景兼当“新意图发现器”4.1 LLM层解决什么问题以及触发时机如何设计小模型再强面对复杂长尾的用户表达准确率始终上不去。我在训练集上做了长尾扰动测试把用户常见的不规范表达比如“昨天买的那个蓝色的能不能换个大一号的”注入测试集小模型的准确率从92%掉到了68%。这些长尾表达恰恰需要LLM的上下文理解能力。具体涉及几个典型场景多意图叠加用户一句话里有多个诉求比如“我想退了这个再买一个新的顺便帮我查下积分”。指代消解用户说“那个东西”指的是上一轮提到的商品。隐含意图用户说“这个太贵了”并不是在评价商品而是隐含了议价意图。情绪识别用户说“你们家服务真好啊”可能是真夸也可能是反讽。LLM层的触发时机是规则层未命中且小模型层置信度低于阈值时。这里要强调一个核心设计理念不要把小模型的输出直接作为LLM的输入条件而是把原始对话文本连同小模型的结果一起给LLM让LLM自己判断小模型的结果是否可信。否则一旦小模型错了LLM会被误导。4.2 Prompt模板与结构化输出如何让LLM稳定输出JSONLLM层的稳定性很大程度上取决于Prompt设计。我打磨了很久的Prompt模板核心思想是“角色定义 任务说明 输出格式 业务词典约束 少量示例”。Prompt模板示例你是电商客服意图识别系统需要从用户对话中识别出用户的真实意图。 要求 1. 意图必须从以下列表中选择[商品咨询, 库存查询, 优惠券咨询, 催发货, 修改地址, 质量问题, 物流查询, 退货申请, 换货申请, 退款进度, 发票问题, 人工客服, 闲聊] 2. 提取关键槽位商品名称、订单号、数量、退货原因。 3. 如果用户表达了多个意图按紧急程度排序输出最多两个意图。 请以JSON格式输出格式如下 {intent_top1: 意图名称, intent_top2: 意图名称, confidence: 0到1之间的小数, slots: {商品名称: , 订单号: , 数量: , 退货原因: }, need_human: true/false} 对话内容 用户{当前用户消息} 上下文{前两轮对话摘要} 候选意图小模型预测{小模型输出}这个Prompt里有几个细节值得说明。意图列表一定要固定并且要和前两层的意图体系完全一致否则后续的仲裁逻辑没法对齐。业务词典约束要写清楚比如“大码”要映射到“尺码咨询”“包邮”要映射到“运费咨询”。need_human字段是我后期加的专门用来识别需要人工介入的高风险场景比如用户情绪激烈、涉及退款金额争议等情况。输出格式校验是必须的环节。LLM偶尔会不按JSON格式输出或者多出一些内容需要做一次解析容错把JSON片段抽取出来必要时补全缺失字段。我维护了一个简单但有效的修复函数按序尝试直接解析、截取首个大括号后解析、正则抽取JSON对象后再解析三层兜底下来基本能覆盖各种幺蛾子情况。4.3 模型选型与部署开源模型的机会与成本账LLM层的模型选型取决于团队资源。我的经验是如果请求量在每天十万级最优做法是自建部署一个7B到14B的开源模型配合量化推理而不是直接调用云端API。我当时在云端API和开源模型之间做了详细对比。云端API的好处是省心、效果好坏处是费用高、延迟不稳定、有数据隐私风险。电商客服对话内容涉及用户手机号、地址、订单信息数据出域本身就有合规压力。开源自建路线的关键是选对底座模型。我实际测试了多个模型最终选了Qwen系列的中等规模版本在中文意图识别上表现最均衡量化后效果损失可控。7B模型在FP16精度下大概需要14GB显存用INT4量化可以压缩到5GB左右。我上线初期用的是一张消费级显卡跑INT4量化版本延迟在300到500毫秒后来流量涨了就扩到两张卡做负载均衡。如果你决定走自建路线有两点建议。一是不要一上来就微调先用现成的模型配上好的Prompt跑一段时间攒够了真实难例再决定是否需要微调。二是预留一个云端API作为逃生通道当自建模型的响应质量明显不达标时可以动态切流到云端API保证业务稳定。4.4 LLM层的降本增效手段LLM层虽然只承担部分流量但单次成本高所以降本增效是必须做的。第一招是“摘要式输入”。多轮对话如果全部喂给LLMtoken消耗会随着轮数线性增长。我的做法是先用规则或者小模型对前几轮做摘要比如“用户已经询问了商品尺码客服已回复有货”然后只把摘要和当前轮喂给LLM。实测同一批测试集上这个操作能把token消耗降低约30%准确率基本持平。第二招是“结果缓存”。用户的高频问题往往是相似的比如双十一期间大量用户问“发货时间”“快递停发时间”。我在缓存里存了用户问题的embedding新请求来了先做向量相似度检索命中就直接复用历史结果不经过LLM。这条策略在活动大促期间效果极其显著。第三招是“批量推理”。把多个低优先级请求拼接在一个Prompt里让LLM一次输出多个结果摊薄单次请求的固定开销。代价是延迟会略微上升适合对实时性要求不高的场景比如离线打标和新意图挖掘。5. 三层联动中控调度与故障降级设计5.1 中控调度核心逻辑从规则到LLM的完整链路三层架构不是各玩各的而是由一个统一的中控调度器串联起来。我整理一下核心调度流程用一个简化的伪代码来说明def handle_message(user_message, session_context): # 第一层规则层快速拦截 rule_result rule_engine.match(user_message) if rule_result.confidence 0.99: return build_response(rule_result.intent, rule_result.slots) # 第二层小模型识别 model_result small_model.predict(user_message, session_context) if model_result.confidence 0.25: return build_response(model_result.intent, model_result.slots) if model_result.confidence 0.15: # 低置信度触发LLM复核 llm_result llm_engine.verify(user_message, session_context, model_result) if llm_result.confidence 0.7: return build_response(llm_result.intent, llm_result.slots) # 第三层LLM直接推理 llm_result llm_engine.predict(user_message, session_context) if llm_result.confidence 0.5: return build_response(llm_result.intent, llm_result.slots) # 兜底策略转人工或者引导用户重新表述 return fallback_to_human(user_message)这个调度逻辑有几个关键点。规则层的拦截优先级最高一旦命中直接短路不给后面两层不必要的计算机会。低置信度复核机制也就是小模型置信度在0.15到0.25之间时先带上小模型的结果让LLM复核而不是直接交给LLM从零推理。这能减少LLM的思考负担也能提升结果稳定性。最终兜底是转人工这个策略在客服场景非常重要宁可让用户排队等人工也不要让机器人乱答一气。5.2 超时控制与降级策略LLM挂了系统不能挂引入LLM层后系统稳定性面临更大的挑战。LLM推理延迟波动大网络抖动或显存不足都可能导致超时而且云端API还可能触发限流。混合架构的降级设计至关重要核心原则是每一层都可以被“切掉”系统要像多米诺骨牌一样逐级降级但不能整体宕机。我的实践方案是这样做的对LLM调用设置硬超时比如600毫秒。超时后如果小模型层已经给出了低置信度结果就按低置信度结果处理否则直接转人工。对LLM服务做健康检查连续失败N次后触发熔断把LLM流量自动切换到备用模型或者云端API。熔断期间系统自动进入“小模型规则”降级模式虽然覆盖范围会缩小但至少保住高频意图的识别能力。人工客服侧兜底所有降级模式下产生的转人工请求进入人工客服队列。这一点需要和业务方提前对齐防止客服承接能力不足导致投诉上升。这里分享一个我真实经历过的故障案例。系统上线第三周我用了一个新版量化配置的模型结果线上请求量一大就频繁超时。监控面板显示LLM成功率从99%掉到70%中控调度自动熔断了LLM流量系统整体退化为“规则小模型”模式。虽然当时的整体意图识别准确率从94%掉到了89%但至少没有影响到客服的基本运转。修复后恢复LLM流量系统逐级回升到正常水位。如果没有提前做降级设计这种情况整条客服链路都会瘫痪。5.3 全链路监控指标与告警体系混合架构链路长任何一层出问题都会影响整体效果。我的监控体系分三个层面第一层是各层流量指标。规则层覆盖率、小模型层覆盖率、LLM层覆盖率三个比例相加应该是100%。正常预期是规则层30%到40%小模型层50%到60%LLM层10%到20%。如果某一层比例异常波动比如LLM层突然升到40%说明前两层的前置能力在退化。第二层是质量指标。整体意图识别准确率、各意图的召回率、转人工率、用户转人工后的满意度。这里的准确率不只是算法侧判对没判对还要结合用户反馈来看用户对回复点了“不满意”也算错误识别。第三层是性能指标。各层响应时间P99、P95、平均耗时规则层要求10毫秒以内小模型层要求80毫秒以内LLM层要求500毫秒以内。超时率超过5%就要排查。我习惯每天早上一睁眼看前一日的三块看板优先关注的是“转人工率”和“用户负反馈率”这两个业务指标。算法准确率再高只要用户不满意说明系统设计一定有没照顾到的地方。6. 上线效果与踩坑实录数据说话教训更要记6.1 效果评估体系与上线指标对比这套混合架构上线四个月后我整理了一份完整的对比数据覆盖40万条线上真实请求对比对象是之前单用小模型加简单规则的旧系统。整体意图识别准确率从85.3%提升到了94.8%提升接近10个百分点是这次改造最核心的收益。规则层拦截了38%的流量响应时间控制在了9毫秒小模型层处理了51%的流量平均响应时间46毫秒LLM层处理了11%的流量平均响应时间380毫秒。整体平均响应时间从旧系统的230毫秒下降到了67毫秒主要原因就是大量简单请求直接被规则层短路了。而用户侧最敏感的“答非所问”比例从7.2%降到了2.1%。转人工率从32%降到了19%说明机器人在更多场景下能独立解决问题了。在成本上LLM层的token费用占整体运营成本的比例约为8%。换算成单次请求成本可比方案是全部用云端大模型我们的方案大约是它的四分之一。到这里这套架构从效果、体验、成本三个维度都通过了验收。6.2 常见问题速查表与独家避坑技巧落地的过程中我积累了不少问题排查经验整理成了一张速查表希望对你有用。问题现象可能原因排查方法解决方案规则层覆盖率突降用户表达方式变化或平台格式变更查看规则匹配失败样本补充新规则建立规则召回率监控小模型低置信度请求过多训练数据覆盖不足或阈值设置过严分析低置信度样本分布补充对应场景训练数据放宽或收紧阈值LLM输出JSON解析失败Prompt引导不够明确或模型版本不稳定查看原始输出日志增强解析容错调整Prompt输出格式用户重复提问同一问题意图识别正确但答案未解决问题分析会话轮次和用户负反馈优化响应策略必要时转人工大促期间LLM延迟飙升流量突增导致计算资源不足查看系统负载和并发数提前扩容开启批量推理和结果缓存小模型过拟合训练集线上泛化差训练数据与线上分布差异大对比训练集与线上样本分布加入更多线上日志数据做对抗验证排坑方面有几点我很想强调。第一个是“新意图发现”机制我在LLM层设置了低置信度聚类任务每周跑一次把LLM识别为某种意图但小模型分类为OOS的样本聚成一堆人工审核后补充进训练集。这套机制保证了系统能持续进化不至于被局限在初始意图集合里。第二个是主动学习小模型层的低置信度样本每隔一段时间自动抽一部分进入标注池攒到一定量后补训练。这是小模型效果持续提升的主要动力。第三个是不要频繁调整阈值。阈值调整直接影响各层流量分配频繁调整会让对比评估失去参照也不利于问题定位。我给自己定的规矩是常规情况下两周最多调整一次而且每次调整留足观察窗口。6.3 后续演进方向从识别到决策的最后一公里三成混合架构上线后我还在持续迭代几个方向供你参考。第一个是有意识引入用户画像“老客催发货”和“新客催发货”的话术应该完全不同。利用平台侧的用户等级、历史购买记录、历史退款率等维度的画像特征不仅提升意图识别准确率更影响后续的回复策略。第二个是升级到“意图识别 策略决策”一体化管线识别出意图后由LLM生成个性化的回复内容再由小模型做一次“回复安全性校验”防止出现不当措辞。第三个是探索自动化客服与人工客服的协同识别出高情绪风险用户后逐步从机器人会话过渡到人工接管这个过程的平稳交接本身就值得一个专项去优化。最后说点实际的体会这套三层混合架构做下来我最大的体会是不要在架构上炫技而是要想清楚每一层该解决什么问题怎么用最低的成本把它解决掉。规则层负责快小模型层负责稳LLM层负责聪明三层各司其职配合好降级策略才是一个经得起生产环境考验的稳健系统。如果你也在做类似的事给你一个很具体的建议先用一个周末把你们的客服对话日志下载下来随机抽1000条人工标一遍意图看看在不同表达方式下模型的表现如何。这1000条标注数据可能比你去网上找什么公开数据集都管用。电商客服的意图识别从来不是靠一个通用模型打天下而是靠理解自己的业务场景、把基础工程做到位。这套“规则 小模型 LLM”的思路不只适用客服任何有成本压力、实时性要求、长尾场景的NLP任务都可以拿去做一次架构升级的参考。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门