今天要讲的就是给 RAG 系统装一个分诊台——意图识别与问题路由 。用户消息进来,先判断它应该走哪条路:查知识库、调工具、直接闲聊、还是反问用户补充信息,然后把请求分发到对应的处理流程。
四种意图类型
在电商客服场景下,用户消息可以分为四种意图类型。这个分类体系不是固定的——不同业务场景可能有不同的分类方式,但这四类覆盖了大多数场景。
知识检索(Knowledge Retrieval)
用户在问一个知识库能回答的问题。这类问题的特点是:答案存在于你的知识库文档里,是“静态”的、通用的知识。
典型问题:
- iPhone 16 Pro 的退货政策是什么?
- 保修期内屏幕碎了能免费换吗?
- 你们的配送范围覆盖哪些城市?
- 会员等级有什么权益?
处理方式:走完整的 RAG 检索流程——Query 改写 → 向量检索 → 重排序 → 生成答案。
工具调用(Tool Invocation)
用户想查询个人数据、实时信息,或者执行某个操作。这类问题的特点是:答案不在知识库里,需要调用外部系统的 API 才能获取。
典型问题:
- 帮我查一下订单 #12345 的物流状态(查个人订单数据)
- 我还剩几天年假?(查 HR 系统)
- 帮我申请退货(执行操作)
- 今天有什么优惠活动?(查实时数据)
处理方式:走 Function Call / MCP 流程——识别出需要调用哪个工具,传入参数,执行工具,把结果返回给模型生成最终答案。
怎么区分知识检索和工具调用?关键看答案的来源。如果答案在你的知识库文档里(退货政策、保修条款、产品参数),就是知识检索;如果答案需要查数据库、调 API、访问外部系统(某个订单的状态、某个人的年假余额、实时库存),就是工具调用。
闲聊对话(Chitchat)
用户在闲聊、打招呼、表达感谢、开玩笑,不涉及具体的业务问题。
典型问题:
- 你好
- 谢谢你的帮助
- 你是 AI 还是真人?
- 今天心情不好
- 哈哈,你真有趣
处理方式:模型直接回答,不走检索,也不调工具。System Prompt 里定义好闲聊时的回复风格就行。
前面说过,闲聊消息走 RAG 检索反而更差。模型自己就能很好地处理这类对话,不需要知识库的辅助。
引导澄清(Clarification)
用户的问题太模糊,系统无法确定该走哪条路。这时候不应该硬答,而是反问用户补充信息。
典型问题:
- 有什么推荐的吗?(推荐什么?手机?配件?)
- 怎么办?(什么怎么办?退货?维修?)
- 帮我看看(看什么?订单?产品?)
- 出问题了(什么产品?什么问题?)
处理方式:不检索也不调工具,直接返回一个引导性的问题,让用户补充关键信息。
引导澄清不是万能的,不能动不动就反问用户。如果用户的问题虽然简短但意图明确(比如“价格呢”,在聊 iPhone 16 Pro 的上下文中意图很清楚),就不应该反问,而是结合对话历史直接处理。只有在真的无法判断意图时才引导澄清。
四种意图对比
意图识别的三种方案
知道了要分哪几类意图,接下来的问题是:怎么判断一条用户消息属于哪个类别?
规则匹配方案
最简单直接的方案:用关键词和正则表达式判断意图。
规则匹配的优缺点很明显:
规则方案最大的问题是无法理解语义 。“帮我看看剩几天假”没有命中“年假”关键词,就会被错分为知识检索。“能退吗”——是问退货政策(知识检索)还是想发起退货(工具调用)?规则无法区分。
规则方案适合做第一层快速过滤 ——把最明确的意图快速识别出来(“你好”就是闲聊,“查订单 #12345”就是工具调用),不确定的交给大模型处理。
大模型分类方案
用大模型做意图分类,核心是设计好分类 Prompt。
2.1 分类 Prompt 的设计
你是一个意图分类助手。根据对话历史和用户的最新消息,判断用户的意图类别。 意图类别定义: 1. knowledge - 知识检索:用户在询问产品信息、政策规定、操作指南等知识库中的内容。 示例:"iPhone 16 Pro 的退货政策是什么""保修期多久""配送范围覆盖哪些城市" 2. tool - 工具调用:用户想查询个人数据、实时信息,或执行某个操作。 示例:"查一下我的订单状态""帮我申请退货""我还剩几天年假" 3. chitchat - 闲聊对话:用户在打招呼、感谢、闲聊,不涉及具体业务问题。 示例:"你好""谢谢""你是AI吗""今天心情不好" 4. clarification - 引导澄清:用户的问题太模糊,缺少关键信息,无法确定意图。 示例:"有什么推荐的""怎么办""帮我看看""出问题了" 判断规则: - 结合对话历史判断,相同的话在不同上下文中意图可能不同 - 如果用户的问题涉及"我的""查一下"等个人化表述,通常是工具调用 - 如果问题在问通用的规则、政策、产品信息,通常是知识检索 - 只有在真的无法判断意图时才分类为 clarification - 以 JSON 格式输出,格式为:{"intent": "分类结果", "confidence": 置信度} - 不要输出 JSON 以外的任何内容 对话历史: {history} 用户最新消息:{query}几个设计要点:
- 每种意图都有明确定义和示例 :这是 Few-shot 的典型用法,给模型足够的参考。定义要写清楚边界——什么算知识检索,什么算工具调用,不能让模型猜
- 强调结合对话历史判断 :同样一句“能退吗”,在不同的对话上下文中意图不同。第一轮对话时大概率是问退货政策(知识检索),前面在聊某个具体订单时大概率是想发起退货(工具调用)
- 输出JSON格式 :方便程序解析。加 confidence 字段可以在置信度低时触发兜底策略
- clarification要谨慎使用 :Prompt 里明确说“只有在真的无法判断时才分类为 clarification”,避免模型动不动就要求澄清
2.2 分类效果与边界情况
大模型分类的准确率通常在 90% 以上,但有一些边界情况需要注意:
混合方案(推荐)
规则匹配速度快但准确率低,大模型分类准确但有延迟和成本。把两者结合起来,就是混合方案:规则做第一层快速过滤,大模型做第二层精确分类 。
流程是这样的:
规则层只处理高置信度 的明确场景:
- 短消息且完全匹配闲聊关键词(“你好”“谢谢”)→ 直接判定为闲聊
- 包含明确的工具触发词且带具体参数(“查订单 #12345”)→ 直接判定为工具调用
- 其他所有情况 → 交给大模型分类
这样做的好处是:
- 大部分闲聊消息不需要调模型 :用户打招呼、说谢谢这种高频场景,规则就能搞定,省了一次 API 调用
- 复杂场景有模型兜底 :语义模糊、上下文相关的消息,交给大模型判断,准确率有保障
- 成本可控 :实际场景中,闲聊和明确的工具调用大约占 30%~40% 的消息量,这部分都可以被规则层拦截
三种方案的对比:
问题路由的架构设计
路由器模式
意图识别完成后,需要一个路由器把请求分发到不同的处理流程。整体架构是这样的:
路由器的职责很简单:拿到意图分类结果,调用对应的处理器。每个处理器各自负责自己的逻辑,互不干扰。
用 Java 代码表示,路由器的核心逻辑就是一个 switch:
public String route(String intent, List<Message> history, String query) throws IOException {switch (intent) {case "knowledge":// 知识检索路径:Query 改写 → 检索 → 生成答案return handleKnowledgeRetrieval(history, query);case "tool":// 工具调用路径:Function Call / MCPreturn handleToolInvocation(history, query);case "chitchat":// 闲聊路径:直接调模型生成回答return handleChitchat(history, query);case "clarification":// 澄清路径:返回引导问题return handleClarification(history, query);default:// 兜底:默认走知识检索return handleKnowledgeRetrieval(history, query);}}default 分支走知识检索是一个安全的兜底策略。知识检索路径本身就有兜底机制——如果检索不到相关内容,模型会说“抱歉,找不到相关信息”。这比走错其他路径(比如误调了工具)要安全得多。
意图识别在 RAG 完整链路中的位置
把意图识别加入后,完整的 RAG 链路变成了这样:
注意意图识别的位置:在会话记忆之后,Query改写之前 。
为什么在会话记忆之后?因为意图识别可能需要对话历史来做判断。用户说“好的,帮我退了吧”,如果不知道前面在聊什么,无法判断这是工具调用(确认退货操作)。
为什么在 Query 改写之前?因为 Query 改写只在知识检索路径上才需要。如果意图是闲聊或工具调用,根本不需要做 Query 改写,直接走对应的路径就行。
生产环境的注意事项
意图分类的准确率监控
意图分类的错误通常不会被用户直接感知到——用户只知道系统回答得不好,不知道是因为意图分错了导致走了错误的处理路径。所以需要主动监控。
建议记录每次分类的完整信息:
{"session_id": "session-001","query": "好的,帮我退了吧","intent": "tool","confidence": 0.92,"method": "llm","history_length": 4,"latency_ms": 280,"timestamp": "2025-03-07T14:30:00Z"}定期抽检分类日志,关注几个指标:
- 分类准确率 :人工标注后计算,目标 90% 以上
- 各意图的分布比例 :如果某类意图占比异常(比如 clarification 占了 30%),可能是 Prompt 太保守,动不动就要求澄清
- 误分类的典型案例 :哪些消息被分错了?错分为什么类别?原因是什么?针对性调整 Prompt 或补充规则
- 规则层命中率 :规则层拦截了多少比例的请求?如果太低(不到 10%),说明规则太少;如果太高(超过 60%),检查一下规则是否太激进导致误分
意图分类失败的兜底
大模型返回结果可能出现几种异常情况:
- 返回了格式不规范的 JSON(比如多了个换行或注释)
- 返回了未定义的意图类别(比如模型自己编了个 complaint)
- API 调用超时或失败
这些情况都需要兜底。前面代码里已经做了处理——解析失败或意图不合法时,默认走知识检索。
public IntentResult safeClassify(List<Message> history, String query) {try {IntentResult result = classify(history, query);// 置信度太低也走兜底if (result.confidence < 0.5) {return new IntentResult("knowledge", 0.5);}return result;} catch (Exception e) { log.warn("意图分类失败,默认走知识检索: {}", e.getMessage());return new IntentResult("knowledge", 0.5);}}为什么兜底走知识检索而不是引导澄清?因为知识检索路径自带兜底——如果检索不到相关内容,生成策略里有兜底回复(“抱歉,未找到相关信息,建议您联系人工客服”)。而引导澄清会让用户觉得系统“太笨了,什么都要问”,体验更差。
意图边界的动态调整
业务发展过程中,意图分类体系可能需要扩展。比如:
- 初期:knowledge / tool / chitchat / clarification 四类
- 中期:加入 complaint(投诉)、urgent(催单)等细分类别
- 后期:不同产品线可能有不同的意图体系
建议把意图分类体系做成配置化 的:
// 意图定义配置(可以放在数据库或配置文件中)List<IntentDefinition> intents = List.of(new IntentDefinition("knowledge", "知识检索","用户在询问产品信息、政策规定、操作指南等通用知识",List.of("退货政策是什么", "保修期多久")),new IntentDefinition("tool", "工具调用","用户想查询个人数据、实时信息,或执行某个操作",List.of("查我的订单", "帮我申请退货")),// 新增意图只需加配置,不改代码new IntentDefinition("complaint", "投诉","用户在表达不满或投诉",List.of("我要投诉", "态度太差了")));意图定义配置化之后,加新意图只需要修改配置,不需要改代码,也不需要重新部署。Prompt 模板从配置中动态生成,规则层的关键词也从配置中加载。
小结与下一篇预告
这篇讲了意图识别与问题路由,核心要点回顾:
- “一根筋”的RAG系统有问题 :所有消息都走 RAG 检索,闲聊消息检索到不相关内容反而更差,工具调用消息在知识库里找不到答案
- 四种意图分类 :知识检索(查知识库)、工具调用(调 API)、闲聊对话(直接回答)、引导澄清(反问用户)
- 三种实现方案 :规则匹配(快但准确率低)、大模型分类(准但有延迟)、混合方案(推荐,规则做快速过滤 + 大模型做精确分类)
- 意图识别在RAG链路中的位置 :会话记忆之后、Query 改写之前。意图识别需要对话历史作为输入,Query 改写只在知识检索路径上才需要
- 兜底策略 :分类失败时默认走知识检索,这是最安全的路径
结合前面所有篇章,到这里多轮对话 RAG 系统的完整链路已经很清晰了:
用户提问→会话记忆(读取/保存对话历史)→意图识别(判断走哪条路)→路由分发:
- 知识检索路径 :Query 改写 → 向量检索 + 重排序 → 生成答案
- 工具调用路径 :Function Call / MCP → 模型生成最终答案
- 闲聊路径 :模型直接生成回复
- 澄清路径 :返回引导问题
→保存assistant回复到会话记忆
从数据入库到多轮对话,从检索生成到工具调用,再到意图识别和路由,RAG 系统的各个环节已经全部讲完了。但有一个关键问题还没有回答:你怎么知道你的RAG系统好不好?
检索召回的 chunk 是不是用户想要的?模型生成的答案是不是忠实于检索到的内容?端到端的用户满意度怎么样?哪个环节是瓶颈?
靠人工抽检能发现一些问题,但效率太低,覆盖不全。你需要一套系统化的评估方法,用数据来量化 RAG 系统每个环节的效果,找到短板,驱动优化。
下一篇咱们来聊 RAG系统的评估与优化 ——怎么量化评估检索准确率、生成忠实度、端到端满意度,怎么通过数据驱动持续优化 RAG 系统的各个环节。