FarseenSh/incident-triage-env

GitHub: FarseenSh/incident-triage-env

一个基于 OpenEnv 的强化学习环境,模拟 8 服务微服务架构中的生产事件,让 AI 代理练习调查告警、追踪依赖链、诊断根因并执行修复操作。

Stars: 0 | Forks: 0

# 事件响应分诊环境 [![OpenEnv 兼容](https://img.shields.io/badge/OpenEnv-Compatible-blue)](https://github.com/meta-pytorch/OpenEnv) [![验证](https://img.shields.io/badge/openenv_validate-6%2F6_passed-brightgreen)]() [![任务](https://img.shields.io/badge/Tasks-5-green)]() [![已测试模型](https://img.shields.io/badge/Baselines-3_models-purple)]() [![HF Space](https://img.shields.io/badge/HF_Space-Running-yellow)](https://huggingface.co/spaces/Farseen0/incident-triage-env) 一个 OpenEnv 兼容的 RL 环境,AI 代理可以在其中调查告警、追踪依赖链、识别根本原因,并修复模拟的跨 8 服务微服务架构的生产事件。 ### 剧集如何运作 ``` Agent receives incident briefing + initial alerts │ ├─→ get_alerts() → See what's firing ├─→ read_logs(service) → Read service logs for clues ├─→ check_metrics(service) → Check CPU, memory, latency, error rates ├─→ get_service_topology() → Understand dependency chain │ ├─→ set_severity("P1") → Classify the incident ├─→ diagnose(service, category) → Identify root cause ├─→ remediate(action, target) → Apply the fix │ └─→ submit_report() → End episode → Get reward (0.0 - 1.0) ``` ## 为什么这很重要 每个科技公司都有值班 SRE。当生产环境在凌晨 3 点出现故障时,工程师必须: 1. **分诊**一墙的触发告警(大多数是症状,不是原因) 2. **调查**跨互联服务的日志和指标 3. **追踪**通过依赖链追踪故障以找到根本原因 4. **修复**在正确的服务上执行正确的操作 这个环境捕捉了 exactly 的推理挑战——包含红鲱鱼、级联故障和真正能难倒前沿 LLM 的间歇性问题。 ## 快速开始 ``` # 安装 pip install openenv-core fastmcp uvicorn fastapi pydantic openai # 启动服务器 uvicorn incident_triage_env.server.app:app --host 0.0.0.0 --port 8000 ``` ``` # 连接并运行 episode import asyncio from incident_triage_env import IncidentTriageEnv from openenv.core.env_server.mcp_types import CallToolAction async def main(): async with IncidentTriageEnv(base_url="http://localhost:8000") as env: await env.reset(task_name="easy_oom_crash") # Investigate await env.call_tool("get_alerts") await env.call_tool("read_logs", service="order-service", lines=50) await env.call_tool("check_metrics", service="order-service", metric="all") # Diagnose & fix await env.call_tool("set_severity", level="P2") await env.call_tool("diagnose", root_cause_service="order-service", root_cause_category="memory_exhaustion") await env.call_tool("remediate", action="restart_service", target_service="order-service") # Submit (ends episode, triggers grading) result = await env.step(CallToolAction(tool_name="submit_report", arguments={})) print(f"Reward: {result.observation.reward}") # 1.0 for perfect diagnosis asyncio.run(main()) ``` ## 架构 ``` ┌─────────────────────────────────────────────────────────┐ │ Agent (LLM) │ │ Investigates → Diagnoses → Remediates │ └──────────────────────┬──────────────────────────────────┘ │ MCP Tool Calls ┌──────────────────────▼──────────────────────────────────┐ │ Incident Triage Environment │ │ │ │ ┌─────────┐ ┌──────────┐ ┌─────────┐ ┌──────────┐ │ │ │ Alerts │ │ Logs │ │ Metrics │ │ Topology │ │ │ └────┬────┘ └────┬─────┘ └────┬────┘ └────┬─────┘ │ │ └─────────┬──┴────────┬────┘ │ │ │ ┌─────▼───────────▼──────────────────▼──┐ │ │ │ Simulation Layer │ │ │ │ 8 services, dependency graph, │ │ │ │ scenario-specific fault injection │ │ │ └───────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────┘ ``` **8 个互联服务:** `api-gateway` → `auth-service`, `order-service` → `inventory-service`, `payment-service`, `database`, `cache` → `message-queue` ## 可用工具 | 工具 | 参数 | 描述 | |------|-----------|-------------| | `get_alerts` | — | 获取所有触发中的告警及事件简报 | | `read_logs` | `service`, `lines`(默认 50) | 读取服务的时间戳日志行 | | `check_metrics` | `service`, `metric`(默认 "all") | 检查 cpu/memory/latency/error_rate/connections | | `get_service_topology` | — | 查看微服务依赖图 | | `set_severity` | `level`(P1/P2/P3/P4) | 分类事件严重程度 | | `diagnose` | `root_cause_service`, `root_cause_category` | 提交根本原因诊断 | | `remediate` | `action`, `target_service` | 对服务应用修复 | | `submit_report` | — | 最终报告 — 结束剧集,触发评分 |
有效的枚举值 **根本原因类别:** `memory_exhaustion`, `connection_pool_exhaustion`, `clock_skew`, `disk_full`, `cpu_throttling`, `network_partition`, `config_error`, `dependency_failure` **修复操作:** `restart_service`, `scale_up`, `rollback_deploy`, `config_change`, `failover`, `clear_cache`, `increase_pool_size`
## 5 个事件场景 | # | 任务 | 难度 | 发生了什么 | 陷阱 | |---|------|-----------|--------------|----------| | 1 | `easy_oom_crash` | 🟢 简单 | order-service OOM 崩溃 | 无 — 告警和日志明确指向内存耗尽 | | 2 | `medium_cascade` | 🟡 中等 | 数据库连接池耗尽级联影响 4 个服务 | CRITICAL 告警在 api-gateway 触发(症状)。数据库仅显示 WARN | | 3 | `medium_disk_full` | 🟡 中等 | 数据库磁盘满 — 写入失败,读取正常 | 非对称故障。order-service 和 payment-service 看起来有问题但根本原因是存储 | | 4 | `hard_intermittent` | 🔴 困难 | auth-service 时钟偏移 + order-service CPU 红鲱鱼 | 8 个告警。order-service 有 CRITICAL CPU 告警和 ERROR 日志(这只是 cron 任务)。Auth 时钟偏移埋藏在 8% 的日志中 | | 5 | `hard_network_partition` | 🔴 困难 | 网络分区将 payment-service 与 message-queue 隔离 | 8 个告警。DB vacuum(红鲱鱼),auth token 峰值(红鲱鱼)。必须识别 network_partition 并应用 failover | ## 奖励函数 ### 终结奖励(4 个组成部分,最高 1.0) | 组成部分 | 权重 | 精确匹配 | 部分得分 | |-----------|--------|-------------|----------------| | 严重程度 | 0.20 | 正确的 P 级别 | 差一个级别 = 0.10 | | 服务 ID | 0.20 | 根本原因服务 | 任何受影响服务 = 0.10 | | 根本原因 | 0.30 | 正确的类别 | — | | 修复 | 0.30 | 正确的操作 + 目标 | 仅正确操作 = 0.10 | ### 每步信号 | 操作 | 奖励 | 条件 | |--------|--------|-----------| | 调查相关服务 | +0.02 | 在受影响服务上执行 `read_logs`/`check_metrics` | | 首次 `get_service_topology` | +0.01 | 一次性奖励 | | 首次 `get_alerts` | +0.01 | 一次性奖励 | | 重启健康服务 | -0.03 | 破坏性操作惩罚 | | 步数耗尽(20) | -0.10 | 剧集强制终止 | **总计** = 终结奖励 + 调查奖励 + 惩罚,钳制到 [0.0, 1.0] ## 验证 ``` $ openenv validate --url https://Farseen0-incident-triage-env.hf.space [PASS] openapi_version_available [PASS] health_endpoint [PASS] metadata_endpoint [PASS] schema_endpoint (action + observation + state) [PASS] mcp_endpoint (JSON-RPC 2.0) [PASS] mode_endpoint_consistency (/reset, /step, /state) Result: 6/6 passed ``` ## 基线分数 — 多模型基准 我们在所有五个任务上对三个模型进行了基准测试。环境产生一致的难度梯度,并真正区分模型能力。 | 模型 | 简单 | 中等级联 | 中等磁盘 | 困难间歇 | 困难网络分区 | 平均 | |-------|------|-------------|----------|----------------|--------------|-----| | **Qwen 3.6 Plus** | 1.00 | 1.00 | 0.68 | 0.75 | 0.82 | **0.85** | | **Kimi K2.5** | 1.00 | 1.00 | 1.00 | 0.00 | 0.80 | **0.76** | | **Gemma 4 26B** | 0.82 | 0.76 | 0.90 | 0.66 | 0.55 | **0.74** | **关键发现:** - 所有模型都能轻松完成简单任务,但在困难场景上挣扎(0.00–0.82) - 不同模型以不同方式失败 — Kimi 完全无法完成 `hard_intermittent`(放弃未提交),Gemma 在 `hard_network_partition` 上得到错误的根本原因 - 红鲱鱼机制真正难倒了前沿模型 - 任务间的分数差异证明评分器区分的是行为,而不仅仅是模型身份 ### 复现 ``` # 免费基线 (HF Router + Qwen 2.5 72B) HF_TOKEN=hf_xxx python inference.py --base-url http://localhost:8000 # 多模型基准测试 ANTHROPIC_API_KEY=x MOONSHOT_API_KEY=y HF_TOKEN=z python inference.py --run-all ``` ## 设置 ### Docker ``` docker build -t incident-triage-env . docker run -p 8000:8000 incident-triage-env ``` ### 本地 ``` pip install -e . uvicorn incident_triage_env.server.app:app --host 0.0.0.0 --port 8000 ``` ### 部署到 HF Spaces ``` pip install openenv-core openenv push --repo-id YOUR_USERNAME/incident-triage-env ``` ## 环境变量 | 变量 | 必需 | 描述 | |----------|----------|-------------| | `API_BASE_URL` | 用于推理 | LLM 端点(默认:HF Router) | | `MODEL_NAME` | 用于推理 | 模型 ID(默认:Qwen/Qwen2.5-72B-Instruct) | | `HF_TOKEN` | 用于推理 | Hugging Face API token | | `ANTHROPIC_API_KEY` | 可选 | 用于 Claude Sonnet 基准 | | `MOONSHOT_API_KEY` | 可选 | 用于 Kimi K2.5 基准 | ## RL 训练集成 与 TRL GRPO 兼容,用于从环境反馈进行强化学习: ``` from trl import GRPOTrainer, GRPOConfig from incident_triage_env.server.incident_environment import IncidentTriageEnvironment from openenv.core.env_server.mcp_types import CallToolAction def reward_fn(completions, task_name="easy_oom_crash"): rewards = [] for completion in completions: env = IncidentTriageEnvironment() env.reset(task_name=task_name) for tool_call in parse_tool_calls(completion): obs = env.step(CallToolAction( tool_name=tool_call["name"], arguments=tool_call["args"])) if obs.done: rewards.append(obs.reward) break else: rewards.append(0.0) return rewards trainer = GRPOTrainer( model=model, config=GRPOConfig(output_dir="./grpo-triage", num_generations=4), reward_funcs=[reward_fn], train_dataset=dataset, ) trainer.train() ``` ## 项目结构 ``` incident_triage_env/ ├── __init__.py # Package exports ├── models.py # IncidentTriageState + enums ├── client.py # MCPToolClient (pass-through) ├── openenv.yaml # OpenEnv manifest ├── pyproject.toml # Dependencies ├── Dockerfile # Multi-stage Docker build ├── inference.py # Baseline agent (multi-model) ├── server/ │ ├── app.py # FastAPI app factory │ └── incident_environment.py # Core MCPEnvironment subclass ├── scenarios/ │ ├── base.py # ScenarioBase ABC + GroundTruth + Registry │ ├── easy_oom_crash.py # Task 1: Single service OOM │ ├── medium_cascade.py # Task 2: Cascading dependency failure │ ├── medium_disk_full.py # Task 3: Database disk full │ ├── hard_intermittent.py # Task 4: Auth clock skew + red herrings │ └── hard_network_partition.py # Task 5: Network partition + red herrings └── simulation/ ├── service_graph.py # 8-service microservice topology ├── log_generator.py # Realistic timestamped log generation ├── metrics_store.py # Per-service metrics with overrides └── alert_engine.py # Alert creation and severity sorting ``` *为 [Meta x PyTorch x HuggingFace OpenEnv 黑客松](https://github.com/meta-pytorch/OpenEnv) 构建*
标签:AIOps, Apex, Incident Response, LLM代理, OpenEnv, RL环境, SRE, 人工智能运维, 偏差过滤, 强化学习, 指标监控, 故障排查, 服务拓扑, 机器学习, 根因分析, 模块化设计, 生产环境监控, 站点可靠性工程, 自动化修复, 请求拦截, 运维自动化, 逆向工具, 靶机