3 级 intent 级联调参——规则 / Embedding / LLM 的成本-精度-延迟三角到底怎么定阈值|Agentic AI 落地方法论(八)

Yaqin Hei··16分钟阅读
中文EN
3 级 intent 级联调参——规则 / Embedding / LLM 的成本-精度-延迟三角到底怎么定阈值|Agentic AI 落地方法论(八)

《Agentic AI 落地方法论》系列第八篇。 前 7 篇拆「方案能不能上线 + 上线后怎么不放养 + 北极星 + 脑手分离 + 怎么测」——L0-L3 定级L2 vs L3 的 5 个架构决策Critic fail-closed上线即放养接住率 vs 解决率Skills vs 知识库双轨测试。这一篇兑现系列二决策 2 的深挖预告——意图分类的 3 级 fallback,阈值到底怎么定。English version: Tuning the Cost / Precision / Latency Triangle for the 3-Tier Intent Cascade.

1102 条样本里的一句"加点 LLM 兜底就行"

某个零售客服 Agent 项目跑了三个月,运营在 dashboard 上看到一组数字:1,102 条用户消息,意图分类准确率 59.44%,unknown 占比 40%。

业务方提了个看起来很合理的要求:「这 40% 的 unknown,加点 LLM 兜底不就好了?」

乙方加完了。一周后第一次月度账单出来——意图分类这一节的 API 成本是之前的 12 倍,准确率上去了 8 个百分点。老板看着账单坐了半个小时没说话。

这件事我在过去一年的项目里看过不下三次,换汤不换药——

  • 第一种走法:纯规则。意图体系从 15 个长到 30 个,规则之间开始打架,三个月后没人愿意维护,整个工程团队反弹。
  • 第二种走法:纯 LLM。「现在大模型这么便宜,不就调个 API 嘛」——高并发场景每天 60 万次调用,月成本拉到六位数,延迟撑不住 SSE 流式。
  • 第三种走法:3 级 fallback。规则 60% + embedding 30% + LLM 10%,成本是纯 LLM 方案的 1/10,准确率反而更高

第三种是这一年我看到所有能稳定上线的客服 Agent 共同的选择。但 3 级 fallback 真正难的不是架构,是阈值怎么调——置信度多少直返、ambiguity gap 多少触发反问、LLM unknown 多少算正常、cache 怎么做、限流怎么走。

这一篇拆开这套调参手册。下次评审会再有人说「加点 LLM 兜底就行」,你能把这张表拍他脸上。

文章后半还会讲一件事:3 级 fallback 跑稳之后,下一步该往哪走——v1 调到顶(意图体系超过 40 个 + policy 边界反复改 + anchor tuning 边际收益跌到 +2pp 以下),自然演进到 v2 LLM Router——LLM 综合 context + query + 多轮历史直接路由到 ACTION / POLICY / CLARIFY 几条主路径,多轮澄清天然支持。两套架构不是替代,是演进,第 8 节专门讲。

两个极端方案为什么都是死路

先把结论摆桌面上:纯规则、纯 LLM、3 级 fallback 是三种架构选择,前两个上线都翻车。

方案成本延迟准确率天花板维护成本上线后死法
纯规则~01ms 以内70-75%极高意图过 30 个之后规则打架,工程半年内反弹
纯 LLM高 10x200-500ms85%月账单 6 位数 + 高并发撑不住 + 输出不稳定
3 级 fallback合理混合90%+能上线

纯规则的死法有两种。意图体系小(10 个以下)时跑得飞快,准确率不高但凑合用;一旦扩到 30+,规则之间互相吞——"退鞋" 命中 product_inquiry 还是 return_request?同一句话两条规则都匹配,先后顺序里藏的判断没人讲得清。半年后规则总数破 100,工程团队接手新人看到 rules.py 直接申请离职。

纯 LLM 的死法有三种。成本:高并发场景每天 60 万次调用,按 qwen-turbo 单价 ¥0.002/1k token 算,月成本到六位数。延迟:意图分类是用户每发一句话都要跑的第一步,LLM 200-500ms 起步,加上后续 RAG 检索 + workflow 执行 + 生成,首字延迟到 2 秒以上,用户 SSE 流式那边看着就是「卡住」。稳定性:温度不为 0 时同一句话每次返回的意图不一样;温度为 0 时遇到 corner case 还是会幻觉(编个体系外的新 intent label)。

3 级 fallback 是工程上 only viable 路径——用最便宜的解决 60%、用稍贵的解决 30%、用最贵的兜底 10%,剩下的转人工。任何把这个比例做反的方案,要么成本失控、要么延迟撑不住高并发、要么准确率上不去。

成本-精度-延迟三角的一张表

下面这张表是接下来所有阈值调参的基准。打印贴墙上。

单次成本单次延迟准确率提升覆盖率目标失败模式
Level 1 规则≈ ¥01ms 以内baseline 70%60-70%规则之间互相吞 / 太宽误匹配
Level 2 Embedding~¥0.000120-50ms+10-15pp20-30%阈值低误匹配 / 阈值高漏召回
Level 3 LLM~¥0.001200-500ms+5-10pp5-10%硬选 / 幻觉新 intent / 超时
unknown 兜底n/an/an/a3-5%比例过低=硬猜,过高=体系缺失

3 个数字记住——60 / 30 / 10。这是 3 级 fallback 各层的目标覆盖率。

3 级 fallback waterfall——规则 60% + embedding 30% + LLM 7%,每升一级成本 10x、延迟一个量级

图中标签为英文:Level 1 RULE / Level 2 EMBEDDING / Level 3 LLM / Unknown → HUMAN,分别对应规则层、embedding 层、LLM 层、人工兜底。每行右侧是该层成功的判定信号 (✓) 和翻车的失败模式 (✘)。点击图片查看原图。

数字本身没什么神奇,神奇的是当你的实际分布偏离这个比例时,对应一定有一处工程问题——

  • 规则覆盖低于 50%:意图体系扩张了但规则没补,要不要拆几个高频意图出来加规则
  • 规则覆盖高于 80%:规则可能吞了具体意图("退鞋" 命中了泛 "鞋" 规则),要排查
  • Embedding 覆盖低于 15%:阈值定得太高,或者高频用户表达跟 anchor sentence 差距太远
  • Embedding 覆盖高于 40%:阈值定得太低,准确率会塌方
  • LLM 覆盖高于 15%:embedding 没填好,把本该 embedding 解决的甩给了 LLM
  • LLM 覆盖低于 3%:可能 LLM 阈值定得太严,或者 embedding 阈值太宽吞了 LLM 该处理的长尾
  • unknown 高于 10%:意图体系里有空白,或者用户表达多样性远超你的标注集

这套监控信号是调参的方向盘。线上跑两周看分布,对照表往回调。

Level 1 — 规则层不是 low-tech,是工程上唯一保 "12315" 的兜底

规则层在评审会上最容易被嫌弃——「我们都 2026 年了还写正则?」——但规则层是整个 3 级 fallback 里唯一能给「合规高优先级意图」做硬兜底的层

举个例子。用户说「再不解决我打 12315 投诉」「我要找消协」「这事我准备发抖音曝光」——这一类舆情高风险信号,绝对不能让它经过 embedding 或 LLM。原因有三:

  • Embedding 召回不稳定——"12315" 的语义跟"消协"、"工商局"、"市场监管" 不近,向量空间里散得开
  • LLM 偶尔会"理解错"——LLM 把"打 12315"理解成"打 12315 块钱",看过这种 bug
  • 这一类必须毫秒级响应——延迟 200ms 给客户反应时间,舆情可能已经发出去

所以规则层的第一职责不是覆盖 60% 高频意图,是优先匹配 8-16 个 safety filter——

INTENT_RULES = [
    # 第一组:safety filter(高优先级,永远先匹配,0.5ms 内返回)
    ("escalate_complaint", [
        r"12315", r"消协", r"消费者协会", r"工商",
        r"市场监管", r"投诉.*抖音", r"曝光", r"315",
    ]),
    ("human_transfer", [
        r"^转人工$", r"^人工$", r"真人", r"客服小姐姐",
    ]),
    ("legal_threat", [
        r"起诉", r"律师函", r"法院", r"违法",
    ]),

    # 第二组:高频业务意图(覆盖 60-70% 日常对话)
    ("return_request", [
        r"退货", r"退换", r"七天无理由",
        r"我要退", r"怎么退", r"申请退",
    ]),
    ("refund_status", [
        r"退款", r"退款.*多久", r"退款.*进度",
    ]),
    # ... 8-12 个高频业务意图
]

规则设计有 3 条铁律,每一条都是踩坑换回来的——

铁律 1:first match wins,所以顺序决定一切。 safety filter 必须在最前面(哪怕你 99% 的对话用不上)。高频意图按"具体优先于宽泛"排:「退鞋」放在 return_request 里,再单独加一条 product_inquiry 兜底"鞋"——反过来 "鞋" 会吞掉「退鞋」。

铁律 2:正则不能太宽不能太窄。 太宽:r"退" 会命中"退伍"、"退烧药"、"打折促销退场"。太窄:r"我想申请退货" 只能匹配完整句子。合适的颗粒度:3-5 个高频表达 + 1-2 个变体——r"退货", r"退换", r"我要退", r"怎么退"

铁律 3:短句要锚定。 r"^你好$" 匹配纯打招呼,r"你好" 会命中"你好吗我想退货" 然后被错路由到 greeting。锚定符 ^ $ 是这层的灵魂。

规则层做到这个程度,覆盖 60-70% 日常意图 + 100% 高风险舆情——是 3 级 fallback 整套架构的地基。

Level 2 — Embedding 层是 ambiguity 的安全网,阈值要分两个

规则 miss 的句子落到 embedding。这一层的核心不是 confidence 阈值,是 ambiguity gap

什么是 ambiguity gap——同一句话跟 top-1 意图的向量相似度 0.78,跟 top-2 意图相似度 0.72。差距 0.06,你根本不应该返回 top-1,应该走澄清流程。

两个阈值要分开调:

def embedding_classify(query):
    candidates = vector_search(query, k=3)  # 返回 top-3
    top1, top2 = candidates[0], candidates[1]

    # 阈值 1: 绝对置信度
    if top1.score < 0.70:
        return None  # 落到 LLM 层

    # 阈值 2: ambiguity gap
    if top1.score - top2.score < 0.20:
        return IntentResult(
            intent="needs_clarification",
            candidates=[top1, top2],
            ask_user=True,
        )

    return top1.intent

阈值 1,top-1 confidence,起步值 0.75。

  • 0.75 以下基本是误召回,往 LLM 层推
  • 0.75-0.85 是 embedding 这一层的甜区
  • 0.85+ 几乎一定对,直接返回

调参方向:线上 embedding 直返的准确率低于 90% → 把阈值升到 0.80;太多句子被推到 LLM 层(LLM 覆盖率高于 15%)→ 降到 0.70。

阈值 2,ambiguity gap,起步值 0.20。

  • gap < 0.20 → 反问用户(多候选 clarification flow)
  • gap >= 0.20 → 直接返回 top-1

ambiguity gap 这件事很多团队不做,这是 embedding 层最大的隐藏 bug。看一个真实场景:

用户: "鞋子有问题"
top-1: complaint_quality, score=0.78
top-2: sizing,             score=0.74  ← gap 只有 0.04
top-3: return_request,     score=0.71

不做 gap 检查 → 强行返回 complaint_quality → workflow 路由到投诉处理 → 用户其实想说尺码不对 → 路错了,用户骂街转人工。

做 gap 检查 → 触发 clarification → 反问:"请问您是想反馈商品质量 / 尺码不合适 / 申请退货?" → 用户选了"尺码不合适" → 准确路由。

clarification 不是用户体验损失,clarification 是把用户体验从"被错路由然后骂街"换成"被反问一句然后顺畅完成"。线上 clarify-rate 调到 5-10% 是健康区间——低于 2% 多半是吞了歧义,高于 15% 说明意图体系本身边界不清。

两个阈值要分开调——同 top-1 = 0.78,gap 不同决定 CLARIFY 还是直返

左例 "鞋子有问题" top-1 与 top-2 差距只有 0.04 → 应该走 CLARIFY 反问,不应该硬选 complaint_quality;右例 "我要退货" gap 0.23 → 可以直返。图中标签均为英文(intent 名 / score)。点击图片查看原图。

Embedding 层另一件事:anchor sentence 的质量决定向量空间。每个意图准备 5-10 句"标准表达"(不是 SOP 文档,是真实用户说过的话),embed 后做 average pooling 作为 intent anchor。anchor 质量差,整层 embedding 准确率上不去——之前那个 1102 样本准确率 59.44% 的项目,就是因为 anchor 是从政策文档里挑的,不是从对话 corpus 里捞的。

Level 3 — LLM 层兜底,最关键的一件事是让它会说 unknown

规则没命中、embedding 也不确定,落到 LLM。这一层最关键的事情不是 prompt 写得多漂亮,是让 LLM 在不确定时返回 unknown,而不是硬选

90% 的 LLM 意图分类 prompt 是这么写的:

你是意图分类器。可选意图:A, B, C, D。
用户消息:{message}
返回 JSON: {"intent": "X"}

这个 prompt 有个致命默认——它没给 LLM "我不确定" 的出口。LLM 收到一句它没法判断的话(比如「上周买的那个能不能那个」),它会硬选一个最像的返回。这种"硬选"的输出在监控里看不出来——log 里就是 {"intent": "return_request", "confidence": 0.6}——但实际上 LLM 是在猜。

正确的 prompt 必须包含三件事:

你是意图分类器。根据用户消息判断意图类别。

可选意图:
- return_request: 申请退货退换
- refund_status: 查询退款进度
- shipping_inquiry: 查询物流
- product_inquiry: 商品咨询
- complaint_quality: 投诉商品质量
- unknown: 无法判断 / 不在以上类别

规则:
1. 只返回 JSON: {"intent": "xxx", "confidence": 0.0-1.0}
2. 不确定时 confidence < 0.7
3. **完全不确定或不在意图列表里 → 返回 {"intent": "unknown", "confidence": 低于 0.5}**
4. 不要创造新的 intent 名

用户消息:{message}

关键设计:

  1. unknown 是一个 first-class intent——明确告诉 LLM "不确定时这是合法答案"
  2. enum 严格约束——用 Pydantic / function calling / JSON schema 强制 LLM 只能返回列表内的 intent,否则解析失败重试
  3. confidence 分级——LLM 返回 0.7 以下的输出当 unknown 处理,不要相信"硬选"

线上 LLM 层 unknown rate 应该在 20-30%。低于 10% 说明 LLM 在硬选(你看的是假准确率);高于 50% 说明 prompt 设计差或意图体系本身有空白。

另外两件 LLM 层必须做的事——

Temperature = 0:意图分类是确定性任务,不需要创造力。temperature 0.5 下同一句话每次返回的 intent 都不一样,监控的统计意义就没了。

Timeout 必须 fail-closed:LLM 300ms 没回 → 走澄清流程或转人工,不要默认放行。原理跟 系列三 Critic fail-closed 一样——超时通常意味着服务降级,正是质量没保障的时刻,硬给一个 intent 比走 clarification 危险得多。

起步阈值一张表——下次评审会拍这张

把上面 4 节压成一张表。第一次上线 / 下次评审 / 内部 review,拿这张对一遍:

参数起步值调参方向
L1 规则safety filter 数量8-16 条漏掉舆情/转人工类 → 加规则;维护到 30+ 条要警惕
L1 规则高频意图规则数8-12 个意图,每个 3-5 条 pattern覆盖低于 60% → 看哪个高频意图没规则;高于 80% → 排查吞具体意图
L2 Embeddingtop-1 confidence≥ 0.75 直返准确率掉 → 0.80;漏召回多 → 0.70
L2 Embeddingambiguity gap< 0.20 → clarifyclarify-rate < 2% 太低(藏歧义);> 15% 太高(用户烦)
L2 Embeddinganchor 数 / intent5-10 句真实用户表达从对话 corpus 捞,不是从政策文档
L3 LLMconfidence 阈值≥ 0.7 接受< 0.7 当 unknown 处理
L3 LLMtemperature0不需要创造力
L3 LLMtimeout300ms超时 → fail-closed 走澄清
L3 LLMunknown rate 目标20-30%< 10% 在硬选;> 50% prompt 或体系问题
系统LLM coverage 目标5-10%> 15% 说明 embedding 没填好
系统overall unknown rate3-5%< 2% 在硬猜;> 10% 体系缺失

11 个参数。这就是一份 3 级 fallback 上线前的全部调参点。

3 级 fallback 调到顶——下一步是 LLM Router,不是再调阈值

3 级 fallback 是起步架构。跑稳之后,有三个信号说明你已经撞到 v1 天花板

  • 意图体系扩张到 40+,policy 类("什么时候退款" vs "退款多久" vs "退款流程")占多数,每周都在改边界
  • Embedding anchor tuning 跑了一轮又一轮,准确率边际收益跌到 +2pp 以下就不动了
  • 用户多轮澄清需求越来越高——一句话不完整、需要反问"您说的是哪笔订单",但 v1 框架下没有自然的"反问入口"

这三件事任何一件单独存在还能调,三件同时出现 → v1 调参已经到顶,问题在意图模型本身,不在阈值

这一年我跟过的一个项目走过这条路。v1 是经典 3 级 fallback:48 个互斥 intent + 31 个 policy intent + 17 个 action intent + safety filter。1102 样本准确率 59.44%。anchor tuning 跑了 4 轮,从 56.5% 提到 58.66%,再到 59.44% 就再也上不去。本质问题:「什么时候退款」和「退款多久」在用户语言里就是同一类问题,强行做成两个互斥 intent 是工程便利,不是用户视角

v2 改成 LLM Router——LLM 把消息路由到 6 条主路径:

ACTION    → 17 个 workflow intent 之一(退款/改单/查询/...)
POLICY    → 直接进 RAG(不再用 intent label 过滤 KB)
SYS       → 系统类(在吗/转人工话术/重启对话)
CLARIFY   → LLM 反问澄清(一句话不完整)
UNKNOWN   → 兜底(不在以上类别)
ESCALATE  → 升级人工(舆情/合规/律师函)

ACTION 路径里 LLM 再选 17 个 workflow 之一,POLICY 路径完全不做 intent 分类——把消息直接丢给 RAG 检索 KB,相当于把 31 个人为的 policy intent 边界一笔勾销。这一步是关键,原因:policy 类用户问题边界本来就模糊,强行分类带来的不准确远多于带来的工程便利。

3 级 fallback 没有被废,只是各层职责重组

v1 HybridClassifier 里干什么v2 LLM Router 里干什么
Rule~150 条规则(policy + action 都覆盖)收缩到 ~16 条,只做高频/资损 action 的 fast-path safety filter
Embeddingtop-1 ≥0.75 直返 intent退出 policy 分类,仅在 ACTION 路径下做 workflow 内细分(可选)
LLM5-10% 兜底覆盖主力,所有非 fast-path 走 LLM Router

两套架构横着对比一遍:

v1 HybridClassifier 强行 48 互斥 intent → v2 LLM Router 6 主路径 + 多轮 CLARIFY

左侧 v1 的 ambiguity 硬选导致路错;右侧 v2 的 ambiguity 走 CLARIFY 路径由 LLM 反问。POLICY 路径绕过 intent label 直接 RAG 是 v2 最大的简化。底部一行写了 v2 的代价:p95 +200ms、单 turn LLM cost ~5x、必须 shadow 部署。点击图片查看原图。
v1 HybridClassifier(3 级 fallback)v2 LLM Router
意图模型48 个互斥 intent6 条主路径 + ACTION 下 17 个 workflow
Policy 处理31 个 policy intent + KB sub_topic 过滤POLICY 路径直接 RAG,不用 intent label
模棱两可硬选 top-1 → 路错CLARIFY 路径 → LLM 反问
Rule 层~150 条规则~16 条 safety filter
LLM 角色兜底(5-10% 覆盖)主力(所有非 fast-path)
多轮澄清不天然支持天然支持
p95 延迟200-300ms+200ms vs v1(关键路径多 1 个 LLM 调用)
单 turn LLM 成本~¥0.001~¥0.005(5x)
适用阶段意图 30 个以内,corpus 还在演进意图 40+,corpus 稳定,需要多轮澄清

升级到 v2 的代价:每个 turn 多 1 个 LLM 调用(qwen-turbo 这种轻量级模型 ~200ms),首字延迟从 ~600ms 升到 ~800ms(仍在 1 秒用户感知阈值内)。单 turn LLM 成本到 ~$0.0007——日均 1000 turn 的项目大约 $2/day,可忽略。

升级到 v2 的收获

  1. policy intent 边界消失——31 个人为边界一次性删掉,让 RAG 自然检索
  2. 模棱两可可以由 LLM 反问澄清——不再硬选,UX 体感「更像在跟人聊天」
  3. Rule 维护面从 ~150 条收缩到 ~16 条——工程负担骤降
  4. 多轮上下文 + 用户历史 + 当前 query 综合判断——而不是单 utterance 硬分类

最关键的工程纪律:v2 不能直接切。新 router 必须跟旧 classifier 并行跑 shadow 部署——shadow router 写到独立的 Langfuse trace(按 session_id 与主 trace join),不影响产品输出。

为什么 shadow 用独立 trace 而不是主 trace metadata:handler.py finally 块 trace.end() 之后 OTel exporter 不接受写入;shadow LLM 调用 200-2000ms 跑得慢时 fire-and-forget task 写入会落空,而且偏向掩盖快路径的数据——这种偏差在统计上是致命的,会让你得出"v2 跟 v1 差不多"的错误结论。独立 trace 自管 end() + flush(),时序解耦。

Shadow 跑一周,按三个 UX 信号决定灰度——

  • S1:v1 硬选 top-1 但 v2 走了 CLARIFY 的对话占比(v2 兜住了多少 v1 路错的场景)
  • S2:v1 路错某个 workflow(用户后续转人工率高)但 v2 路对的对话占比
  • S3a:异家族 LLM judge(Kimi / 火山等)对 v1 / v2 输出的偏好率,需要 30 条 calibration 集校准到 ≥70% 一致率

如果团队的客服 Agent 还在 v1,先把这一篇的 3 级 fallback 调参做扎实——意图 30 个以内 v1 完全够用,过早跳 v2 是钱白花。意图体系超过 40 + anchor tuning 收益跌到 +2pp 以下 + 多轮澄清需求强,三个信号同时出现,再考虑 v2。

Cache 是高并发能不能撑住的关键——不是优化项

如果你的客服 Agent 日均对话 > 5000 次,cache 不是优化项,是上线必要条件

意图分类天生是 cache-friendly——很多用户的开场白和短问句是高度重复的。「在吗」「你好」「我要退货」「物流到哪了」这些表达,一个客服 Agent 一天可能见到上百次。每一次都打一遍 LLM = 烧钱。

# 一个最简 cache 设计
import hashlib
from redis import Redis

def cache_key(message):
    # 简单 normalize: lower + strip + 去标点
    normalized = message.lower().strip().replace("?", "").replace("?", "")
    return f"intent:{hashlib.md5(normalized.encode()).hexdigest()}"

def classify_with_cache(message):
    key = cache_key(message)
    cached = redis.get(key)
    if cached:
        return IntentResult.from_json(cached)

    result = three_tier_classify(message)  # 3 级 fallback
    if result.intent != "unknown":         # 只 cache 确定结果
        redis.setex(key, ttl=86400, value=result.to_json())
    return result

Cache 命中率到 30-50% 时,整体成本掉一半,p95 延迟掉 2/3。三件事要注意:

  • 只 cache 确定的结果:unknown / clarification 这些不要 cache,否则用户每次都被反问
  • TTL 不能太长:意图体系会演进(v1 36 个 → v2 48 个),cache 不能跨版本污染。1 天 TTL + 体系变更时显式 flush 是稳的
  • 不能 cache 写操作上下文:cache 只对"判断意图"安全,不能 cache "调用哪个 tool 用什么参数"

实测一个数字:日均 1 万对话的项目接 cache 之前 LLM 月成本 ¥8000,接 cache 之后 ¥3500——命中率 45%。

5 个红灯信号——评审会上一票否决

下次乙方介绍意图分类方案时,5 个红灯——

信号 1:「我们直接用 LLM 分类,简单可靠」。问他高并发月成本 + 有没有 safety filter + 有没有 shadow 验证——三者都答得上来 = 可能在做 v2 LLM Router(合理);只说"调 LLM 就完事"= 上线 1 个月内大概率账单事故 + 舆情 fast-path 漏放。LLM Router 跟"裸奔 LLM 分类"差的就是这三件事。

信号 2:「我们 100% 用规则,绝对可控」。问他意图数现在多少,规则总数多少——意图 > 30 而规则 > 80 = 已经在维护地狱,下一波团队接手会推翻重做。

信号 3:「embedding 阈值我们设 0.5 直接返回」。0.5 在向量空间里几乎是噪声水平——大部分相似度都 > 0.5,等于没设阈值。这种方案准确率比纯规则还差。

信号 4:「LLM unknown rate 是 0」。等于 LLM 在硬选。问他「LLM 怎么处理它不认识的句子」——答「会返回最相近的」就是这个问题。

信号 5:「我们没做 cache」。日均 > 5000 对话的场景一定要做。没做 = 成本是命中率倒数倍数。

5 个里出现 1 个 → 方案有重大返工;出现 2-3 个 → 这个方案上线后跑不久;出现 4+ → 直接拒掉,让乙方拿回去重写。

11 件这周可以做的事

  1. 把 Agent 现在的意图分类逻辑画出来——是 3 级 fallback 吗?哪一层缺
  2. 跑一次 baseline——1000 条真实对话上各级 coverage 是多少,对照 60/30/10
  3. 给 fast-path 加 8-16 条 safety filter(12315 / 转人工 / 消协 / 律师函 / 曝光 必走规则)
  4. 给 embedding 加 ambiguity gap clarify branch(top-1 与 top-2 差距小于 0.2 → 反问)
  5. 给 LLM prompt 加 unknown 出口和 enum strict(Pydantic / function calling schema)
  6. 把 LLM temperature 设 0,timeout 设 300ms,timeout → 走澄清不要硬选
  7. 把高频用户原话的分类结果 cache 起来——同句直返
  8. 把每次分类的 source(rule / embedding / llm / cache)打到日志,每天看分布
  9. 给每个意图加准确率监控(用 LLM-as-Judge 异家族模型校)
  10. 准备好 fallback:LLM 超时 / 错 / 低置信 → 升级人工或反问,不要硬猜
  11. 评估 v1 → v2:意图数现在多少 / anchor tuning 边际收益 / policy 边界改动频率 / 多轮澄清需求强不强——四项都达 v2 升级门槛 → 启动 shadow 部署评估,否则继续把 v1 调参做扎实

6 个评审问题——下次乙方说"意图准确率 90%"时问回去

问题 1:「3 级各占多少?」 合格答案:60/30/10 左右。答"只有 LLM" / "只有规则" → 红灯。答"我们没分层" → 大红灯。

问题 2:「embedding 阈值多少,ambiguity gap 怎么处理?」 答不出 / < 0.7 / 不做 gap → 准确率不达标。合格答案:top-1 ≥ 0.75 直返 + gap < 0.20 反问。

问题 3:「LLM unknown rate 是多少?」 答 "0" → LLM 在硬选;答 "20-30%" → 正常。这是最简单也最有杀伤力的一问——大部分供应商的 PPT 上甚至没有这个指标。

问题 4:「意图 cache 命中率?」 答"没做" → 月成本会爆。合格答案:30-50% 命中率 + TTL 1 天。

问题 5:「90% 准确率是怎么算的——抽样多少 / 用什么 judge / 包不包含 unknown?」 这一问是从系列五解决率系列七双轨测试里来的——没有可解释的 90% 等于没有 90%。合格答案:每周抽样 200-500 条 + 异家族 LLM judge + 校准集 + unknown 单独算召回。

问题 6(进阶):「v1 还是 v2 架构 / shadow 怎么跑」。问他用的是 HybridClassifier 还是 LLM Router、shadow 部署用主 trace metadata 还是独立 trace、shadow 跑了多久、用哪些 UX 信号判定灰度。答"我们没 shadow 直接切"= 高风险;答"shadow 写在主 trace metadata 里"= 统计偏差致命,结论不可靠。合格答案:独立 trace + 一周以上 shadow + 至少 2 个 UX 信号 + 异家族 judge 校准。

写在最后:意图分类是地基,地基塌了上层全垮

这一年我见过太多客服 Agent 项目,模型用最贵的、prompt 写得最长、RAG 套了 3 层 rerank——第一步意图分类做错,后面所有努力全白费

意图分了错,workflow 路由就错,Critic 审查的是错路径上的动作,写操作打到错的 tool,监控指标看上去全是绿的——但用户那头每次都被路错。

意图分类的工程价值不在算法,在工程取舍——用 60% 高频规则省成本、用 30% embedding 兜歧义、用 10% LLM 处理长尾。三个数字、11 个调参点、3 条不该走的死路。

如果团队方案是「直接用 LLM」「100% 规则」「embedding 0.5 直返」「LLM unknown 0%」「没做 cache」这五个里的任何一个——把这一篇拍他脸上,让他重写。


工具包领取

如果你想把这一篇里的工具立刻用到下次评审会 / 团队意图分类调参,我整理了一个 PDF 工具包:

回复关键词「意图三角」,我把工具包发给你:

  1. 3 级 fallback 调参表(11 个参数 + 起步值 + 调参方向)
  2. 5 红灯信号 + 6 评审问题(评审供应商方案专用,含 v1/v2 架构评估)
  3. Safety filter 8-16 条 starter pack(中文客服场景已填好)
  4. Embedding ambiguity gap clarification flow 模板(含反问话术)
  5. LLM 意图分类 prompt 模板(含 unknown / enum strict / fail-closed timeout)
  6. v1 HybridClassifier → v2 LLM Router 升级评估清单(4 个升级信号 + shadow 部署 checklist + UX 信号定义)

这一年跟项目里收敛出来的调参手册,送给读到这里的你。

回复渠道见页脚(公众号 / X)。不方便回复的,评论区留邮箱也行。

系列接下来排期

A4 系列下一篇——

  • LLM 接入企业 SaaS 生态:25 API → 5 tool 的契约和幂等性(系列二决策 4 深挖)
  • 中文意图体系演进:从客服话术 corpus 到 codebook 的迭代方法论(v1 36 → v2 48 的真实演进,配 v2 LLM Router 上线 shadow 部署的实战)
  • 企业 LLM Agent 踩坑合集:async ES 阻塞事件循环 / Critic timeout fallback 误用 / proxy 拦 localhost / intent rename 跨 7+ 文件 / KB-ES 不同步

如果团队正在做 L2 客服 Agent 或别的需要意图分类的写操作类 Agent,这 3 篇接下来一篇一篇出。

Subscribe for updates

Get the latest AI engineering posts delivered to your inbox.

评论