Spaces:
Sleeping
Sleeping
Upload BLOG.md
Browse files
BLOG.md
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ML Debug Env β Teaching AI to Debug PyTorch Like an Engineer
|
| 2 |
+
|
| 3 |
+
**Meta Γ PyTorch Γ Scaler OpenEnv Hackathon β April 2026**
|
| 4 |
+
|
| 5 |
+
π₯ [Watch the Demo Video](https://youtu.be/TjEavKODTQQ) | π» [GitHub](https://github.com/RAK2315/ml-debug-env) | π€ [HF Space](https://rak2315-ml-debug-env.hf.space) | π [Training Notebook](https://github.com/RAK2315/ml-debug-env/blob/main/ml_debug_env_grpo_fixed.ipynb)
|
| 6 |
+
|
| 7 |
+
---
|
| 8 |
+
|
| 9 |
+
## The Problem
|
| 10 |
+
|
| 11 |
+
Every ML engineer knows this moment. Your training job fails. You open the terminal and see:
|
| 12 |
+
|
| 13 |
+
```
|
| 14 |
+
Training job crashed. No epochs completed. Exit code 1.
|
| 15 |
+
```
|
| 16 |
+
|
| 17 |
+
No code. No traceback. Just that one line.
|
| 18 |
+
|
| 19 |
+
Current AI debugging benchmarks hand the agent the full broken script and say "fix this." That is not how debugging works in the real world. Real engineers have to investigate β run the code, read the output, check the gradients, form a hypothesis, and only then commit to a fix.
|
| 20 |
+
|
| 21 |
+
We asked: what if we trained an AI to debug the same way?
|
| 22 |
+
|
| 23 |
+
---
|
| 24 |
+
|
| 25 |
+
## What We Built
|
| 26 |
+
|
| 27 |
+
**ML Debug Env** is a reinforcement learning environment where an AI agent learns to debug broken PyTorch training scripts β using diagnostic tools, not oracles.
|
| 28 |
+
|
| 29 |
+
The agent starts every episode completely blind. It receives one line. It has five tools and five steps to figure out what went wrong and fix it.
|
| 30 |
+
|
| 31 |
+
On reset, the agent sees only this:
|
| 32 |
+
|
| 33 |
+
```json
|
| 34 |
+
{
|
| 35 |
+
"alert": "Training job failed. Final loss: nan.",
|
| 36 |
+
"available_tools": ["run_code", "get_traceback", "inspect_gradients", "print_shapes", "view_source"],
|
| 37 |
+
"step_budget": 5
|
| 38 |
+
}
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
No source code. No traceback. No hints.
|
| 42 |
+
|
| 43 |
+
This is called **partial observability** β the agent cannot see the full picture, just like a real engineer getting paged at 3am with no context. It has to decide: do I run the code first? Check the gradients? Every tool call costs a step. Fix it in two steps and earn a 1.2Γ efficiency bonus.
|
| 44 |
+
|
| 45 |
+
---
|
| 46 |
+
|
| 47 |
+
## The Five Tools
|
| 48 |
+
|
| 49 |
+
The agent investigates using five diagnostic tools:
|
| 50 |
+
|
| 51 |
+
- **run_code** β runs the buggy script and returns the output or crash
|
| 52 |
+
- **get_traceback** β returns the full Python error traceback
|
| 53 |
+
- **inspect_gradients** β injects gradient logging and returns per-layer gradient norms after one batch
|
| 54 |
+
- **print_shapes** β injects forward hooks and returns tensor shapes at each layer
|
| 55 |
+
- **view_source** β reveals the full buggy source code
|
| 56 |
+
|
| 57 |
+
The clever part: `inspect_gradients` and `print_shapes` inject diagnostic code into the script before running it β deep introspection without revealing the source. The agent decides which tools to call and in what order. That strategy is what gets learned.
|
| 58 |
+
|
| 59 |
+
---
|
| 60 |
+
|
| 61 |
+
## The 8 Tasks
|
| 62 |
+
|
| 63 |
+
Eight broken PyTorch scripts, easy to expert:
|
| 64 |
+
|
| 65 |
+
| Task | Difficulty | What's broken |
|
| 66 |
+
|---|---|---|
|
| 67 |
+
| `shape_mismatch` | π’ Easy | Wrong `nn.Linear` dimensions β explicit crash |
|
| 68 |
+
| `training_collapse` | π‘ Medium | Bad learning rate β NaN loss |
|
| 69 |
+
| `wrong_device` | π‘ Medium | Model on GPU, data on CPU β explicit crash |
|
| 70 |
+
| `gradient_not_zeroed` | π Medium-Hard | Missing `zero_grad()` β loss explodes silently |
|
| 71 |
+
| `data_leakage` | π΄ Hard | Normalized before split β inflated metrics, no crash |
|
| 72 |
+
| `missing_eval_mode` | π΄ Hard | No `model.eval()` β non-deterministic metrics |
|
| 73 |
+
| `compound_shape_device` | π Medium-Hard | **Two bugs:** shape + device |
|
| 74 |
+
| `compound_leakage_eval` | π£ Expert | **Two bugs:** data leakage + missing eval mode |
|
| 75 |
+
|
| 76 |
+
The compound tasks are the hardest β two completely silent bugs in one script. Fix one and miss the other: **0.60**. Fix both: **0.99**.
|
| 77 |
+
|
| 78 |
+
---
|
| 79 |
+
|
| 80 |
+
## How Scoring Works
|
| 81 |
+
|
| 82 |
+
Scoring is a staircase, not binary:
|
| 83 |
+
|
| 84 |
+
```
|
| 85 |
+
0.01 β Wrong bug type
|
| 86 |
+
0.20 β Right type, fixed code crashes
|
| 87 |
+
0.40 β Code runs, training incomplete
|
| 88 |
+
0.60 β Training completes, root cause not fixed
|
| 89 |
+
0.80 β Root cause fixed, success signal missing
|
| 90 |
+
0.99 β Perfect fix β
|
| 91 |
+
```
|
| 92 |
+
|
| 93 |
+
The grader actually runs the fixed code in a subprocess. No pattern matching. No string similarity. The code has to work.
|
| 94 |
+
|
| 95 |
+
---
|
| 96 |
+
|
| 97 |
+
## The Training Story
|
| 98 |
+
|
| 99 |
+
### Run 1 β The Exploit
|
| 100 |
+
|
| 101 |
+
We trained Qwen2.5-1.5B with GRPO on T4 for 200 steps. Reward went down.
|
| 102 |
+
|
| 103 |
+
We investigated. Our grader had a bug β it was giving partial credit to fundamentally wrong fixes. The agent found the exploit before we did. It learned to game the reward function instead of actually debugging.
|
| 104 |
+
|
| 105 |
+
**The agent was right. Our environment was wrong.**
|
| 106 |
+
|
| 107 |
+

|
| 108 |
+
*Run 1: reward trending down as agent exploits broken grader*
|
| 109 |
+
|
| 110 |
+
### Run 2 β The Breakout
|
| 111 |
+
|
| 112 |
+
We fixed the grader. The agent had no shortcut anymore β it had to actually learn to debug.
|
| 113 |
+
|
| 114 |
+
**Result: 0.024 β 0.190. 690% improvement in 200 steps on a free T4 GPU.**
|
| 115 |
+
|
| 116 |
+

|
| 117 |
+
*Run 2: 0.024 β 0.190, +690% improvement after grader fix*
|
| 118 |
+
|
| 119 |
+
### Run 3 β The Self-Improvement Loop
|
| 120 |
+
|
| 121 |
+
We fixed the training loop β added short-output filtering so the model couldn't game reward by outputting garbage, and implemented proper GRPO over all completions instead of just the best one.
|
| 122 |
+
|
| 123 |
+
**The baseline reward at step zero lifted from 2.4% to 15.2%.** The floor raised β proof the grader fixes held across runs.
|
| 124 |
+
|
| 125 |
+

|
| 126 |
+
*Run 3: baseline lifted from 2.4% to 15.2% β training loop fixed*
|
| 127 |
+
|
| 128 |
+
Every run taught us something. The environment improved itself because of what training revealed.
|
| 129 |
+
|
| 130 |
+
---
|
| 131 |
+
|
| 132 |
+
## Before vs After Training
|
| 133 |
+
|
| 134 |
+
| | Average Reward |
|
| 135 |
+
|---|---|
|
| 136 |
+
| Untrained baseline (partial obs, blind start) | 0.024 |
|
| 137 |
+
| After GRPO training (200 steps, T4) | 0.190 |
|
| 138 |
+
| **Improvement** | **+690%** |
|
| 139 |
+
|
| 140 |
+
---
|
| 141 |
+
|
| 142 |
+
## What the Agent Learned
|
| 143 |
+
|
| 144 |
+
These behaviors emerged from reward signal alone β never explicitly programmed:
|
| 145 |
+
|
| 146 |
+
- **Investigate before fixing** β learned to call `run_code` or `inspect_gradients` before attempting a fix
|
| 147 |
+
- **Tool selection by bug type** β gradient issues β `inspect_gradients` first. Crashes β `get_traceback` first
|
| 148 |
+
- **Avoid `view_source`** β learned that the traceback alone is usually enough and reading full source wastes a step
|
| 149 |
+
- **Efficiency matters** β learned to fix in fewer steps to maximize the 1.2Γ efficiency bonus
|
| 150 |
+
|
| 151 |
+
---
|
| 152 |
+
|
| 153 |
+
## The Engine Under the Hood
|
| 154 |
+
|
| 155 |
+
**Adversarial Scheduler** β tracks which bug types the agent struggles with and serves those 70% of the time with novel random seeds. The environment gets harder as the agent improves.
|
| 156 |
+
|
| 157 |
+
**LLM Judge** β after every fix, a Groq LLM scores the agent's diagnosis quality β root cause correctness and mechanistic explanation β adding up to 0.15 reasoning reward.
|
| 158 |
+
|
| 159 |
+
**Subprocess Grader** β fixed code is written to a temp file and executed with a 40-second timeout. AST checks verify structure. Output parsed for success signals. No shortcuts.
|
| 160 |
+
|
| 161 |
+
---
|
| 162 |
+
|
| 163 |
+
## Try It
|
| 164 |
+
|
| 165 |
+
```python
|
| 166 |
+
import requests
|
| 167 |
+
|
| 168 |
+
session = requests.Session()
|
| 169 |
+
BASE = "https://rak2315-ml-debug-env.hf.space"
|
| 170 |
+
|
| 171 |
+
obs = session.post(f"{BASE}/reset", json={"task_id": "shape_mismatch"}).json()["observation"]
|
| 172 |
+
print(obs["alert"]) # "Training job crashed immediately..."
|
| 173 |
+
|
| 174 |
+
result = session.post(f"{BASE}/step", json={"action": {
|
| 175 |
+
"action_type": "inspect", "tool_name": "run_code"
|
| 176 |
+
}}).json()
|
| 177 |
+
|
| 178 |
+
result = session.post(f"{BASE}/step", json={"action": {
|
| 179 |
+
"action_type": "fix",
|
| 180 |
+
"bug_type": "shape_mismatch",
|
| 181 |
+
"diagnosis": "nn.Linear input dim wrong",
|
| 182 |
+
"fixed_code": "... complete fixed script ..."
|
| 183 |
+
}}).json()
|
| 184 |
+
print(result["observation"]["grader_score"]) # 0.99
|
| 185 |
+
```
|
| 186 |
+
|
| 187 |
+
Or visit **[rak2315-ml-debug-env.hf.space/ui](https://rak2315-ml-debug-env.hf.space/ui)** to try it interactively.
|
| 188 |
+
|
| 189 |
+
---
|
| 190 |
+
|
| 191 |
+
## Links
|
| 192 |
+
|
| 193 |
+
- π€ HF Space: [rak2315-ml-debug-env.hf.space](https://rak2315-ml-debug-env.hf.space)
|
| 194 |
+
- π» GitHub: [github.com/RAK2315/ml-debug-env](https://github.com/RAK2315/ml-debug-env)
|
| 195 |
+
- π Training Notebook: [ml_debug_env_grpo_fixed.ipynb](https://github.com/RAK2315/ml-debug-env/blob/main/ml_debug_env_grpo_fixed.ipynb)
|
| 196 |
+
- π₯ YouTube: [youtu.be/TjEavKODTQQ](https://youtu.be/TjEavKODTQQ)
|
| 197 |
+
|
| 198 |
+
---
|
| 199 |
+
|
| 200 |
+
*Meta Γ PyTorch Γ Scaler OpenEnv Hackathon β April 2026*
|