Skip to content

bench/lora: RunPod warm-agent LoRA runbook + training script#98

Merged
madmax983 merged 2 commits into
mainfrom
lora-runbook
Jul 16, 2026
Merged

bench/lora: RunPod warm-agent LoRA runbook + training script#98
madmax983 merged 2 commits into
mainfrom
lora-runbook

Conversation

@madmax983

Copy link
Copy Markdown
Owner

Refs #83

Before / After (plain language)

Before: the v0.7 design doc specifies a "warm" MTL agent — a LoRA fine-tune that writes MTL with zero quickref preamble in context — but there was no checked-in, runnable way to train it. An operator had nothing to point at a rented GPU.

After: a self-contained kit under bench/lora/ takes an operator from laptop to a trained adapter in 8 commands, with a GPU-free preflight, a mandatory contamination gate, and a pre-registered evaluation plan.

How

train_mtl_lora.py is config-driven (YAML + CLI overrides). It loads the oracle-validated MTL JSONL (instruction→user / response→assistant), renders with the tokenizer's native chat template, and applies completion-only loss (loss only on the assistant/response span; the check provenance field is ignored). It mixes in general-code replay (default bigcode/the-stack-smol — permissively-licensed code only, trained as plain code-continuation, sized to ~15% of the MTL token budget) as a catastrophic-forgetting mitigation, carves a deterministic tier-stratified eval holdout, and on completion exports the adapter + tokenizer + a MODEL_CARD.md and run_manifest.json recording the full resolved config, seed, dataset sha256, record count, and the verbatim success gate. Checkpointing (save_steps/save_total_limit) + --resume make it eviction-recoverable when --out is on the RunPod network volume. All heavy/GPU imports (torch, unsloth, trl, datasets, vllm) are lazy — they live only inside the real training path — so --smoke runs torch-free on a laptop or in CI. Three sweep configs (r32/r64/r128) hold the effective batch constant; r128.yaml carries an OOM-fallback block. serve_adapter.py wraps vllm serve --enable-lora to expose the adapter as the OpenAI-compatible warm arm for the existing bench/agent-trial/ batteries.

Lives under bench/ (not kit/) because kit/ holds only replication-driver scripts while every experiment lives under bench/<name>/. Docs/tests only — no Rust changed.

Command count: 8 (laptop → adapter)

clone → install Rust toolchain → pip install -r requirements.txt → in-pod gen --seed 0cargo test -p mtl-datagen (contamination gate) → train (auto-exports adapter + model card) → huggingface-cli uploadrunpodctl stop pod.

Smoke-test result

python bench/lora/train_mtl_lora.py --smoke --config bench/lora/config/r64.yaml exits 0 / SMOKE PASSED on the committed pilot (1500 records): config sanity ✓, JSONL schema ✓, chat-template + real tokenizer encode/decode round-trip ✓ (downloaded and verified; a self-contained ChatML structural check is the offline fallback), VRAM estimate ✓ (~7.7 GB peak at r=64 → fits 24 GB / 80 GB). Also verified end-to-end against a freshly generated gen --count 300 --seed 0 slice. cargo test -p mtl-datagen (8 contamination tests) passes; cargo test --workspace stays 322 / 0.

Success gate (pre-registered, verbatim from design doc §6)

Eval gate  warm pass@1 ≥ cold, tok→correct within ±2, 0 preamble, N* ≤ 2 on ≥3/5 price configs, on the #53 sealed set

AND the warm-arm gate:

warm cspm > Python AND N* ≤ 2

Cost / wall-clock (RunPod Secure Cloud)

Job RTX 4090 @ $0.69/hr A100 80GB @ $1.40/hr
Single run (r=64), ~2–3 h $1.38 – $2.07 $2.80 – $4.20
Full sweep (r=32/64/128 + eval), ~14 h / ~6 h ~$9.66 (14 h) ~$8.40 (6 h)

Recommend the A100 for the full sweep / time-sensitive work (cheaper and faster over a long job), the 4090 for cost-optimizing a single run.

Note: #53 vs #87 discrepancy

The task referred to a "#87 gate", but #87 does not exist in this repo. The real, checked-in contamination gate is #53 — the sealed-manifest gate run via cargo test -p mtl-datagen (salt mtl-sealed-v1:issue-53). The RUNBOOK and model card cite #53.

🤖 Generated with Claude Code

https://claude.ai/code/session_018P54D8vTMhDcmX5nExnzoK


Generated by Claude Code

claude added 2 commits July 16, 2026 15:36
Add the checked-in training kit for the v0.7 warm-agent experiment (refs #83):
config-driven QLoRA training script with a GPU-free --smoke preflight,
completion-only loss, general-code replay mixing, deterministic eval holdout,
adapter + model-card + run-manifest export, and --resume checkpointing; r32/r64/
r128 sweep configs (effective batch held constant, r128 carries an OOM-fallback
block); a vLLM --enable-lora serve wrapper for the warm arm; pinned requirements;
and an operator RUNBOOK (laptop -> adapter in 8 commands) covering pod choice,
in-pod datagen, the mandatory sealed-manifest contamination gate (#53), cost
table, OOM playbook, and the pre-registered warm-arm eval gate.

Lives under bench/ (not kit/) per repo convention. Docs/tests only; no Rust
changed. Smoke passes on the committed pilot; cargo test --workspace stays 322/0.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_018P54D8vTMhDcmX5nExnzoK
Remove unused imports (math, sys, dataclasses.field) and two dead
module constants (the ASCII SUCCESS_GATE, superseded by the byte-exact
SUCCESS_GATE_VERBATIM actually written to the manifest/model card; and
RESPONSE_TEMPLATE, a duplicate of ASSISTANT_HEADER that was never
referenced). No behavior change: the --smoke preflight and the training
recipe (r/alpha/rsLoRA/targets/LR/epochs/replay/completion-only-loss)
are untouched. Smoke still exits 0/SMOKE PASSED; cargo test --workspace
still 322/0.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_018P54D8vTMhDcmX5nExnzoK
@madmax983
madmax983 marked this pull request as ready for review July 16, 2026 16:29
@madmax983
madmax983 merged commit e438ed1 into main Jul 16, 2026
3 checks passed
@madmax983
madmax983 deleted the lora-runbook branch July 16, 2026 16:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants