意图识别模块的必要性
在简单场景下,比如场景单一,可调用工具数目少,意图识别模块的必要性较低,本身工具调用也是意图识别的一种。但是在复杂场景下,比如提供多种服务,模型可调用的工具达到上百种时,就很有必要做意图识别。
我们为不同的服务做专项Agent,为其配备服务所需的工具集和system_prompt,书写更为详尽的提示词,以提升模型执行某个服务的能力,提高服务的质量,还不用为将上百个工具全部塞给同一个模型。
**同样的 LLM,配上不同的工具集和 system prompt,在同一个任务上的表现差距极大。**专门回答知识问答的 Agent,会用知识库工具、深入解释概念;而一个通用 Agent 面对同样的问题,可能随手搜索了一下就返回了一个搜索摘要。意图识别层做的事是:在把请求分发给专项 Agent 之前,先判断用户真正想要什么。这样每个专项 Agent 只需要把自己的那件事做好。
意图识别模块怎么设计
意图识别模块不能直截了当的交给大模型去做,一方面是响应时间问题,另一方面是成本的问题,可以采用三层漏斗式的设计思路,由简至繁的去一层一层过滤请求,尽量将简单请求过滤在交给模型之前,提高响应速度,节省成本。
模块设计:
用户输入 │ ▼ ┌─────────────────────────────┐ │ Layer 1: 规则路由 │ < 1ms │ 精确关键词 + 正则 + 有限状态机│ ← 处理 ~5% 的明确指令 └─────────────┬───────────────┘ │ 未命中 ▼ ┌─────────────────────────────┐ │ Layer 2: 微调小模型 │ 10~50ms │ 5B/7B SLM(Qwen/GLM/Llama)│ ← 处理 ~90% 的常规意图 └─────────────┬───────────────┘ │ 低置信 / 长尾 ▼ ┌─────────────────────────────┐ │ Layer 3: 大模型兜底 │ 100~500ms │ GPT-4o / Claude / Qwen-72B │ ← 处理 ~5% 的复杂边界场景 └─────────────┬───────────────┘ │ ▼ OOD 拒识层 (过滤与系统无关的请求)第一层:规则路由器
通过定义语义精确的关键词,可以采用正则匹配,或者有限状态集来直接匹配某些服务,不需要再向下请求。比如查询订单号这种语义明确,没有歧义我们可以直接匹配到对应的服务,不要将其交给模型来判断。
但是这里我们需要注意的是定义的规则即关键词语义应该精确,不能有较大的歧义,同时还需要不断沉淀新的表达,新的场景。比如如果发现大量用户的同一种输入无法匹配到对应的服务,我们应该考虑是否将其追加进规则中,不过这也会引发其他问题比如新旧规则冲突。
第二层:微调轻量模型做分类器
我们可以训练轻量模型进行本地部署,以此做一个分类器,处理规则路由无法处理的情况,这种方式可以处理更为泛化的场景,没有那么严密的要求输入和规则中的关键词严格匹配,一定程度上支持语义理解,更灵活。
第三层:交给专门的路由Agent
可以用更强大的模型,做一个专门用来路由的Agent,来处理用户输入复杂,语义不明的情况,进而识别用户的意图,这种效果更好但成本高。
置信度设计
意图分类不是非黑即白的——"帮我改一下"这种输入,LLM 也无法确定用户在说什么。不猜测,直接问,是更好的策略。在识别意图后,要有一个评判标准,判定此次识别的置信度是多少,如果置信度低要触发其他机制,比如向用户提供可选清单,或者直接询问用户。
通过置信度阈值控制路由行为:
# 置信度 < 0.6 → LLM 应返回 clarify 意图 # clarify_node:不调工具,直接生成澄清问题 def clarify_node(state: RouterState) -> dict: resp = llm.invoke([ SystemMessage( "用户的表达不够清晰。" "请用一句简洁友好的中文问句请用户说清楚他的需求。不要猜测,直接问。" ), HumanMessage(state["user_input"]), ]) return {"response": resp.content.strip()}[低置信-歧义] 输入:「帮我改一下」 置信度:50% 意图:clarify 澄清回答:请问您需要修改什么内容呢? [高置信-明确] 「2 的 10 次方是多少」 置信度:100% 意图:calculate → 直接计算多轮对话意图跟踪---对话状态跟踪机制
如果孤立的理解用户的某句话,很难理解真实意图。
比如:
已有代码对话历史:
用户:帮我写一个 Python 函数,计算列表的平均值
助手:def average(lst): return sum(lst) / len(lst) if lst else 0.0
用户:这个函数如果列表里有非数字怎么办
助手:可以用 try/except TypeError 捕获...
输入:「优化一下」
✗ 无历史 → clarify (50%) 输入不清晰,无法判断意图。
✓ 有历史 → code (80%) 用户请求优化代码,结合历史上下文,判断为code意图。
用户说出“优化一下”,如果没有上下文,很难判断用户的真实意图。这时候就需要对话历史,追踪对话状态。我们可以为任务维护一个结构化的状态对象,记录当前的任务信息、需要的参数,历史输入输出等等,但这也需要我们对对话状态做生命周期管理,避免状态遗留造成幻觉,或者在新对话被误用。
JEV模型做意图识别
Jev 模型可以用来实现 Agent 的意图识别模块。它是专门的结构化决策模型,不生成文本,给定预设意图列表后直接输出意图标签和置信度,速度快、成本低,适合 Agent 前置路由、闲聊过滤、高危请求拦截。但它只能在给定选项中选择,无法直接完成槽位抽取,遇到低置信请求,需要兜底到通用大模型。