一、什么是意图识别?

在 AI Agent 项目中,**意图识别(Intent Recognition)**是 Agent 理解用户输入的第一步。它的任务是:判断用户到底想做什么,并将自然语言映射到一个结构化的、可执行的意图标签上。

举个例子:

# 用户输入
"帮我查下明天的天气"

# 意图识别输出
{
  "intent": "get_weather",
  "slots": { "date": "明天", "location": null },
  "confidence": 0.95
}

Agent 拿到这个结构化结果后,就知道该调用天气查询工具、提取哪些参数,整个执行链路才得以运转。可以说,意图识别是 Agent 的"耳朵"——听不懂用户在说什么,后面的一切都无从谈起。

意图识别 vs. 对话管理

意图识别回答"用户想做什么",对话管理(Dialog Management)回答"接下来怎么回应"。前者是理解,后者是决策。在实际项目中两者紧密配合,但职责不同。

二、意图识别在 Agent 架构中的位置

一个典型的 Agent 系统架构如下:用户输入 → 意图识别 → 路由分发 → 执行模块 → 响应输出。意图识别处于最前沿的位置,直接决定了后续走哪条处理路径。

在这里插入图片描述

意图识别完成后,Agent 根据识别出的意图将请求路由到不同的执行模块:

  • 单轮问答:如"Python 怎么读文件?" → 走 RAG / 知识库检索
  • 多轮对话:如"继续刚才的话题" → 走对话管理器,依赖上下文
  • 工具调用:如"帮我订一张明天去上海的机票" → 走 Function Call 执行链
  • 复杂规划:如"帮我分析竞品的定价策略并写一份报告" → 走 Planner + Executor 多步执行

三、三种主流方案对比

意图识别的技术方案经历了三个阶段的演进,目前实际项目中通常是多种方案的混合使用。

在这里插入图片描述

当前主流:混合方案

实际项目中很少只用一种方案。典型做法是规则前置 + LLM 兜底:高频意图用关键词/正则秒级命中,未命中的交给 LLM 做语义理解,再通过置信度路由决定是直接执行还是追问澄清。

四、LLM 意图识别处理流程详解

下面详细拆解一个生产级意图识别 pipeline 的完整流程:
在这里插入图片描述

五、代码实现示例

5.1 意图定义

首先定义系统支持哪些意图,以及每个意图需要哪些槽位(slot):

# intents.py

INTENT_DEFINITIONS = {
    "get_weather": {
        "description": "查询天气信息",
        "slots": {
            "date": "日期,如:今天、明天、后天",
            "location": "城市名,如:北京、上海"
        }
    },
    "search_product": {
        "description": "搜索商品",
        "slots": {
            "keyword": "搜索关键词",
            "category": "商品分类"
        }
    },
    "chitchat": {
        "description": "闲聊,不属于任何业务意图",
        "slots": {}
    },
    "fallback": {
        "description": "无法识别的意图",
        "slots": {}
    }
}

5.2 规则匹配层

# rule_matcher.py
import re

class RuleMatcher:
    def __init__(self):
        self.rules = [
            {
                "intent": "get_weather",
                "keywords": ["天气", "气温", "下雨"],
                "patterns": [
                    re.compile(r"(今天|明天|后天|大后天).*(天气|气温)"),
                    re.compile(r"(天气|气温).*(今天|明天|后天)"),
                ]
            },
            {
                "intent": "search_product",
                "keywords": ["搜索", "找", "买"],
                "patterns": [
                    re.compile(r"(搜|找|买).*(商品|东西|产品)"),
                ]
            }
        ]

    def match(self, text):
        # 先走正则
        for rule in self.rules:
            for pattern in rule["patterns"]:
                if pattern.search(text):
                    return {
                        "intent": rule["intent"],
                        "confidence": 1.0,
                        "source": "rule"
                    }
        # 再走关键词
        for rule in self.rules:
            if any(kw in text for kw in rule["keywords"]):
                return {
                    "intent": rule["intent"],
                    "confidence": 0.7,
                    "source": "keyword"
                }
        return None  # 未命中,交给 LLM

5.3 LLM 意图识别层

# llm_intent.py
import json
from openai import OpenAI

client = OpenAI()

class LLMIntentRecognizer:
    def __init__(self, intent_defs):
        self.intent_defs = intent_defs
        self.system_prompt = self._build_system_prompt()
        self.few_shot = self._build_few_shot()

    def _build_system_prompt(self):
        intent_list = "\n".join(
            f"- {name}: {def_['description']}, slots: {def_['slots']}"
            for name, def_ in self.intent_defs.items()
        )
        return f"""你是一个意图识别系统。根据用户输入,判断其意图并提取槽位。

可用意图列表:
{intent_list}

输出格式(严格 JSON):
{{"intent": "意图名称", "slots": {{}}, "confidence": 0.0-1.0}}

注意:
- confidence 低于 0.6 时使用 "fallback"
- 闲聊使用 "chitchat"
- 只输出 JSON,不要有其他文字"""

    def _build_few_shot(self):
        return [
            {"role": "user", "content": "今天北京天气怎么样"},
            {"role": "assistant", "content": '{"intent":"get_weather","slots":{"date":"今天","location":"北京"},"confidence":0.95}'},
            {"role": "user", "content": "帮我找一下无线耳机"},
            {"role": "assistant", "content": '{"intent":"search_product","slots":{"keyword":"无线耳机","category":null},"confidence":0.92}'},
            {"role": "user", "content": "你好呀"},
            {"role": "assistant", "content": '{"intent":"chitchat","slots":{},"confidence":0.88}'},
        ]

    def recognize(self, user_input):
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {"role": "system", "content": self.system_prompt},
                *self.few_shot,
                {"role": "user", "content": user_input}
            ],
            temperature=0,  # 意图识别用低温度保证稳定
            response_format={"type": "json_object"}
        )
        return json.loads(response.choices[0].message.content)

5.4 完整 Pipeline 编排

# pipeline.py

class IntentPipeline:
    def __init__(self):
        self.rule_matcher = RuleMatcher()
        self.llm_recognizer = LLMIntentRecognizer(INTENT_DEFINITIONS)
        self.confidence_threshold = 0.8

    def recognize(self, text):
        # 1. 规则快通道
        rule_result = self.rule_matcher.match(text)
        if rule_result:
            return rule_result

        # 2. LLM 慢通道
        llm_result = self.llm_recognizer.recognize(text)

        # 3. 置信度判断
        if llm_result["confidence"] < self.confidence_threshold:
            return {
                "intent": "fallback",
                "slots": {},
                "confidence": llm_result["confidence"],
                "need_clarify": True,
                "source": "llm_low_conf"
            }

        return {**llm_result, "source": "llm"}


# 使用
pipeline = IntentPipeline()
result = pipeline.recognize("帮我查下明天的天气")
print(result)
# {'intent': 'get_weather', 'confidence': 1.0, 'source': 'rule'}

六、关键设计考量

6.1 意图体系设计

原则 说明
MECE 互斥 意图之间不应有重叠,同一条输入只能匹配一个意图
层次化 一级意图粗分(如"购物"),二级意图细分(如"搜索商品"→"下单")
兜底意图 始终保留 fallback / chitchat 作为安全网
可扩展 新增意图不应影响已有意图的识别(避免重新训练)

6.2 槽位提取(Slot Filling)

意图识别通常和槽位提取配合使用。识别出意图后,还需要从用户输入中提取执行所需的参数:

# 用户输入
"帮我订一张明天去上海的机票"

# 意图识别 + 槽位提取
{
  "intent": "book_flight",
  "slots": {
    "date": "明天",       # 必填
    "destination": "上海", # 必填
    "departure": null,      # 缺失 → 追问
    "quantity": 1           # 可选,默认值
  }
}

# 缺槽追问
Agent: "请问您从哪个城市出发呢?"

6.3 多轮意图切换

用户可能在对话中途切换意图,Agent 需要处理这种场景:

# 对话历史
User: "查下明天北京天气"     → intent: get_weather
User: "顺便帮我买张去上海的票" → intent: book_flight (切换!)
User: "还是查天气吧"         → intent: get_weather (切回!)

# 处理策略
# 1. 每轮独立识别 + 对话状态追踪 (DST)
# 2. 将最近 N 轮对话作为上下文传给 LLM
# 3. 检测到意图切换时,清空上一意图的槽位

6.4 置信度策略

置信度范围 策略 示例
> 0.9 直接执行 “查天气” → 立即调用天气 API
0.6 - 0.9 执行 + 确认 “您是想查天气吗?”
0.3 - 0.6 追问澄清 “您能详细说说想做什么吗?”
< 0.3 Fallback “抱歉,我暂时无法理解您的需求”

七、实践建议

1. 从简单开始

先用规则匹配跑通 MVP,验证核心链路。不要一上来就堆 LLM,简单的关键词匹配往往能覆盖 60% 以上的高频场景。

2. Prompt 是核心资产

LLM 方案中,System Prompt 和 Few-shot 示例的质量直接决定识别效果。建议:

  • 意图描述要精确,避免歧义
  • 每个意图至少 2-3 个 Few-shot 示例
  • 包含反例(“这不应该被识别为 XX 意图”)
  • temperature=0 保证输出稳定

3. 闭环优化

意图识别不是一次性的工作,需要持续迭代:

线上 bad case → 人工标注 → 补充 few-shot → 更新规则 → 上线验证

4. 监控指标

指标 说明 目标
意图准确率 识别正确的比例 > 90%
Fallback 率 走兜底路径的比例 < 5%
平均延迟 规则路径 vs LLM 路径 规则 <10ms,LLM <500ms
槽位完整率 必填槽位提取成功的比例 > 85%

5. 安全边界

  • 敏感意图(如涉及支付、删除操作)需要二次确认
  • 对 LLM 输出做 JSON 校验,避免解析失败导致系统崩溃
  • 设置最大重试次数,防止 LLM 超时拖垮整个链路

八、总结

意图识别是 Agent 系统的"第一道关卡",直接影响用户体验和后续执行链路。对于刚接触 Agent 开发的实习生,建议掌握以下核心要点:

  1. 理解定位:意图识别是"理解层",负责把自然语言翻译成结构化指令
  2. 掌握三套方案:规则匹配(快)、ML 分类(准)、LLM 提示词(灵活),各有适用场景
  3. 学会混合编排:规则前置 + LLM 兜底 + 置信度路由是生产环境的标配
  4. 关注闭环:bad case 回流 → 补充示例 → 更新规则,持续迭代
  5. 重视工程化:JSON 校验、超时处理、监控指标,这些"脏活"决定了系统稳定性

希望这篇博客能帮你快速建立对 Agent 意图识别的全局认知。纸上得来终觉浅,建议找一个具体的 Agent 项目动手实现一遍 pipeline,你会对每个环节有更深的体会。

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐