意图识别三层策略:当你的 Agent 能在 100ms 内猜中用户心思

> 用户说"3号机没劲了",系统要在 100ms 内判定他要报修并解析出目标设备。本文详解 IntentAgent 的三层策略架构:别名解析(DB)→ 静态关键词(0ms 内存匹配)→ 本地意图模式(DB patterns)→ LLM 兜底分类(~200ms),以及背后意图学习系统的实现。

1. 问题定义

传统 ChatBot 的意图识别是 LLM-First 的:每次对话都调用 LLM 做分类。但实际场景中存在大量高频、可预判的意图模式——"报修""查设备""看工单"——这些意图用静态规则匹配即可达到 95% 准确率,完全不需要 LLM。

EAMX 的 IntentAgent 设计原则是 渐进式策略:能用静态规则就不用 DB,能用缓存的模式就不用 LLM。每一层都是"如果命中就立即返回,未命中才下沉到下一层"。

2. 三层策略架构

``<br>preprocessIntent(message, tenantId)<br> │<br> ├─ Step 1: 别名解析 (lookupAliases)<br> │ entity_aliases DB 查询 → "3号机" → "3号注塑机"<br> │ 同时扫描 equipments.aliases JSONB 字段<br> │<br> ├─ Step 2a: 静态关键词规则 (matchStaticRule)<br> │ 12 条规则,纯内存匹配,0ms<br> │ "处于故障的设备" → list_equipments + operationalStatus:"fault"<br> │<br> ├─ [未命中] Step 2b: 本地意图模式 (lookupPattern)<br> │ intent_patterns DB,关键词重叠度评分<br> │ "3号机没劲了" → 匹配历史模式 → create_fault_report<br> │<br> ├─ [仍低置信度] Step 3: LLM 兜底 (classifyWithLLM)<br> │ AI_FAST_MODEL,整体管线的最后保障<br> │<br> └─ 输出: IntentPreprocessResult<br> 含 primaryIntent / confidence / contextBlock / needsConfirmation<br>``

整个流程有 100ms 超时保护,防止 LLM 调用阻塞主对话管道。

3. Step 1:别名解析
3.1 entity_aliases 表

``sql<br>CREATE TABLE entity_aliases (<br> id UUID PRIMARY KEY,<br> tenant_id UUID NOT NULL,<br> alias TEXT NOT NULL, -- "3号机"<br> entity_type TEXT NOT NULL, -- "equipment" | "spare_part" | "location"<br> entity_id UUID NOT NULL,<br> canonical_name TEXT NOT NULL, -- "3号注塑机"<br> usage_count INT DEFAULT 0,<br> created_at TIMESTAMPTZ,<br> updated_at TIMESTAMPTZ<br>);<br>``

3.2 查找逻辑

```typescript<br>async function lookupAliases(message: string, tenantId: string) {<br> // 1. 查询高频别名(TOP 100,按 usageCount 降序)<br> const storedAliases = await db<br> .select().from(entityAliasesTable)<br> .where(eq(entityAliasesTable.tenantId, tenantId))<br> .orderBy(desc(entityAliasesTable.usageCount))<br> .limit(100);

// 2. 字符串包含匹配 → 命中后异步 usageCount +1<br> for (const alias of storedAliases) {<br> if (message.includes(alias.alias)) {<br> results.push({ original: alias.alias, entityType, entityId, canonicalName });<br> // 异步增加使用次数<br> db.update(entityAliasesTable)<br> .set({ usageCount: alias.usageCount + 1 })<br> .where(eq(entityAliasesTable.id, alias.id))<br> .catch(console.error);<br> }<br> }

// 3. 降级扫描:entity_aliases 未命中时查询 equipments.aliases JSONB 字段<br> // 用户可能在设备录入时手动填写过别名字段<br>}<br>```

关键设计

4. Step 2a:静态关键词规则

```typescript<br>const STATIC_RULES: StaticRule[] = [<br> // 设备列表 + 运行状态过滤<br> { keywords: ["故障状态", "处于故障", "故障的设备", "故障设备列表"],<br> intent: "list_equipments",<br> entities: { operationalStatus: "fault" },<br> confidence: 0.95 },

// 故障上报<br> { keywords: ["报修", "上报故障", "提交故障"],<br> intent: "create_fault_report",<br> confidence: 0.93 },

// 我的工作<br> { keywords: ["我的工作", "我的任务", "我的工单", "我的维修"],<br> intent: "list_my_work",<br> confidence: 0.95 },

// 库存查询<br> { keywords: ["备件库存", "库存查询", "查询库存", "库存情况"],<br> intent: "query_spare_part_stock",<br> confidence: 0.93 },<br> // ... 共 12 条规则<br>];

function matchStaticRule(message: string) {<br> const lower = message.toLowerCase();<br> for (const rule of STATIC_RULES) {<br> if (rule.keywords.some(kw => lower.includes(kw.toLowerCase())))<br> return rule;<br> }<br> return null;<br>}<br>```

12 条规则覆盖了最高频意图(设备故障查询、报修、工单查看、库存查询、技术标准推荐、资产概览)。匹配逻辑是简单的子串包含,O(n×m) 复杂度,但由于 n=12、m<10,实际耗时接近 0ms。

为什么不用更复杂的 NLP 分类器? 因为 12 条高频规则已经有 95% 命中率。剩下的长尾意图交给 Step 2b 和 Step 3。

5. Step 2b:本地意图模式库
5.1 模式匹配算法

``typescript<br>async function lookupPattern(message: string, tenantId: string) {<br> const patterns = await db<br> .select().from(intentPatternsTable)<br> .where(and(<br> eq(intentPatternsTable.tenantId, tenantId),<br> sqlconfirmed_count >= 1`,<br> ))<br> .orderBy(desc(intentPatternsTable.confirmedCount))<br> .limit(50);

for (const p of patterns) {<br> const expr = p.rawExpression.toLowerCase();<br> const msg = message.toLowerCase();

// 策略 1:字符串包含(最强信号)<br> if (msg.includes(expr) || expr.includes(msg)) {<br> score = minLength / maxLength;<br> }<br> // 策略 2:关键词重叠(至少 2 个公共词)<br> else {<br> const overlap = exprWords.filter(w => msgWords.includes(w)).length;<br> if (overlap >= 2) score = overlap / maxWords * 0.7;<br> }<br> // 取最高分,阈值 ≥ 0.80 命中<br> }<br>}<br>```

评分使用两种策略的加权最大值,阈值 0.80 保证匹配质量。

5.2 模式学习

每次 AI 对话后,coordinator 异步记录意图模式:

``typescript<br>// orchestrator.ts — Phase 4 Learning<br>recordIntentPattern({<br> tenantId, rawExpression: userMessage.slice(0, 200),<br> resolvedIntent: toolName, confidence: 0.85,<br>}).catch(() => {}); // fire-and-forget<br>``

如果同一表达多次出现,confirmedCount 递增;新表达则创建新记录。高频确认的模式会自然上升到 TOP 50,被 Step 2b 优先匹配。

6. Step 3:LLM 兜底分类

当前两层都未命中(或置信度不足以做决策),调用 LLM:

``typescript<br>async function classifyWithLLM(message, resolvedAliases) {<br> const prompt = 你是EAMX工业设备管理系统的意图分类专家。

可用操作列表

${ACTION_CATALOG} // 26 个 action 的完整列表

用户输入

${message}<br>${aliasContext} // 已解析的别名上下文

任务

分析用户意图并返回JSON:<br>{<br> "intent": "最匹配的action名称",<br> "confidence": 0.95,<br> "entities": { "equipmentName": "...", "assigneeName": "..." },<br> "reasoning": "一句话"<br>}`;

const resp = await openai.chat.completions.create({<br> model: AI_FAST_MODEL, // DeepSeek-V3.2<br> ...FAST_OPTS, // enable_thinking: false<br> max_completion_tokens: 300,<br> temperature: 0,<br> });<br>}<br>```

合并策略:如果本地模式命中但置信度偏低(<0.85),调用 LLM。若 LLM 结果与本地一致,置信度加权合并;若不一致,以 LLM 为准(更可靠)。

7. 置信度三分法与用户交互

``typescript<br>// confidence >= 0.85 → 直接执行,不询问<br>// 0.60 <= confidence < 0.85 → 执行前确认<br>// confidence < 0.60 → 询问澄清<br>if (confidence >= 0.85) {<br> needsConfirmation = false;<br>} else if (confidence >= 0.60) {<br> needsConfirmation = true;<br> clarificationQuestion = 您是要「${intentLabel}」吗?;<br>} else {<br> needsConfirmation = true;<br> clarificationQuestion = "您的意图不明确,请问您想要执行什么操作?";<br>}<br>``

8. 性能数据

| 层级 | 耗时 | 命中率(高频场景) |<br>|---|---|---|<br>| Step 1 别名解析 | 5-15ms (DB) | 60% |<br>| Step 2a 静态关键词 | 0ms (内存) | 25%(高频意图中) |<br>| Step 2b 本地模式 | 3-8ms (DB) | 10% |<br>| Step 3 LLM 兜底 | ~200ms | 5% |

在高频场景(报修/查设备/看工单)中,95% 的请求在第一、二层就完成了,根本不会调用 LLM,整体延迟控制在 15ms 以内。

9. 核心文件索引

下一篇:AI Pipeline 编排器——Coordinator 如何从 880 行巨石文件重构为 233 行的四阶段 Pipeline 编排器。

作者:白杨,十余年设备资产管理从业经验,EAMX 产品负责人。