Agent意图识别分层漏斗:召回、分类、置信、仲裁四层架构实践
带过工业级Agent的朋友都知道真正的难点往往不是把大模型接进业务流程而是搞清楚“用户这句话到底想让我干什么”。Agent的意图识别和传统ChatBot完全不是一回事——用户可能在一次会话里连续切换三四个目标可能把“帮我查一下昨天的订单”说成“那个单子到哪了”甚至可能在对话中段突然从查询意图跳到投诉意图。单纯的分类模型处理不了这种动态、碎片、多义的输入拿大模型硬做分类又面临延迟、成本和置信度不可信的问题。我在这类项目里反复踩坑后最终沉淀下来一套方案把意图识别拆成“召回—分类—置信—仲裁”四个层级每一层只负责一件事层层收敛最终只把高置信度的结果交给Agent执行。这套分层漏斗思路已经在我们多个线上项目中稳定运行今天把完整设计和实践细节写出来给正在做Agent底层能力的朋友一个可复用的参考。文章适合算法工程师、Agent平台开发者和技术负责人阅读也适合准备自建Agent意图识别体系但还没理清架构的团队。1. 为什么工业级Agent需要“分层漏斗”而不是一个模型1.1 单模型意图识别在真实场景里的三个致命短板很多团队一开始都会用最直接的办法把所有用户输入丢给一个微调过的分类模型或者干脆让LLM做zero-shot分类。在小流量Demo里这个方案看起来一切正常但一旦放到生产环境三个问题会立刻暴露。第一个是召回不全。用户的表达方式极其多样同一个意图可能有几十种说法还夹杂着口语、错别字、行业黑话。单模型依赖训练时见过的表达模式对没见过的变体几乎必然漏召回。尤其当意图类别超过几十个时分类模型在类别间容易产生混淆长尾意图的召回率会急剧下降。第二个是置信度不可信。分类模型输出的softmax概率和LLM的logits都不能直接当作真实置信度使用。模型对某条输入可能特别自信但实际上完全分错也可能对明显的高频意图给出50%左右的概率导致无法决策。我见过太多团队把softmax概率当阈值用上线后误判率比想象中高一倍。第三个是无法兜底。单模型方案是一个封闭的黑盒分错了没有中间层去拦截也没有机会通过交互澄清。用户一句话被错误归类后Agent会直接执行一个错误动作这种体验在工业场景里是致命的。比如用户说“我不要这个方案了”如果Agent把它识别成“确认下单”后果非常严重。1.2 漏斗思想从哪里来搜索引擎的分层架构迁移分层漏斗的思路其实很朴素就是借鉴搜索引擎经典的“召回—粗排—精排”架构。搜索引擎面对的是海量网页不可能让精排模型处理所有候选而是先用廉价的召回通道把候选集缩小再用更精细的模型排序。意图识别面对的输入空间同样巨大——用户说什么都行但Agent真正能执行的意图是有限的、收敛的。因此我们需要做的就是设计一个漏斗最上层用最便宜、最快的方式把和任何已知意图相关的输入捞出来中间层做精细分类再往上一层专门判断“这个分类结果可不可信”最后一层根据可信度决定是直接执行、继续追问还是转人工。每层只做一个任务这带来了单模型方案完全没有的工程优势每一层可以独立测试、独立回滚、独立优化。召回率低了只调召回层精度低了只调分类层阈值策略不对只调仲裁层。出了问题生产链路自带有日志定位不用像单模型那样一换就全局风险。1.3 分层漏斗的整体架构一览我把整套漏斗设计成四个层级下面用表格把每层的职责、输入输出和典型技术选型列清楚层级核心任务输入输出典型实现L1 语义召回层从原始输入中快速捞回候选意图用户raw query候选意图列表TopN关键词规则、BM25、向量检索多路召回L2 意图分类层对候选意图做精细区分候选意图列表 query判别式意图 类别分数微调分类模型 / LLM few-shotL3 置信度评估层判断分类结果是否可信分类结果 query特征置信度分数 决策标志熵计算、多次采样一致性、校准器L4 路由仲裁层决定如何执行、是否澄清、是否降级置信度分数 业务上下文路由指令执行/澄清/转人工规则策略 Agent编排系统联动这个架构可以理解为“漏斗闸门”前三层不断收窄候选并评估质量第四层是最终闸门决定输出流向。下面我把每一层怎么设计和落地的细节展开写这些才是整个方案的真正干货。2. 四个层级的设计要点与实操细节2.1 第一层语义召回层先别急着分类先捞回来很多人做意图识别会跳过分层直接进入分类这个步骤其实是漏斗里性价比最高的一环。召回层的目标不是精准识别意图而是“宁多勿漏”——把可能相关的意图全部捞出来宁可捞出一堆无关候选也不能把真正意图漏掉。召回层我建议做成多路召回而不是单一通道。至少需要三路规则召回、关键词召回、向量语义召回。规则召回用来处理确定性极强的场景比如正则匹配订单号、手机号、纯数字ID。这一路延迟最低5ms准确率100%是漏斗里最稳定的底座。关键词召回靠维护一个“意图词表”每个意图对应一组同义词和关键词。比如“查订单”意图可能对应“订单”“物流”“到哪了”“发货没”等词。关键词召回的优点是可控性强缺点是扩展性弱需要持续维护。向量语义召回是核心。先选一个合适的embedding模型把用户query编码成向量然后和预置的“意图种子向量”做余弦相似度检索。这里的操作要点是不要用单个向量代表一个意图而要用一个意图的多个表达向量共同表示。操作上可以给每个意图准备至少20-50条种子表达把这些表达向量聚集成2-5个类心检索时分别比对这些类心。召回层有一个容易踩的坑向量检索的相似度阈值不能定太高否则漏召回。我经验上是先定一个偏低的阈值比如0.55-0.65取决于embedding模型确保召回率在95%以上宁可把后层负担加重也不能在这一层丢掉真实意图。召回层的TopN建议设定在5-10个左右太少容易漏太多会让分类层压力过大。2.2 第二层意图分类层核心是意图体系设计召回层把候选意图列表送进来之后分类层要做精细区分。这一层的效果好坏80%取决于前期的意图体系设计而不是模型选型。意图体系设计有两个关键原则一是层级化二是互斥性。层级化是指把意图拆成“粗意图细意图”两个级别。粗意图可以理解为业务模块比如“订单管理”“客户服务”“系统设置”细意图才是真正执行的动作比如“查询物流”“修改收货地址”“投诉快递员”。分类层先判断属于哪个粗意图模块再在模块内部做细分类。这么做的好处是每个细分类只需要在几十个同类之间做区分难度远低于在几百个不相关意图之间做区分。互斥性要求每个意图定义必须彼此独立不能有重叠。我见过很多失败案例比如同时定义了“取消订单”和“订单退款”用户说“我不要了”时两个意图概率都高分类器就糊涂了。正确的做法是定义“订单售后”这个粗意图细意图分别是“取消订单”“退款申请”“退货申请”让它们之间的边界清晰可判。模型选型上我的经验是“微调小模型为主、LLM为辅”。当意图数量在50个以内、每条意图的训练样本超过200条时微调一个百亿参数以下的小模型比如基于BERT系列的分类模型或7B级别的对话模型效果都不错延迟可控。如果意图数量特别多几百个或者标注数据不足再用LLM few-shot兜底。LLM分类的prompt一定要给示例并且要求输出JSON格式方便后链路解析{ intent_group: order_management, intent: query_logistics, confidence: 0.78 }分类层的输出不能只有一个预测结果必须把候选列表里每个候选意图的分数都保留下来因为下一层置信度评估需要拿到整体分布信息而不仅仅是Top1。2.3 第三层置信度评估层别信模型自带的概率这一层是整个漏斗里最有价值、也最容易被忽略的部分。工业级Agent能不能让人放心就看这层闸门是否可靠。分类模型输出的softmax概率在真实场景中通常是过度自信的。一个训练得不错的分类器对错误样本也可能给出0.9以上的概率。所以我不直接使用模型的原始概率而是重新做一个“置信度评估”。置信度的来源我常用三个内部熵、多次采样一致性、语义相似度。内部熵是指对分类结果的所有类目概率求信息熵。熵越低表示模型在类别间越确定熵越高表示模型在犹豫。把熵值作为一个负向特征高熵样本转入人工或澄清流程。多次采样一致性针对LLM分类用相同prompt、不同temperature比如0.2和0.7各采一次看两次结果是否一致。一致度越高置信度越高。这个方案对LLM特别有效因为它可以检测模型的随机性——真实置信的意图不容易被温度扰动改变瞎猜的意图很容易翻车。语义相似度是指把query和意图种子表达做向量相似度校验。如果query和“预测意图”的种子向量相似度都不高说明分类结果很可能有问题。比如用户说“你们客服电话是多少”分类器可能把它分到“投诉建议”但query和“投诉建议”的种子表达在向量空间其实没那么接近这时相似度校验就会给低分。拿到多个置信度信号后还需要做置信度校准。校准的目标是让分数真实反映准确率。我常用的是保序回归Isotonic Regression把“模型分数-是否预测正确”作为训练对拟合一个校准函数。校准后的分数可以直接作为决策依据比如0.8分意味着大约80%的概率预测正确。阈值设定方面我建议引入业务代价矩阵。不同意图的错误识别代价差异很大误把“取消订单”识别成“确认收货”的代价极高误把“闲聊”识别成“查询天气”则无所谓。因此不能全局一个阈值要对高代价意图设定更高的阈值比如0.9对低代价意图设低阈值比如0.7。这就是漏斗比单模型灵活的关键——每个意图有自己的闸门。2.4 第四层路由仲裁层把决策变成可执行的策略最后一层不涉及模型推理而是策略引擎。它接收置信度分数和业务上下文输出Agent执行指令。我把路由策略设计成三档高置信区间比如校准置信度≥0.85直接执行。这一档的意图不需要向用户二次确认Agent直接调用对应的工具或流程。中置信区间0.60-0.85进入澄清会话。Agent不是直接执行而是反问用户确认比如“您是想查询物流状态还是修改收货地址”这比错误执行要好得多也增加了用户参与的感知。低置信区间0.60降级处理包括转人工客服或者返回通用兜底话术。路由层必须和Agent编排系统做好联动。我在项目里的做法是路由层输出一个标准的意图事件包含意图编码、置信度、是否需要澄清等字段Agent编排系统统一消费这个事件。仲裁结果同时也记录到日志作为后续优化漏斗的数据回流。这一层的工程要点是策略可配置化。不要让策略硬编码在代码里而是通过配置中心下发这样线上的阈值调整不用发版算法团队可以直接通过管理后台调整每个意图的置信度阈值。我见过太多团队在路由策略上写死参数导致每次调整代价极高。3. 实操过程从零搭建一个可上线的分层漏斗3.1 第一步梳理业务意图清单建立意图编号体系任何漏斗都不能在意图清单不清晰的情况下动工。梳理意图清单的正确顺序是先收集产品功能列表再收集客服对话日志最后做聚类整合。产品功能列表告诉你系统希望用户做的事情有哪些客服日志则能暴露用户真实问法。实际操作时我们拉取了近3个月的用户会话日志过滤掉无效噪音如纯语气词、空白信息做一次聚类统计把高频片段提取出来再映射到产品功能上。这样得到的意图清单既有业务逻辑支撑又有真实数据依据。意图编号体系是从工程角度必须做好的事。建议格式[模块]-[动作]-[序号]比如order-query-01、order-cancel-02。等级编号的好处是后链路可以拿编号做权限控制、统计分析和错误归因。我见过直接用中文描述当意图ID的项目最后在代码里到处都是魔法字符串排查问题时无从下手。3.2 第二步构建评测集与三层指标体评测集是整个漏斗能否持续优化的基础。我建议按三个来源构建真实线上日志占比60%以上、人工构造困难样本20%、公开领域相关数据集20%。其中人工构造的困难样本尤其重要包括同义改写、错别字、歧义表达、多意图混合等。每个意图至少准备50-100条评测样本整体评测集规模建议在2000条以上。评测指标不能只看最终准确率要分各层独立看。召回层看召回率真实意图是否在候选列表中分类层看分类精度候选排序后Top1是否正确置信度层看校准误差ECEExpected Calibration Error和AUC-ROC路由层看最终决策的正确率和澄清率。每层指标独立监控才能快速定位漏斗的瓶颈层。这里有一个实操技巧把评测集构建成带“意图分层标签”的格式。每条数据除了标注最终意图还要标注是否属于长尾表达、是否包含歧义、是否需要澄清。这样无论在做模型调优还是路由策略时都能针对特定样本子集观察效果。3.3 第三步确定各层阈值与参数先跑通再优化阈值和参数在冷启动阶段很难一步到位我的方式是“初始保守一周内校准”。初始参数可以参考这个表格参数初始值说明向量召回相似度阈值0.60宁低勿高保召回召回TopN8留住长尾候选分类模型温度0.3降低随机性LLM采样一致性阈值2/2一致两次采样必须一致高置信执行阈值0.85初始偏高中置信澄清区间0.60-0.85留足澄清空间低置信转人工阈值0.60低于此值不执行上线后一周内通过日志统计实际分布每个意图的置信度分布、漏斗各层漏出率、澄清率、人工转接率。然后根据数据反向调整阈值。注意阈值调整每次只动一个参数而且要看业务指标如下单成功率、投诉率联动变化不要只看模型指标。3.4 第四步灰度发布与线上监控漏斗模型改造要经过灰度发布不能一把梭全量切换。我的经验是分三个阶段内部环境验证2-3天→ 5%流量灰度3-5天→ 50%流量灰度3天→ 全量。灰度期间重点监控三类指标漏斗各层延迟确保P99在500ms以内、决策分布高/中/低置信的比例、业务侧转化率比如Agent执行成功率、用户满意度。这里的对比逻辑很重要要把新漏斗的结果和旧方案同时输出对比而不是直接切换后只看新指标。我踩过这个坑切换后忘记做对比结果效果好不好全靠感觉。4. 常见问题与排查技巧实录4.1 问题一漏斗整体漏出率过高用户请求大量落到低置信这是上线初期最常碰到的情况。排查路径是逐层看日志先看召回层命中了没有。如果召回层就没把真实意图捞入候选说明向量阈值太高或意图种子表达不足再看分类层是否把候选排错这通常是意图体系边界不清或训练样本不足最后看置信度层分数是否普遍偏低这可能是校准器没有训练好或者是query本身在意图体系中确实边界模糊。一个典型的案例某电商场景上线时用户说“这衣服我能退吗”被归到低置信转人工。日志显示分类层正确分到“退货申请”但置信度层因为query里带有“吗”这个疑问语气词语义相似度打分偏低。这个问题的本质是置信度评估特征不够丰富后来我们把“是否包含确认性问句”作为附加特征加入校准器问题解决。这种case如果不逐层查日志根本定位不到原因。4.2 问题二用户的意图在会话中漂移工业级Agent的意图识别必须跟踪多轮会话中的意图转变。用户第一句说“查一下订单”中间可能插一句“你们发的是什么快递”然后又回到订单主题。如果漏斗只看单轮query会把每个query独立判断导致Agent“失忆”。我的解决方案是引入会话级状态管理维护一个“当前活跃意图栈”每当新的高置信意图出现时判断它和当前意图的关系——如果是子意图比如从“查订单”变为“查物流公司”则采用子意图如果是完全无关的新意图从“查订单”变为“投诉”则切换意图栈如果置信度不够高优先在当前意图上下文中理解而非独立判断。这个策略在工程上需要Agent状态层配合给漏斗传入会话上下文。实际操作里我们做了一个轻量级的上下文注入把最近3轮的用户输入和Agent动作拼成一段摘要文本附加到分类层的输入中。这样做的好处是分类层能感知上下文坏处是输入变长延迟和成本会上升所以要控制摘要的长度和结构。4.3 问题三中置信区间样本太多澄清话术让用户厌烦澄清机制是双刃剑。如果系统整天问“您是想A还是B”用户很快就会失去耐心。我在实践中发现中置信区间过大的根本原因往往是意图体系粒度不当而不是澄清策略本身的问题。解决思路有两个方向。第一个方向是压缩中置信区间通过增加训练样本、细化种子表达把原本模糊的样本提升到高置信区。第二个方向是改进澄清方式不要每次都把选项全部抛给用户而是用更自然的确认话术比如“您是要查这个订单的物流对吗”这样用户回答“嗯”就能确认成本比“您是选A还是B还是C”低得多。另外路由层要能做“基于背景的澄清跳过”。如果当前是投诉场景用户又说了一遍订单号这时哪怕置信度不高也不要再澄清订单相关意图直接在当前意图上下文里执行。这个规则不复杂但能把澄清率降低不少。4.4 问题四冷启动阶段没有标注数据漏斗跑不起来很多团队拿到新业务时面临真实数据不足的困境。我的做法是“用伪标注启动漏斗”。从历史客服对话日志中用LLM批量打标一批数据然后人工抽检修正形成初期种子集。这种方法的有趣之处在于LLM打标的数据有噪音但噪音分布相对均匀用来做初始召回层和意图体系的验证完全够用。另外一个冷启动技巧是“复用通用意图库”。很多场景的意图是通用的比如“转人工”“投诉”“咨询帮助”“再见”这四类在任何业务里都存在。这些通用意图可以先固定进漏斗让漏斗在业务意图还没丰富起来时也能正常工作业务意图再随着数据积累逐步加入。冷启动阶段还需要特别注意评测集的建设逻辑评测集应该和训练集分开不能用同样的伪标注数据评测。我建议冷启动评测集用人工标注数量不用太多每个意图30条左右但务必是人工确认过的否则评测指标会虚高。5. 分层漏斗的扩展思考与个人经验分层漏斗的价值不只是提高准确率还在于它让Agent底层决策变得可解释、可观测、可治理。每一条用户输入在漏斗中的流转轨迹都会被记录出问题时可以回溯到具体层级。这在Agent需要审计或合规的工业场景里非常重要——你必须能说清楚“为什么Agent做了这个动作”。基于这套方案后续还可以向几个方向扩展。一是把漏斗输出和Agent记忆模块打通让历史交互沉淀为更精细的意图先验降低重复识别成本。二是引入主动学习机制把中置信和人工处理的样本自动回流到标注平台每周形成一次“难例集”持续迭代分类层。三是针对具体行业构建垂直意图模板库比如金融、医疗、电商各自有一套召回种子表达和意图层级减少跨场景重复建设的工作量。我个人的经验是不要让漏斗一开始就追求全覆盖。先覆盖业务最核心、最频繁、代价最高的20个意图把漏斗跑顺畅再逐步扩张到长尾意图。每扩张一批意图都要重新评估阈值和评测集因为意图体系变大后类别间的混淆会重新抬头。这个过程需要耐心但走稳每一步后你的Agent意图识别能力会非常扎实。最后再说一句实操感受分层漏斗最值钱的不是某一层模型多强而是这种“层层设防、闸门决策”的工程结构让你在模型不够完美时也能保证线上不出大事故。