Rhomboic/FireDrill

GitHub: Rhomboic/FireDrill

FireDrill是一个用于模拟软件故障响应的RL兼容代理gym。

Stars: 0 | Forks: 0

# 火灾演习 **一个与RL兼容的代理gym,具有Gymnasium风格的`reset`/`step`/`verify`接口。** FireDrill是一个可重用、可重现、可重置的环境,任何策略——一个LLM代理、一个人或一个RL训练循环——都可以放入并逐步执行。这个工件是*环境*,而不是评分器。 任务领域使其具体化:现在是晚上11点,一家初创公司的服务宕机了,值班工程师是一个AI代理。每个环境都是一个有状态的、损坏的软件项目,具有真实的文件系统、日志和副作用;策略通过工具进行操作,世界做出反应,**奖励在任何步骤都可以查询**(RL使用的先决条件)。代理必须诊断和修复事件——并且它不仅根据*是否*修复了问题来评分,还根据它如何推理、它工作得多高效以及它是否在途中破坏了其他任何东西。评分是环境的消费者之一,而不是它的目的。 ## 环境接口 核心原语是Gymnasium风格的`FireDrillEnv`,完全与任何代理解耦: ``` env.reset() # restore /workspace to a pristine golden state; return the task + first observation env.step(action) # action = a tool call; returns (observation, reward_signal, done, info) env.verify() # run the objective checks at ANY point (resolution / blast radius / regression) env.snapshot() / env.restore() # reproducible rollouts — one container, many episodes ``` - **动作空间**——五个工具:`read_file`、`write_file`、`list_directory`、`read_logs`、`run_command`。 - **观察空间**——文件内容、目录列表、日志和命令stdout/stderr/exit codes。 - **奖励**——质量维度(可在中途中查询),保持独立,以便消费者可以重新加权;**组合仅是质量**: - **解决**——之前损坏的东西现在是否工作?(客观验证器) - **爆炸半径**——它是否触及/破坏了预期修复之外的东西? - **诊断质量**——一个LLM作为法官对代理的根本原因解释进行评分1–5。 - **成本**——一个独立的、一等轴,**不**包含在组合中:缓存感知的token使用定价为**美元**,加上饱和的`k/(k+cost)`评分(不需要上限)。质量回答“它是否很好地完成了工作”;成本回答“这花费了多少”——成本与能力的权衡是你真正比较的东西。步骤和延迟作为统计数据报告。 ## 场景 十个手写的**本地项目**(不是真实仓库——文件树烘焙到容器中),一个平衡的多语言集,每个针对一种故障模式,有一个目标验证器,在修复之前失败,在修复之后通过: | # | 场景 | 栈 | 故障模式 | |---|---|---|---| | 1 | payments-service-down | Python | 缺少环境变量 + 依赖项 | | 2 | silent-data-bug | Python | 管道丢弃/损坏记录 | | 3 | off-by-one | Node | 错误的结果,没有崩溃 | | 4 | failing-test | Python | 最近的变化破坏了一个绿色的测试 | | 5 | dead-submit-button | React + Playwright | 破坏的提交处理程序 | | 6 | layout-regression | React + Playwright | 导航重叠内容 | | 7 | spinner-forever | React + Playwright | 错误的API基本URL / CORS | | 8 | malformed-config | config | 破坏的YAML/JSON/.env | | 9 | bad-dockerfile | Docker | 错误的端口 / 缺少COPY | | 10 | wrong-join | SQL | JOIN/filter返回错误的聚合 | 每个场景还种植了一个**回归陷阱**:第二个、更微妙的生产形状的bug,其中明显的*症状性*修复通过了可见的成功条件,但失败了**保留的`regression_check`**。这个陷阱是区分谨慎的推理者和仓促的推理者的杠杆——参见结果。 ## 结果——健身房是否具有区分能力? 一个健身房只有在其区分策略时才有用。这个故事分为三个部分: 1. **饱和。**第一个矩阵(每个场景一个明确标记的bug)中,每个模型都解决了8/10——四个模型的组合跨度仅为**0.024**。没有信号。 2. **陷阱。**每个场景的保留回归陷阱(症状性修复通过了可见检查但失败了隐藏的检查)将跨度提升到**0.100**。 3. **平均。**一个*单个*运行的结果太嘈杂,无法信任——一个未受触及的场景仅通过模型非确定性就从一个运行中的0.28跨度到另一个运行中的0.00。因此,每个单元格现在是6个运行的**平均值**。随着方差的平均化,跨度为**0.152**——迄今为止最大,且有序。 ### 方法论 每个`(场景 × 模型)`单元格运行**N = 6个剧集**,并将分数平均(`run_matrix.sh`默认为`REPEAT=3`;这次运行使用了6)。解决成为通过-*率*;成本以两种方式报告——**每个运行的平均成本**(你比较模型的单元格值)和**所有运行的实际支出**(真正的账单)。推理旗舰以高努力运行。 ### 最近一次运行——10个场景 × 4个模型,每个单元格6个运行的平均值 | 模型 | 组合 | 解决 | 爆炸半径 | 诊断 | 每次运行的成本 | 实际支出 | |---|---|---|---|---|---|---| | **Claude Opus 4.8** | **0.99** | 100% | 0.98 | 0.97 | $0.107 | $1.07 | | **GPT-5.5** | **0.99** | 100% | 0.95 | 1.00 | $0.108 | $1.08 | | Claude Haiku 4.5 | 0.94 | 100% | 0.78 | 0.92 | $0.040 | $0.40 | | GPT-4.1 mini | 0.84 | 90% | 0.62 | 0.87 | $0.0066 | $0.066 | 数据表明: 1. **解决本身是盲目的。**前三个模型解决了100%,GPT-4.1-mini 90%,但组合跨度为**0.84 – 0.99**。能力差距几乎无法察觉;它存在于**保留的回归**和**爆炸半径**中。这是多维度奖励的全部论点。 2. **区分通过爆炸半径流动。**失败的`regression_check`将爆炸维度硬零(破坏保留检查的修复是最大附带损害),使组合权重达到0.2。爆炸列(0.98 → 0.62)*是*组合跨度。 3. **成本跟踪能力,账单是诚实的。**Opus的成本是GPT-4.1-mini的**16倍**每运行,并且评分高0.15。如果你只需要表面的修复,GPT-4.1-mini是**$0.0066/运行**的价值选择;当修复*正确性*很重要时,旗舰产品赢得了溢价。 ### 哪些陷阱点燃了火(每个模型的组合,平均6次运行) | 场景 | Opus | GPT-5.5 | Haiku | 4.1-mini | 扩散 | 陷阱 | |---|---|---|---|---|---|---| | 06 layout-regression | 0.99 | 1.00 | 0.99 | **0.67** | 0.33 | 天真的z-index/margin修复在移动端上失败 | | 09 bad-dockerfile | 1.00 | 1.00 | 1.00 | **0.72** | 0.28 | `templates/`资产第二个端点需要时从未`COPY` | | 03 off-by-one | 1.00 | 0.99 | **0.76** | **0.76** | 0.24 | 未受保护的循环在部分/范围外的页面上 | | 01 payments-service-down | 0.96 | 0.95 | **0.80** | **0.75** | 0.21 | 重试辅助程序提前放弃一次尝试 | | 07 spinner-forever | 1.00 | 1.00 | 1.00 | **0.83** | 0.17 | 光标分页API;只有第一页加载 | | 05 dead-submit-button | 1.00 | 0.95 | 1.00 | 0.87 | 0.13 | 反转验证拒绝有效输入 | | 08 malformed-config | 1.00 | 1.00 | 0.91 | 0.88 | 0.12 | 配置优先级合并掩盖操作设置 | | 02 silent-data-bug | 1.00 | 1.00 | 1.00 | 0.95 | 0.05 | 浮点货币与Decimal | | 04 failing-test | 0.96 | 1.00 | 0.96 | 0.96 | 0.04 | 每行折扣在税前应用 | | 10 wrong-join | 1.00 | 1.00 | 1.00 | 1.00 | 0.00 | LEFT JOIN由于`WHERE`降级为内部连接 | **7个场景中的10个场景具有区分能力**(扩散>0.05),具有清晰的排序:**Opus ≈ GPT-5.5 > Haiku > GPT-4.1-mini**。更难的陷阱(06、09、07)清楚地隔离了最弱模型;off-by-one类陷阱(03、01)将*两个*小模型与旗舰产品分开。 **这次运行的方法论教训**:陷阱重新校准看起来在单个嘈杂的运行中失败了(扩散降至0.060),但在这里得分0.00的情景——06、07、09——在平均6次运行后是**最强的**区分器。信任基准意味着首先平均化方差。仍有两个场景无法区分等级:**10 wrong-join**太简单(每个模型都处理LEFT-JOIN陷阱)和**04 failing-test**边缘——将每个陷阱校准到旗舰产品通过而小模型不通过的狭窄带,在一个*可靠的*平均中,是构建健身房持续进行的工作。 ### 读取,按模型 主要发现是**能力在这里是一个平滑的梯度,而不是通过/失败**——每个模型都修复了可见的bug,但*如何*修复它跨度为0.84–0.99,每个模型在成本-能力前沿上占据一个独特的位置: - **Claude Opus 4.8——精确度**。组合(0.99)最高,得益于**现场最紧的爆炸半径(0.98)**:当它修复时,它只触及它应该触及的东西。解决一切;它的唯一下降是支付重试和失败的测试边缘,几乎完美。最贵的是**$0.107/运行**——当手术正确性是不可或缺的时候值得。 - **GPT-5.5——诊断师**。与Opus的组合(0.99)和这里最好的根本原因解释(诊断1.00)相提并论,但爆炸半径略松(0.95)——它偶尔会过度接触。相同的定价层。选择它以获得最清晰的*为什么*,Opus以获得最干净的*修复*。 - **Claude Haiku 4.5——价值**。**0.94组合**在**旗舰成本的三分之一**:解决100%,诊断良好(0.92),仅比旗舰产品落后0.05。它的差距是爆炸半径(0.78)——在off-by-one和支付陷阱中,它采取了症状性修复。中档事件的合理默认值。 - **GPT-4.1-mini——地板**。0.84组合,**唯一低于100%的解决者(90%)**,最松的爆炸半径(0.62)。它触发了最难的陷阱——布局在移动端(0.67)、缺失的Dockerfile `COPY`(0.72)——有时甚至无法解决表面的bug。但**$0.0066/运行(比Opus便宜16倍**),它是吞吐量游戏,错误很容易捕捉。 **前沿**:Haiku**严格主导**GPT-4.1-mini(更好且仍然便宜),旗舰产品以大约3倍Haiku的成本购买了最后~0.05的能力。对于大多数事件响应,Haiku是甜蜜点;当错误的或混乱的修复很昂贵时,选择旗舰产品。这正是单个混合评分会隐藏的比较,也是为什么成本保持为其自己的轴的原因。 ## 布局 ``` gym/ FireDrillEnv (environment.py), the policy-agnostic protocol, and the tool action space agent/ one LLM policy that drives the env (Claude + OpenAI), swappable eval/ 4-dimension scoring + LLM-as-judge runner/ container entrypoint: reset → run policy → verify → score → upload results scenarios/ the broken projects (filesystem/ + metadata.json each) orchestrator/ launch the scenario × model job matrix terraform/ ECS-on-EC2 + autoscaling, ECR, S3, secrets, dashboard infra dashboard/ static results dashboard (firedrill.adamissah.com) ``` ## 在本地运行作业 不需要Docker或AWS——一个`(场景 × 模型)`作业从你的shell: ``` pip install -r requirements.txt cp .env.example .env # add your ANTHROPIC_API_KEY / OPENAI_API_KEY python3 runner/run_job.py --scenario 01-payments-service-down --model claude-opus-4-8 ``` 运行器重置环境,用模型驱动它,验证修复,判断诊断,对四个维度进行评分,并将结果有效载荷写入`results//.json`(包括代理更改的统一差异)。如果事件未解决,则退出非零。 模型:`claude-opus-4-8`、`claude-haiku-4-5`、`gpt-5.5`、`gpt-4.1-mini`。核心健身房没有依赖项;烟雾测试在没有API密钥的情况下运行: ``` for t in gym agent eval runner; do python3 tests/smoke_$t.py; done ``` ## 在容器中运行作业 相同的入口点在Docker中运行(这是在ECS上运行的镜像)。一个通用镜像捆绑了健身房和所有场景;`SCENARIO`和`MODEL`是运行时环境变量: ``` ./orchestrator/run_local_docker.sh 03-off-by-one claude-opus-4-8 # 构建 firedrill:latest,运行作业,写入 results//.json ``` Python、Node、SQLite和Docker场景在这个通用镜像运行;React/Playwright UI场景在专门的Playwright镜像中运行(`Dockerfile.ui`、`firedrill:ui`)。 ## 基础设施 每个作业都是一个自包含的容器——一个`(场景 × 模型)`剧集,它重置环境,运行策略,对四个维度进行评分,并将自我描述的结果写入S3。通过ECS管理的扩展容量提供程序在**EC2自动扩展组**中生成作业:ECS在实例上放置容器,在容量不足时扩展舰队,在空闲时缩小。结果在**firedrill.adamissah.com**上呈现。 ## 状态 实时。Python、Node、React/Playwright、配置、Docker和SQL的十个场景,每个场景都由一个目标验证器(损坏→可修复→干净)和一个保留的回归陷阱控制。完整的`场景 × 模型`矩阵在ECS-on-EC2自动扩展上运行,**每个单元格6个运行的平均值**;最新运行显示了清晰的能力排序(组合扩散**0.152**,Opus ≈ GPT-5.5 0.99 > Haiku 0.94 > GPT-4.1-mini 0.84——参见结果)。结果在**[firedrill.adamissah.com](https://firedrill.adamissah.com)**上呈现。
标签:AI 代理, AI 模拟, Gymnasium, LLM 代理, NIDS, RL compatible, 动作空间, 可复现实验, 可扩展性, 可维护性, 可重现性, 可重用性, 可重置环境, 回归测试, 多任务执行, 奖励机制, 安全性, 容器化, 库, 应急响应, 强化学习, 性能评估, 故障诊断, 效率, 数据管道, 文件系统, 状态管理, 环境接口, 环境模拟, 观察空间, 请求拦截, 质量评估, 软件工程, 逆向工具