# Agent 架构设计(MVP 版) ## 一、MVP 全景 ``` 用户输入 ↓ ┌──────────────────────────────────────────┐ │ 意图识别(Intent Recognition) 🆕 │ │ "用户想干什么?" │ │ │ │ 诊断意图 → 路由到诊断 Skill │ │ 文档意图 → 路由到文档问答 │ │ 案例意图 → 路由到案例查询 │ │ 闲聊 → 快速响应(不启动 Agent) │ │ 模糊/无关 → 提示用户,直接中断 │ └──────────────┬───────────────────────────┘ │ 诊断意图 ↓ ┌──────────────────────────────────────────┐ │ Supervisor Agent(调度者) │ │ "谁来干?什么时候停?" │ └──────────────┬───────────────────────────┘ ↓ ┌──────────────────────────────────────────┐ │ Planner Agent(规划者) │ │ 分析问题 → 制定策略 → 生成报告 │ └──────────────┬───────────────────────────┘ ↓ ┌──────────────────────────────────────────┐ │ Executor Agent(执行者) │ │ 调用工具收集证据 │ └──────────────┬───────────────────────────┘ ↓ ┌──────────────────────────────────────────┐ │ Verifier Agent(验证者) │ │ 事实核查 → 判定通过/修正/驳回 │ └──────────────┬───────────────────────────┘ ↓ 诊断报告输出 ↓ 用户反馈(有用/无用) ↓ 案例沉淀 + BadCase 优化 ``` --- ## 二、意图识别(入口层)🆕 ### 2.1 设计理念 ``` 定位:独立模块,不嵌入任何单一 Agent 分层策略(不是二选一,而是组合): L0: 正则规则 —— 0 成本,毫秒级 ✅ MVP ├─ 处理 80%+ 的结构化查询 ├─ 正则匹配订单号/traceId/错误码格式 └─ 关键词匹配("报错"/"异常"/"失败") L1: 小模型 Agent —— 低成本,百毫秒级 ✅ MVP ├─ L0 未命中时触发 ├─ 处理灵活的模糊表达("系统有点慢"、"怎么查不到了") ├─ 不启动全链路 Agent,只做意图分类 └─ 判断为诊断意图 → 路由到诊断 Skill L2: 兜底策略 —— 极少使用 ├─ L0+L1 都无法判断 → 意图不明 → 中断 └─ Phase 2 增强 ``` ### 2.2 意图分类与路由 ``` ┌────────────────────────────────────────────────────┐ │ 意图 │ 说明 │ 路由 │ ├────────────────────────────────────────────────────┤ │ 诊断意图 │ 包含结构化标识或错误描述 │ → 诊断Skill│ │ 文档问答 │ "XX接口的参数有哪些" │ → 直接RAG │ │ 案例查询 │ "之前有类似的问题吗" │ → 案例检索 │ │ 闲聊 │ "你好"/"谢谢" │ → 快速响应 │ │ 意图不明 │ 无法识别 │ → 中断+提示 │ └────────────────────────────────────────────────────┘ 关键原则: - 只有诊断意图才启动 Agent 全链路 - 非诊断意图走轻量路径或直接中断 ``` ### 2.3 L0:正则规则(MVP,处理 80%) ``` 为什么先做 L0? → 0 成本(不调 LLM),毫秒级响应 → 结构化查询占比最大(订单号、traceId、错误码、关键词) → L0 命中直接路由,不需要走后续逻辑 规则配置(可扩展): ┌────────────────────────────────────────────────┐ │ 规则 │ 意图 │ 方式 │ ├────────────────────────────────────────────────┤ │ 匹配 \d{12,} │ 诊断 │ 正则 │ │ 匹配 trace[-_]?\w{8,} │ 诊断 │ 正则 │ │ 包含"报错‖失败‖异常‖挂了‖超时" │ 诊断 │ 关键词│ │ 包含"文档‖接口‖参数‖字段‖API" │ 文档 │ 关键词│ │ 包含"案例‖之前‖类似‖历史" │ 案例 │ 关键词│ │ 长度 <= 5 字符 │ 闲聊 │ 规则 │ └────────────────────────────────────────────────┘ 命中 → 直接路由,不调 L1 未命中 → 进入 L1 ``` ### 2.4 L1:小模型 Agent(MVP,处理剩余 20%) ``` 为什么用小模型 Agent 而非嵌入到 Supervisor? → 意图识别是独立职责,不应耦合到任何业务 Agent → 轻量 Agent:单一职责,只分类不执行 → 成本低(~50 token),延迟低(~200ms) 何时触发:L0 规则未命中 System Prompt: "你是意图分类器,判断用户想做什么。 只返回一个词:[诊断 / 文档查询 / 案例查询 / 闲聊 / 意图不明] 诊断:用户描述了故障、报错、异常 文档查询:用户询问接口文档、字段含义 案例查询:用户询问历史案例、类似问题 闲聊:简单的问候、感谢 意图不明:无法判断用户意图" 输入:用户原始输入 输出:意图类型 + 置信度 ``` ### 2.5 L2:兜底策略 ``` L0+L1 都无法判断 → L2 兜底 中断规则: ├─ 意图不明 → 提示用户 + 中断 │ "无法判断您的意图,请提供订单号或错误码" ├─ 闲聊 → 快速响应 + 中断 │ "我是故障诊断助手,请描述您遇到的问题" └─ 不启动 Agent,直接返回 路由规则: ├─ 诊断意图 → 启动 Supervisor + 4 Agent 全链路 ├─ 文档意图 → 不启动 Agent,直接 RAG 检索 └─ 案例意图 → 不启动 Agent,直接查询 case_library ``` ### 2.5 架构位置 ``` 用户输入 ↓ ┌──────────────────────────────────────────┐ │ 意图识别模块(独立) │ │ │ │ L1: 小模型 Agent ─→ 诊断意图? │ │ │ 文档意图? │ │ │ 案例意图? │ │ │ 闲聊? │ │ ↓ │ │ L2: 兜底 ─────────→ 意图不明 → 中断 │ │ 闲聊 → 快速响应 │ └───────────────┬──────────────────────────┘ │ 诊断意图 ↓ Supervisor → Planner → Executor → Verifier ``` ### 2.6 MVP vs Phase 2 ``` MVP L0(正则)+ L1(小模型Agent) 覆盖 95%+ 场景 Phase 2 L2(兜底增强) 细化中断提示,支持多轮澄清 ``` --- ## 三、4 个 Agent 设计 ### 2.1 Supervisor Agent(调度者) **职责**:总指挥,协调工作流 ``` 调度规则: ├─ 接收任务 → 发给 Planner 分析 ├─ Planner 完成 → 发给 Executor 执行 ├─ Executor 完成 → 发给 Verifier 校验 └─ Verifier PASS → 输出报告 / REJECT → 返回 Planner 重新规划 不做: - 不直接调用工具 - 不直接生成报告 ``` ### 2.2 Planner Agent(规划者 + 分诊) **职责**:分析问题、制定策略、生成报告草稿 ``` 分析规则: ├─ 有 errorCode + 接口 URL → EXTERNAL_API(外部接口故障) ├─ 有堆栈信息 → INTERNAL_ERROR(系统内部错误) ├─ 有数据库错误码(如 1213)→ DATABASE(数据库问题) └─ 其他 → 通用排查 规划流程: 1. 确定 fault_category 2. 制定排查步骤(每步:工具名 + 参数 + 预期) 3. 生成决策:EXECUTE(继续执行)| FINISH(生成报告) Replanner 职责: ├─ Executor 每次返回结果后 → 评估证据是否充分 ├─ 需要补充?→ 调整步骤,继续执行 ├─ 证据齐全?→ FINISH,生成报告草稿 └─ 连续 3 次失败?→ 降级 禁止: - 编造数据 - 引用未经工具返回的内容 ``` ### 2.3 Executor Agent(执行者) **职责**:调用工具收集证据 ``` 工具清单: ├─ queryOrder:查询订单/业务数据(MySQL 只读) ├─ searchDoc:检索接口文档(混合检索 Milvus + MySQL) ├─ recommendCase:推荐相似案例(精确匹配 + 语义检索) └─ getCurrentTime:获取当前时间 执行规则: ├─ 每次只执行 Planner 指定的一个步骤 ├─ 返回结构化的执行结果 ├─ 失败时返回错误详情(便于 Planner 调整) └─ 禁止编造结果 扩展预留: // 代码中 Executor 是接口,后续可扩展为 SubAgent public interface Executor { ExecutionResult execute(Step step); } ``` ### 2.4 Verifier Agent(验证者) **职责**:验证诊断报告,防止编造 ``` 验证流程: 1️⃣ 事实核查(最重要) ├─ 报告中的错误码 → 在 tool_calls 中存在? ├─ 根因结论 → 有日志/文档证据支撑? ├─ 修复方案 → 引用了文档或案例? └─ 发现编造数据 → 直接 REJECT 2️⃣ 完整性检查 ├─ 根因分析章节不能为空 ├─ 证据链章节不能为空 └─ 修复方案章节不能为空 判决结果: ├─ PASS:报告成立,直接输出 ├─ REVISE:小问题可修正,返回 Planner 微调 └─ REJECT:编造数据或严重错误,返回 Planner 重新分析 ``` --- ## 四、RAG 两层加载策略 ### 4.1 设计理念 ``` 问题: ❌ 全前置:启动时把所有文档塞给 Agent → 信息过载,推理变慢 ❌ 纯被动:等到需要才查 → Planner 没有全局视野,可能跑偏 ❌ 固定步骤:每次都调 → 内部错误查接口文档浪费 正确做法:两层互补 L1 预加载(Planner 启动时) → 通用领域知识:系统架构、通用错误码、业务流程 → 给 Planner 全局视野,避免方向性错误 L2 按需加载(Executor 执行中) → 具体接口文档:字段定义、错误码含义、调用规范 → 给 Executor 精准证据,定位具体问题 ``` ### 4.2 两层对比 | | L1 预加载 | L2 按需加载 | |------|---------|-----------| | 触发时机 | 意图识别后,Planner 启动前 | Executor 拿到具体信息后 | | 内容 | 通用知识(架构、流程、高频错误码) | 具体接口文档(字段、错误码含义) | | 目的 | 让 Planner 有全局视野 | 让 Executor 有精准证据 | | 成本 | 固定,每次诊断 1 次 | 按需,最多 2-3 次 | | 谁负责 | Supervisor 注入 | Executor 自主调用 | ### 4.3 实现方式 ``` L1 预加载: Supervisor 在启动 Planner 前: searchDoc(keyword="系统架构 通用错误码 业务流程") → 注入到 Planner 的 System Prompt 中 → Planner 拥有"领域背景知识" L2 按需加载: Executor 执行 Step 2 时: 拿到 errorCode=40003, faultSource="广东" → 自主调用 searchDoc(errorCode="40003", faultSource="广东") → 获取该接口的具体字段定义和错误码说明 → 作为证据写入诊断报告 ``` --- ## 五、Skill 设计(1 个) ### /diagnose-by-orderid(按订单号诊断) ``` 输入:orderId 工作流(6 步): Step 1: 查询订单信息 工具:queryOrder 失败:ABORT(订单不存在则终止) Step 2: 检索接口文档 工具:searchDoc 参数:errorCode + faultSource 失败:SKIP(标注"文档缺失") Step 3: 查询日志 工具:queryLogs(Mock) 参数:traceId 失败:SKIP(标注"日志缺失") Step 4: 检索相似案例 工具:recommendCase 参数:errorCode + faultCategory 失败:SKIP(标注"无相似案例") Step 5: 生成诊断报告 汇总所有证据,按模板生成报告 Step 6: Verifier 验证 事实核查 → 判决 门禁规则: ├─ Step 1 失败 → 终止,返回"订单不存在" ├─ Step 2-4 失败 → 跳过,标注缺失信息 ├─ 任意步骤超时 30s → 终止 └─ Verifier REJECT → 返回 Planner 重新规划 ``` --- ## 六、Harness 控制层(精简版) ### 4.1 5 个 Quality Gates ``` 输入门禁(2 个): ├─ Gate 1: 输入参数非空校验 └─ Gate 2: 5 分钟内同一订单 → 返回缓存 执行门禁(1 个): └─ Gate 3: 工具调用超时(10 秒) 输出门禁(2 个): ├─ Gate 4: 报告章节完整性(3 章节不全 → 不通过) └─ Gate 5: 置信度阈值(< 60 → 标记"低置信度") ``` ### 4.2 中断规则 ``` 自动中断: ├─ 工具连续失败 3 次 → 终止,降级输出 └─ 全局超时 30 秒 → 终止 条件降级: ├─ 文档检索为空 → 跳过继续 ├─ 案例推荐为空 → 跳过继续 └─ 日志查询失败 → 跳过继续 降级输出: "无法自动诊断,请人工介入" + 已收集的证据(订单信息 + 部分日志 + 已知错误码) ``` --- ## 七、技术实现 ### 5.1 基于 Spring AI Alibaba ```java // Supervisor - 框架提供 SupervisorAgent supervisor = SupervisorAgent.builder() .name("diagnosis_supervisor") .model(chatModel) .subAgents(List.of(planner, executor, verifier)) .build(); // Planner ReactAgent planner = ReactAgent.builder() .name("planner_agent") .model(chatModel) .systemPrompt(plannerPrompt) .outputKey("planner_plan") .build(); // Executor(代码中预留 SubAgent 扩展接口) ReactAgent executor = ReactAgent.builder() .name("executor_agent") .model(chatModel) .systemPrompt(executorPrompt) .methodTools(diagnosisTools) .tools(new ToolCallback[]{queryOrder, searchDoc, recommendCase, getCurrentTime}) .build(); // Verifier ReactAgent verifier = ReactAgent.builder() .name("verifier_agent") .model(chatModel) .systemPrompt(verifierPrompt) .outputKey("verifier_result") .build(); ``` ### 5.2 工具注册 ```java @Component public class DiagnosisTools { @Tool(description = "查询订单/业务数据(只读)") public OrderInfo queryOrder(@ToolParam(description = "订单号") String orderId) { // MySQL 只读 + SQL 注入防护 } @Tool(description = "检索接口文档") public List searchDoc( @ToolParam(description = "错误码") String errorCode, @ToolParam(description = "省份/服务名") String faultSource ) { // 混合检索:精确匹配 + 向量检索 } @Tool(description = "推荐相似历史案例") public List recommendCase( @ToolParam(description = "错误码") String errorCode, @ToolParam(description = "故障类别") String faultCategory ) { // 精确匹配 MySQL + 语义检索 Milvus } } ``` --- ## 八、闭环机制 ``` 诊断报告输出 ↓ 用户反馈(useful / not_useful) ↓ ├─ useful → 自动生成 case_library └─ not_useful → 记录 BadCase ↓ 每周 BadCase 分析 ↓ Prompt / Skill 优化 ↓ 准确率验证(测试集重跑) ``` --- ## 九、MVP vs 扩展方向 | 维度 | MVP | 扩展方向 | |------|-----|---------| | Agent | 4 个 Agent | SubAgent 模式(专科医生) | | Skill | 1 个 | 渐进式披露(3 层知识) | | 工具 | @Tool 注解 | MCP 独立 Server | | 回退 | 2 级(失败→降级) | 4 级路由 | | Gates | 5 个 | 15 个全流程门禁 | | 隔离 | 单 JVM | K8s Pod 进程隔离 | | 进化 | 案例自动生成 | 模式识别 + Prompt 自优化 | --- ## 十、面试话术(精简版) > "我用 Spring AI Alibaba 实现了一个故障诊断 Agent 系统。 > > 入口层是**意图识别**:先判断用户想干什么——诊断故障、查文档、查案例还是闲聊。 > 非诊断意图直接走轻量路径,只有诊断意图才启动 Agent 全链路,节省资源。 > > 4 Agent 协作:Supervisor 调度、Planner 制定策略、 > Executor 调用工具收集证据、Verifier 验证报告防止编造。 > > 诊断流程封装成了 Skill,标准化 6 个步骤和异常处理。 > Harness 层 5 个门禁保证质量——最关键的是输出门禁, > Verifier 会对比报告数据和工具返回数据,发现编造就驳回。 > > 闭环机制:用户反馈 → BadCase 分析 → Prompt 优化。 > 案例自动沉淀,系统越用越智能。"