abdur-code/IncidentResponse_RL
GitHub: abdur-code/IncidentResponse_RL
一个与OpenEnv兼容的强化学习环境,用于训练和评估AI智能体在微服务架构中进行事件调查、根因分析和修复的能力。
Stars: 0 | Forks: 1
# SRE 事件响应环境
一个与 OpenEnv 兼容的强化学习环境,模拟生产环境事件响应。AI 智能体必须调查微服务架构、诊断根本原因并应用修复方案——就像真正的值班 SRE 工程师一样。
## 主要贡献
- **多根本原因推理基准**
支持并发独立故障的部分计分。
- **严格的基于动作的评估**
仅奖励已应用的修复措施,而非仅正确的诊断。
- **确定性评分系统**
无需 LLM 评判;通过结构化匹配实现可重现的分数。
- **渐进式调查设计**
信息通过动作(日志、指标、追踪)揭示。
- **故障模式真实性**
包括级联故障、误导性信号和干扰项。
## 为什么这个环境具有挑战性
- 模型倾向于识别一个根本原因就停止,错过并发故障。
- 日志包含信号和噪声,需要过滤。
- 修复一个服务可能无法解决整个系统问题。
- 需要推理和动作执行。
## 动机
每个科技公司都有值班轮换,但目前没有标准化的基准来评估 AI 智能体的事件响应能力。此环境通过模拟现实的生产事件来填补这一空白,包括:
- **多服务架构**,具有依赖链和级联故障
- **渐进式信息揭示** —— 智能体必须主动调查(读取日志、检查指标、追踪请求)
- **干扰项和误导性症状** —— 警报指向症状,而非根本原因
- **最难级别的并发故障** —— 测试智能体是否能找到多个独立的根本原因
- **真实的运维数据** —— 每个服务 50+ 行包含噪声的日志、时间序列指标、分布式追踪、部署历史、运维手册和配置差异
## 服务架构
所有任务共享相同的 7 服务微服务架构:
```
+--------------+
+-------->| auth-service |<------+
| +------+-------+ |
| | depends | depends
+---------+------+ +------v------+ +-----+--------+
| api-gateway | | cache-redis | | notification |
| (entry point) | +-------------+ | -service |
+-+----------+---+ +--------------+
| |
| depends | depends
v v
+------------+ +-----------------+
|user-service| |payment-service |
+-----+------+ +--------+--------+
| depends | depends
v v
+----------------------------+
| db-postgres |
+----------------------------+
```
每个服务都有:名称、状态(`HEALTHY`/`DEGRADED`/`DOWN`)、版本、副本数、依赖、日志、指标、追踪、部署历史、配置和运维手册数据。
## 任务
任务从 `tasks/` 目录自动发现。每个任务是一个定义 `SCENARIO` 对象的自包含 Python 文件。
| 任务 ID | 名称 | 难度 | 最大步数 | 根本原因 | 所需修复 |
|---------|------|-----------|-----------|------------|--------------|
| `easy` | 单服务 OOM 崩溃 | 简单 | 15 | `auth-service` (OOM) | `restart_service(auth-service)` |
| `easy_disk` | 数据库磁盘满 | 简单 | 15 | `db-postgres` (磁盘满) | `restart_service(db-postgres)` |
| `easy_dns` | 通知服务 DNS 故障 | 简单 | 15 | `notification-service` (DNS 故障) | `restart_service(notification-service)` |
| `medium` | 级联数据库死锁 | 中等 | 25 | `db-postgres` (死锁) | `restart_service(db-postgres)` |
| `medium_cert` | 过期 TLS 证书级联故障 | 中等 | 25 | `api-gateway` (证书过期) | `restart_service(api-gateway)` |
| `medium_config` | 配置错误伴误导性数据库症状 | 中等 | 25 | `user-service` (配置错误) | `restart_service(user-service)` |
| `hard` | 并发故障 + 误导性证据 | 困难 | 35 | `payment-service` (错误部署) AND `cache-redis` (内存泄漏) | `rollback_deploy(payment-service, v3.8.1)` AND `restart_service(cache-redis)` |
| `hard_partition_ratelimit` | 网络分区伴并发限速 | 困难 | 35 | `cache-redis` (网络分区) AND `api-gateway` (限速) | `restart_service(cache-redis)` AND `restart_service(api-gateway)` |
| `hard_disk_cert` | 数据库磁盘耗尽伴认证证书故障 | 困难 | 35 | `db-postgres` (磁盘满) AND `auth-service` (证书过期) | `restart_service(db-postgres)` AND `restart_service(auth-service)` |
### 任务详情
**简单:单服务 OOM 崩溃** —— 警报直接指出 `auth-service` 宕机。日志清楚显示 OOM 崩溃循环(堆增长、OOM 杀死、重启耗尽)。单一根本原因,单一修复方案。
**简单:数据库磁盘满** — WAL 归档器在 `db-postgres` 上落后,磁盘填满至 100%,数据库 panic 并关闭。`user-service` 和 `payment-service` 因无法连接而宕机。日志显示明显的 PANIC,显示 "No space left on device"。
**简单:DNS 故障** — `notification-service` 的内部 DNS 缓存在 SMTP 中继提供商更改 IP 后变得陈旧。DNS 查询失败,只有 `notification-service` 受到影响(叶子节点)。零级联——简单的单服务修复。
**中等:级联数据库死锁** — 警报指责 `payment-service` 和 `user-service`(两者都是受害者)。真正的原因是长时间运行的分析查询导致 `db-postgres` 死锁。智能体必须注意到"写入失败但读取正常",沿着依赖链追踪到数据库,并读取 `db-postgres` 日志找到死锁。干扰项:`cache-redis` 未命中率警报(良性 TTL 过期)。
**中等:过期 TLS 证书** — `api-gateway` 的 TLS 证书已过期,但 cert-manager 已在 Kubernetes secret 中续期——运行中的进程内存中仍持有旧证书。大约 40% 的传入连接在 TLS 握手时失败。干扰项:`auth-service` 显示连接重置(受害者,非原因),`notification-service` 队列积压(下游影响)。智能体必须追踪故障到入口点。
**中等:配置错误** — configmap 更新向 `user-service` 推送了错误的数据库主机名(`db-postgres-primary.svc.cluster.local` 不存在)。干扰项:`db-postgres` 有关于断开连接的信息性警报(实际上它没问题),错误看起来像 DNS 失败但 `diff_config` 显示是配置错误。关键推理:如果 `db-postgres` 坏了,`payment-service` 也会宕机——但它没有。
**困难:并发故障 + 误导性证据** — 两个同时发生的独立故障:(1) `payment-service` 有一个错误的部署(v3.8.2,新验证器模块中的 NullPointerException),(2) `cache-redis` 有内存泄漏导致驱逐风暴,从而降低 `auth-service` 的性能。干扰项:`user-service` 配置警告(良性),`notification-service` 队列积压(auth-service 的受害者)。智能体必须找到并修复两个故障。修复仅一个后,修复后检查显示服务仍然不健康。
**困难:网络分区 + 限速** — 两个独立故障:(1) `cache-redis` 与应用 Pod 网络分区,但仍可从监控子网访问(在仪表板中显示"健康"但有 0 个连接的客户端),(2) `api-gateway` 有限速配置错误(RATE_LIMIT_RPS 从 1000 降至 100,导致 60% 的合法流量收到 429)。干扰项:cache-redis 指标看起来正常,`db-postgres` 显示连接数升高(auth 后备),`notification-service` 队列增长(受害者)。
**困难:磁盘满 + 认证证书过期** — 两个独立故障在不同的依赖路径上:(1) `db-postgres` 磁盘因 WAL 积累而填满,数据库崩溃——`user-service` 和 `payment-service` 宕机,(2) `auth-service` 的内部 mTLS 证书已过期——30% 的请求失败(缓存的 TLS 会话仍然有效)。db-postgres 崩溃是响亮的(100% 宕机),而 auth-service 失败是安静的(30% 间歇性)。智能体必须理解依赖图,意识到 auth-service 降级不可能来自 db-postgres。
### 添加新任务
要添加新任务:
1. 在 `tasks/` 中创建新文件(例如 `tasks/my_new_task.py`)
2. 定义 `SCENARIO = IncidentScenario(task_id="my_new_task", ...)` —— 参见现有任务文件作为模板
3. 完成。`tasks/__init__.py` 中的任务加载器会自动发现任何导出 `SCENARIO` 对象的 `.py` 文件。
无需更改环境引擎、评分器、服务器或推理脚本。评分器是通用的——它从场景定义中读取真实情况(根本原因服务、所需修复、关键词、权重)。
##结构
```
IncidentResponse_RL/
├── models.py # Pydantic models: Action, Observation, State, enums
├── openenv.yaml # OpenEnv manifest (tasks, models, runtime config)
├── requirements.txt # Python dependencies
├── Dockerfile # Container for HF Spaces deployment
├── inference.py # Baseline agent using OpenAI client
├── README.md
│
├── env/ # Core environment engine
│ ├── __init__.py
│ ├── scenario.py # IncidentScenario, ServiceConfig, RequiredFix dataclasses
│ ├── environment.py # step() / reset() / state() implementation
│ └── services.py # Alert generation, dependency cascade, data formatting
│
├── tasks/ # Task definitions (auto-discovered)
│ ├── __init__.py # Auto-discovery loader → SCENARIOS dict
│ ├── easy_oom.py # Easy: Single Service OOM Crash
│ ├── easy_disk.py # Easy: Database Disk Full
│ ├── easy_dns.py # Easy: Notification Service DNS Failure
│ ├── medium_deadlock.py # Medium: Cascading Database Deadlock
│ ├── medium_cert.py # Medium: Expired TLS Certificate Cascading Failures
│ ├── medium_config.py # Medium: Config Error with Misleading DB Symptoms
│ ├── hard_concurrent.py # Hard: Concurrent Faults + Misleading Evidence
│ ├── hard_partition_ratelimit.py # Hard: Network Partition + Rate Limiting
│ └── hard_disk_cert.py # Hard: Disk Exhaustion + Auth Certificate Failure
│
├── graders/ # Scoring engine
│ ├── __init__.py
│ └── grader.py # Generic rubric-based grader (0.0-1.0)
│
└── server/ # FastAPI web server
├── __init__.py
└── app.py # /reset, /step, /state, /tasks endpoints
```
## 动作空间
所有动作都作为带有 `action_type` 字段的单个 JSON 对象发送。可选字段取决于动作类型。
### 调查动作(只读,收集信息)
| 动作 | 必填字段 | 返回 |
|--------|----------------|--------|
| `read_logs` | `service` | 50+ 条带时间戳的日志行,包含噪声和信号 |
| `check_metrics` | `service` | 时间序列表(CPU、内存、延迟、错误率等) |
| `ping_service` | `service` | 可达性检查及延迟 |
| `check_dependencies` | `service` | 上游依赖列表及当前健康状态 |
| `inspect_deploy` | `service` | 部署历史(版本、时间戳、状态) |
| `query_traces` | `service` | 显示延迟分解的分布式追踪跨度 |
| `check_runbook` | `service` | 包含故障排除步骤的运维手册 |
| `diff_config` | `service` | 当前与之前配置的比较 |
### 修复动作(修改环境状态)
| 动作 | 必填字段 | 效果 |
|--------|----------------|--------|
| `restart_service` | `service` | 重启 Pod。修复 OOM/泄漏问题。如果根本原因在其他地方则无效。 |
| `rollback_deploy` | `service`, `target_version` | 回滚到指定版本。必须匹配精确的版本字符串。 |
| `scale_up` | `service`, `replicas` | 增加副本数。可以缓解内存压力。 |
### 终止动作
| 动作 | 必填字段 | 效果 |
|--------|----------------|--------|
| `submit_diagnosis` | `fix_description` + (`root_cause_service`, `root_cause_category`) 或 (`root_cause_services[]`, `root_cause_categories[]`) | 结束回合,触发评分。 |
### 根本原因类别
`oom_crash`、`db_deadlock`、`bad_deploy`、`memory_leak`、`network_partition`、`disk_full`、`config_error`、`cert_expiry`、`dns_failure`、`rate_limit`
### 示例动作
```
{"action_type": "read_logs", "service": "auth-service"}
{"action_type": "check_metrics", "service": "db-postgres"}
{"action_type": "rollback_deploy", "service": "payment-service", "target_version": "v3.8.1"}
{"action_type": "submit_diagnosis", "root_cause_service": "db-postgres", "root_cause_category": "db_deadlock", "fix_description": "Restarted db-postgres to clear deadlock caused by analytics-cron query"}
{"action_type": "submit_diagnosis", "root_cause_services": ["payment-service", "cache-redis"], "root_cause_categories": ["bad_deploy", "memory_leak"], "fix_description": "Rolled back payment-service to v3.8.1 and restarted cache-redis"}
```
## 观察空间
在 `reset()` 时,智能体收到:
- **服务健康仪表板** — 所有 7 个服务及其状态(`HEALTHY`/`DEGRADED`/`DOWN`)、版本、副本数
- **活动警报** — 带严重性标签的警报(SEV-1/SEV-2/SEV-3)
- **事件摘要** — 情况文本描述
在每个 `step()` 时,智能体收到:
- **更新的服务状态** — 修复后健康状况可能改变
- **更新的警报** — 服务恢复时警报清除
- **动作结果** — 动作返回的数据(日志、指标、追踪等)
- **奖励** — 每步奖励信号
- **完成标志** — 回合是否结束
- **分数** — 最终分数(仅在终止步)
### 渐进式揭示
智能体不会预先看到所有数据。它必须主动选择要调查哪些服务以及请求哪些数据。每个调查动作消耗一步,产生规划压力:智能体必须在步数预算内平衡信息收集和修复。
### 修复后反馈
任何修复动作后,观察包含 `[POST-REMEDIATION CHECK]`,列出仍然不健康的服务。这对于困难任务至关重要——在修复两个故障之一后,检查显示剩余问题。
## 奖励函数
### 每步塑造
| 动作 | 奖励 |
|--------|--------|
| 调查根本原因服务 | +0.01 |
| 调查非根本原因服务 | 0.00 |
| 正确修复(匹配所需修复) | +0.05 |
| 错误修复(错误服务或错误修复类型) | -0.05 |
### 终止评分 (0.0 - 1.0)
评分器是通用的且基于评分规则。每个任务定义自己的权重:
| 组件 | 简单 | 中等 | 困难 |
|-----------|------|--------|------|
| 识别正确的根本原因服务 | 0.30 | 0.25 | 0.15 |
| 正确的根本原因类别 | 0.20 | 0.20 | 0.10 |
| 应用主要修复 | 0.30 | 0.25 | 0.15 |
| 应用次要修复 | -- | -- | 0.20 |
| 诊断文本质量(关键词匹配) | 0.10 | 0.10 | 0.15 |
| 调查彻底性 | 0.10 | 0.10 | 0.10 |
| 错误修复惩罚 | -0.03/次 | -0.05/次 | -0.05/次 |
**诊断文本评分**使用确定性关键词匹配——评分器检查修复描述是否提及关键术语(服务名、故障类型、修复动作)。无需基于 LLM 的评判。
**多根本原因评分**使用部分计分(例如,2 个原因中找到 1 个获得根本原因组件的 50%)。
**所需修复评分**与顺序无关且基于集合。精确匹配的所需修复无论执行顺序如何都计分;替代修复不计分。
**无修复上限**适用于未匹配到所需修复的情况:终止分数被限制在解决阈值以下。
**调查彻底性**检查智能体在提交前是否至少检查了一个根本原因服务。
## 设置
### 本地开发
```
pip install -r requirements.txt
python -m uvicorn server.app:app --host 0.0.0.0 --port 8000
```
### 测试
```
python -m pytest -q
```
Pytest 缓存文件通过 `.gitignore` 忽略(`.pytest_cache/`)。
### Docker
```
docker build -t sre-incident-response .
docker run -p 8000:8000 sre-incident-response
```
### API 使用
```
# 列出可用任务
curl http://localhost:8000/tasks
# Reset(开始新的一轮)
curl -X POST http://localhost:8000/reset \
-H "Content-Type: application/json" \
-d '{"task_id": "easy"}'
# Step(采取行动)
curl -X POST http://localhost:8000/step \
-H "Content-Type: application/json" \
-d '{"session_id": "", "action": {"action_type": "read_logs", "service": "auth-service"}}'
# 获取当前回合状态
curl http://localhost:8000/state/
```
OpenEnv 前缀的端点也可使用:`/openenv/reset`、`/openenv/step`、`/openenv/state/{session_id}`、`/openenv/tasks`。
### 运行推理
```
export HF_TOKEN=your_token
export API_BASE_URL=https://router.huggingface.co/v1
export MODEL_NAME=Qwen/Qwen2.5-72B-Instruct
python inference.py
```
推理脚本针对所有任务运行基线 LLM 智能体,发出结构化 stdout 日志:
```
[START] task=easy env=sre_incident_response model=Qwen/Qwen2.5-72B-Instruct
[STEP] step=1 action=read_logs(auth-service) reward=0.01 done=false error=null
[STEP] step=2 action=check_metrics(auth-service) reward=0.01 done=false error=null
[STEP] step=3 action=restart_service(auth-service) reward=0.05 done=false error=null
[STEP] step=4 action=submit_diagnosis reward=1.00 done=true error=null
[END] success=true steps=4 score=1.00 rewards=0.01,0.01,0.05,1.00
```
## 基线分数
所有基线通过 Groq 免费层运行。
| 任务 | 难度 | Llama 3.1 8B | Llama 4 Scout 17B | Llama 3.3 70B |
|------|:---:|:---:|:---:|:---:|
| easy | 简单 | 1.00 | 1.00 | 0.77 |
| easy_disk | 简单 | 0.72 | 0.10 | 0.72 |
| easy_dns | 简单 | 0.40 | 0.00 | 0.10 |
| medium | 中等 | 0.90 | 0.90 | 0.90 |
| medium_cert | 中等 | 0.59 | 0.64 | 0.64 |
| medium_config | 中等 | 0.62 | 0.62 | 0.10* |
| hard | 困难 | 0.00 | 0.65 | 0.78 |
| hard_partition_ratelimit | 困难 | 0.68 | 0.65 | 0.68 |
| hard_disk_cert | 困难 | 0.55 | 0.64 | 0.28* |
| **平均** | | **0.61** | **0.58** | **0.66** |
\* 受 Groq 免费层速率限制(100K TPD);分数低于预期。
**关键观察:**
- 没有单一模型在所有任务上占主导——不同架构在不同故障模式下表现不同
- `easy_dns` 具有欺骗性难度:智能体执着于 SMTP 中继而不是重启服务来刷新 DNS 缓存
- 困难的多根本原因任务(hard、hard_partition_ratelimit、hard_disk_cert)真正挑战所有模型
- 较大模型在多根本原因诊断方面更好,但所有模型都在新故障模式下挣扎
- 分数因 LLM 采样而非确定性——跨运行存在方差是预期的
## 环境变量
| 变量 | 描述 | 默认值 |
|----------|-------------|---------|
| `API_BASE_URL` | LLM API 端点 | `https://router.huggingface.co/v1` |
| `MODEL_NAME` | 模型标识符 | `Qwen/Qwen2.5-72B-Instruct` |
| `HF_TOKEN` | HuggingFace API 密钥 | 必需 |
| `PORT` | 服务器端口 | `8000` |
| `SRE_TASKS` | 逗号分隔的任务 ID,用于推理运行 | `easy,e_disk,easy_dns,medium,medium_cert,medium_config,hard,hard_partition_ratelimit,hard_disk_cert` |
## OpenEnv 规范合规
- 带有元数据、任务定义、类型化模型和运行时配置的 `openenv.yaml`
- `step(action)` 返回 observation、reward、done、info
- `reset()` 返回初始 observation
- `state()` 返回当前回合元数据
- Action、Observation 和 State 的类型化 Pydantic 模型
- 跨 3 个难度级别的 9 个任务,包含覆盖所有 10 个根本原因类别的程序化评分器
- 0.0-1.0 范围内的分数及部分进度信号
- 用于容器化执行的工作 Dockerfile
- 基线推理脚本(`inference.py`)具有可重现的分数
标签:AI代理, Apex, API集成, Benchmark, Docker, Homebrew安装, OpenEnv, SRE, 人工智能, 偏差过滤, 分布式系统, 分布式追踪, 可观测性, 响应大小分析, 多服务架构, 安全防御评估, 强化学习, 强化学习环境, 性能基准, 指标监控, 故障排除, 故障诊断, 机器学习, 根本原因分析, 混沌工程, 生产环境, 用户模式Hook绕过, 站点可靠性工程, 级联故障, 请求拦截, 运维自动化, 逆向工具