Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
135 commits
Select commit Hold shift + click to select a range
e16079b
fix(train): gfx1201 ROCm fixes + Gemma 4 26B-A4B QLoRA config
ulises-c May 29, 2026
e6796c4
feat(train): target unsloth bnb-4bit Gemma 4 31B for R9700 QLoRA
ulises-c May 29, 2026
d04bc83
fix(train): inference-matching SFT format + W&B + quantization_config…
ulises-c May 30, 2026
e5a8a7d
test(sft): inference-format parity gate for socrat-*-sft loaders
ulises-c May 31, 2026
492b2a0
fix(hooks): run pre-commit tools via `python -m` so they work under -…
ulises-c May 31, 2026
e31b059
docs: handoff to finish #101/#94 training readiness (Phase 0 + EOS ga…
ulises-c May 31, 2026
eb12dbd
fix(sft): Phase 0 — close #94 action/eval drift in socrat-*-sft loaders
ulises-c May 31, 2026
d51f828
Merge main into feat/gfx1201-rdna4-qlora-fla-training
ulises-c May 31, 2026
860fc5f
fix(train): strip expandable_segments + hipBLASLt + setsid for gfx1201
ulises-c May 31, 2026
0b588e4
docs(gpu): gfx1201 (RDNA4/R9700) LLM training field report
ulises-c May 31, 2026
15bddbc
docs(gpu): link source repo + absolute GPU_SUPPORT.md in gfx1201 report
ulises-c May 31, 2026
282edd9
docs(gpu): correct expandable_segments verdict (contested, default off)
ulises-c May 31, 2026
0dff9d7
chore(deps): sync uv.lock — register wandb as a core dependency
ulises-c May 31, 2026
57641eb
fix(eos_gate): handle BatchEncoding from apply_chat_template + add ha…
ulises-c May 31, 2026
dbc61a2
fix(train): include <turn|> terminator in assistant loss mask
ulises-c May 31, 2026
c752a2b
docs(handoff): record EOS root cause (terminator masked) + fix
ulises-c May 31, 2026
1c86dc6
fix(train): switch eos-gate to HIPBLASLT=0; add autonomous monitors
ulises-c May 31, 2026
c3db5ed
chore(scripts): add execute permission to monitor scripts
ulises-c May 31, 2026
e755aa9
perf(train): flash-attn Triton + hipBLASLt for gfx1201 stage2
ulises-c May 31, 2026
7589374
chore(test): set FLASH_ATTENTION_TRITON_AMD_ENABLE in gpu stack test …
ulises-c May 31, 2026
8ef5a57
fix(train): revert FA2 — backward OOMs on gfx1201 (64KB shm limit)
ulises-c May 31, 2026
0492170
docs(handoff): confirm 70s/step ceiling for gfx1201 Stage 2
ulises-c May 31, 2026
3c2f93d
perf(train): Stage 2b to 1 epoch (3× cut) + FA2 de-risk profiler
ulises-c May 31, 2026
df689a8
fix(profile): measure attention share honestly + flag checkpoint-resu…
ulises-c May 31, 2026
65b4079
fix(profile): slice train split to a few steps' worth of records
ulises-c May 31, 2026
35d44db
fix(profile): force ga=1 + make chrome trace opt-in (fast post-proces…
ulises-c May 31, 2026
bdaf40f
perf(train): env knobs for dataset_num_proc + dataloader workers
ulises-c May 31, 2026
5c5bf35
perf(profile): aggregate key_averages once in report()
ulises-c May 31, 2026
23a29e9
fix(profile): correct kernel-class metric + record NF4-dequant bottle…
ulises-c May 31, 2026
28d85c6
fix(profile): run SDPA probe in subprocess to free Triton/HIP VRAM
ulises-c May 31, 2026
95cce17
style(scripts): silence SC2016 on PR-notify printf; sync profiler doc…
ulises-c May 31, 2026
5b21dd4
perf(train): default dataloader workers to 0 (GPU-bound step, fewer p…
ulises-c May 31, 2026
72db9b4
fix(train): remove PYTORCH_HIP_ALLOC_CONF GC threshold — races with g…
ulises-c Jun 1, 2026
473a44d
fix(train): HIPBLASLT=0 on stage2-unsloth; restore GC threshold; corr…
ulises-c Jun 1, 2026
6eae4b6
fix(train): TRAIN_SAVE_STEPS 100→10 so resume survives the gfx1201 pa…
ulises-c Jun 1, 2026
8287e24
fix(train): gfx1201 fault — GPU preflight gate, hardened resume, diag…
ulises-c Jun 1, 2026
b610830
fix(ci): shellcheck SC2317/SC2015 on diagnose script trap cleanup
ulises-c Jun 1, 2026
d001019
fix(diag): default AMD_LOG_LEVEL=1 — level 3 wrote multi-GB diag.log
ulises-c Jun 1, 2026
1bf4cad
feat(monitor): archive full traceback + dmesg per crash before relaunch
ulises-c Jun 1, 2026
f7ece93
docs(handoff): gfx1201 fault diagnosis — serialized run faulted at st…
ulises-c Jun 1, 2026
8580844
diag(gfx1201): Phase 0 serialized-kernel run — fault at step 84, race…
ulises-c Jun 1, 2026
81cebb4
feat(diag): BNB_DEQUANT_PROBE — log NF4 dequant output descriptors
ulises-c Jun 1, 2026
1b752c2
feat(diag): BNB_DEQUANT_PROBE also logs grad_output (GEMM A operand)
ulises-c Jun 1, 2026
dad8f4a
feat(diag): BNB_DEQUANT_PROBE extends to MatMul4Bit.forward (probe-3)
ulises-c Jun 1, 2026
51ad43e
docs(diag): canonical gfx1201 fault ablation/run tracker
ulises-c Jun 1, 2026
b6cb557
docs(handoff): gfx1201 Bucket #2 confirmed — handoff for upstream bug…
ulises-c Jun 1, 2026
a70a2d1
docs(diag): ablation log — runs #8/#9 complete, Bucket #2 closed; arm…
ulises-c Jun 1, 2026
11c13b6
docs(diag): ablation log — arm D complete (run #10), expandable_segme…
ulises-c Jun 1, 2026
e364545
docs(sft): recommendation — relocate Stage-2 SFT to NVIDIA (conditional)
ulises-c Jun 2, 2026
0c0eec2
docs(diag): point upstream filing target at ROCm/rocm-libraries
ulises-c Jun 2, 2026
154aa8b
feat(diag): env-collector script for the gfx1201 rocBLAS bug report
ulises-c Jun 2, 2026
78e224d
feat(diag): BNB_FORCE_B_CONTIGUOUS probe + ablation log runs #11/#12
ulises-c Jun 2, 2026
afa46e0
gfx1201 report generated
ulises-c Jun 2, 2026
4167d84
chore(diag): env-collector writes to docs/diagnostics/; trim output n…
ulises-c Jun 2, 2026
0c763e0
new gfx1201 report generated
ulises-c Jun 2, 2026
64b6e48
docs(diag): consultant/reviewer handoff for the next session
ulises-c Jun 2, 2026
6877a95
docs(diag): record crawl viability go/no-go; hold Arm E off the baseline
ulises-c Jun 2, 2026
7bd3b7e
feat(train): data_seed lever + data-order dump to break the sticky gf…
ulises-c Jun 2, 2026
253a749
docs(handoff): session 3 complete — all fix arms exhausted, crawl pha…
ulises-c Jun 2, 2026
30509a3
docs(diag): record run #13 — crawl STALLED, data-order sticky fault
ulises-c Jun 2, 2026
587b60e
feat(monitor): rotate TRAIN_DATA_SEED per resume to break sticky fault
ulises-c Jun 2, 2026
aebcc3f
feat(monitor): pass WANDB_PROJECT to training launches
ulises-c Jun 2, 2026
623bb06
docs(handoff): session 4 complete — crawl running, rotating seed fix …
ulises-c Jun 2, 2026
d4ce31d
feat(train): enable W&B in config (next-crash pickup) + pin run for c…
ulises-c Jun 2, 2026
9016f9f
fix(monitor): crash_hint matches the real gfx1201 fault signature
ulises-c Jun 2, 2026
21fc7ab
feat(diag): add rocblas bench capture + replay scripts for gfx1201 repro
ulises-c Jun 3, 2026
67498b6
docs(handoff): session 5 — monitor STALLED 8/8, GPU needs driver rese…
ulises-c Jun 4, 2026
8a9c90a
Merge branch 'main' into feat/gfx1201-rdna4-qlora-fla-training
ulises-c Jun 5, 2026
e6ed01a
feat(train): HF auto-push callback + raise save_total_limit to 5
ulises-c Jun 5, 2026
71d6111
refactor(train): extract HFCheckpointCallback to module level + tests
ulises-c Jun 5, 2026
109eb72
feat(diag): standalone gfx1201 ISA1201 Tensile GEMM reproducer
ulises-c Jun 5, 2026
b108052
docs(handoff): session 7 — diagnostic SYNC run active, AMD report rea…
ulises-c Jun 5, 2026
65b830b
fix(lint): shellcheck SC2086 + SC2164 in rocblas bench scripts
ulises-c Jun 5, 2026
3aa3b7d
fix(scripts): reword comment that shellcheck parsed as a directive
ulises-c Jun 5, 2026
e9ae500
feat(monitor): post training log to issue #120 single comment, not PR
ulises-c Jun 5, 2026
aac092f
feat(repro): dense-VA reproducer + session 8 handoff update
ulises-c Jun 7, 2026
158af59
docs(handoff): session 10 — system-rocBLAS hypothesis disproved, moni…
ulises-c Jun 7, 2026
0a46b0c
fix(monitor): strip tqdm progress bar from crash_signature Note cell
ulises-c Jun 7, 2026
5cd8c96
fix(train): HF push persistence + launch check + verbosity
ulises-c Jun 7, 2026
817bedc
feat(train): auto-generated SFT_STAGE2B_CHECKPOINT_LOG.md on HF
ulises-c Jun 7, 2026
3c60b40
Merge branch 'main' into feat/gfx1201-rdna4-qlora-fla-training
ulises-c Jun 7, 2026
b768781
fix(hf_callback): rename on_init -> on_init_end so Trainer calls it, …
ulises-c Jun 7, 2026
6e6e758
fix(monitor/hf_callback): correct crash step and filter non-50 uploads
ulises-c Jun 7, 2026
c6f779c
feat(monitor): checkpoint-driven progress rows with token accuracy
ulises-c Jun 7, 2026
0ae748d
feat(probe): default M=607 (SYNC-confirmed faulting shape) + --m-swee…
ulises-c Jun 7, 2026
4564feb
Merge branch 'main' into feat/gfx1201-rdna4-qlora-fla-training
ulises-c Jun 7, 2026
a4fe2a2
updated uv.lock
ulises-c Jun 7, 2026
c096f77
fix(monitor): parse training-step tqdm bar by s/it anchor, not bare N/M
ulises-c Jun 7, 2026
fb82188
feat(gemma4-12b): scaffold SFT-uplift PoC + MTP serving on NVIDIA RTX…
ulises-c Jun 7, 2026
81686c2
feat(gemma4-12b): add merge→GGUF convert wrapper (12B NAME_TAG + auto…
ulises-c Jun 7, 2026
cc69c23
docs(handoff): add Gemma 4 12B NVIDIA SFT-uplift PoC handoff
ulises-c Jun 7, 2026
5e00014
fix(gemma4-12b): bump transformers→5.10.2 to load gemma4_unified
ulises-c Jun 8, 2026
ed1e902
feat(eval): env-gated W&B Weave LLM tracing (#111)
ulises-c Jun 8, 2026
fa70544
docs(handoff): reconcile 12B PoC handoff with on-box findings
ulises-c Jun 8, 2026
a531ff0
updated uv.lock
ulises-c Jun 8, 2026
9ba6a05
feat(eval): log eval metrics to W&B (env-gated, base↔SFT comparable)
ulises-c Jun 8, 2026
0e0e52f
docs(handoff): refresh for a fresh instance (start at G3)
ulises-c Jun 8, 2026
8b7e04a
refactor: detach W&B tracking into src/project/wandb_tracking.py
ulises-c Jun 8, 2026
8ce81aa
docs(handoff): point at wandb_tracking.py + MELE TODO for next instance
ulises-c Jun 8, 2026
f638af2
feat(eval): crash-crawl monitor + HF-push for the 12B NVIDIA eval phase
ulises-c Jun 8, 2026
ecb072d
docs(handoff): refresh START pointer for the eval crash tooling
ulises-c Jun 8, 2026
ada9e6c
refactor(scripts): collapse 20 eval_*.sh into one runner + archive st…
ulises-c Jun 8, 2026
3fcc748
gemma4-12b mtp done
ulises-c Jun 10, 2026
9126e09
disabled english dataset for now
ulises-c Jun 10, 2026
761bd4b
fix(ci): silence shellcheck SC2015 in eval monitor
ulises-c Jun 10, 2026
a9d2a84
feat(eval): per-dialogue wandb metric curves + replay for finished runs
ulises-c Jun 10, 2026
6c7ce97
docs(log): convergence read + leaderboard placement for 12B-base base…
ulises-c Jun 10, 2026
d5565c7
feat(serve): GEMMA4_12B_KV env forces KV cache type without MTP
ulises-c Jun 10, 2026
74ce6b6
docs(log): MTP-off baseline complete — losslessness confirmed, σ cali…
ulises-c Jun 10, 2026
a300b44
docs: SFT phase-2 handoff for a fresh session
ulises-c Jun 20, 2026
730906a
feat(train): auto-resume monitor for Gemma4-12B SFT on the unstable N…
ulises-c Jun 21, 2026
73c72e0
fix(train): live-quantize Gemma4-12B base instead of false pre-quant …
ulises-c Jun 21, 2026
66becca
fix(train): skip eval-dataset tokenization when eval_strategy=no
ulises-c Jun 21, 2026
728c9a7
docs: eval-phase SFT handoff (training recovered, merge done)
ulises-c Jun 23, 2026
394bd5d
docs: add why-stopped + future-SFT recommendations to handoff
ulises-c Jun 23, 2026
54f1c77
fix(convert): allow CPU-only llama-quantize via QUANTIZE override
ulises-c Jun 24, 2026
dcec741
docs(sft): eval-plan rationale (MTP-off/concurrent) + workers A/B + H…
ulises-c Jun 24, 2026
98db3e6
feat(eval): --hf-repo flag + monitor dataset override for EN/syntheti…
ulises-c Jun 24, 2026
83899c0
fix(dataset): ZH synthetic is one 75-record config (merged n75 extens…
ulises-c Jun 24, 2026
a3bbada
docs: SFT-vs-base further-analysis & ablation plan
ulises-c Jun 24, 2026
ef46f7b
fix(monitor): log the GPU's actual enforced power, not the card max
ulises-c Jun 24, 2026
538972c
docs: SFT-vs-base results report (full 2x2 + headline)
ulises-c Jun 26, 2026
fdc15f5
docs: handoff for consultant ablation (no-consultant + consultant-as-…
ulises-c Jun 26, 2026
fd0d0d9
docs: correct consultant-ablation handoff — SFT consumes state, doesn…
ulises-c Jun 26, 2026
6d513ba
feat(eval): NO_CONSULTANT self-consult toggle + sft→base ablation chain
ulises-c Jun 26, 2026
909c13a
docs: consultant-ablation (T1.1) results — SFT internalized quality, …
ulises-c Jul 6, 2026
efa77a6
feat(eval): oracle-consultant mode — feed ground-truth state to isola…
ulises-c Jul 7, 2026
a99c2fd
feat(eval): oracle 2-arm chain wrapper (sft→base) + make target
ulises-c Jul 7, 2026
7b85ff7
docs: oracle-consultant results — SFT teacher-turn quality largest wi…
ulises-c Jul 10, 2026
46f84d6
fix(eval): commit the isinstance oracle guard (stale blob staged in e…
ulises-c Jul 10, 2026
af5c64b
feat(eval): claude-code subscription backend for the absolute-quality…
ulises-c Jul 12, 2026
95d49b1
feat(eval): paired stratified compare mode for the absolute-quality L…
ulises-c Jul 12, 2026
4fe1ee0
docs: handoff for the absolute-quality LLM-judge run (built, verified…
ulises-c Jul 12, 2026
90f78ec
docs(eval): LLM-judge confirms oracle SFT win on absolute quality (+0…
ulises-c Jul 13, 2026
4382f01
docs: post-judge handoff for the next session + mark LLM-judge handof…
ulises-c Jul 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,10 @@ MAX_NEW_TOKENS=512
# x-api-key: <key>
TEACHER_SERVER_API_KEY=

# Weights & Biases — experiment tracking for the state-classifier trainers
# (scripts/train_state_classifier_34way*.py, run with --wandb). Grab the key
# from https://wandb.ai/authorize. The training launch sources .env, so the key
# is picked up automatically for online logging; leave blank to log offline.
# Weights & Biases — experiment tracking for SFT trainers (train_sft.py) and
# state-classifier trainers (train_state_classifier_34way*.py, run with --wandb).
# Get your key at https://wandb.ai/authorize, then run `wandb login` or set here.
WANDB_API_KEY=
# Optional overrides (defaults: project=csen346-state-classifier, run=out-dir basename)
# WANDB_PROJECT=csen346-state-classifier
# WANDB_RUN_NAME=
# Optional overrides (training scripts set sensible defaults if omitted)
# WANDB_PROJECT=csen346-sft
# WANDB_RUN_NAME=gemma4-31b-stage2
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ references/KELE-EN/.cache/
# Railguard
.railguard/*

# W&B local run artifacts
wandb/
# macOS
.DS_Store
**/.DS_Store
Expand Down
262 changes: 232 additions & 30 deletions Makefile

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions configs/gemma4-12b-local.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Experiment: Gemma 4 12B-it BASE teacher — fully local, dual-role on llama.cpp.
#
# Both teacher and consultant hit the same llama.cpp server on port 8080, mirroring
# configs/gemma4-31b-local.env. For the SFT-uplift PoC the eval RE-points the
# consultant role at the Qwen3.5-LoRA state classifier via `--bert-consultant
# <path>` — but CONSULTANT_* below must still be set, because config.py:load_config
# require()s them unconditionally at load time.
#
# Serve the base weights with: make serve-gemma4-12b (UD-Q8_K_XL)
# or, to A/B the MTP speculative drafter: make serve-gemma4-12b-mtp
# Eval: make eval-gemma4-12b-base-smoke / make eval-gemma4-12b-base-full
#
# Shares port 8080 with the other local llama.cpp configs — only one model fits at
# a time on the RTX 4000 Ada's 20 GB. The teacher alias "Gemma 4 12B" must match
# the serve wrapper's -a so the eval can't run against the wrong loaded weights.

CONSULTANT_API_KEY=not-needed
CONSULTANT_BASE_URL=http://localhost:8080/v1
CONSULTANT_MODEL_NAME=Gemma 4 12B
# 8192 leaves ample room for structured JSON output. Gemma 4 has no thinking-mode
# equivalent (Qwen-specific) so no CoT budget needed.
CONSULTANT_MAX_TOKENS=8192

TEACHER_API_KEY=not-needed
TEACHER_BASE_URL=http://localhost:8080/v1
TEACHER_MODEL_NAME=Gemma 4 12B

DEBUG_MODE=false
MAX_TEACHING_ROUNDS=8
KELE_TEACHER_LANG=auto
26 changes: 26 additions & 0 deletions configs/gemma4-12b-sft-local.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Experiment: Gemma 4 12B-it SFT teacher (Socratic QLoRA, merged → Q6/Q8 GGUF).
#
# Same dual-role / fully-local pattern as gemma4-12b-local.env. The ONLY
# difference is the alias "Gemma 4 12B SFT" — distinct so the eval orchestrator
# refuses to run against the BASE weights by mistake (it requests this teacher
# name from the server's /v1/models and fails fast if absent). The Qwen3.5-LoRA
# consultant is held identical to the baseline run so the metric delta isolates
# the SFT adapter.
#
# Serve the merged SFT weights with: make serve-gemma4-12b-sft
# Eval: make eval-gemma4-12b-sft-smoke / make eval-gemma4-12b-sft-full
#
# Shares port 8080 — stop the base server before serving the SFT model.

CONSULTANT_API_KEY=not-needed
CONSULTANT_BASE_URL=http://localhost:8080/v1
CONSULTANT_MODEL_NAME=Gemma 4 12B SFT
CONSULTANT_MAX_TOKENS=8192

TEACHER_API_KEY=not-needed
TEACHER_BASE_URL=http://localhost:8080/v1
TEACHER_MODEL_NAME=Gemma 4 12B SFT

DEBUG_MODE=false
MAX_TEACHING_ROUNDS=8
KELE_TEACHER_LANG=auto
96 changes: 96 additions & 0 deletions configs/train-sft-gemma4-12b-qlora.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# SFT fine-tuning — Socratic teaching QLoRA on Gemma 4 12B-IT (PoC, 1 epoch)
#
# Target hardware: NVIDIA RTX 4000 Ada (20 GB), CUDA. This box is KNOWN-UNSTABLE
# (see memory: training-host-hardware-fault) — checkpoint frequently and rely on
# train_sft.py auto-resume rather than expecting a clean single run.
# Gemma 4 uses standard softmax attention (attn_implementation="sdpa" in
# train_sft.py) — no flash-linear-attention dependency, no patch-fla step, and
# none of the gfx1201/ROCm env (TORCH_USE_HIPBLASLT / PYTORCH_HIP_ALLOC_CONF)
# the 31B AMD config carries.
#
# This is the 12B PoC sibling of configs/train-sft-stage2-gemma4-31b.env. Goal:
# measure whether 1-epoch Socratic SFT gives eval uplift over the BASE Gemma 4
# 12B teacher (consultant = Qwen3.5-LoRA state classifier, held fixed).
#
# Launch (recommended — train from the community bnb-4bit base, no BF16 staging):
# make train-gemma4-12b
# which overrides TRAIN_BASE_MODEL=unsloth/gemma-4-12b-it and TRAIN_PREQ=true.
#
# Dry run (no weights): make train-gemma4-12b-dry-run

# ── Base model ────────────────────────────────────────────────────────────────
# Default is the BF16 hub model (live-quant path). The make target overrides this
# to the unsloth bnb-4bit checkpoint with TRAIN_PREQ=true to skip BF16 CPU staging.
TRAIN_BASE_MODEL=google/gemma-4-12b-it

# ── Training method ───────────────────────────────────────────────────────────
TRAIN_METHOD=qlora

# ── LoRA hyperparameters ──────────────────────────────────────────────────────
LORA_RANK=16
LORA_ALPHA=32
LORA_DROPOUT=0.05
# google/gemma-4-12b-it is the same multimodal Gemma4ForConditionalGeneration
# family as the 31B (text decoder + vision_tower + audio_tower). The anchored
# regex (build_lora_config detects the leading ^) scopes LoRA to text-decoder
# nn.Linear paths only; the vision_tower's Gemma4ClippableLinear wrappers crash
# get_peft_model otherwise. It is layer-count-agnostic (\d+), so it ports from
# the 31B's 60 decoder layers to the 12B's 48 unchanged.
LORA_TARGET_MODULES=^model\.language_model\.layers\.\d+\.(self_attn|mlp)\.(q_proj|k_proj|v_proj|o_proj|gate_proj|up_proj|down_proj)$

# ── Training hyperparameters ─────────────────────────────────────────────────
# 1 epoch over the ~77k per-turn records (~4826 steps @ effective-batch 16) is
# ample SFT signal for a PoC. Bump to 3 only if the downstream eval shows the
# single epoch underfits.
# NB: train_sft.py auto-resumes from any checkpoint-* in TRAIN_OUTPUT_DIR built
# for the OLD schedule. If you re-run after changing TRAIN_EPOCHS, clear them:
# rm -rf outputs/sft-gemma4-12b-qlora/checkpoint-*
TRAIN_EPOCHS=1
TRAIN_LR=5e-5
TRAIN_BATCH_SIZE=1
TRAIN_GRAD_ACCUM=16
# Measured on socrat-zh-sft + socrat-en-sft (scripts/determine_max_sequence.py):
# real token max = 909 (train) / 892 (eval), p99 = 673. 1280 truncates NOTHING;
# with batch_size=1 + dynamic padding the activation peak is set by the actual
# longest sequence (909), not by this cap, so lowering it frees no VRAM.
TRAIN_MAX_SEQ_LEN=1280
TRAIN_BF16=true
TRAIN_GRAD_CKPT=true
# One-time tokenization fan-out across CPU cores (procs exit before training).
TRAIN_DATASET_NUM_PROC=12
# Step is GPU/dequant-bound; data is pre-tokenized; async prefetch buys nothing.
TRAIN_DATALOADER_WORKERS=0

# ── Dataset sources ───────────────────────────────────────────────────────────
# Per-turn, state/action-conditioned format that matches the inference schema
# socrates_teacher() sends (历史对话记录 / 当前学生输入). Using socrat-*-sft
# (NOT plain socrat-zh,socrat-en) avoids confounding the SFT uplift measurement
# with train/serve schema drift.
TRAIN_SOURCES=socrat-zh-sft,socrat-en-sft

# ── Output & logging ─────────────────────────────────────────────────────────
TRAIN_OUTPUT_DIR=outputs/sft-gemma4-12b-qlora
TRAIN_LOGGING_STEPS=10
# Save every 50 steps so the auto-resume monitor can crawl the run forward across
# a crash on this known-unstable box instead of restarting at step 0. NOTE: this
# is NOT the AMD gfx1201 backward page fault (that is ROCm-specific and does not
# occur on CUDA) — the rationale here is purely the host hardware instability.
# Disk is bounded by save_total_limit (a couple of ~50 MB LoRA adapters). Drop to
# 10 only if a crash ever lands inside the 0–50 window and stalls.
TRAIN_SAVE_STEPS=50
TRAIN_EVAL_STEPS=200
# Disable in-training eval — the eval forward's logits.float() cast doubles the
# 256K-vocab logits tensor (transient multi-GB), which can OOM the 20 GB card.
# The downstream KELE eval pipeline produces the paper numbers anyway. Also
# forces load_best_model_at_end=False (which needs eval).
TRAIN_EVAL_STRATEGY=no

# ── Weights & Biases ──────────────────────────────────────────────────────────
# Requires `wandb login` or WANDB_API_KEY; train_sft._check_wandb disables
# reporting if auth fails. Pinned run id + resume=allow so every crash-resume
# APPENDS to one run with a continuous step axis. Bump WANDB_RUN_ID for a
# brand-new crawl (else it resumes this run's step history).
WANDB_PROJECT=csen346-sft
WANDB_RUN_ID=gemma4-12b-qlora-poc
WANDB_RESUME=allow
WANDB_RUN_NAME=gemma4-12b-qlora-poc
75 changes: 65 additions & 10 deletions configs/train-sft-stage2-gemma4-31b.env
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@
# # 2a → 2b sequence: run 2a first, then point TRAIN_BASE_MODEL at the 2a
# # checkpoint dir and re-run with the default TRAIN_SOURCES.
#
# Launch (R9700):
# Launch (R9700) — recommended: skip the 62 GB BF16 CPU staging at load by
# training from the community pre-quantized unsloth bnb-4bit checkpoint:
# make train-gemma4-31b-stage2-unsloth
# which overrides TRAIN_BASE_MODEL=unsloth/gemma-4-31B-it-unsloth-bnb-4bit and
# TRAIN_PREQ=true. The default TRAIN_BASE_MODEL below is the live-quant path
# (make train-gemma4-31b-stage2), which stages the full BF16 model in CPU RAM.
#
# Launch (live quant, BF16 base):
# mkdir -p outputs/sft-stage2-gemma4-31b
# nohup env TORCH_USE_HIPBLASLT=0 PYTORCH_HIP_ALLOC_CONF=garbage_collection_threshold:0.8 \
# uv run --no-sync python scripts/train_sft.py \
Expand Down Expand Up @@ -48,31 +55,79 @@ LORA_DROPOUT=0.05
LORA_TARGET_MODULES=^model\.language_model\.layers\.\d+\.(self_attn|mlp)\.(q_proj|k_proj|v_proj|o_proj|gate_proj|up_proj|down_proj)$

# ── Training hyperparameters ─────────────────────────────────────────────────
TRAIN_EPOCHS=3
# Stage 2b is a proof-of-concept for the larger SFT plan; 1 epoch over the ~77k
# per-turn records is ample SFT signal and is a clean 3× wall-time cut
# (~281h → ~94h) against the gfx1201 ~70s/step ceiling. Bump back to 3 only if
# the downstream eval shows the single epoch underfits.
# NB: train_sft.py auto-resumes from any checkpoint-* in TRAIN_OUTPUT_DIR. An
# epochs=3 run already wrote checkpoints there, built for a ~14.5k-step schedule.
# Clear them before relaunching at epochs=1, or the trainer resumes the old
# 3-epoch schedule (wrong LR decay, or exits immediately if past 1-epoch steps):
# rm -rf outputs/sft-stage2-gemma4-31b/checkpoint-*
TRAIN_EPOCHS=1
TRAIN_LR=5e-5
TRAIN_BATCH_SIZE=1
TRAIN_GRAD_ACCUM=16
# Measured, not assumed (scripts/determine_max_sequence.py, 2026-06-01 on
# socrat-zh-sft + socrat-en-sft): real token max = 909 (train) / 892 (eval),
# p99 = 673. Nothing exceeds 1024 → 1280 truncates NOTHING; it is non-binding.
# NB: with batch_size=1 + dynamic padding the activation peak is set by the
# actual longest sequence (909), not by this cap, so lowering it frees no VRAM.
TRAIN_MAX_SEQ_LEN=1280
TRAIN_BF16=true
TRAIN_GRAD_CKPT=true
# CPU parallelism (12C/24T box). dataset_num_proc fans the one-time tokenization
# of the 77k-record split across processes (single-process by default → pegs one
# core for minutes at startup); 12 ≈ physical cores. Those procs exit before
# training.
TRAIN_DATASET_NUM_PROC=12
# Dataloader workers are 0 on purpose: the step is GPU/dequant-bound (~70s), data
# is pre-tokenized, and collation is trivial — async prefetch buys nothing here.
# Each worker also forks a HIP context that shows up in nvtop and costs a little
# VRAM on the tight 32GB/31B budget. Raise only if profiling shows data-feed stall.
TRAIN_DATALOADER_WORKERS=0

# ── Dataset sources ───────────────────────────────────────────────────────────
# Default: Stage 2b — structural fine-tuning on state-annotated SocratDataset.
# socrat-synthetic is the contamination-control eval set; never include it here.
TRAIN_SOURCES=socrat-zh,socrat-en
# Stage 2b — per-turn inference-matching format (fixes train/serve schema drift).
# socrat-zh-sft / socrat-en-sft produce one (system, user, assistant) triple per
# dialogue turn with the exact 历史对话记录 / 当前学生输入 structure that
# socrates_teacher() sends at inference. socrat-synthetic is eval-only; never here.
TRAIN_SOURCES=socrat-zh-sft,socrat-en-sft

# ── Output & logging ─────────────────────────────────────────────────────────
TRAIN_OUTPUT_DIR=outputs/sft-stage2-gemma4-31b
TRAIN_LOGGING_STEPS=10
# Save every 100 steps (~32 min at 19s/step on Gemma 4 31B QLoRA). Tighter
# than the 200-step default — halves the worst-case rollback after a crash
# at the cost of ~2× I/O for adapter checkpoints (~500 MB each, ~11 GB total
# across the 23 checkpoints expected for the full 2298-step run).
TRAIN_SAVE_STEPS=100
# Save every 10 steps. The gfx1201 GPU page fault (Memory access fault / page
# not present) is non-deterministic and hits during the QLoRA backward as early
# as step 14 — BEFORE any 100-step checkpoint lands. With save_steps=100 the
# auto-resume monitor had nothing to resume from, so every restart began at
# step 0 and re-crashed before 100: a permanent loop with zero forward progress.
# save_steps=10 lands a checkpoint before the earliest observed crash, so the
# resume monitor crawls the run forward across faults instead of looping. Disk
# is bounded by save_total_limit=2 (~1 GB of LoRA adapters). Drop to 5 if a
# crash ever lands inside the 10–20 window and stalls.
TRAIN_SAVE_STEPS=10
TRAIN_EVAL_STEPS=200
# Disable in-training eval — the eval forward's logits.float() cast doubles
# the logits tensor (256K vocab × 1280 seq × 4 bytes = 8.6 GB transient on
# Gemma 4 31B), which OOMs the 5090 at the first eval step. The downstream
# eval pipeline (eval_bert_gemma_fewshot10_full.sh) produces paper numbers
# anyway. Also forces load_best_model_at_end=False (which needs eval).
TRAIN_EVAL_STRATEGY=no

# ── Weights & Biases ──────────────────────────────────────────────────────────
# Enabled for the gfx1201 crawl. This lives in the CONFIG, not monitor_stage2.sh,
# on purpose: the auto-resume monitor is a long-running process with start_stage2()
# already parsed into memory, so editing the monitor script does NOT change its
# next relaunch. train_sft.py re-reads this config on every `make` relaunch, so a
# change here is picked up on the NEXT CRASH without restarting the monitor.
# (load_env_file setdefaults these into os.environ; a CLI/env override still wins.)
# Tracking still requires W&B auth — `wandb login` or WANDB_API_KEY. If login fails,
# train_sft._check_wandb disables reporting regardless of these vars.
WANDB_PROJECT=csen346-sft
# Pin a stable run id + resume=allow so every crawl resume APPENDS to one run with a
# continuous step axis, instead of spawning a fresh W&B run per crash cycle. Bump
# this id when starting a brand-new crawl (else it resumes this run's step history).
WANDB_RUN_ID=stage2-gemma4-31b-crawl
WANDB_RESUME=allow
WANDB_RUN_NAME=gemma4-31b-stage2-crawl
Loading