# AI智能巡检与故障归因平台 阶段1落地方案

## 1. 目标重述

阶段 1 只做一条可验证主线闭环：

1. 外网巡检按周期执行。
2. 发现异常后固化截图和失败说明。
3. 按任务绑定的服务模板补采内网上下文。
4. 通过安全推送接口入库上下文。
5. 调用 AI 诊断得到结构化归因结果。
6. 在异常详情页和日报页完成交付。

不做多租户，不做自动修复，不做复杂大屏，不做脚本自动生成。

## 2. 建议技术方案

为降低阶段 1 复杂度，建议采用单体应用 + 轻量 agent 的分层结构。

### 2.1 技术栈

- 前端：`Next.js 15 + React + TypeScript + Ant Design`
- 后端：`NestJS + TypeScript`
- 数据库：`PostgreSQL`
- 缓存/任务队列：`Redis + BullMQ`
- 浏览器巡检：`Playwright`
- ORM：`TypeORM`
- 定时调度：`BullMQ repeatable jobs` 或 `Nest Schedule`
- AI 调用：统一封装 `LLMProvider`
- 日志：`Pino`
- 鉴权：阶段 1 先做本地账号密码 + JWT Session

原因：

- `Playwright` 适合实现步骤脚本、截图、状态码、DOM 检查。
- `NestJS + TypeORM` 便于按数据库方言切换到 `MariaDB / PostgreSQL兼容模式`。
- `BullMQ` 既能做定时调度，也能承接执行任务、诊断任务，避免后续重构。
- 单体后端能快速闭环，后续再拆服务。

## 3. 系统架构

建议拆成 4 个运行单元：

### 3.1 Web 应用

职责：

- 登录
- 首页总览
- 任务管理
- 模板管理
- 巡检记录列表
- 异常详情
- 日报页

### 3.2 Platform API

职责：

- 提供 `API-01` 到 `API-08`
- 任务 CRUD
- 调度注册
- 记录落库
- 诊断编排
- 报表聚合

### 3.3 Inspector Worker

职责：

- 消费巡检任务
- 使用 `Playwright` 执行步骤脚本
- 做异常检测
- 保存截图与执行日志
- 触发上下文采集

### 3.4 Context Agent

职责：

- 从模板生成指标查询和探测请求
- 汇总 `metrics / probes / logs`
- 进行签名与加密
- 调用 `/agent/context/push`

阶段 1 可以先把 `Context Agent` 做成同仓库里的独立 Node 进程，既保留“内外网边界”的设计，又不把真实内网接入复杂化。

## 4. 核心模块拆分

后端建议按模块组织：

- `auth`
- `dashboard`
- `tasks`
- `runs`
- `scheduler`
- `inspector`
- `templates`
- `context`
- `security-push`
- `diagnosis`
- `reports`
- `storage`

每个模块尽量遵循：

- `controller`: 对外 API
- `service`: 业务逻辑
- `repository`: 数据访问
- `dto`: 入参与出参校验
- `entity/model`: TypeORM Entity 或领域模型

## 5. 关键数据流

### 5.1 巡检执行链路

1. 创建任务 `inspection_task`
2. 调度器根据 `cron_expr` 投递执行任务
3. Worker 创建 `inspection_run`，状态为 `queued -> running`
4. Playwright 执行 `steps_json`
5. 检查状态码、关键元素、白屏
6. 成功则 `run_status=success`
7. 失败则保存截图、错误标签、失败说明
8. 触发上下文采集
9. 上下文 push 成功后触发诊断
10. 诊断完成后更新详情聚合数据

### 5.2 AI 诊断链路

1. 读取 `inspection_run + context_payload`
2. 执行脱敏映射
3. 组装提示词模板
4. 调用模型，要求 JSON 输出
5. 校验字段完整性
6. 写入 `diagnosis_result`
7. 更新页面可见状态

## 6. 数据库设计建议

在文档给出的 4 张核心表基础上，建议至少补齐以下表，避免后续状态无法闭环。

### 6.1 inspection_task

保留文档字段，并补充：

- `created_at`
- `updated_at`
- `created_by`
- `last_run_at`

### 6.2 inspection_run

建议补充：

- `status`：`queued/running/success/failed/partial`
- `failure_reason`
- `step_logs_json`
- `watermarked_screenshots_json`
- `context_status`
- `diagnosis_status`

说明：

文档里同时出现了 `run_status` 和状态机中的 `queued/running/success/failed/partial`，实际落地时建议统一为 `status`，避免双状态冲突。

### 6.3 context_payload

建议补充：

- `id`
- `task_id`
- `run_id`
- `payload_status`：`pending/accepted/rejected`
- `encrypted_payload`
- `signature`
- `received_at`

### 6.4 diagnosis_result

建议补充：

- `status`：`pending/success/failed`
- `model_name`
- `prompt_version`
- `masked_context_json`
- `raw_response`
- `created_at`

### 6.5 probe_template

用于承接 P-04：

- `id`
- `service_key`
- `template_name`
- `probe_type`：`http/tcp`
- `target`
- `method`
- `headers_json`
- `timeout_ms`
- `success_condition`
- `threshold_json`

### 6.6 metric_template

- `id`
- `service_key`
- `metric_name`
- `promql`
- `threshold_json`
- `display_order`

### 6.7 daily_report

- `id`
- `report_date`
- `report_text`
- `items_json`
- `created_at`

## 7. 步骤脚本设计

`steps_json` 不建议一开始支持自由脚本，阶段 1 应限制为声明式 DSL：

```json
[
  { "action": "goto", "url": "https://example.com", "timeoutMs": 10000 },
  { "action": "waitForSelector", "selector": "input[name=q]", "timeoutMs": 5000 },
  { "action": "input", "selector": "input[name=q]", "value": "test" },
  { "action": "click", "selector": "button[type=submit]" },
  { "action": "assertText", "selector": "body", "contains": "结果" }
]
```

先只支持：

- `goto`
- `waitForSelector`
- `click`
- `input`
- `assertText`
- `assertVisible`
- `sleep`
- `screenshot`

这样可控、易验收，也符合文档“不得抢跑复杂能力”的原则。

## 8. 异常检测策略

阶段 1 建议把异常检测收敛为 4 类：

- `HTTP_4XX`
- `HTTP_5XX`
- `ELEMENT_MISSING`
- `BLANK_PAGE`

判定逻辑：

- HTTP：基于主请求状态码
- 关键元素缺失：`waitForSelector/assertVisible` 失败
- 白屏：`body.innerText` 长度过低且无核心元素

不要在阶段 1 加太多启发式规则，否则误报率和调试成本会上升。

## 9. 安全推送落地方式

阶段 1 重点是“验签失败不能入库”和“链路可复现”。

建议：

- 签名：`HMAC-SHA256(secret, trace_id + ts + payload_hash)`
- 加密：阶段 1 可先使用 `AES-GCM`
- 传输字段：
  - `encrypted_payload`
  - `sign`
  - `ts`
  - `trace_id`
- 服务端校验：
  - 时间窗校验
  - 签名校验
  - 去重校验

如果当前阶段只是演示闭环，可以“真签名 + 真验签 + 简化加密实现”，但不要只做假字段。

## 10. AI 归因设计

### 10.1 输入结构

输入模型的上下文建议固定为：

- 异常摘要
- 页面证据摘要
- 指标摘要
- 探测摘要
- 日志摘要
- 脱敏映射规则版本

### 10.2 输出结构

强制模型输出：

```json
{
  "root_cause": "可能为上游网关异常",
  "confidence": 0.82,
  "evidence_points": [
    "外网访问返回 502",
    "应用存活探测失败",
    "CPU 正常但接口探活超时"
  ],
  "next_actions": [
    "检查网关 upstream 配置",
    "核对应用实例健康状态"
  ],
  "report_text": "本次故障初步判断为..."
}
```

### 10.3 保守策略

- 模型输出先做 JSON Schema 校验
- 校验失败则标记 `diagnosis_result.status=failed`
- 页面只展示“诊断失败”，不展示拼接伪结论

## 11. 前端页面落地建议

### 11.1 首页 P-02

组件：

- 今日任务数
- 今日异常数
- 最近一次诊断结果
- 最近异常列表

阶段 1 重点是信息可读，不追求大屏。

### 11.2 任务管理 P-03

能力：

- 列表
- 新建/编辑弹窗
- 启停切换
- 手动执行

### 11.3 模板配置 P-04

分成两个 Tab：

- 指标模板
- 探测模板

### 11.4 巡检记录 P-05

字段：

- 任务名
- 开始时间
- 执行耗时
- 状态
- 异常标签
- trace_id

### 11.5 异常详情 P-06

建议三栏或纵向三块：

1. 外网证据
2. 内网上下文
3. AI 诊断

默认偏“技术排障视角”，因为这是阶段 1 的核心价值；后续可再补“领导汇报摘要卡片”。

### 11.6 日报页 P-07

输出两部分：

- 结构化表格
- 可复制自然语言摘要

这样兼顾技术复盘和领导汇报。

## 12. API 与内部服务映射

### 12.1 对外 API

- `POST /api/tasks`
- `GET /api/tasks`
- `POST /api/runs/execute/:taskId`
- `GET /api/runs`
- `GET /api/runs/:runId`
- `POST /agent/context/push`
- `POST /api/diagnosis/run`
- `GET /api/reports/daily`

### 12.2 建议补充 API

为了支撑页面，建议增加：

- `PUT /api/tasks/:id`
- `PATCH /api/tasks/:id/status`
- `GET /api/templates/metrics`
- `POST /api/templates/metrics`
- `GET /api/templates/probes`
- `POST /api/templates/probes`

这些属于页面所需的补全接口，不算越界扩展。

## 13. 开发顺序建议

严格按文档的 S1-S6 推进，但工程上建议拆成下面 10 个开发包。

### 包 1：工程骨架

- 前端、后端、worker 初始化
- TypeORM Entity 与数据库初始化脚本
- 本地开发环境
- 登录页、首页空态

### 包 2：任务管理

- 任务表
- 任务 CRUD
- 页面表单
- 启停状态

### 包 3：调度与执行记录

- cron 注册
- 手动执行
- `inspection_run` 状态流转
- 列表查询

### 包 4：Playwright 巡检

- DSL 解析
- 页面执行
- 日志记录
- 成功/失败收口

### 包 5：异常证据

- 截图
- 水印
- 失败原因
- 详情页证据区

### 包 6：模板与上下文补证据

- 指标模板
- 探测模板
- 模拟日志
- payload 打包

### 包 7：安全推送

- 加密签名
- push 接口
- 验签入库

### 包 8：AI 诊断

- 脱敏
- 提示词模板
- JSON 校验
- 结果落库和展示

### 包 9：日报

- 按日聚合
- 固定结构文本
- 复制导出

### 包 10：验收与样例数据

- 构造 502 页面
- 构造成功站点
- 预置任务模板
- 验收脚本

## 14. 里程碑建议

如果 1 人主开发，建议按 3 周压缩版推进：

- 第 1 周：S1 + S2
- 第 2 周：S3 + S4
- 第 3 周：S5 + S6 + 验收修复

如果 2 到 3 人并行：

- A 负责前端页面与联调
- B 负责后端 API / 数据库 / 调度
- C 负责 Playwright / context agent / AI 诊断

## 15. 当前最合理的保守实现

结合文档的“先主线、后增强”，我建议阶段 1 先这样收敛：

- 只支持 1 个示例站点
- 只支持 1 个服务标识 `service_key`
- 只支持 HTTP 探测 + 模拟 Prometheus 返回
- 日志先使用样例文本，不接真实日志平台
- AI 先使用单一诊断模板，不做多模型切换
- 详情页默认技术视角
- 日报同时输出表格摘要和自然语言摘要

## 16. 我对文档的几个架构修正建议

### 16.1 统一状态字段

文档里 `inspection_run.run_status` 与状态机表有轻微冲突，建议统一成：

- `status`: `queued/running/success/failed/partial`

### 16.2 明确任务与模板关系

建议：

- 一个任务绑定一个 `service_key`
- 一个 `service_key` 可以关联多条指标模板和多条探测模板

这样比“任务直接挂一堆模板”更稳。

### 16.3 详情页以 trace_id 聚合

不要只靠 `run_id` 聚合，因为后续上下文推送和诊断结果天然更适合用 `trace_id` 串联。

### 16.4 日报生成做成可重放

日报不要只做实时拼接，建议落 `daily_report` 表，便于复查与导出。

## 17. 下一步建议

如果直接开工，最推荐的顺序是：

1. 先搭 `NestJS + Next.js + PostgreSQL + Redis + Playwright` 基础工程。
2. 先完成 `S1-S2`，让任务创建、调度、手动执行、记录落库跑通。
3. 再接 `S3-S4`，把异常证据和上下文补证据补齐。
4. 最后接 `S5-S6`，把 AI 归因与日报交付收口。

这会是当前文档下最稳、最省返工的一条实现路径。
