摘要

在智能对话系统、Agent平台和客服机器人中,意图识别是基础,但真正的工程难点在于意图路由——即识别出用户意图后,如何精准、高效地将请求分发到正确的业务处理单元。传统方案常将所有请求送入单一LLM进行意图识别和路由决策,导致算力浪费、时延升高。本文从工程实战角度,提出一套分层意图路由架构,通过规则层、轻量模型层和大模型兜底层三级流水线,将90%以上的常规请求拦截在前两层,仅将复杂歧义请求交给大模型处理。结合线上智能客服案例,详细拆解路由策略设计、置信度截断、多意图拆分与分发逻辑,并提供基于Spring AI Alibaba的完整Java实现。

一、引言:意图路由为何重要

意图识别解决了“用户想干什么”,而意图路由解决的是“这个需求应该由谁处理”。在大型对话系统中,后端往往挂接着多个业务模块:订单查询、物流跟踪、退款处理、人工客服、FAQ问答、第三方API调用等。如果路由错误,用户体验直接受损;如果路由效率低,系统资源被白白浪费。

然而,实际线上流量中,绝大部分用户请求都是高频、简单、意图明确的,比如“查物流”“转人工”“退款”。这些请求完全可以用极低成本的规则或轻量模型进行快速路由,根本不需要大模型介入。只有少部分复杂、歧义、多意图的请求才真正需要大模型的深度理解能力。

因此,分层意图路由成为大模型工程落地的核心优化手段之一。

二、意图路由的核心挑战

  1. 多意图叠加:用户一句话可能包含多个意图,如“查一下我的订单到哪了,顺便帮我催一下”,需要拆分成多个子意图并分别路由。
  2. 语义歧义:同一句话在不同上下文中有不同含义,例如“我要退了”可能指退货,也可能指退出登录。
  3. 上下文依赖:多轮对话中,意图可能需要结合历史信息才能准确判断。
  4. 路由目标多样性:可能路由到不同服务、不同工具、不同知识库,甚至需要并行路由。
  5. 成本与效果的平衡:简单请求用大模型路由是浪费,但规则过于复杂又难以维护。

三、分层意图路由架构设计

3.1 总体架构

采用经典的三层漏斗模型,与意图识别分层流水线一脉相承,但更强调路由决策

用户输入Query
    ↓
【第一层:规则路由】正则/关键词/模板匹配
├─命中 → 直接路由到对应业务处理器(毫秒级)
└─未命中 → 进入【第二层:轻量模型路由】
        ↓
        轻量分类器输出意图+置信度
        ├─置信度≥阈值且意图单一 → 直接路由
        ├─置信度≥阈值但意图多个 → 按主次路由或并行路由
        └─置信度<阈值或意图混淆 → 进入【第三层:LLM精细路由】
                ↓
                LLM解析意图、拆分多意图、消歧,输出路由指令
                ↓
                路由分发,样本回流

3.2 各层职责与选型

层级技术方案路由能力适用场景时延成本
规则路由关键词词典、正则表达式、固定模板精确匹配固定模式,直接映射到处理器高频固定请求:问候、转人工、查物流等<5ms零算力
轻量模型路由轻量BERT/TextCNN/SVM + 置信度阈值处理句式变体,输出意图标签和置信度语义明确但表达多变的常规请求10-50ms极低
LLM精细路由大模型Prompt工程 + Function Calling多意图拆分、语义消歧、复杂上下文理解歧义、多意图、口语化、多轮对话场景500-2000ms

3.3 路由策略细节

  • 单意图高置信:直接路由到对应处理器。
  • 多意图高置信:按置信度排序,支持并行路由或顺序路由(取决于业务是否允许同时处理)。
  • 低置信/混淆:交给LLM,LLM输出结构化路由指令(如JSON),包含意图列表、目标处理器、参数等。
  • 兜底路由:如果LLM也无法确定,路由到默认处理器(如转人工或澄清询问)。

四、线上实战案例:智能客服多意图路由

4.1 业务背景

某大型电商平台智能客服,日均对话量150w+,后端挂载订单服务、物流服务、退款服务、投诉服务、人工客服等10+个业务模块。初期采用“全量LLM意图识别+路由”方案,导致:

  • 日均LLM调用量150w次,GPU成本高昂;
  • 平均响应时延900ms,高峰期超时严重;
  • 简单请求(如“转人工”)也走大模型,浪费资源。

4.2 分层路由改造

第一层:规则路由(拦截68%)
维护高频意图关键词库和正则模板,直接映射到处理器:

关键词/正则意图路由目标
转人工、人工客服manual_service人工客服队列
物流、快递、到哪了logistics_query物流查询服务
退款、退货、退钱refund_apply退款服务
投诉、差评complaint投诉工单系统
你好、在吗greeting欢迎语模块
帮助、怎么用helpFAQ模块
第二层:轻量模型路由(拦截22%)
训练轻量BERT分类模型,输出意图标签和置信度,阈值设为0.85。对于模型输出的多意图情况,如果主意图置信度≥0.85且次意图<0.5,则按主意图路由;否则进入LLM。
第三层:LLM精细路由(穿透10%)
针对复杂请求,使用LLM进行意图拆分和路由规划,输出JSON格式:
{
  "intents": [
    {"intent": "logistics_query", "confidence": 0.9, "params": {"order_id": "12345"}},
    {"intent": "complaint", "confidence": 0.7, "params": {"reason": "物流太慢"}}
  ],
  "route_strategy": "parallel",
  "target_services": ["logistics_service", "complaint_service"]
}

系统根据该JSON并行调用多个服务,汇总结果返回。

4.3 落地效果

  • LLM调用量从150w/日降至15w/日,成本降低90%;
  • 平均RT从900ms降至65ms;
  • 用户满意度提升5%,因简单请求响应更快;
  • 复杂多意图请求处理准确率提升,因LLM专注于真正需要深度理解的场景。

五、Java代码实现(基于Spring AI Alibaba)

下面展示如何用Spring AI Alibaba实现分层意图路由。第一层规则路由使用正则和关键词映射;第二层轻量模型使用简单关键词打分模拟(实际可替换为ONNX小模型或独立服务);第三层使用ChatClient调用通义千问进行精细路由。

5.1 环境准备

Maven依赖:

<dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-starter</artifactId>
    <version>1.0.0-M3.2</version>
</dependency>

application.yml

spring:
  ai:
    dashscope:
      api-key: ${DASHSCOPE_API_KEY}
      chat:
        options:
          model: qwen-plus

5.2 核心代码

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.regex.Pattern;
@Service
public class IntentRouterService {
    // 第一层:规则路由表
    private final Map<String, RouteRule> ruleRoutes = new LinkedHashMap<>();
    {
        ruleRoutes.put("manual_service", new RouteRule(
                Pattern.compile(".*(转人工|人工客服|找人工).*"), "manual_service"));
        ruleRoutes.put("logistics_query", new RouteRule(
                Pattern.compile(".*(物流|快递|到哪|发货|派送).*"), "logistics_service"));
        ruleRoutes.put("refund_apply", new RouteRule(
                Pattern.compile(".*(退款|退货|退钱|退了).*"), "refund_service"));
        ruleRoutes.put("complaint", new RouteRule(
                Pattern.compile(".*(投诉|差评|态度差).*"), "complaint_service"));
        ruleRoutes.put("greeting", new RouteRule(
                Pattern.compile("^(你好|您好|hi|hello|在吗).*"), "greeting_module"));
        ruleRoutes.put("help", new RouteRule(
                Pattern.compile(".*(帮助|怎么用|使用说明).*"), "faq_module"));
    }
    // 第二层:轻量分类器(模拟)
    private final LightIntentClassifier lightClassifier = new LightIntentClassifier();
    // 第三层:大模型
    private final ChatClient chatClient;
    private final ObjectMapper objectMapper = new ObjectMapper();
    public IntentRouterService(ChatClient.Builder builder) {
        this.chatClient = builder.build();
    }
    /**
     * 路由入口
     */
    public RouteResult route(String userInput) {
        // 第一层:规则路由
        for (RouteRule rule : ruleRoutes.values()) {
            if (rule.pattern().matcher(userInput).matches()) {
                return new RouteResult(
                        List.of(new Intent(rule.intent(), 1.0)),
                        List.of(rule.targetService()),
                        "rule",
                        userInput
                );
            }
        }
        // 第二层:轻量模型路由
        List<Intent> lightIntents = lightClassifier.classify(userInput);
        if (!lightIntents.isEmpty()) {
            Intent mainIntent = lightIntents.get(0);
            if (mainIntent.confidence() >= 0.85 &&
                    (lightIntents.size() == 1 || lightIntents.get(1).confidence() < 0.5)) {
                // 单意图或主意图明显,直接路由
                return new RouteResult(
                        List.of(mainIntent),
                        List.of(mapIntentToService(mainIntent.intent())),
                        "light_model",
                        userInput
                );
            }
            // 多意图但不够置信,进入LLM
        }
        // 第三层:LLM精细路由
        return llmRoute(userInput);
    }
    private RouteResult llmRoute(String userInput) {
        String prompt = """
                你是智能路由助手,请分析用户输入,输出JSON格式的路由指令。
                可用意图:logistics_query, refund_apply, complaint, order_query, manual_service, faq, other。
                路由目标:logistics_service, refund_service, complaint_service, order_service, manual_queue, faq_service。
                要求:
                1. 如果包含多个意图,在intents数组中列出所有意图及置信度。
                2. 如果多个意图需要同时处理,route_strategy设为"parallel",否则"sequential"。
                3. target_services列出需要调用的服务。
                4. 只输出JSON,不要有其他内容。
                
                用户输入:%s
                """.formatted(userInput);
        String response = chatClient.prompt().user(prompt).call().content();
        try {
            JsonNode json = objectMapper.readTree(response);
            List<Intent> intents = new ArrayList<>();
            json.get("intents").forEach(node -> {
                intents.add(new Intent(
                        node.get("intent").asText(),
                        node.get("confidence").asDouble()
                ));
            });
            List<String> services = new ArrayList<>();
            json.get("target_services").forEach(node -> services.add(node.asText()));
            return new RouteResult(intents, services, "llm", userInput);
        } catch (Exception e) {
            // 解析失败,兜底到默认服务
            return new RouteResult(
                    List.of(new Intent("fallback", 0.5)),
                    List.of("clarification_service"),
                    "fallback",
                    userInput
            );
        }
    }
    private String mapIntentToService(String intent) {
        return switch (intent) {
            case "logistics_query" -> "logistics_service";
            case "refund_apply" -> "refund_service";
            case "complaint" -> "complaint_service";
            case "order_query" -> "order_service";
            case "manual_service" -> "manual_queue";
            case "faq" -> "faq_service";
            default -> "other_service";
        };
    }
    // 内部类:路由规则
    record RouteRule(Pattern pattern, String intent, String targetService) {
        RouteRule(Pattern pattern, String targetService) {
            this(pattern, targetService, targetService);
        }
    }
    // 内部类:意图
    public record Intent(String intent, double confidence) {}
    // 内部类:路由结果
    public record RouteResult(List<Intent> intents, List<String> targetServices, String source, String rawInput) {}
    // 轻量分类器模拟(基于关键词打分)
    static class LightIntentClassifier {
        private final Map<String, List<String>> intentKeywords = new HashMap<>();
        {
            intentKeywords.put("logistics_query", List.of("物流", "快递", "到哪", "发货", "派送"));
            intentKeywords.put("refund_apply", List.of("退款", "退货", "退了", "不要了"));
            intentKeywords.put("complaint", List.of("投诉", "差评", "态度差"));
            intentKeywords.put("order_query", List.of("订单", "买了", "购买", "下单"));
            intentKeywords.put("manual_service", List.of("人工", "客服", "转人工"));
        }
        public List<Intent> classify(String text) {
            Map<String, Double> scores = new HashMap<>();
            for (Map.Entry<String, List<String>> entry : intentKeywords.entrySet()) {
                double score = 0;
                for (String kw : entry.getValue()) {
                    if (text.contains(kw)) {
                        score += 0.3;
                    }
                }
                if (score > 0) {
                    scores.put(entry.getKey(), Math.min(score, 1.0));
                }
            }
            // 按分数降序
            return scores.entrySet().stream()
                    .sorted((e1, e2) -> Double.compare(e2.getValue(), e1.getValue()))
                    .map(e -> new Intent(e.getKey(), e.getValue()))
                    .toList();
        }
    }
}

5.3 调用示例

RouteResult r1 = intentRouterService.route("帮我查一下快递到哪了");
// 规则命中,source=rule,targetServices=[logistics_service]
RouteResult r2 = intentRouterService.route("我的订单好几天了还没派送,帮我看看");
// 轻量模型命中,source=light_model,targetServices=[logistics_service]
RouteResult r3 = intentRouterService.route("我上周买的衣服没收到,而且质量看着不好,想退了顺便投诉一下");
// LLM处理,可能输出多个意图,source=llm

六、工程避坑指南

  1. 规则维护成本:规则层只保留最高频、最稳定的模式,避免规则爆炸。定期分析规则命中率和误报率,及时清理低效规则。
  2. 轻量模型更新:轻量模型需要定期用线上穿透样本进行微调,提升拦截率。
  3. 置信度阈值动态调整:根据A/B测试数据,平衡拦截率和准确率。阈值过高会导致过多请求进入LLM,过低则可能误路由。
  4. 多意图并行路由的资源控制:并行调用多个服务时,需要设置超时和熔断机制,避免一个服务拖垮整个请求。
  5. 上下文处理:多轮对话中,路由决策应结合历史上下文,轻量模型可以引入对话状态特征,LLM可提供对话摘要。
  6. 监控与告警:监控各层流量占比、平均RT、路由准确率、LLM调用量、错误率等,异常时及时告警。

七、总结

意图路由是对话系统中的关键环节,分层架构能够用极低的成本处理绝大多数简单请求,同时保证复杂请求的精准处理。通过“规则→轻量模型→LLM”三级漏斗,我们实现了成本、时延和效果的最优平衡。本文提供的Java代码基于Spring AI Alibaba,可以直接集成到现有Spring Boot项目中,帮助开发者快速落地分层意图路由。

在未来的演进中,可以进一步引入强化学习优化路由策略,或使用更高效的模型蒸馏技术压缩轻量模型,持续提升系统性能。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐