Spaces:
Sleeping
Sleeping
File size: 10,525 Bytes
bb5e238 27cdb3e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | ---
title: DevOps RL Agent
emoji: π€
colorFrom: blue
colorTo: green
sdk: docker
app_file: app.py
pinned: false
---
# π€ DevOps RL Agent
**An AI agent that learns to fix broken Linux/Python environments through reinforcement learning.**
Built with **OpenEnv + TRL (GRPO) + Unsloth** β no agent frameworks, no multi-agent systems, just one LLM and one RL loop.
[](https://python.org)
[](LICENSE)
---
## π― What It Does
The agent observes broken environments (missing packages, port conflicts, config errors), generates shell commands to fix them, executes those commands in a Docker sandbox, and improves through GRPO training over episodes.
```
=== BEFORE TRAINING (episode 0) ===
Error: ModuleNotFoundError: flask
Step 1: python app.py β failed (exit 1)
Step 2: sudo pip install β DANGEROUS COMMAND BLOCKED
Step 3: apt install python β wrong approach
Result: FAILED (reward: -8.2)
=== AFTER TRAINING (episode 500) ===
Error: ModuleNotFoundError: flask
Step 1: pip install flask β success
Step 2: python app.py β Server running on :5000
Result: SOLVED in 2 steps (reward: +12.6)
```
---
## π How the RL Loop Works
This is the core architecture β one agent, one environment, one training loop:
```mermaid
graph LR
A[π§ LLM Agent] -->|shell command| B[π³ Docker Sandbox]
B -->|stdout/stderr/exit_code| C[ποΈ Environment]
C -->|observation + reward| A
C -->|episode data| D[πΎ Replay Buffer]
D -->|training batches| E[π GRPO Trainer]
E -->|updated weights| A
```
### The Loop in Detail
1. **Reset**: Environment loads a random broken scenario (e.g., Flask not installed)
2. **Observe**: Agent receives an error log, command history, and error type classification
3. **Act**: Agent outputs ONE shell command (e.g., `pip install flask`)
4. **Execute**: Command runs in an isolated Docker container with safety checks
5. **Reward**: Multi-signal reward computed (success +10, correct command +3, progress +1, etc.)
6. **Repeat**: Steps 2-5 repeat up to 10 times per episode
7. **Train**: After N episodes, GRPO updates the model using grouped completions
### Error Fingerprinting (Key Differentiator)
Before the agent acts, a rule-based classifier identifies the error type from the terminal output:
| Error Type | Pattern | Example |
|---|---|---|
| `missing_package` | `ModuleNotFoundError` | `No module named 'flask'` |
| `port_conflict` | `Address already in use` | Port 5000 occupied |
| `missing_env` | `KeyError` on env var | `DATABASE_URL` not set |
| `version_conflict` | `ResolutionImpossible` | Package version clash |
| `config_error` | `NameError`, misconfig | Wrong host binding |
This gives the LLM better context and lets us analyze which error categories the agent struggles with.
### Multi-Signal Reward System
The reward engine returns a breakdown dict with 10 independent signals:
| Signal | Value | Purpose |
|---|---|---|
| `success` | +10.0 | Scenario fully solved |
| `correct_command` | +3.0 | Matches optimal fix sequence |
| `progress` | +1.0 | Error log changed (likely improvement) |
| `efficiency_bonus` | +2.0 | Solved in minimal steps |
| `invalid_command` | -2.0 | Command not whitelisted |
| `dangerous_command` | -10.0 | Matches blocklist (rm -rf /, etc.) |
| `no_progress` | -1.0 | Error log unchanged |
| `timeout` | -5.0 | Command exceeded 30s |
| `repeated_command` | -1.5 | Same command twice in episode |
| `step_cost` | -0.2 | Encourages efficiency |
Each column is logged separately during training to detect reward hacking.
### Curriculum Learning
Scenarios unlock progressively based on rolling 50-episode solve rate windows:
- **Level 1** (single-step): Always available β `missing_flask`, `missing_numpy`, `wrong_python`
- **Level 2** (two-step): Unlocks at L1 solve rate > 80% β `port_conflict`, `missing_env_var`, `broken_requirements`
- **Level 3** (multi-step): Unlocks at L2 solve rate > 80% β `corrupt_venv`, `wrong_config`, `db_migration`
---
## π Project Structure
```
devops-rl-agent/
βββ devops_env/ # OpenEnv-style RL environment
β βββ env.py # DevOpsEnv (reset/step/reward)
β βββ state_manager.py # Observation tracking
βββ scenarios/ # 9 scenarios across 3 difficulty levels
β βββ registry.py # ScenarioRegistry
β βββ level1/ # Single-step fixes
β βββ level2/ # Two-step fixes
β βββ level3/ # Multi-step fixes (3-5 steps)
βββ executor/ # Docker sandbox execution
β βββ docker_executor.py # Container management + local fallback
β βββ safety.py # Command whitelist/blocklist
βββ fingerprint/ # Error classification system
β βββ classifier.py # Rule-based regex classifier
βββ rewards/ # Multi-signal reward computation
β βββ engine.py # 10 independent reward signals
βββ replay/ # Episode storage (SQLite + SQLAlchemy)
β βββ buffer.py # ReplayBuffer with batch sampling
β βββ models.py # ORM models
βββ agent/ # LLM + baseline agents
β βββ baseline_agent.py # Rule-based (for loop validation)
β βββ devops_agent.py # LLM agent (Unsloth/HF)
β βββ prompts.py # System & user prompt templates
βββ training/ # GRPO training pipeline
β βββ train_grpo.py # Training loop + anti-hacking monitor
β βββ curriculum.py # Rolling-window curriculum scheduler
βββ api/ # FastAPI server (OpenEnv pattern)
β βββ main.py
βββ frontend/ # Dashboard (vanilla HTML/CSS/JS)
β βββ index.html
β βββ style.css
β βββ app.js
βββ docker/ # Sandbox container
β βββ Dockerfile.sandbox
β βββ docker-compose.yml
βββ tests/ # Unit tests
β βββ test_env.py
β βββ test_rewards.py # 100% reward engine coverage
β βββ test_executor.py
βββ scripts/
β βββ demo.py # Before/after training demo
βββ requirements.txt
βββ README.md
```
---
## π Quick Start
### 1. Install Dependencies
```bash
cd devops-rl-agent
pip install -r requirements.txt
```
### 2. Validate the RL Loop (No GPU Required)
Run the baseline agent to confirm environment, executor, and rewards work:
```bash
# Run the demo script
python scripts/demo.py --episodes 50
# Run unit tests
python -m pytest tests/ -v
```
### 3. Start the API Server
```bash
uvicorn api.main:app --reload --port 8000
```
Then visit:
- API docs: [http://localhost:8000/docs](http://localhost:8000/docs)
- Dashboard: [http://localhost:8000/app](http://localhost:8000/app)
### 4. Build the Docker Sandbox (Optional)
```bash
cd docker
docker compose build
docker compose up -d sandbox
```
### 5. Run GRPO Training (Requires GPU)
```bash
python -c "
from training.train_grpo import GRPODevOpsTrainer
trainer = GRPODevOpsTrainer(model_name='unsloth/llama-3.2-3b-instruct')
trainer.train(num_episodes=500)
"
```
## βοΈ Deploy to Hugging Face Spaces
This repository is set up as a Docker Space. To deploy:
1. Create a new Hugging Face Space.
2. Choose `Docker` as the SDK.
3. Push this repository contents to the Space repo.
4. Hugging Face will build the root [Dockerfile](Dockerfile) and start the API on port `7860`.
Useful endpoints after deployment:
- `GET /` health check
- `POST /reset` OpenEnv session reset
- `POST /step` OpenEnv step
- `POST /close` OpenEnv session cleanup
- `POST /episode/run` one-shot episode execution
Notes:
- Runtime DB files are ignored via [.dockerignore](.dockerignore).
- If you want model training inside Spaces, keep `use_grpo=False` unless the Space has a GPU and enough VRAM.
---
## π Safety
The executor enforces strict command safety:
**Whitelisted**: `pip`, `python`, `cat`, `ls`, `grep`, `sed`, `ps`, `kill`, `curl`, `echo`, `mkdir`, `cp`, `mv`, `export`, `source`
**Blocked**: `rm -rf /`, fork bombs, `dd if=`, `mkfs`, `chmod 777 /`, `sudo` + destructive ops
Commands that fail safety checks are immediately blocked, the agent receives a -10.0 penalty, and the episode terminates.
---
## π Success Criteria
After 500 training episodes:
| Metric | Target |
|---|---|
| Level 1 solve rate | > 90% |
| Level 2 solve rate | > 70% |
| Mean steps to solve L1 | β€ 2 |
| Reward hacking detected | None |
| Model saves/loads correctly | β |
---
## π§ API Endpoints
| Method | Path | Description |
|---|---|---|
| `POST` | `/reset` | OpenEnv-style session reset (returns session_id + initial observation) |
| `POST` | `/step` | OpenEnv-style step for a session (`{session_id, action:{command}}`) |
| `POST` | `/close` | OpenEnv-style explicit session cleanup |
| `POST` | `/episode/run` | Run one episode, returns full step log |
| `GET` | `/episode/{id}` | Get stored episode by UUID |
| `GET` | `/stats` | Solve rates, rewards, training progress |
| `GET` | `/replay/{id}` | Step-by-step replay data |
| `POST` | `/train/step` | Trigger training batch |
| `GET` | `/scenarios` | List scenarios with solve rates |
| `GET` | `/recent` | Recent episodes |
---
## π‘οΈ Anti-Reward Hacking
The training loop includes active monitoring:
1. **Generation inspection** every 50 steps β actual agent outputs are printed
2. **Success column tracking** β alerts if total reward rises but success rate stays flat
3. **Command repetition detection** β flags if one command dominates >50% of actions
4. **Dangerous command counting** β terminates if blocklist triggers repeatedly
5. **Per-column reward breakdown** β logged separately to catch gaming of individual signals
---
## ποΈ Tech Stack
- **RL Framework**: TRL (GRPOTrainer) + Unsloth (4-bit LoRA)
- **Base Model**: `unsloth/llama-3.2-3b-instruct`
- **Environment**: OpenEnv-compatible API pattern
- **Execution**: Docker SDK with safety layer
- **Storage**: SQLite via SQLAlchemy
- **API**: FastAPI + Uvicorn
- **Frontend**: Vanilla HTML/CSS/JS (dark theme, glassmorphism)
- **Testing**: pytest (100% reward engine coverage)
---
## π License
MIT
|