Team Ai
Apppublic

an8136/pytorch-triage-env

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
App README
OpenEnv Hackathon 2026 โ€” A PyTorch Training Infrastructure Triage RL Environment

![OpenEnv](https://huggingface.co/spaces/an8136/pytorch-triage-env) ![HuggingFace Space](https://huggingface.co/spaces/an8136/pytorch-triage-env) ![Python](https://python.org) ![Docker](Dockerfile)

An LLM agent acts as a Staff ML Infrastructure Engineer debugging real production PyTorch training failures. It reads virtual files, edits code, runs mock training (generating authentic PyTorch error traces), and submits a verified fix with a deep technical explanation.


Architecture

mermaid
flowchart TD
    subgraph AGENT ["๐Ÿค– Inference Agent (inference.py)"]
        A1[make_llm_client] --> A2[preflight_llm_test]
        A2 --> A3[warmup_env]
        A3 --> A4[run_episode loop]
        A4 --> A5[get_action via LLM]
        A5 --> A4
    end

    subgraph LLM ["โ˜๏ธ LLM Proxy"]
        L1[HuggingFace Router\nrouter.huggingface.co/v1]
        L2[Qwen/Qwen2.5-72B-Instruct]
        L1 --> L2
    end

    subgraph SERVER ["๐Ÿ–ฅ๏ธ FastAPI Server (port 7860)"]
        S1[POST /reset] --> E1
        S2[POST /step] --> E1
        S3[GET /health]
        S4[GET /state]
        S5[GET /schema]

        subgraph ENV ["PyTorchTriageEnv"]
            E1[environment.py] --> E2[VirtualFilesystem]
            E1 --> E3[MockExecutionEngine]
            E1 --> E4[Rubrics]

            E2[virtual_fs.py\nIn-memory files\nGit diff tracking]
            E3[mock_execution_engine.py\nPre-written error traces\n4 task scenarios]
            E4[rubrics.py\nTrajectoryRubric\nLLMJudgeRubric]
        end
    end

    subgraph TASKS ["๐Ÿ“‹ 4 Debug Tasks"]
        T1["oom_graph_leak\n(easy)"]
        T2["fsdp_collective_deadlock\n(medium)"]
        T3["compile_graph_break\n(medium)"]
        T4["ddp_gradient_hang\n(hard)"]
    end

    A5 -->|JSON action| SERVER
    SERVER -->|observation + reward| A5
    A5 <-->|API calls| LLM
    E1 --> TASKS

Data Flow

mermaid
sequenceDiagram
    participant Agent as ๐Ÿค– inference.py
    participant Proxy as โ˜๏ธ LLM Proxy
    participant Env as ๐Ÿ–ฅ๏ธ FastAPI /reset /step
    participant FS as ๐Ÿ“ VirtualFS
    participant Engine as โš™๏ธ MockEngine
    participant Judge as ๐Ÿ† LLMJudge

    Agent->>Proxy: preflight_llm_test() โ€” READY
    Proxy-->>Agent: "READY"
    Agent->>Env: POST /reset {task: "oom_graph_leak"}
    Env->>FS: initialize virtual files
    Env-->>Agent: observation (task_description, files, instructions)

    loop Each Step (up to max_steps)
        Agent->>Proxy: build_prompt(obs) โ†’ get_action()
        Proxy-->>Agent: {"action_type": "execute_bash", ...}
        Agent->>Env: POST /step {action}
        alt execute_bash
            Env->>Engine: run(command, task)
            Engine-->>Env: authentic error trace / success output
        else edit_file
            Env->>FS: apply string replacement
        else read_file
            Env->>FS: return file content
        else submit_fix
            Env->>Judge: score explanation (keyword heuristic / LLM)
            Judge-->>Env: 0.0 โ€“ 1.0 quality score
        end
        Env-->>Agent: {observation, reward, done}
    end

Tasks

TaskDifficultyMax StepsRoot CauseFix
oom_graph_leakEasy8epoch_loss += loss retains computation graph across batches โ†’ CUDA OOMUse loss.item() to detach
fsdp_collective_deadlockMedium9all_reduce inside if rank == 0 โ€” only rank 0 calls it, others hangMove collective ops outside rank conditionals
compile_graph_breakMedium10Data-dependent Python branch forces Dynamo to eager mode โ†’ recompilation overheadAdd @torch.compiler.disable to problematic function
ddp_gradient_hangHard9Conditional auxiliary head used every 5th step โ†’ unused params โ†’ DDP hangs on gradient syncSet find_unused_parameters=True in DDP wrapper

Action Space

Agents interact via JSON actions sent to POST /step:

json
// Read a file
{"action_type": "read_file", "filename": "train.py"}

// Edit a file (old_str must match exactly)
{"action_type": "edit_file", "filename": "train.py", "old_str": "epoch_loss += loss", "new_str": "epoch_loss += loss.item()"}

// Run a command
{"action_type": "execute_bash", "command": "python train.py"}

// View git diff
{"action_type": "view_git_diff", "filename": null}

// Submit fix with deep explanation
{"action_type": "submit_fix", "explanation": "The root cause is X because Y. The fix works because Z."}

Available files: train.py, model.py, config.py, data_loader.py


Reward System

Dense per-step rewards:
  +0.08  reading signal files (train.py, model.py)
  +0.12  correct diagnostic flags detected
  +0.05  running training (execute_bash)
  +0.05  file edits
  -0.08  syntax errors introduced

Terminal reward (on submit_fix):
  up to 1.0 ร— LLMJudge score

  "I changed X to Y"                    โ†’ 0.3
  "Root cause is A because B; fix C"    โ†’ 0.7
  "Root cause + mechanism + prevention" โ†’ 1.0

Score range: strictly (0.001, 0.999) โ€” open interval required by validator

Project Structure

pytorch_triage_env/           # Installable Python package
โ”œโ”€โ”€ __init__.py
โ”œโ”€โ”€ openenv.yaml              # OpenEnv spec definition (RFC 004)
โ”œโ”€โ”€ pyproject.toml
โ”œโ”€โ”€ Dockerfile                # Port 7860
โ”œโ”€โ”€ README.md
โ””โ”€โ”€ server/
    โ”œโ”€โ”€ __init__.py
    โ”œโ”€โ”€ app.py                # FastAPI server โ€” /reset /step /state /health /schema
    โ”œโ”€โ”€ environment.py        # PyTorchTriageEnv โ€” reset() step() state property
    โ”œโ”€โ”€ virtual_fs.py         # In-memory file system with git diff tracking
    โ”œโ”€โ”€ mock_execution_engine.py  # 4 task scenarios with authentic PyTorch traces
    โ”œโ”€โ”€ rubrics.py            # TrajectoryRubric + LLMJudgeRubric scoring
    โ”œโ”€โ”€ models.py             # Pydantic v2 discriminated union action models
    โ””โ”€โ”€ requirements.txt

inference.py                  # Baseline LLM agent (repo root โ€” required by validator)
tests/
โ”œโ”€โ”€ test_engine.py
โ”œโ”€โ”€ test_rubrics.py
โ”œโ”€โ”€ test_environment.py
โ””โ”€โ”€ test_server.py

Setup & Installation

Requirements

  • โ€”Python 3.11+
  • โ€”Docker (optional, for containerized deployment)

Install

bash
# Clone the repo
git clone https://github.com/AkankshaNarula/pytorch-triage-env.git
cd pytorch-triage-env

# Install the package
cd pytorch_triage_env && pip install -e . && cd ..

Run the Server

bash
# Start the FastAPI server
uvicorn pytorch_triage_env.server.app:app --port 7860

# Or with Docker
docker build -f pytorch_triage_env/Dockerfile -t pytorch-triage-env ./pytorch_triage_env
docker run -p 7860:7860 pytorch-triage-env

Run the Agent

bash
export HF_TOKEN=hf_your_token_here
export MODEL_NAME=Qwen/Qwen2.5-72B-Instruct
export ENV_URL=http://localhost:7860   # or https://an8136-pytorch-triage-env.hf.space

python inference.py

Environment Variables

VariableRequiredDefaultDescription
HF_TOKENYesnoneHuggingFace API token (injected by validator)
API_BASE_URLNohttps://router.huggingface.co/v1LiteLLM proxy endpoint
MODEL_NAMENoQwen/Qwen2.5-72B-InstructModel identifier
ENV_URLNohttps://an8136-pytorch-triage-env.hf.spaceEnvironment server URL
LOCAL_IMAGE_NAMENononeDocker image name (optional)

Testing

bash
# Level 1: Unit tests (no server needed)
python tests/test_engine.py
python tests/test_rubrics.py

# Level 2: Environment logic tests
python tests/test_environment.py

# Level 3: Full server integration tests
uvicorn pytorch_triage_env.server.app:app --port 7860 &
sleep 3
ENV_URL=http://localhost:7860 python tests/test_server.py

# Level 4: Full agent run
export HF_TOKEN=your_token
ENV_URL=http://localhost:7860 python inference.py

# Level 5: OpenEnv validation
cd pytorch_triage_env && openenv validate && cd ..

API Reference

EndpointMethodDescription
/healthGETServer health check โ†’ {"status": "ok"}
/schemaGETOpenEnv schema (from openenv.yaml)
/resetPOSTStart a new episode: {"task": "oom_graph_leak"}
/stepPOSTTake an action: {"action_type": "...", ...}
/stateGETCurrent episode state

Observation Space

Each step returns an observation with:

json
{
  "task_name": "oom_graph_leak",
  "task_description": "Incident report...",
  "terminal_output": "CUDA out of memory...",
  "current_files": {"train.py": "..."},
  "run_status": "failing",
  "system_status": "training_failed",
  "step_number": 2,
  "max_steps": 8,
  "budget_remaining": 6,
  "actions_taken": ["execute_bash"],
  "hint": null,
  "instructions": "Strategy guide for this task...",
  "done": false,
  "reward": 0.05
}

After 3+ failed runs, a hint field is populated with a diagnostic clue.


How the Baseline Agent Works

inference.py implements a simple but effective debugging loop:

  1. 1.Pre-flight test โ€” makes one guaranteed API call through the LLM proxy at startup
  2. 2.Env warm-up โ€” polls /health for up to 120s (handles HuggingFace Space cold-starts)
  3. 3.Episode loop โ€” for each task:
  4. 4.Reset the environment
  5. 5.Ask the LLM for the next action (JSON)
  6. 6.Submit the action, observe the result
  7. 7.Repeat until done=True or max_steps reached
  8. 8.Scoring โ€” scores clamped to open interval (0.001, 0.999) per validator spec

The system prompt guides the LLM through a execute_bash โ†’ read_file โ†’ edit_file โ†’ execute_bash โ†’ submit_fix workflow with emphasis on deep technical explanations (which the LLM judge rewards with higher scores).


Baseline Scores

Scores measured by running the oracle (optimal) agent locally against the mock environment. The oracle takes the known-correct fix actions for each task in minimal steps.

TaskDifficultyMax StepsOracle StepsOracle ScoreFix Verified
oom_graph_leakEasy850.999โœ…
fsdp_collective_deadlockMedium950.999โœ…
compile_graph_breakMedium1060.999โœ…
ddp_gradient_hangHard960.999โœ…
Mean5.50.999
Oracle score = perfect agent that knows the exact fix. A real LLM agent (Phase 2 evaluation) is expected to score lower due to exploration steps, imprecise edits, and explanation quality variance.

Phase 2 Evaluation โ€” What the judges run

In Phase 2, the hackathon judges run a standard Open LLM agent (e.g. Nemotron Super 49B) against your environment with no task-specific tuning. Your environment needs to be solvable by a general-purpose agent, not just your own baseline.

How to simulate Phase 2 locally โ€” swap MODEL_NAME for any model the judge might use:

bash
export HF_TOKEN=hf_yourtoken
export MODEL_NAME=nvidia/Llama-3_1-Nemotron-51B-Instruct   # judge's model
export ENV_URL=http://localhost:7860

python inference.py

What makes an environment score well in Phase 2:

  • โ€”The LLM can read the error trace and understand what's wrong (clear task_description + authentic traces)
  • โ€”The file edit old_str is a short, unambiguous, exact-match string (easier for an LLM to quote correctly)
  • โ€”After a correct fix, run_status flips to passing immediately (clear reward signal)
  • โ€”The hint field (appears after 3 failed runs) guides a stuck agent toward the fix
  • โ€”submit_fix explanations are scored on depth โ€” a brief explanation still gets partial credit (0.3+)

Expected Phase 2 score range (general LLM, no fine-tuning): 0.40 โ€“ 0.75 per task depending on model reasoning quality. The gap between oracle (0.999) and a general agent represents the exploration + explanation quality challenge.


Live Demo

๐Ÿค— HuggingFace Space: https://huggingface.co/spaces/an8136/pytorch-triage-env

๐Ÿ™ GitHub: https://github.com/AkankshaNarula/pytorch-triage-env


License

MIT License โ€” see LICENSE for details.


Built for the OpenEnv Hackathon 2026 โ€” deadline April 12, 2026