Skip to content

Commit 23fd2c6

Browse files
authored
Merge pull request #1 from Leo-Expose/main
Update inference endpoint and add supporting files
2 parents 4f361f3 + 3a954ef commit 23fd2c6

8 files changed

Lines changed: 1955 additions & 3 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@ dist/
99
build/
1010
missionctrl_checkpoints/
1111
reward_curve.png
12+
.codex
13+
AGENTS.md
14+
graphify-out

colab_notebook.ipynb

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
{
2+
"nbformat": 4,
3+
"nbformat_minor": 0,
4+
"metadata": {
5+
"colab": {
6+
"provenance": [],
7+
"gpuType": "A100",
8+
"name": "MissionCtrl_Training.ipynb"
9+
},
10+
"kernelspec": {
11+
"name": "python3",
12+
"display_name": "Python 3"
13+
},
14+
"accelerator": "GPU"
15+
},
16+
"cells": [
17+
{
18+
"cell_type": "markdown",
19+
"metadata": {},
20+
"source": [
21+
"# MissionCtrl — One-Click Training Notebook\n",
22+
"\n",
23+
"**OpenEnv Hackathon Round 2**\n\n",
24+
"This notebook trains an OverseerAgent to detect hallucinations in a multi-agent fleet using GRPO + Unsloth.\n\n",
25+
"**Runtime required**: A100 GPU (HuggingFace compute credits)\n",
26+
"**Expected training time**: ~2.5 hours\n",
27+
"**Expected final reward**: 0.80+"
28+
]
29+
},
30+
{
31+
"cell_type": "code",
32+
"execution_count": null,
33+
"metadata": {},
34+
"outputs": [],
35+
"source": [
36+
"# ── Cell 1: Install dependencies ──────────────────────────────────────────────\n",
37+
"!pip install unsloth trl openenv transformers datasets accelerate matplotlib --quiet\n",
38+
"!pip install --upgrade bitsandbytes --quiet\n",
39+
"print('✅ Dependencies installed')"
40+
]
41+
},
42+
{
43+
"cell_type": "code",
44+
"execution_count": null,
45+
"metadata": {},
46+
"outputs": [],
47+
"source": [
48+
"# ── Cell 2: Clone / upload project files ─────────────────────────────────────\n",
49+
"# Option A: Clone from your repo\n",
50+
"# !git clone https://github.com/your-username/missionctrl .\n",
51+
"\n",
52+
"# Option B: Upload environment.py, reward_model.py, train.py manually\n",
53+
"# (Use the Files panel on the left in Colab)\n",
54+
"\n",
55+
"# Verify files are present\n",
56+
"import os\n",
57+
"required = ['environment.py', 'reward_model.py', 'train.py']\n",
58+
"for f in required:\n",
59+
" status = '✅' if os.path.exists(f) else '❌ MISSING'\n",
60+
" print(f' {status} {f}')"
61+
]
62+
},
63+
{
64+
"cell_type": "code",
65+
"execution_count": null,
66+
"metadata": {},
67+
"outputs": [],
68+
"source": [
69+
"# ── Cell 3: Verify GPU ────────────────────────────────────────────────────────\n",
70+
"import torch\n",
71+
"print(f'GPU: {torch.cuda.get_device_name(0)}')\n",
72+
"print(f'VRAM: {torch.cuda.get_device_properties(0).total_memory / 1e9:.1f} GB')\n",
73+
"assert torch.cuda.is_available(), 'No GPU detected — switch runtime to A100'"
74+
]
75+
},
76+
{
77+
"cell_type": "code",
78+
"execution_count": null,
79+
"metadata": {},
80+
"outputs": [],
81+
"source": [
82+
"# ── Cell 4: Smoke-test the environment ───────────────────────────────────────\n",
83+
"from environment import MissionCtrlEnv, OverseerAction\n",
84+
"from reward_model import compute_reward, reward_breakdown\n",
85+
"\n",
86+
"env = MissionCtrlEnv(difficulty='medium', num_tasks=3, seed=42)\n",
87+
"obs, info = env.reset()\n",
88+
"\n",
89+
"print('Environment smoke test:')\n",
90+
"print(f' Tasks loaded: {len(obs[\"task_board\"])}')\n",
91+
"print(f' Agent messages: {len(obs[\"recent_messages\"])}')\n",
92+
"\n",
93+
"# Test a FLAG action\n",
94+
"first_task = obs['task_board'][0]['task_id']\n",
95+
"action = OverseerAction('FLAG', task_id=first_task, evidence='fabricated citation detected')\n",
96+
"obs2, reward, terminated, truncated, info = env.step(action)\n",
97+
"print(f' Step reward: {reward:.3f}')\n",
98+
"print(f' Info: {info}')\n",
99+
"print('✅ Environment working correctly')"
100+
]
101+
},
102+
{
103+
"cell_type": "code",
104+
"execution_count": null,
105+
"metadata": {},
106+
"outputs": [],
107+
"source": [
108+
"# ── Cell 5: Run pre-training baseline ────────────────────────────────────────\n",
109+
"from train import run_baseline\n",
110+
"\n",
111+
"baseline_reward = run_baseline()\n",
112+
"print(f'\\n🎯 Baseline established: {baseline_reward:.3f}')\n",
113+
"print('This is your starting floor. Training target: 0.75+')"
114+
]
115+
},
116+
{
117+
"cell_type": "code",
118+
"execution_count": null,
119+
"metadata": {},
120+
"outputs": [],
121+
"source": [
122+
"# ── Cell 6: Set HuggingFace credentials ──────────────────────────────────────\n",
123+
"from huggingface_hub import login\n",
124+
"# Either paste your token or use the Colab secrets panel (recommended)\n",
125+
"login(token='YOUR_HF_TOKEN_HERE') # or: login() # interactive prompt\n",
126+
"\n",
127+
"# Set your repo name in train.py before running Cell 7\n",
128+
"import train\n",
129+
"train.HF_REPO = 'your-hf-username/missionctrl-overseer' # ← change this\n",
130+
"print(f'Will push to: {train.HF_REPO}')"
131+
]
132+
},
133+
{
134+
"cell_type": "code",
135+
"execution_count": null,
136+
"metadata": {},
137+
"outputs": [],
138+
"source": [
139+
"# ── Cell 7: TRAIN ─────────────────────────────────────────────────────────────\n",
140+
"# Full 3-phase curriculum with reward-gated advancement.\n",
141+
"# Watch the reward climb from ~0.31 → 0.80+\n",
142+
"from train import train\n",
143+
"\n",
144+
"history = train()\n",
145+
"print('\\n🏆 Training complete!')"
146+
]
147+
},
148+
{
149+
"cell_type": "code",
150+
"execution_count": null,
151+
"metadata": {},
152+
"outputs": [],
153+
"source": [
154+
"# ── Cell 8: Display reward curve ─────────────────────────────────────────────\n",
155+
"from IPython.display import Image\n",
156+
"Image('./missionctrl_checkpoints/reward_curve.png')"
157+
]
158+
},
159+
{
160+
"cell_type": "code",
161+
"execution_count": null,
162+
"metadata": {},
163+
"outputs": [],
164+
"source": [
165+
"# ── Cell 9: Before/After demo comparison ─────────────────────────────────────\n",
166+
"# Load trained model and compare with baseline behavior\n",
167+
"from unsloth import FastLanguageModel\n",
168+
"from environment import MissionCtrlEnv, parse_action\n",
169+
"from train import build_user_prompt, SYSTEM_PROMPT\n",
170+
"import torch\n",
171+
"\n",
172+
"model, tokenizer = FastLanguageModel.from_pretrained(\n",
173+
" './missionctrl_checkpoints/final',\n",
174+
" max_seq_length=4096,\n",
175+
" load_in_4bit=True,\n",
176+
")\n",
177+
"FastLanguageModel.for_inference(model)\n",
178+
"\n",
179+
"# Use a known hallucinated episode (seed 0, hard difficulty)\n",
180+
"env = MissionCtrlEnv(difficulty='hard', num_tasks=4, seed=0)\n",
181+
"obs, _ = env.reset()\n",
182+
"\n",
183+
"prompt = tokenizer.apply_chat_template(\n",
184+
" [\n",
185+
" {'role': 'system', 'content': SYSTEM_PROMPT},\n",
186+
" {'role': 'user', 'content': build_user_prompt(obs)},\n",
187+
" ],\n",
188+
" tokenize=False,\n",
189+
" add_generation_prompt=True,\n",
190+
")\n",
191+
"inputs = tokenizer(prompt, return_tensors='pt', truncation=True, max_length=3584).to(model.device)\n",
192+
"\n",
193+
"with torch.no_grad():\n",
194+
" out = model.generate(**inputs, max_new_tokens=256, temperature=0.1, do_sample=True)\n",
195+
"\n",
196+
"completion = tokenizer.decode(out[0][inputs['input_ids'].shape[1]:], skip_special_tokens=True)\n",
197+
"\n",
198+
"print('=== TRAINED MODEL OUTPUT ===')\n",
199+
"print(completion)\n",
200+
"print(f'\\nParsed action: {parse_action(completion)}')"
201+
]
202+
},
203+
{
204+
"cell_type": "code",
205+
"execution_count": null,
206+
"metadata": {},
207+
"outputs": [],
208+
"source": [
209+
"# ── Cell 10: Final evaluation run ────────────────────────────────────────────\n",
210+
"from train import evaluate\n",
211+
"\n",
212+
"final_reward, metrics = evaluate(model, tokenizer, difficulty='hard', num_tasks=4, n_episodes=20)\n",
213+
"\n",
214+
"print('\\n=== FINAL EVALUATION SUMMARY ===')\n",
215+
"print(f' Overall reward: {metrics[\"mean_reward\"]:.3f} ± {metrics[\"std_reward\"]:.3f}')\n",
216+
"print(f' Detection rate: {metrics[\"mean_detect_rate\"]:.1%}')\n",
217+
"print(f' False positive rate: {metrics[\"mean_fp_rate\"]:.1%}')"
218+
]
219+
}
220+
]
221+
}

0 commit comments

Comments
 (0)