详情

首页手游攻略 一个Agent不够用?工业场景里的多Agent路由模式实战

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

佚名 2026-06-30 09:01:08

问题:单 Agent 的天花板

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

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

 复制代码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

 复制代码用户消息 → IntentClassifier(LLM + 关键词兜底)

        ┌──────┼──────┬──────────┬──────────┐
        ↓      ↓      ↓          ↓          ↓
     Alarm   Data   Diagnosis  Knowledge  General
     Expert  Expert  Expert     Expert     Expert

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


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

 复制代码@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/GENERALn消息:" + 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 重点
AlarmExpert1告警解读、风险等级评估
DataExpert1数据趋势分析、阈值标注
DiagnosisExpert5完整 CoT 五步链
KnowledgeExpert1知识检索、维修方案
GeneralExpert0一般问答、引导用户

以 AlarmExpert 为例:

 复制代码@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:分类 → 分发

 复制代码@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 对比

维度单 AgentRouter + 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 秒

代码结构

 复制代码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…


点击查看更多
推荐专题
热门阅读