MohitSalvi16/devops-incident-response-openenv

GitHub: MohitSalvi16/devops-incident-response-openenv

一个基于 OpenEnv 的 AI 代理训练与评测环境,用于解决 DevOps 与 SRE 场景下的实战事件响应问题。

Stars: 1 | Forks: 0

title: DevOps 事件响应 emoji: 🚨 colorFrom: red colorTo: indigo sdk: docker app_port: 7860 pinned: false license: mit short_description: 用于 AI agents 的 OpenEnv SRE 事件响应环境 tags: - openenv - rl - agents - devops - sre - incident-response # DevOps 事件响应 — OpenEnv 环境 [![openenv](https://img.shields.io/badge/openenv-validated-brightgreen)](https://github.com/meta-pytorch/OpenEnv) [![tests](https://img.shields.io/badge/tests-24%20passing-brightgreen)]() [![tasks](https://img.shields.io/badge/tasks-4-blue)]() ## 为什么存在这个环境 生产环境事件导致公司平均每分钟的停机时间损失 **$5,600**(Gartner)。值班工程师必须快速切换上下文、阅读密集的日志、关联跨服务的故障,并应用精确的修复——通常是在凌晨 3 点进行。这个环境提供了一个现实的、确定性的测试平台,用于评估 AI agents 是否能处理该工作流: - 跨多个服务的**日志分析** - 在模糊条件下的**根因诊断** - 带有评分器验证修复的**代码与配置修复** - 针对级联故障的**多服务关联** - 通过模拟 shell 命令进行**恢复验证** 这是我们未曾见过的在任何现有 OpenEnv 环境中进行过建模的领域,并且对 RL / agent 社区具有直接价值:训练 agents 进行事件响应可直接缩短平均解决时间(MTTR)并提高系统可靠性。 ## 快速开始 ### 运行服务器(本地) ``` pip install -r requirements.txt python -m server.app # listens on 0.0.0.0:${PORT:-7860} ``` ### 运行服务器(Docker) ``` docker build -t devops-incident-env . docker run -p 7860:7860 -e PORT=7860 devops-incident-env curl http://localhost:7860/health # → {"status":"healthy"} curl -X POST -H 'Content-Type: application/json' \ -d '{}' http://localhost:7860/reset # → initial observation ``` Dockerfile 会识别 `$PORT`(Hugging Face Spaces 会注入它),因此同一个镜像可以在 HF Spaces 和本地保持不变地运行。 ### 运行 baseline agent ``` export API_BASE_URL=https://api.openai.com/v1 export MODEL_NAME=gpt-4o-mini export HF_TOKEN=sk-... python inference.py ``` 如果未设置 `HF_TOKEN` / `OPENAI_API_KEY`,`inference.py` 将回退到确定性的启发式 baseline,以便脚本始终产生可复现的分数。 ### 运行本地提交前验证器 ``` bash scripts/pre_validate.sh # full SKIP_DOCKER=1 bash scripts/pre_validate.sh # skip docker build ``` ## OpenEnv 合约 此环境使用 `openenv.core.env_server.http_server.create_app`,因此所有标准 endpoint 都会自动连接: | Method | Path | Purpose | |--------|----------------|-----------------------------------------------| | GET | `/health` | 用于存活探针的 `{"status":"healthy"}` | | GET | `/metadata` | 环境名称 + 描述 + 版本 | | GET | `/schema` | `action`、`observation`、`state` 的 JSON schema | | GET | `/openapi.json`| OpenAPI 3.x spec(由 `openenv validate` 使用) | | POST | `/reset` | 重置并返回初始 observation | | POST | `/step` | 执行 action,返回 observation | | GET | `/state` | 当前 `episode_id` + `step_count` | | POST | `/mcp` | JSON-RPC MCP endpoint | | WS | `/ws` | 持久 WebSocket session | `openenv validate` 通过: ``` [OK] Meta_Hackathon: Ready for multi-mode deployment ``` ## Action 空间 agent 在每步发出一个 `DevOpsAction`(`openenv.core.env_server.types.Action` 的子类): | `action_type` | `target` | `content` | |----------------|--------------------------|---------------------------------------------| | `read_log` | 日志文件名 | _空_ | | `read_file` | 文件路径 | _空_ | | `diagnose` | _空_ | 根因假设 | | `edit_file` | 文件路径 | **完整**替换文件内容 | | `run_command` | _空_ | shell 命令(例如 `nginx -s reload`) | | `submit_fix` | _空_ | 修复内容总结 | ## Observation 空间 `DevOpsObservation`(`openenv.core.env_server.types.Observation` 的子类): | Field | Type | Description | |----------------------|------------------|----------------------------------------------| | `step` | `int` | 当前步数 | | `max_steps` | `int` | Episode 步数限制 | | `task_id` | `str` | 活动任务标识符 | | `task_description` | `str` | 人类可读的目标 | | `alert_message` | `str` | PagerDuty 风格告警(仅首步) | | `logs` | `dict[str,str]` | 以文件名为键的日志文件内容 | | `files` | `dict[str,str]` | 以路径为键的源代码/配置文件 | | `command_output` | `str` | 上次 `run_command` 的输出 | | `system_status` | `str` | `up` / `degraded` / `down` | | `diagnosis_feedback` | `str` | 关于上次 `diagnose` action 的反馈 | | `error` | `str` | 上次 action 无效时的错误 | | `cumulative_reward` | `float` | 累计 reward | | `final_score` | `float` | 归一化的 [0,1] 分数(在 `done` 时设置) | | `done` | `bool` | Episode 已终止 | | `reward` | `float` | 该步的 reward | ## Reward 函数 每一步都会产生密集的 reward(没有稀疏的 episode 结束 reward)。 | Component | Reward | Trigger | |-----------------------|-----------------|---------------------------------------------| | 信息收集 | +0.02 | 首次读取每个日志/文件/命令 | | 部分诊断 | +0.05 – 0.15 | 识别出部分根因 | | 完整诊断 | +0.20 – 0.30 | 识别出所有根因 | | 部分修复 | +0.05 – 0.25 | 修复部分文件 | | 完整修复 | +0.40 – 0.50 | 所有文件均被正确修复 | | 成功解决 | +0.20 | `system_status == "up"` 时 `submit_fix` | | 效率奖励 | +0.00 – 0.10 | 步数越少 → 奖励越高 | | 重复动作 | −0.05 × 次数 | 对循环的逐步升级惩罚 | | 错误提交 | −0.10 × 次数 | 系统仍宕机时 `submit_fix` | | **裸提交** | **−0.20 × 次数** | 没有任何事先 `edit_file` 的 `submit_fix`(防漏洞利用) | | Episode 超时 | −0.10 | 达到最大步数且系统仍宕机 | 评分器将累计 reward 归一化为 `final_score ∈ [0, 1]`。**没有任何评分器返回常数分数** —— 每个任务都会根据 agent 的质量产生明显不同的分数(已通过 `tests/test_tasks.py::test_grader_score_bounds` 参数化测试验证)。 ## 任务 | ID | 难度 | 最大步数 | 根因 | |---------------------------------|------------|-----------|-------------| | `easy_port_misconfiguration` | easy | 15 | 1 | | `medium_database_connection` | medium | 20 | 2 | | `medium_kubernetes_crashloop` | medium | 22 | 2 | | `hard_microservice_cascade` | hard | 25 | 5 | ### Easy — 端口配置错误 Nginx 被配置为 `listen 8080;`,但负载均衡器期望使用端口 80。端口 8080 被监控 agent 占用。**一个**根因;主要测试日志读取和基本配置编辑能力。 ### Medium — 数据库连接池耗尽 应用程序在负载下返回 503 错误。**两个**相互作用的故障:连接池大小设置为 2(必须 ≥ 10),并且应用程序代码从不将连接释放回池中。agent 必须同时编辑 `database.yml` 和 `user_service.py`。 ### Medium — Kubernetes CrashLoopBackOff `payment-service` 的所有 3 个副本都处于 CrashLoopBackOff 状态。**两个**相互作用的故障:(1) Secret `payment-secrets` 缺少 `database_url` 键,并且 (2) 存活探针路径为 `/health`,但服务仅暴露了 `/healthz`。agent 必须检查 kubectl 事件、Deployment YAML 和 Secret YAML,并修补这两者。 ### Hard — 微服务级联故障 跨越 `api-gateway`、`order-service`、`inventory-service` 和 Redis 的 SEV-1 级联宕机。**五个**相互作用的根因:禁用的断路器、重试风暴、缺失的服务间超时、未处理的 Redis `WatchError`,以及具有 `noeviction` 策略的 Redis OOM。真正挑战前沿模型 —— 每次修复都会获得部分积分。 ## Baseline 分数 可通过 `python inference.py` 复现: | Task | 启发式 agent | `mistral-small-latest`¹ | |-----------------------------------|-----------------|--------------------------| | `easy_port_misconfiguration` | **0.99** | **0.99** (10 步) | | `medium_database_connection` | 0.01 | 0.01 | | `medium_kubernetes_crashloop` | **0.99** | **0.99** (11 步) | | `hard_microservice_cascade` | 0.01 | 0.01 | | **平均** | **0.50** | **0.50** | | **通过的任务 (≥0.5)** | **2/4** | **2/4** | ¹ 代表性运行于 2026-04-12 通过 Mistral La Plateforme API 针对 `mistral-small-latest` 进行,`temperature=0`。托管的 LLM API 即使在零温度下也表现出残余的非确定性;在 3 次独立运行中,该模型的平均分数范围在 **0.23 – 0.50** 之间,这正是 Phase 2 评估所寻找的那种方差类型(跨运行的恒定分数是一票否决标准)。启发式 baseline 是完全确定性的。“medium-DB”和“hard-cascade”仍然无法被小型开放模型解决 —— 它们需要多文件协调编辑和级联根因分析,这真正挑战了前沿模型。**这个差距就是 agent 评估信号**:更强的模型(GPT-4.1、Claude Opus、Llama-3.1-405B、Nemotron 3 Super)预计在中等/困难任务上得分会显著更高,从而在评估准则中产生有意义的分数方差。 推理脚本使用扁平化(系统 + 一次用户回合)的提示策略,因此每次调用的上下文保持在 ~1.5k token 以下,使得小型模型(≤8B 参数)能够在不触及上下文长度错误的情况下完成整个轨迹。 ## 项目布局 ``` . ├── openenv.yaml # OpenEnv manifest (spec_version: 1) ├── pyproject.toml # project + [project.scripts] server entry ├── uv.lock # locked deps (required by openenv validate) ├── Dockerfile # python:3.10-slim + uvicorn ├── .dockerignore ├── README.md # this file ├── requirements.txt # pip-style deps mirroring pyproject.toml ├── inference.py # baseline agent (LLM + heuristic fallback) ├── models.py # OpenEnv-typed Action / Observation / State ├── server/ │ ├── __init__.py │ ├── app.py # create_app(...) + main() │ └── devops_environment.py # Environment subclass wrapping the inner env ├── env/ │ ├── env.py # core stateful env (reset/step/state) │ ├── grader.py # dense reward computation │ ├── models.py # internal action/observation │ └── tasks/ │ ├── base_task.py │ ├── task_registry.py │ ├── easy_port_misconfiguration.py │ ├── medium_database_connection.py │ ├── medium_kubernetes_crashloop.py # ← 4th task │ └── hard_microservice_cascade.py ├── tests/ # 24 unit tests │ ├── test_tasks.py │ └── test_env.py └── scripts/ └── pre_validate.sh # local pre-submission validator ``` ## License MIT
标签:AI智能体, SRE, 人工智能, 仿真环境, 偏差过滤, 强化学习, 故障排查, 用户模式Hook绕过, 运维