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绕过, 站点可靠性工程, 级联故障, 请求拦截, 运维自动化, 逆向工具