Files
esh-pfi-infrastructure/scripts/r49-corpus/launch-h02-4b-instruct.sh
T
vh e15c5ee5ea Instruct probe: voice and instruction-following coexist
Trained the same corpus onto Qwen3-4B instruct rather than -Base, with seed, steps
and token count held so the carrier is the only variable. The chain picked
checkpoint-150 by loss automatically, applying the lesson that cost a re-cut on
4B-Base.

The central risk did not materialise. The assistant prior did not block the voice:
curly quotes land at 16 of 18, identical to the 4B-Base tuned arm, against 1 of 18
on the unadapted control, and task-leak is 0 of 18 where the base carrier leaked 4.
Instruction-following also survived raw-text training -- 10 of 10 on-beat through
the chat template, the same as the untuned control.

The cost is length discipline rather than comprehension. In-band dropped from 10 of
10 to 6 of 10 and the median went from 124 to 140 words. Training on Victorian
prose made it wordier, which is a soft degradation and not a break.

Held-out sits at 2.908 against 4B-Base's 2.814, and it plateaus without turning
where the base carrier overfit at step 75. The assistant prior competes for
capacity, so the instruct carrier absorbs less rather than overfitting more.

What raw-continuation training does not fix is the plot furniture. The tuned
instruct arm renders the beat and then drags the referent -- "He licked her clean...
my master thus, my husband thus", turning the dog into a man, because the corpus is
about masters and husbands. Another beat ran to 247 words and gave the narrator a
list of duties. That is precisely what instruction-pair training addresses, since
pairs teach render-this-and-stop where continuation teaches keep-writing. The probe
de-risks the instruction-pair path without substituting for it.

One metric note against future misreading: ran_on reports 10 of 10 on both arms and
is uninformative on this job, because a single paragraph contains no blank line for
it to find.
2026-09-11 08:32:30 -07:00

46 lines
2.7 KiB
Bash

#!/usr/bin/env bash
# R49 H02 — the instruct probe. Qwen3-4B (INSTRUCT, not -Base), 1 epoch, seed 4919.
#
# WHY, in the operator's words: "I think we need the instruct model trained -- if
# nothing else to see what our options are." Three arguments drove it and all three
# are about the REGIME rather than the output quality:
#
# 1. A completion carrier reaches for BRONTË's plot devices, not Skaldsong's. We
# measured that: the gloom-override killed the animals on a prompt that asked
# for a wonderful story, and the rename pool rewrote "Alice" into "Alexander
# the Alexander". When the author owns the plot, importing hers is a conflict,
# not a blemish.
# 2. Drift scales with generated length. In the ten-format bake-off the short
# samples stayed nearest the beat and the 224-253 word ones wandered furthest.
# 3. ⭐ If a frontier model must judge every paragraph, the tiny model has no
# purpose. Reliability has to be intrinsic, not bought back downstream.
#
# ⚠ THIS IS A PROBE, NOT THE PRODUCT PATH. It trains RAW CONTINUATION text into a
# model whose weights expect <|im_start|> framing, which can degrade the template
# behaviour — that is exactly the risk being measured, and the reason the chained
# test drives it through the chat template afterwards. The product path builds an
# instruction-pair corpus; that is a separate and larger piece of work, and it is
# only worth starting if instruction-following survives this.
#
# Everything else held from the 4B-Base rung so the CARRIER is the only variable:
# unwrapped corpus (sha 77f37057b2782e49), seed 4919, rank 32, lr 1e-4, seq 4096,
# batch 1 x accum 8, 1 epoch, eval+save every 25.
#
# ⚠ Expect the loss minimum EARLY. 4B-Base turned at ~step 75 of 159, and an
# instruct model already fluent in English should saturate at least as fast.
set -euo pipefail
OUT=/home/infra-ops/r49-runs/h02-4b-instruct-1ep
LOG=$OUT/train.log
apps=$(nvidia-smi --query-compute-apps=pid --format=csv,noheader | tr -d '[:space:]')
[ -n "$apps" ] && { echo "REFUSING: GPU not clear" >&2; nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv >&2; exit 1; }
[ -e "$LOG" ] && { echo "REFUSING: $LOG exists" >&2; exit 1; }
mkdir -p "$OUT"
echo "# launched $(date -Is) Qwen3-4B INSTRUCT, 1 epoch, seed 4919, unwrapped corpus" > "$LOG"
setsid nohup /home/infra-ops/ml/.venv/bin/python /home/infra-ops/r49-prep/train_voice_lora.py \
--corpus /home/infra-ops/r49-corpus-renamed-unwrapped \
--base /home/infra-ops/carriers/Qwen3-4B-Instruct \
--seed 4919 --epochs 1 --eval-steps 25 --save-steps 25 \
--out "$OUT" >> "$LOG" 2>&1 < /dev/null &
echo $! > "$OUT/run.pid"
echo "launched pid $(cat "$OUT/run.pid") -> $LOG"