一个 Agent 不够用?工业场景下的多 Agent 路由模式实战

单 Agent 挂 5 个工具已经是极限------工具越多,LLM 选错率越高,系统消息越臃肿。这篇文章用 Router + Expert 模式拆分职责,让每个 Agent 只做自己最擅长的事。


问题:单 Agent 的天花板

Phase 2 的 DeviceAgent 把 5 个工具全注册在一个 Agent 上:

java 复制代码
AiServices.builder(IndustrialAssistant.class)
    .chatModel(chatModel)
    .tools(alarmTool, dataTool, diagnosisTool, knowledgeBaseTool, workOrderTool)
    .build();

三个问题逐渐暴露:

  1. 工具选错 ------用户问「温度趋势」,LLM 有时调了 queryDeviceAlarms 而不是 queryDeviceHistory
  2. 系统消息臃肿------CoT 路径 + 5 个工具描述 + 约束条件 ≈ 800 token,每次请求都重复消耗
  3. 无法差异化优化------查告警和做诊断的推理路径完全不同,一个 SystemMessage 不可能两边兼顾

方案:Router + Expert

markdown 复制代码
用户消息 → IntentClassifier(LLM + 关键词兜底)
               ↓
        ┌──────┼──────┬──────────┬──────────┐
        ↓      ↓      ↓          ↓          ↓
     Alarm   Data   Diagnosis  Knowledge  General
     Expert  Expert  Expert     Expert     Expert

核心思路:先分类,再分发。每个 Expert 只带 1-2 个工具和专精的系统消息。


意图分类:LLM 优先 + 关键词兜底

java 复制代码
@Component
public class IntentClassifier {

    public Intent classify(String message) {
        // 1. 先用 LLM 分类(~50 token 的轻量调用)
        Intent intent = classifyByLlm(message);
        // 2. LLM 失败时退化到关键词匹配
        if (intent == null) {
            intent = classifyByKeyword(message);
        }
        return intent;
    }

    private Intent classifyByLlm(String message) {
        String prompt = "将以下消息分类为:ALARM/DATA/DIAGNOSIS/KNOWLEDGE/GENERAL\n消息:" + message;
        String result = chatModel.chat(prompt).trim().toUpperCase();
        // 从返回文本中匹配枚举值
        for (Intent i : Intent.values()) {
            if (result.contains(i.name())) return i;
        }
        return null;  // LLM 返回无效 → 交给关键词
    }

    private Intent classifyByKeyword(String message) {
        if (Pattern.matches(".*诊断|故障|排查|工单.*", message)) return Intent.DIAGNOSIS;
        if (Pattern.matches(".*告警|报警|警告.*", message)) return Intent.ALARM;
        if (Pattern.matches(".*温度|振动|压力|数据|趋势.*", message)) return Intent.DATA;
        if (Pattern.matches(".*知识|手册|怎么修.*", message)) return Intent.KNOWLEDGE;
        return Intent.GENERAL;
    }
}

为什么不只用关键词?因为「CNC-001 最近震动有点大,帮我看看是不是轴承的问题」不含「诊断」二字,但意图明显是 DIAGNOSIS。LLM 能理解语义,关键词只能匹配字面。

为什么不只用 LLM?因为 LLM 偶尔会返回奇怪的格式(「我认为这属于 ALARM 类别」而不是纯 「ALARM」),关键词兜底确保系统不卡死。


Expert:最小工具集 + 专精提示词

每个 Expert 是一个独立的 AiServices 实例,关键差异在 SystemMessage:

Expert 工具数 SystemMessage 重点
AlarmExpert 1 告警解读、风险等级评估
DataExpert 1 数据趋势分析、阈值标注
DiagnosisExpert 5 完整 CoT 五步链
KnowledgeExpert 1 知识检索、维修方案
GeneralExpert 0 一般问答、引导用户

以 AlarmExpert 为例:

java 复制代码
@Component
public class AlarmExpert {

    interface AlarmAssistant {
        @SystemMessage("""
            你是工业设备告警分析专家。你只负责设备告警的查询和解读。
            使用 queryDeviceAlarms 工具查询设备当前活跃告警。
            回复规范:
            - 列出所有告警,标注严重级别
            - 对每条告警给出简要风险评估
            - 如果无告警,明确说明设备状态正常
            """)
        String chat(String message);
    }

    public String chat(String message) {
        AlarmAssistant assistant = AiServices.builder(AlarmAssistant.class)
                .chatModel(chatModel)
                .chatMemory(MessageWindowChatMemory.withMaxMessages(10))
                .tools(alarmTool)  // 只有1个工具
                .build();
        return assistant.chat(message);
    }
}

对比单 Agent 的 SystemMessage(800 token),AlarmExpert 只用 120 token------省 85% 的提示词开销,且不会选错工具(因为只有一个可选)。


Router:分类 → 分发

java 复制代码
@Service
public class RouterAgent {

    public RouteResult route(String message) {
        long start = System.currentTimeMillis();
        Intent intent = classifier.classify(message);

        String reply = switch (intent) {
            case ALARM -> alarmExpert.chat(message);
            case DATA -> dataExpert.chat(message);
            case DIAGNOSIS -> diagnosisExpert.chat(message);
            case KNOWLEDGE -> knowledgeExpert.chat(message);
            case GENERAL -> generalExpert.chat(message);
        };

        long elapsed = System.currentTimeMillis() - start;
        return new RouteResult(intent, reply, elapsed);
    }

    public record RouteResult(Intent intent, String reply, long latencyMs) {}
}

返回值带 intentlatencyMs,方便前端展示路由决策过程和性能监控。


实测结果

测试消息 分类结果 延迟
"CNC-001 有什么告警?" ALARM ✅ 6.8s
"查一下最近一小时的温度趋势" DATA ✅ 6.6s
"振动异常,诊断并创建工单" DIAGNOSIS ✅ 16.5s
"轴承温度过高怎么修?" KNOWLEDGE ✅ 16.6s
"你好,你是谁?" GENERAL ✅ 2.5s

分类准确率 5/5 = 100%。

延迟分析:

  • GeneralExpert 最快(2.5s)------无工具调用,纯 LLM 回复
  • ALARM/DATA 中等(~7s)------分类 + 1 次工具调用 + LLM 生成
  • DIAGNOSIS 最慢(16.5s)------分类 + 多次工具调用(告警+数据+知识+诊断+工单)

单 Agent vs Router 对比

维度 单 Agent Router + Expert
工具选择准确率 ~85%(偶尔选错) ~99%(Expert 只有 1 个工具)
系统消息开销 800 token/次 120-300 token/次
可扩展性 加工具越多越难管理 加 Expert 不影响其他
延迟 一次 LLM 调用 分类 + Expert 两次调用
复杂度

Router 的额外延迟(~1s 分类)换来了更高的准确率和更低的 token 消耗。 对工业场景来说,准确率比延迟重要。


什么时候不需要 Router?

  • 工具 ≤ 3 个------LLM 选得足够准,Router 是过度设计
  • 所有请求都需要多工具协作------Router 反而多一跳,不如让单 Agent 自由编排
  • 对延迟极度敏感------每多一次 LLM 调用就多 1-2 秒

代码结构

markdown 复制代码
agent/
├── DeviceAgent.java           --- 原有单 Agent(保留做对比)
├── router/
│   ├── Intent.java            --- 5 种意图枚举
│   ├── IntentClassifier.java  --- LLM + 关键词分类器
│   └── RouterAgent.java       --- 路由编排器
└── experts/
    ├── AlarmExpert.java       --- 告警专家(1 工具)
    ├── DataExpert.java        --- 数据专家(1 工具)
    ├── DiagnosisExpert.java   --- 诊断专家(5 工具 + CoT)
    ├── KnowledgeExpert.java   --- 知识专家(1 工具)
    └── GeneralExpert.java     --- 通用对话(无工具)

下一步

Router 解决了「分发」问题,但每个 Expert 是独立的------它们之间不会协作。下一篇文章引入 Supervisor 模式:一个「主管 Agent」动态规划多步任务,委派给不同 Expert,汇总结果后统一回复。


代码仓库:github.com/LaoLiang-ag...


本文由 LaoLiang 原创,首发于掘金/知乎/微信公众号。转载请联系作者。

相关推荐
贵慜_Derek1 小时前
复杂系统没法一把梭重构:Semi-Autoresearch 怎么小步迁移还不掉功能
人工智能·agent·ai编程
HjhIron1 小时前
工具调用:当LLM学会使用"武器",AI Agent的底层逻辑拆解
llm·agent
武子康1 小时前
调查研究-195 从 AmEx 支付系统看 Cell-based Architecture:真正的高可用,不是无限重试,而是控制失败边界
人工智能·openai·agent
米小虾2 小时前
Prompt Engineering —— 意图的精确表达
人工智能·agent
老梁agent17 小时前
从 0 到 22 篇:工业 Agent 的六大设计原则
物联网·agent
搬砖的码农17 小时前
(08)为什么我的 Agent 一跑后台服务就卡死
前端·agent·ai编程
leeyi17 小时前
ADK 入门:不写图,也能搭 Agent
aigc·agent·ai编程
Databend18 小时前
在 AWS 中国峰会逛了一天,我在 Databend 展台看到了 Agent 数据基础设施的新思路
数据库·人工智能·agent
米小虾19 小时前
从 Prompt 到 Loop:2026 年 AI 工程师必须掌握的 Loop Engineering 实战指南
人工智能·agent