意图识别做不好,后面的工具调用全在错误方向

0 阅读5分钟

意图识别做不好,后面的工具调用全在错误方向

为什么第一道闸门是意图识别

Agent 系统处理用户请求的的第一件事不是生成回答,是先搞清楚用户想要什么。

对日活百万量级的 Agent 系统,意图识别准确率每提升 1%,就能少几十万次错误流程跳转、无效大模型调用和人工客服转接。反过来,意图识别做不好,后面的工具调用、知识检索、多轮规划,可能全都错了。

技术上它看起来很简单:判断用户问题属于哪个预设类别,输出对应标签。但成熟系统要做到的不止分类。它得同时看当前对话上下文、用户画像、历史交互记录,去推断表层语句背后的真实需求。用户说"帮我看看这个",这个"这个"指什么、去哪查,答案不在这句话里,在上下文里。

为什么是小模型

大模型零样本就能理解意图,为什么还要专门训一个小模型?

主要是成本考虑和延迟,如果请求量巨大的,大模型扛不住。业界主流做法是混合架构:小模型主路由,大模型兜底。高频、可枚举的意图,小模型用极低的单次成本处理掉;置信度不够或者命中长尾,再升级给大模型。成本压住了,复杂案例的质量也有保障。

还有一层常被忽略:可控。小模型输出的是受限的标签空间,下游路由拿到的就是一个稳定接口。大模型自由生成的答案,路由前永远要多做一层解析和校验。

数据构建:三类样本,一个都不能少

小模型的上限由数据决定。训练集要覆盖三类。

正样本:每个业务意图下的真实表述。最优质的来源是线上真实日志,缺点是标注贵,长尾意图攒得慢。

负样本:跟业务无关的请求。很多团队在这重视不够。只训正样本的模型,遇到闲聊和无关提问,会硬设定一个业务标签,造成错误路由。

长尾意图样本:低频但真实存在的意图。

配比可以参考这个起点:正样本每类 200 条起步,负样本总量与正样本同量级,长尾每类至少 50 条。

意图体系:先设计标签,再谈模型

动手训模型之前,先回答一个业务问题:你的标签空间长什么样?

常见的失误有两种。标签太粗:"查询类"一个标签装下查订单、查物流、查余额,下游路由没法分流。标签太碎:按功能点罗列几十上百个,互相重叠,标注员自己都分不清。

合理的粒度只有一条:一个意图,对应下游一条明确的路由路径。路由后走不同流程的,拆开;走同一条流程的,合并。

体系一般是两层:一级大类(咨询、交易),二级具体意图(查物流、退换货)。小模型直接预测二级标签,一级由二级聚合,方便统计监控。另外建议显式定义两个特殊类:OOD 类,承接体系之外的请求;敏感类,承接需要合规拦截的请求。它们不是业务上的"意图",但系统安全运行靠它们兜底。

意图体系不会一次设计到位。季度级的新增与合并评审要有,上线后的 badcase 日志就是最好的依据。

训练方式:全量微调还是 LoRA

数据有了,训练路线就两条。

全量微调:在预训练模型所有参数上端到端再训练。适配最深,数据充足、算力够时性能上限最高;代价是训练贵,每个业务场景要单独维护一份权重。

LoRA:冻结底座,只训低秩适配矩阵。显存占用小、训练快,适配器可以按业务插拔。多场景并存的团队,现在基本默认选它。

底座选型倒简单。意图分类不需要生成能力,BERT-base 级别(一亿参数上下)的编码器,或者 0.5B 级别的轻量解码器,这两个都够用。这个环节拼的是数据和工程化,不是模型能力。

一个最小骨架(LoRA + 分类头):

from peft import LoraConfig, get_peft_model
from transformers import AutoModelForSequenceClassification

base = AutoModelForSequenceClassification.from_pretrained(
    "Qwen/Qwen2.5-0.5B", num_labels=len(INTENT_LABELS)
)
model = get_peft_model(base, LoraConfig(
    r=8, lora_alpha=16,
    target_modules=["q_proj", "v_proj"],
    task_type="SEQ_CLS",
))
# 训练后保存 adapter,按业务场景插拔

推理侧的路由逻辑比模型本身更关键:

def route(text, session_ctx):
    probs = model.predict(text, session_ctx)
    top, conf = probs.argmax(), probs.max()
    if conf < THRESHOLD:          # 低置信度 → 大模型兜底
        return escalate_to_llm(text, session_ctx)
    if top == OOD_LABEL:          # 负样本类 → 拒答或引导
        return polite_reject(text)
    return dispatch(INTENT_HANDLERS[top], text)

两个容易被忽视的工程细节

安全边界先于准确率。并非用户提出的任何问题都应被回应:合规、伦理、业务规则的约束,要在意图层就挡住,别等大模型生成完再审查。负样本训练天然承担了一部分这个职责,敏感意图建议单独设类、单独评测。

上线标准可以量化。三类数据配比合理(尤其负样本覆盖充足)时,小模型微调后的意图识别准确率通常能到 98.5% 以上,满足多数企业级 Agent 的上线要求。达不到这个数,先怀疑数据是否足够,再怀疑模型。

最后

意图识别是 Agent 系统里一个起眼的模块。它只是安静地给每个请求打标签。但成本、延迟、可控性远胜大模型,大模型应该留给真正需要它的地方。这也是 Harness 工程思想的一个具体切面:不追求让模型更聪明,把模型的边界支撑环境工程化。