
工业级Agent意图识别分层漏斗从“一把梭”到四层闸门你是不是也遇到过这种场景用户对Agent说了一句“帮我弄一下这个”系统既不知道该调哪个工具也不知道该不该反问一句“你说的‘这个’到底指什么”。意图识别没做好整个Agent就像个耳背的客服后面接再多的工具、再强的模型也白搭。在工业级Agent项目里意图识别从来不是“接一个意图分类模型”那么简单。线上环境要面对的是高吞吐请求、秒级响应要求、动态变化的业务意图、还有那些你根本没法提前枚举的“奇怪说法”。我在这类项目里反复调优后最终沉淀下来一套“工业级Agent意图识别分层漏斗”的方案用规则、轻量模型、大模型和人工兜底四层闸门逐级过滤把昂贵且不稳定的单次大模型意图判断改造成一条可控、可观测、可逐渐迭代的流水线。这篇文章就把这套漏斗的完整设计思路、每一层的实现细节、工程落地时容易踩的坑以及我的一些实操经验完整写出来。无论你是在用LangChain、Dify、CrewAI这类框架还是自己从零搭Agent这套思路都能直接拿过去用。1. 为什么“一把梭”方案在真实业务里撑不住最早做Agent意图识别我的第一反应和大多数人一样把所有工具描述、业务规则、历史对话一股脑塞进一个Prompt让大模型直接输出用户意图。POC阶段跑起来效果确实不错Demo演示也很惊艳。但一旦进入生产环境这个方案会快速暴露出三个绕不开的问题。第一个问题是成本。LLM是按照Token计费的而意图识别恰恰是调用链路上最前面的一个环节意味着它要承受所有流量。你的业务可能有几十个工具每个工具描述几百字再叠加历史对话、系统Prompt一次意图识别的Prompt轻松超过2000 Token。日请求量到十万级别的时候光是这一个环节的模型费用就足够让老板脸色变青。更麻烦的是成本还伴随着吞吐压力每一次大模型调用都要占GPU资源识别速度上不去整体QPS就卡在这里。第二个问题是延迟不可控。大模型推理是流式输出的虽然现在各家都在优化首Token延迟但相比规则匹配和轻量分类模型仍然慢一个数量级。真实业务里用户发出请求到看到回复通常要求2秒以内。如果你在入口处就用LLM做一次完整意图识别这一步就可能吃掉500到1500毫秒留给后面工具调用、知识检索、结果生成的时间就非常紧张了。我曾经遇到过一个线上事故某次模型升级后意图识别环节P95延迟从800毫秒飙到3秒直接导致整个Agent的响应超时率暴涨业务方当天就打电话过来质问。第三个问题是“长尾意图”无法清晰界定。业务意图不是静态的运营活动会变、产品功能会加、用户的话术更是千奇百怪。你不可能把所有意图都写进Prompt里即使写进去也会因为意图数量太多导致模型混淆。更麻烦的是LLM会有一种“强行归类”的倾向遇到无法判断的话术时它倾向于编造一个看起来合理的意图而不是老老实实说“我不知道”。在交易、退款、投诉这类场景里这种幻觉会直接导致误操作这是工业级系统完全无法接受的。所以要想让Agent在真实业务里稳定跑起来意图识别就不能再走“单模型一把梭”的路线了。正确的思路是把它拆成一个分层漏斗便宜的、确定性的手段放在前面拦截掉大部分简单流量昂贵的、智能化的手段放在后面只处理少部分疑难杂症。每一层都有明确的输入输出边界、有可观测的指标、有独立的降级方案这样整个系统才谈得上“工业级”。2. 分层漏斗的四层结构与边界划分工业级Agent意图识别分层漏斗我把整体设计成四层每一层解决一个特定的问题。第一层规则闸门Rule Gate用正则、关键词、黑白名单把明显不需要意图识别的流量直接拦下来。第二层轻量分类模型层Intent Classifier用FastText或者小型BERT模型处理高频意图把能确定的部分快速消化掉。第三层LLM精识别层LLM Judge处理小模型拿不准的模糊表达和长尾意图在这个环节引入大模型的理解能力。第四层兜底与人工转接层Fallback Human Handoff当前面所有层都无法给出足够置信度的判断时用标准话术引导用户甚至转接人工。这四层的关系可以类比成机场安检先做大件行李的X光扫描规则快速过一遍再分流到不同通道做人员检查分类模型扫高频人群碰到可疑行李再开箱人工检查LLM精判最后如果真的查出问题移交专门处理人工兜底。每一层的目的都是“少让后面的层干活”越往后越贵、越慢、越不可控所以要让前面的层尽量多干活。这个分层结构的关键不在于“分了四层”而在于每层之间有清晰的Decision Boundary决策边界。每一层都必须回答两个问题我能确定这个请求属于哪个意图吗我能确定这个请求不在我的处理范围内吗对应到工程实现上就是每一层都要输出一个置信度度量并且设定一个Lower Threshold和Upper Threshold。置信度高于上限的直接放行低于下限的交给下一层如果出现在中间地带那是规则的边界问题需要通过评测集持续校准。实际落地的时候我强烈建议把每一层都设计成独立模块通过一个统一的Router路由器串联。这样后面想替换模型、调整阈值、增加规则都不需要动其他层。另外每层都要做好降级预案比如LLM层超时了就退回第二层的结果第二层模型挂了就退回第一层的规则匹配结果。宁可让用户觉得“这个Agent笨一点”也不能让整个服务因为意图识别模块故障而完全不可用。3. 分层漏斗的四层结构与边界划分这里其实应该接具体每一层的实现细节但因为章节标题定了在这一节里把四层的具体设计和细节讲透3.1 第一层规则闸门挡住沉默流量规则闸门是整个漏斗成本最低、速度最快的一层通常请求经过这里的耗时在几毫秒以内。它要处理的是那些“根本不算意图识别问题”的流量比如用户随手发的“在吗”“你好”、系统的空请求、明显是垃圾内容的重复刷屏还有一些你希望从业务入口就彻底挡掉的敏感话题。为什么用规则而不是模型来处理这部分因为规则是确定性的一条正则命中了就命中没命中就没命中行为和结果完全可预期出了问题可以逐条追查。模型在这方面天然做不到尤其是大模型你很难解释它为什么放行了某条内容。第一层的实现通常由三部分组成关键词表、正则表达式和简单的长度/频率过滤。举个例子用户输入“你好”“谢谢”“再见”这类纯礼貌用语我们把它归结为“寒暄意图”直接走预设的欢迎语回复不需要识别任何业务意图用户输入“请联系人工”“转人工”“人工客服”这类话术则直接路由到人工客服队列也不需要在意图分类模型里绕一圈。关键词表要基于真实线上日志去补充而不是人工拍脑袋编。我见过很多团队把关键词表做得非常大结果出现“包含‘删除’就认为用户要删除数据”的误杀这类问题在规则层最容易犯。正则要小心几个经典陷阱中文的分词边界、同音字、口语化的变体表达。比如“退款”和“退钱”是同一个意图但正则如果只匹配“退款”就漏掉了后者。比较好的做法是建立同义词映射表把“退钱”“退票”“款项退回”这类说法统一归一化之后再匹配。还有一个经验是规则层只做“能明确判定的”不要试图用规则覆盖所有场景。一条规则能覆盖1%的稳定流量就是有价值的但如果一条规则的命中条件模棱两可宁愿不写。模糊不定的规则会让系统行为变得难以预测这在工业级系统里是大忌。3.2 第二层轻量分类模型扛起高频意图的大头当请求通过了规则闸门进入第二层时面对的才是真正需要语义理解的流量。这一层的目标是把高频业务意图快速识别出来。什么叫高频按照二八定律通常20个意图就能覆盖80%以上的真实业务请求。比如在一个电商Agent里“查订单”“退款”“改地址”“催发货”“开发票”可能就是最高频的几个意图。这些意图的用户表述相对固定用轻量模型就能学得很好完全不需要动用LLM。我推荐在这一层使用FastText或者小型TextCNN两者在CPU上都能跑到毫秒级延迟内存占用几百MB级别。升级一点的方案是用蒸馏出来的BERT-Lite模型分类效果会更好但推理延迟大概在10到20毫秒仍然在可接受范围内。具体选哪个取决于你线上能承担的延迟预算和运维成本。我的经验是如果意图数量在50个以内FastText的准确率已经能达到90%以上意图数量超过100个、且相似意图较多时建议直接上BERT-Lite。这一层的训练数据来源是历史日志中已经标注好的用户query这么做的核心逻辑是“用便宜的模型去模拟昂贵模型的行为”。初始阶段你可以先用LLM做离线标注生成一批伪训练数据再用这批数据训练小模型。等线上跑一段时间后再把真实请求中LLM判定的结果回流为训练语料不断迭代小模型。这里有一个很关键的参数经验第二层只负责“高置信度的快速路由”。建议设定一个较高的置信度阈值比如0.7或0.8只有超过阈值的才直接放行低于阈值的全部送到下一层。宁可让请求多走一层也不要为了让模型“硬做决定”而强行拉低阈值。因为一旦误判后面工具调用可能就执行错了补救成本极高。3.3 第三层LLM精识别吃掉长尾和模糊表达前面两层已经处理掉了大部分简单流量能把进入第三层的请求比例压缩到总量的10%甚至更低。这10%的流量就是真正的硬骨头用户表达模糊、涉及长尾低频意图、或者与某个已知意图有一定相关性但又不完全对得上。这类请求才值得动用LLM。但LLM层的设计与最开始的“一把梭”完全不同重点是做“候选意图裁剪”。当请求到达这一层先通过第二层模型输出的概率分布或者一个简单的相似度检索从全量意图清单里排出Top 5到Top 10个候选意图然后把Prompt限制在这几个候选里让LLM从中选择一个。为什么这样做因为全量意图可能有200个全部塞进Prompt既浪费Token又会让模型在相近意图之间产生混淆。裁剪之后LLM只需要做一个N选1的选择题准确率和稳定性都会显著提升。这个环节的Prompt设计要刻意“克制”。我通常用这样的结构先说明任务背景和约束——“你是意图识别器只能从给定的候选列表中选择一个意图禁止臆造列表之外的意图”然后列出候选意图清单附上每个意图的简短定义和2到3个示例最后让模型以结构化JSON输出结果包含intent_id、confidence和reason三个字段。要求模型给出reason是为了后续排障当判定错误时你能看到模型当时是怎么“想”的这比一个黑盒判定结果要好排查得多。一个重要的经验是LLM层的Prompt里不需要塞入完整的历史对话。历史对话会让Token开销成倍增长还容易引入无关噪声。我们做过对比实验完整对话作为上下文意图识别准确率反而下降了3到5个百分点因为对话里用户改口、开玩笑、临时插话都会混淆模型的判断。更可靠的做法是只传入当前这一轮的用户query加上从对话状态里提取的关键要素比如“用户当前正在看的订单编号”“用户所在页面”这类结构化字段。如果多轮对话是必须的也要做截断只保留最近两轮。3.4 第四层兜底与拒识让系统有“安全感”当规则、小模型、LLM三层都判定不出足够置信度的意图时最终兜底层就要出场了。工业级系统里这层最重要的作用不是“解决问题”而是“安全地承认自己没听懂”同时给用户留出重新表达的机会。在实际项目里我见过不少团队对兜底层的设计极不重视只用一句“对不起我还没学会这个功能”就结束了。这其实是巨大的浪费。兜底层应该做两件事一是Standard Disambiguation标准澄清二是Limited Option Offering有限选项引导。用户问了一个模糊的问题你要让用户感觉系统是在“努力理解”而不是“直接摆烂”。比如用户说“我想弄一下之前那个”系统可以回复“您是想修改订单信息还是想申请退款或者是想催一下发货进度”给用户几个明确的选项让用户一次点击就能完成选择。这种方式比让用户重新描述一遍体验要好得多。兜底层同时还是整个漏斗的“数据回收站”。所有走到这一层的请求都必须被完整记录下来原始query、每一层给出的confidence、中间结果、最终路由决策。这些数据经过人工标注后会成为下一轮迭代的黄金训练语料。我通常要求项目组每周固定抽检一次兜底层数据把所有badcase分好类哪些是应该进第三层但没进去的说明小模型漏召回了、哪些是LLM判错了但置信度还给很高说明Prompt引导有问题、哪些是真实的新意图说明意图体系需要扩充。这些分类结果就是整个漏斗持续迭代的核心动力。4. 工程实现意图体系、数据流转和成本控制的关键细节4.1 意图体系设计先画好地图再动工分层漏斗跑得好不好其实一半的功夫在设计意图体系上。这不是排一堆意图名就行的事情。我的建议是采用“父意图子意图”的两级结构父意图控制在10个以内子意图控制在50到200个之间。比如“售后服务”是一个父意图下面挂“退款”“换货”“维修”“物流异常”等子意图。分类模型先判断父意图再在子意图里精细分类。这样做的好处是规则层和轻量模型层可以只针对父意图做快速判断把子意图的精判留给后面的层降低每一层的决策难度。意图体系的另一个关键点是“互斥设计”。每两个意图之间最好能保证语义上的互斥性避免出现“A和B看起来差不多模型只能靠细节猜”的状况。如果发现两个意图经常混淆优先考虑合并成一个意图而不是通过增加示例去硬区分。示例加得越多模型的决策边界越模糊反而越容易出错。宁可让一个意图的覆盖面宽一点也不能让两个意图重叠。此外一定要设计一个“未知意图”OOSOut-of-Scope的类别专门接收那些新出现的、还没归纳进意图体系的用户需求。很多团队会忽略这个类别导致模型在实际遇到未见过的表达时被强行归到某一个近似的已知意图里从而执行错误操作。有了OOS类加上第四层的兜底系统才能对新需求做出“我暂时不会但我知道我不会”的正确响应。4.2 各层接口设计与数据流转规范分层漏斗想要跑得稳各层之间的接口必须非常干净。我给每一层定义的统一输入是normalized_query归一化后的用户输入输出是一个统一的判定结构包含以下核心字段字段类型说明query_idstring当前请求的唯一ID用于全链路追踪intent_idstring判定出的意图ID可能是未知意图confidencefloat当前判定置信度范围0~1routestring由哪个层完成判定rule/clf/llm/fallbacklatencyint当前层耗时毫秒model_outputjson模型原始输出保留排查线索每一层只做“读入统一结构、尝试判定、更新结果后传给下一层”这件事。第X层永远不修改第X层的判定结论只决定“要不要往下走”。这样实现的另一个好处是可以对每一层单独记录指标rule通过率、clf决定率、llm精判率、fallback率。这些比例数字加起来能直接反映漏斗的健康度。有一个工程细节要特别提醒在设计数据流转时给每一层都设定超时上限并且做超时降级。比如规则层超时上限10毫秒分类模型层50毫秒LLM层800毫秒。一旦这一层超时Router直接跳过它用上一步已有的结果继续往下走。这里的原则是“可以用弱一点的结果但不能让整个请求卡死”。4.3 成本与延迟的量化控制我在做技术方案评审时最常被问到的两个问题是这套漏斗比直接调LLM识别到底省多少钱线上延迟能压到多少这里给出一份基于真实场景的估算方法。假设业务日请求量10万次每次请求都会过意图识别环节。如果直接使用LLM做全量识别假设一次调用平均消耗1500 Token含工具描述和Prompt模板按照当前主流大模型API的价格估算一天光意图识别的Token费用就在数百元级别。如果改成分层漏斗规则层阶段能拦截掉30%的寒暄类和非业务类请求分类模型层能再消化掉60%的高频意图请求真正走到LLM层的只有10%。而这一层经过候选裁剪后单次Prompt的Token消耗可以控制在300到500 Token整体费用只有原来的五分之一到十分之一。延迟方面规则层目标在5毫秒内完成分类模型层目标在20毫秒内完成LLM层单独分配800毫秒预算。设计漏斗时的整体策略是控制进入LLM层的比例只要这个比例低总体延迟就稳定。我给一个常规的目标参考整体意图识别环节P95延迟不超过300毫秒TP99不超过800毫秒。如果LLM层因为模型升级或者服务异常导致延迟恶化即使只有10%的流量受影响整体P95也会被拉高所以这一层的超时控制和降级策略必须额外重视。顺带回答一个很多新手问的高频问题“AI Agent Token是什么意思”。在LLM体系里Token是模型处理和计费的基本单位可以简单理解成把一段文字切分成若干小块英文通常一个单词拆成1到2个Token中文通常一个汉字对应1到2个Token。模型输入输出都会消耗Token消耗量和Prompt长度、生成内容长度直接相关这就是前面所有成本计算的基础。5. 衡量、排障与迭代把漏斗用起来5.1 怎么衡量漏斗好与坏分层漏斗的指标体系和平常用准确率一把梭的评测方式完全不同。我建议重点看四个指标端到端意图识别准确率所有请求中最终判定意图与实际业务意图一致的占比。漏斗逐层通过率每层处理的请求占全部请求的比例最终要形成一条清晰的分流曲线。兜底率Fallback率走到第四层的请求占比过高说明前面各层能力不足过低则说明冒进判定太多。单次请求平均成本与P95延迟这两项直接决定这套方案能不能在生产环境长期运行。评测集的建设是整个漏斗优化的起点。千万不要只在测试集上跑一两个模型的对比实验那只能看出模型本身的差距看不出漏斗整体的行为。我习惯从线上日志里按周抽样每周抽300到500条真实请求用两条标准去做标注标注者之间的Kappa一致性系数要达到0.7以上去掉标注分歧的样本后再进行模型评估。这样积累12周后就有了一个超过5000条样本的黄金评测集每一轮漏斗改动都要在这个评测集上回归。这里有个经验要分享评测集不是越新越好而是要保持一定比例的历史数据避免模型每次迭代都只迎合最近一周的业务波动。5.2 线上排障实录我踩过的四个坑再好的设计方案上线后都会碰到维护层面的问题。这几个坑是我在排障时最常遇到的写出来给大家避一避。第一个坑是规则层误杀。我们曾设置了一条正则命中“删除”关键词就归为“删除数据意图”结果用户在小程序里输入“我想问下删除了之后还能恢复吗”直接被规则层抓走系统差点执行了不可逆操作。排查后发现这类“含触发词但语义并非触发本意”的请求占比还不低。解决办法是对规则层增加一套否定模式当命中关键词且前后附带“吗”“能不能”“怎么”等疑问词时不直接判定为执行意图而是降级到分类模型层处理。规则层可以做快速路但绝对不能做独裁者。第二个坑是few-shot示例把模型带偏。LLM层一开始想覆盖“查物流”意图就在示例里写了很多“我的快递到哪了”之类的话。结果上线后用户说“我的订单到哪一步了”也会被判成“查物流”。原因倒不复杂示例太集中在某一种表达形态上模型学到了“到哪”这个短语的信号。后来我们重新整理few-shot示例要求每个意图的5到10个示例必须覆盖不同的句式疑问句、陈述句、名词短语、口语化表达同时删掉容易误解的敏感词。示例要均衡宁可每个意图的示例少而精也不要某个意图的示例多而偏。第三个坑是置信度阈值拍脑袋。很多同学喜欢直接把阈值设成0.85或者0.9觉得“越高越安全”。我在实际调优中发现置信度分布并不是均匀铺开的它往往会在某几个特定区间出现密集聚集。如果阈值定在密集区间中间线上行为就会极其不稳定业务高峰时流量稍微变化就有大量请求从放行变成下一层导致延迟和成本大幅波动。正确做法是画置信度分布图找到分布曲线的“自然低谷”把阈值定在低谷处弗并配套一个隔离区间范围让系统在峰值波动时也不会来回横跳。第四个坑是日志不全判断问题只能靠猜。最早的版本里我们没有在漏斗各层记录完整的model_output只记了最终判定结果。结果等到badcase分析的时候根本不知道是分类模型算错了还是LLM Prompt出了问题还是规则层误拦了。后来我们改成全链路日志方案每个请求的query_id贯穿始终每一层的输入、输出、耗时时长、置信度全部落到日志系统。排障时的思路从“猜哪里出事”变成“顺着query_id翻链路”效率提升了不止一个量级。5.3 迭代闭环从badcase到新一轮上线漏斗上线之后优化的过程其实是一个持续不断的循环。每周的节奏大概是周一抽检日志把badcase按发生层归好类周二周三做标注和根因分析周四周五根据根因做调整可能是新增规则、补充训练数据、调整few-shot示例或者是微调意图体系下一周灰度发布并回归评测集。这里有一个“灰度发布”的技巧对漏斗的任何改动都不要一次性全量推上线。因为每一种改动的影响范围不同规则层的小调整可能影响1%的流量但LLM Prompt的重写可能影响全部进入第三层的请求。我们习惯的做法是在漏斗Router层做一个“影子模式”新规则和新模型先并行运行一段时间只记录判定结果而不影响线上行为等结果对比稳定后再切换流量。这个方法额外增加的成本很低却能规避掉绝大多数上线事故。5.4 高频问题小汇总那些被问烂的选型和概念问题最后整理几个项目评审和面试阶段的高频问题顺便帮大家理清思路。有同学问“LangChain、Dify、CrewAI哪个好”。这个问题如果脱离场景来回答是没有标准答案的。LangChain更像一套积木库灵活但需要自己拼装适合有工程能力、想深度控制逻辑的团队Dify偏可视化工作流上手快适合生存周期短、以快速搭建验证为主的场景CrewAI则更侧重多Agent协同。回到我们讨论的意图识别分层漏斗反而要提醒一句框架选型跟漏斗本身没有强绑定关系。这套漏斗可以挂在任何框架前面本质上它只是一个独立的服务对外暴露一个“给定输入返回意图和置信度”的接口。不要让你的框架选型一开始就限制了架构设计。还有同学纠结“Harness和Agent的区别”。“Harness”这个词在Agent语境里通常指的是Agent运行时的那套挂载结构比如工具定义、上下文管理、执行编排、安全边界这些跟模型推理解耦的工程化能力。Agent本身更偏“大脑”负责理解和决策而Harness是“骨架和四肢”负责让决策能真正落地执行。放到意图识别漏斗里你可以把整个漏斗看作是Harness的一部分它在模型和业务动作之间为Agent提供了关于“用户到底想干什么”的结构化输入。再看“Agent Skill是什么跟Tool有什么区别”。Tool是Agent可以调用的外部能力接口通常是确定性的执行一个动作、返回一个结果。Skill则更接近一种组合能力它可能内部包含了多个步骤、多个Tool的编排甚至有自己的Prompt策略。举个例子Tool就像一把螺丝刀Skill则是“组装一张桌子的完整流程”。在意图识别场景下用户表达了“帮我写一封英文邮件”Agent识别出来的意图会映射到一个具体的Skill上这个Skill内部再去调用翻译工具、草稿生成工具、发送邮件工具等。至于“Agent开发学习路线怎么规划”实话说现在网上资料很多但我建议少看那些“从零到高手”式的教程大多数都停在玩具Demo层面。有两条主线值得投入一条是理解Agent的运行时基础包括工具定义、上下文管理、记忆系统、多Agent通信另一条是掌握这个领域的工程化评估方法包括评测集构建、badcase归因分析、灰度发布。这两条主线恰恰是工业级Agent和Demo级Agent的分水岭也是我们这套意图识别分层漏斗背后的核心功力所在。6. 从POC到生产我在这套方案上得到的几条实在经验整套漏斗跑了一年多回看最初一版“一个Prompt走天下”的方案最大的收获不是省了多少钱、降了多少延迟而是整个系统变得“可解释、可控制”了。一条很具体的经验是开始千万别贪多求全。第一次落地漏斗时先只挑一个业务域的3到5个高频意图跑通闭环等指标、日志、迭代节奏都稳定下来再逐步扩展开来。上来就铺200个意图只会被badcase淹没团队也容易失去信心。另一个经验是越分层越要尊重“每层只做自己的事”这个边界。规则层不要试图理解语义分类模型层不要试图覆盖长尾LLM层不要试图包揽全部一旦某层越界整个漏斗的行为就会变得难以预测。还有一点关于和业务方沟通的经验意图识别漏斗的指标不要只谈技术指标准确率、延迟而是要和业务指标挂钩。比如兜底率和用户满意度之间的关系、误判率对订单退款流程风险的影响把这些讲清楚业务方才会配合你设置兜底话术、提供标注人力。毕竟漏斗做得再好最终目的也不是炫技而是让用户觉得“这个Agent真的懂我”。如果你正在做工业级Agent想把意图识别真正做成一个稳定、可控、能持续运转的模块不妨从这套分层漏斗开始。规则层不要贪多分类模型层要敢用LLM层要克制兜底层要当成数据仓库来用。这套方案能走多远最终还是取决于你对线上的每一层数据有多敏感、对badcase的归因有多认真。