Spaces:
Runtime error
Runtime error
Commit History
-
feat: add support for lowercase Hugging Face Space secrets
63726b6 -
Submission-ready: README, blog, training pipeline, baseline evidence, OpenEnv compliance
7a90355 -
fix(grpo): Unsloth inference-mode swap + smaller LoRA + KV cleanup (T4 OOM #2)
Episode generation was silently leaking ~7 GB of VRAM per pair of episodes because the model stayed in train mode with use_gradient_checkpointing= "unsloth" during all rollout calls. Even under torch.no_grad(), the checkpointing hooks pre-allocated activation buffers that were never released between Doctor turns. By the time GRPO update fired, 14.34 GiB were pinned and the first forward couldn't allocate even 24 MiB. Fixes (all needed together): 1. FastLanguageModel.for_inference(model) before each rollout group; for_training(model) before manual_grpo_step. This is Unsloth's intended pattern for switching between modes within one process. 2. lora_dropout: 0.05 -> 0.0. Any non-zero dropout disables Unsloth's fused LoRA kernels and roughly doubles peak activation VRAM. 3. LoRA target_modules: drop MLP (gate/up/down) projections, attention only. Cuts trainable params from ~45 M to ~17 M and AdamW state from 360 MB to 130 MB. 4. generate_doctor_action: max_new_tokens 25…a3804d9 -
fix(grpo): per-step backward to bound VRAM during update (T4 OOM fix)
Root cause of the recurrent CUDA OOM during the first GRPO update: the loss was summed across all (prompt, response) pairs in the group BEFORE a single backward(), which kept every forward pass's activation graph alive in VRAM simultaneously. With group_size=2 x ~20 steps each = ~40 forward graphs, peak VRAM on the 8B 4-bit + LoRA model exceeded the T4's 14.56 GiB and backward() OOM'd before producing any gradient. Fix: scale each step's loss by 1/n_steps_total and call backward() immediately. Gradients accumulate correctly in .grad while each forward's graph is released before the next forward begins. One optimizer.step() at the end with grad_clip applied, exactly as before. Also: - gc.collect() + torch.cuda.empty_cache() between groups - best-effort recovery if a single update OOMs (zero grads, empty cache) - set PYTORCH_ALLOC_CONF before the first torch import in clean_launch.py - assert the new per-step backward patch is live before launch Made-with: Cursor8f20926 -
feat(kaggle): add clean_launch.py + shrink budget to 20/25/30 = 75 eps
Made-with: Cursorcd923aa
-
feat(kaggle): default to fixed-budget curriculum 20/30/50 episodes
Made-with: Cursor69f89ec -
fix(grpo): skip reference model when kl_beta=0 to save 5GB VRAM on T4
Made-with: Cursor0566783 -
fix(kaggle): align pip-managed numpy with kernel's loaded numpy
Symptom: Cell 5 (post-restart verify) blew up with RuntimeError: numpy was upgraded mid-session (loaded: 2.4.4, installed: 2.4.3) because Kaggle ships numpy 2.4.4 at /usr/lib/python3/dist-packages while pip writes to /usr/local/lib/python3.12/dist-packages — and torch's cu128 install pulled numpy 2.4.3 as a transitive dep into the latter. unsloth_zoo's startup does a strict string-equality check between `numpy.__version__` (loaded via Python's import path priority) and importlib.metadata.version("numpy") (reads pip records) and bails on any mismatch, even patch-level. Fix in REPAIR cell: * Detect the kernel's actual loaded numpy version up front and append `numpy=={detected}` to the pip constraints file, so unsloth/trl/bnb cannot resolve a different one. * Add a 5b realign step that does pip install --force-reinstall --no-deps numpy=={detected} to overwrite whatever pip put in /usr/local/lib with the version the kernel actually loads. After this, importlib.met…27cf9cd -
fix(kaggle): pin torch via constraints file in REPAIR cell
Step [3/6] (`pip install --force-reinstall bitsandbytes`) and step [4/6] (`unsloth unsloth_zoo trl`) were re-resolving torch from default PyPI, which is currently torch 2.11.0. That clobbered the cu128 torch 2.10.0 installed in step [2/6], producing: torchvision 0.25.0+cu128 requires torch==2.10.0, but you have torch 2.11.0 which is incompatible. Fix: * Write `/tmp/ermap_constraints.txt` immediately after step 2 pinning `torch==2.10.0 / torchvision==0.25.0`. * Step 3 (bnb) now uses `--no-deps` (bnb dlopens torch at runtime, so install-time deps are unnecessary). * Steps 4 + 5 pass `-c /tmp/ermap_constraints.txt` so pip can never upgrade torch out from under us, regardless of what unsloth or trl declare in their requirement lists. Made-with: Cursor112679c -
fix(kaggle): escape backslash-n in REPAIR cell separator print
Cell 3 of the rebuilt notebook contained `print("\n" + "=" * 72)` whose `\n` was interpreted by Python's triple-quoted string at build time, so the resulting notebook source was split across two lines: 118 | print(" 119 | " + "=" * 72) which Kaggle rejected with `SyntaxError: unterminated string literal`. Use `\\n` to keep the escape literal in the generated cell source, matching the other four print statements that already do this. AST-validates all 15 code cells after regeneration. Made-with: Cursor04688c1 -
chore(kaggle): rebuild notebook v3 + clean dev-scratch files
* New `kaggle/build_notebook.py` - single source of truth that regenerates the Kaggle notebook + KAGGLE_QUICKSTART.md from scratch (run once whenever the layout drifts). * New `kaggle/KAGGLE_QUICKSTART.md` - concise step-by-step run order with troubleshooting table for every dependency-hell symptom we hit. * `kaggle/train_ermap_grpo_kaggle.ipynb` rebuilt as a clean 20-cell layout: - new constant per-phase reward thresholds (P1=+1.2 / P2=+1.1 / P3=+1.0) - idempotent REPAIR cell (pins torch 2.10 cu128 + bnb + unsloth/zoo + trl, verifies in a subprocess so the kernel never gets poisoned mid-install) - pre-flight Groq routing + PING smoke test using router._models / _clients - explicit dry-run + HF-push hook + per-phase dashboards + final push. * `train_grpo.py`: add optional `phase_episode_budgets` (fixed-budget curriculum mode) alongside the existing reward-threshold early-stop. Fully backward compatible (default behaviour unchanged); CLI flags --phase{1,2,3}-budg…2df5c63 -
fix(kaggle): unpin torch and loosen trl floor to prevent bnb/unsloth break
71a0a91 -
kaggle: unpin unsloth, install matched zoo pair
Fixes the import error users hit on a fresh Kaggle session: ImportError: cannot import name 'create_gradient_checkpointing_buffer' from 'unsloth_zoo.gradient_checkpointing' Root cause: kaggle/requirements_kaggle.txt pinned `unsloth==2024.12.4` (Dec 2024) while leaving `unsloth_zoo` unpinned, so pip happily paired a year-old unsloth with whatever fresh zoo build it pulled this morning. The two are released as a matched pair, so the fresh zoo no longer exports symbols the old unsloth imports at module-load time. Fix: - Drop the unsloth==2024.12.4 pin; require unsloth>=2025.3.0 - Add unsloth_zoo>=2025.3.0 as an EXPLICIT requirement so pip resolves both in one pass against the same wheel index - Add --upgrade to the install cell so both packages always end up at the latest compatible pair, even when Kaggle's pre-baked layer caches an old unsloth - Print both versions in the sanity check (was just unsloth) - Inline-document the manual recovery command for users who hit the err…2e98419 -
kaggle: refresh cell-8 promotion timing for per-phase early-stop
The cell-8 markdown still advertised the OLD pre-early-stop wall-clock (Phase 1 -> 2 promotion at episode 30-60, "6-10 min per GRPO update"). Under the new per-phase reward bars (1.5 / 1.2 / 1.0 sustained x 3 groups), promotion fires much earlier: - Phase 1 -> 2 force-promote: episode 16-30 (was 30-60) - Phase 2 -> 3 force-promote: episode 40-70 (new line) - Phase 3 EARLY STOP: episode 70-130 (new line) Also corrected per-update cost: 1-2 min amortized (not 6-10 min; that figure conflated the whole group with just the GRPO step) and the section title timing (6-11 h, not 8-12 h). No code changes; cell sources untouched. Notebook JSON validates. Made-with: Cursorc64ec55 -
train: per-phase reward thresholds for early-stop
Replace the single global TARGET_ROLLING_REWARD with per-phase reward bars that drive both forced promotion (P1, P2) and final termination (P3). The phases are not equally easy to score on (P1 wins ~+2.0, P3 wins ~+1.4 after empathy/consent costs), so a single global bar either gates P3 too aggressively or passes P1 with garbage P2 behaviour. New behaviour: - P1 sustains rolling-avg-reward >= +1.5 for 3 consecutive groups -> CurriculumScheduler.force_promote() to P2 (buffer cleared so stale P1 entries cannot pre-satisfy the P2 check). - P2 sustains >= +1.2 for 3 groups -> force_promote() to P3. - P3 sustains >= +1.0 for 3 groups -> END TRAINING. - Soft PHASE_MIN_WIN_RATE=0.20 floor prevents stopping on partial- credit-only groups. - CONVERGENCE_WINDOW=3 (was 5). API changes in train_grpo.train(): - Removed: target_rolling_reward, target_win_rate, convergence_min_phase - Added: phase_reward_targets: Dict[int, float] (default {1: 1.5, …d490143 -
kaggle: lower convergence bar to +1.2 reward (3.1x baseline P3)
Made-with: Cursor13ae8dd -
kaggle: route Patient + Nurse to 8B-instant pool
d8c3b18 -
kaggle: 8B Doctor + train-until-optimal early-stop
Replaces hardcoded demo Groq/ElevenLabs keys with a git-ignored .env loader; adds .gitignore and .env.example so secrets never land in git. Made-with: Cursor9c68ba6