CoolFace
Apppublic

versokuro/mechinterp-env

sourceHugging Faceupdated 6mo agoView on Hugging Face
1likes
App README

๐Ÿ”ฌ mechinterp-env

Finding a circuit in a transformer is like locating a faulty transistor in a running CPU using only a voltmeter. It takes human researchers weeks of careful activation patching. mechinterp-env is the training ground to automate this โ€” we trap an AI agent inside a toy transformer with a mathematically planted circuit, hand it the tools of mechanistic interpretability, and force it to perform neurosurgery on the model.

The first RL environment where agents learn to debug transformer circuits โ€” built on toy models with known ground-truth circuits, so every score is provably correct.

Built for the OpenEnv AI Hackathon 2026 (Meta ร— Hugging Face ร— PyTorch).


What the Agent Actually Sees

Circuit Visualization

Left: The circuit head (H2) concentrates all attention on the RED token โ€” copying it perfectly. Middle: A noise head spreads attention uniformly โ€” no structured information flow. Right: The ablation evidence an agent uses to identify the circuit โ€” ablating H2 causes a -1.0 behavioral collapse. Ablating noise heads: zero effect.


How It Works

                    THE SURGICAL LOOP
                    โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

[reset(task_id)]
      โ”‚
      โ–ผ
Agent receives:
  โ€ข target_behavior  โ€” "This head copies a token. Find it."
  โ€ข available_actions โ€” ablate_head, patch_activation, query_logit_lens...
  โ€ข prerun_results   โ€” (Task 1 only) ablation results already computed
      โ”‚
      โ–ผ
[Agent Action: ablate_head(layer=0, head=2)]
      โ”‚
      โ–ผ
Environment runs forward pass with H2 zeroed out
      โ”‚
      โ–ผ
[Observation returned]:
  โ€ข behavioral_delta: -1.0000  โ† H2 is CRITICAL
  โ€ข baseline_prob:     0.9999
  โ€ข ablated_prob:      0.0000
  โ€ข interpretation:   "IMPORTANT โ€” likely circuit component"
      โ”‚
      โ–ผ
[Reward: +0.40]  โ† Information gain: |delta| ร— 0.3 + high-delta bonus
      โ”‚
      โ–ผ
Agent ablates more heads, finds delta โ‰ˆ 0.0 for all others
      โ”‚
      โ–ผ
[Agent Action: submit_hypothesis({"(0, 2)": 1.0})]
      โ”‚
      โ–ผ
[Grader: F1 against ground truth] โ†’ score=0.999
[END] success=true steps=1 score=0.999

The Three Planted Circuits

Each task uses a different transformer model with a mathematically designed circuit. Ground truth is known by construction โ€” we built the weights.

Induction Circuit

Task 2's two-head induction circuit: L0H1 (lookup head) concentrates attention on the signal token, writes its identity into dims 17-32. L1H2 (transcode head) reads that signal via K-composition and converts it to the target token. Ablating either head collapses the behavior entirely.

Task 1 โ€” Copy Head (Easy)

Model1 layer, 4 heads, d=64
Circuit{(0, 2): 1.0} โ€” single copy head
BehaviorModel copies key token from position 2 to final position
Agent taskRead pre-run ablation results, identify the head with delta=-1.0, submit
Budget4 steps
Why it's easyAnswer is in the initial observation. Tests reading comprehension of MI evidence.

Task 2 โ€” Induction Circuit (Medium)

Model2 layers, 4 heads each, d=64
Circuit{(0, 1): 0.6, (1, 2): 1.0} โ€” two-head composition
BehaviorL0H1 writes signal token identity โ†’ L1H2 transcodes it to target
Agent taskDesign and run ablation experiments across 8 heads, identify the 2-head circuit
Budget12 steps
Why it's mediumNo pre-run results. Agent must plan experiments and reason across layers.

Task 3 โ€” Committee Circuit (Hard)

Model4 layers, 8 heads each, d=64
Circuit{(0,3):0.7, (1,1):0.8, (1,5):0.6, (2,2):1.0, (3,6):0.9} โ€” 5 heads
Behavior5 independent heads each contribute a fraction of the output signal
Agent taskNavigate a 32-head search space strategically, identify all 5 circuit heads
Budget20 steps (can't ablate everything โ€” must prioritize)
Why it's hardLarge search space, strategic exploration required, partial credit via weighted F1

Ablation Deltas

Ablation deltas across all three tasks. Circuit heads (red) cause catastrophic behavioral collapse when removed. Noise heads (gray) have exactly zero effect. The signal is clean โ€” this is what real MI research looks like.


Reward Function

Dense reward โ€” the agent gets signal at every step, not just at the end.

Step-level rewards

ComponentFormulaRationale
Information gain`\behavioral_delta\ร— 0.3`Rewards ablations that reveal something real
High-delta bonus+0.10 if delta < -0.35Extra reward for identifying clearly important heads
Redundancy penalty-0.10 per re-queried headPunishes aimless repetition
Efficiency penalty-0.05 per step after step 8Encourages decisive behavior

Terminal reward (on submit_hypothesis)

ComponentValueCondition
Circuit F1 ร— 2.00 โ€“ 2.0Primary signal โ€” how correct is your circuit?
Speed bonus+0.30F1 โ‰ฅ 0.8 AND steps โ‰ค budget/2
Attempt bonus+0.05Always โ€” reward for submitting vs timing out
Normalizedรท 2.35 โ†’ (0, 1)Perfect fast solve = 0.999

Calibration: Random agent โ‰ˆ 0.05 avg reward. Systematic agent โ‰ˆ 0.35. Agent understanding MI workflow โ‰ˆ 0.75+.


Frontier Model Baselines

Tested with Qwen/Qwen2.5-72B-Instruct via the HF inference router:

TaskScoreStepsNotes
head-identification (Easy)0.9991Identified H2 immediately from pre-run results
circuit-localization (Medium)0.9999Systematic ablation found both circuit heads
full-hypothesis (Hard)0.35 โ€“ 0.4520Partial โ€” found 2-3 of 5 circuit heads before budget

The difficulty progression is genuine. Hard tasks are actually hard.


Action Space

ActionJSONWhat it does
ablate_head{"action_type": "ablate_head", "layer": 0, "head": 2}Zero out head. Measures how critical it is.
patch_activation{"action_type": "patch_activation", "layer": 1, "head": 2, "position": 3, "source_prompt_id": 1}Replace activation with corrupted source.
query_logit_lens{"action_type": "query_logit_lens", "layer": 1, "position": -1}See model's intermediate token predictions.
query_attn_pattern{"action_type": "query_attn_pattern", "layer": 0, "head": 1, "prompt_id": 0}View full attention weight matrix.
submit_hypothesis{"action_type": "submit_hypothesis", "circuit_mask": {"components": {"(0, 2)": 1.0}}}Terminal. Triggers grader. Ends episode.

Grading

All graders are deterministic โ€” no LLM, no randomness. Same hypothesis always gets the same score.

TaskMethodPerfect Score
Task 1Exact match (0.999) + partial layer credit (0.5)0.999
Task 2Standard F1 on circuit head set (threshold 0.3)0.999
Task 3Weighted F1 โ€” important heads (L2H2 at 1.0) count more0.999

Why Toy Transformers?

This is how mechanistic interpretability research actually bootstraps. Elhage et al. (2021), Olsson et al. (2022), Wang et al. (2022) โ€” all foundational MI papers start with toy models where ground truth is provable by construction.

Advantages over cached GPT-2 activations:

  • โ€”โœ… Ground truth is mathematically exact โ€” not approximate
  • โ€”โœ… No GPU, no PyTorch, no TransformerLens โ€” pure numpy
  • โ€”โœ… Docker image is tiny โ€” no 500MB activation cache files
  • โ€”โœ… Microsecond forward passes โ€” well within 20-minute budget
  • โ€”โœ… Perfect determinism โ€” same input always gives same score

Real-World Utility

MI circuit discovery is bottlenecked by researcher time. A senior MI researcher spends days to weeks localizing a single circuit. An RL agent trained on this environment is a step toward automating that โ€” a research assistant that can run activation patching experiments, form hypotheses, and narrow down circuit components autonomously.

This environment serves as a curriculum: start with provably correct ground truth on toy models, then scale to real models with activation caches. The architecture already supports this.

The target community: Anthropic, DeepMind, EleutherAI, and every independent MI researcher would have direct use for an agent trained on this environment.


Setup

Quick start

bash
git clone https://github.com/ChoudharyDeven/mechinterp-env
cd mechinterp-env
pip install numpy fastapi uvicorn pydantic httpx openai
python verify_tasks.py        # 46/46 checks passed
uvicorn server.app:app --host 0.0.0.0 --port 7860

Test it

bash
curl http://localhost:7860/health
curl -X POST http://localhost:7860/reset \
     -H "Content-Type: application/json" \
     -d '{"task_id": "head-identification"}'

Docker

bash
docker build -t mechinterp-env .
docker run -p 7860:7860 mechinterp-env

Run inference

bash
export MECHINTERP_ENV_URL=https://potatochoudhary-mechinterp-env.hf.space
export HF_TOKEN=your_hf_token
export API_BASE_URL=https://router.huggingface.co/v1
export MODEL_NAME=Qwen/Qwen2.5-72B-Instruct
python inference.py

Environment Variables

VariableRequiredDefaultDescription
HF_TOKENYesโ€”Hugging Face API token
API_BASE_URLNohttps://router.huggingface.co/v1LLM endpoint
MODEL_NAMENoQwen/Qwen2.5-72B-InstructModel for inference
MECHINTERP_ENV_URLYes (inference)http://localhost:7860Space URL

Project Structure

mechinterp-env/
โ”œโ”€โ”€ inference.py              โ† Baseline inference script (mandatory)
โ”œโ”€โ”€ openenv.yaml              โ† OpenEnv manifest
โ”œโ”€โ”€ models.py                 โ† Pydantic types: Action, Observation, CircuitMask
โ”œโ”€โ”€ client.py                 โ† Python client (async + sync)
โ”œโ”€โ”€ verify_tasks.py           โ† 46-check verification script
โ”œโ”€โ”€ Dockerfile
โ”œโ”€โ”€ server/
โ”‚   โ”œโ”€โ”€ app.py                โ† FastAPI: /reset /step /state /health
โ”‚   โ”œโ”€โ”€ environment.py        โ† Core logic: reset(), step(), action handlers
โ”‚   โ”œโ”€โ”€ transformer.py        โ† Numpy transformer engine
โ”‚   โ”œโ”€โ”€ tasks.py              โ† Task definitions + ground truth circuits
โ”‚   โ”œโ”€โ”€ graders.py            โ† Deterministic graders (no LLM)
โ”‚   โ””โ”€โ”€ rewards.py            โ† Dense reward function
โ””โ”€โ”€ data/
    โ”œโ”€โ”€ models/
    โ”‚   โ”œโ”€โ”€ model_1layer.py   โ† 1L copy head (d=64)
    โ”‚   โ”œโ”€โ”€ model_2layer.py   โ† 2L induction circuit (d=64)
    โ”‚   โ””โ”€โ”€ model_4layer.py   โ† 4L committee circuit (d=64)
    โ””โ”€โ”€ circuits/
        โ”œโ”€โ”€ circuit_1.json    โ† {"(0, 2)": 1.0}
        โ”œโ”€โ”€ circuit_2.json    โ† {"(0, 1)": 0.6, "(1, 2)": 1.0}
        โ””โ”€โ”€ circuit_3.json    โ† 5-head ground truth

OpenEnv Spec Compliance

  • โ€”โœ… Typed Action, Observation Pydantic models
  • โ€”โœ… step(action) โ†’ (observation, reward, done, info)
  • โ€”โœ… reset() โ†’ initial observation
  • โ€”โœ… state() โ†’ current state
  • โ€”โœ… openenv.yaml with 3 tasks and grader definitions
  • โ€”โœ… Passes openenv validate
  • โ€”โœ… Docker build clean, port 7860
  • โ€”โœ… Phase 1 + Phase 2 passed

References

  • โ€”Elhage et al. (2021) โ€” A Mathematical Framework for Transformer Circuits
  • โ€”Olsson et al. (2022) โ€” In-context Learning and Induction Heads
  • โ€”Wang et al. (2022) โ€” Interpretability in the Wild: a Circuit for Indirect Object Identification in GPT-2 small
  • โ€”Conmy et al. (2023) โ€” Towards Automated Circuit Discovery for Mechanistic Interpretability

License

MIT