Every comment that cited a named law, an incident date, or an internal nickname now states the underlying mechanism and why it matters, generically: curl exit-0 artifacts and byte-count gates, argv-in-/proc secret exposure, tag mutability vs digest pinning, shape-specialized kernels refusing uncompiled slot counts, MTP heads as file tensors no flag can supply, drafter/slot coupling as an engine property, pkill -f matching its invoker, pinned-RAM pairing with LimitMEMLOCK, one-encoding-per-table, the short-run first-token noise floor, and the protected-expert rule. No behavior change: comment/string text only; suite green (371 tests).
75 lines
4.1 KiB
Bash
Executable File
75 lines
4.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# convert-swift15-w4dn8.sh — RUNS ON DANKSERVER. The final recipe convert of
|
|
# the Swift 1.5 checkpoint: gate_up experts through GPTQ against the 10M-token
|
|
# calibration Grams, down projections block-fp8, protected experts bf16,
|
|
# trunk int8, PLE fixed-scale fp8 (scripts/recipes/
|
|
# qwen4exp-swift15-w4dn8-i8-hc8m.recipe).
|
|
#
|
|
# The convert engine is 1.0.13 — the SAME pin that will serve the result, so
|
|
# the .rad crosses no version boundary. Only the Gram files cross versions
|
|
# (1.2.0 wrote them; the RADGRAM2 magic, gram.r%d.%s.bin naming and the
|
|
# calib_gram/calib_resolve/calib_stem symbols are byte-identical between the
|
|
# two libquant.so). rad-convert runs on the host backend (no GPU visible in
|
|
# the container) — production can stay up through this script.
|
|
#
|
|
# Prereqs (campaign order): calibration complete (calib-push printed TAP_DONE),
|
|
# the protected-expert cast lines rewritten into the recipe by
|
|
# derive-protected-experts.py, and the 335 GiB bf16 container deleted —
|
|
# the peak-disk arithmetic needs that space (checkpoint 335.3 + output ~132
|
|
# GiB on the volume; --reuse is NOT used, see the recipe header).
|
|
set -euo pipefail
|
|
|
|
PIN_1013=sha256:4c3f484564bb2872784e46b0a59cbd71becc9c1e746e301a3596ffae253c322e
|
|
IMAGE="stilldeadcode/radiance@$PIN_1013"
|
|
CKPT=/home/dank/models/ukisai/Swift1.5-Qwen3.8-Flash-Next
|
|
RECIPE=/home/dank/serverAppConfigs-swift15/scripts/recipes/qwen4exp-swift15-w4dn8-i8-hc8m.recipe
|
|
CALIB=/home/dank/corpora/calib
|
|
OUT=/home/dank/models/rad/qwen4exp-swift15-w4dn8-i8-hc8m.rad
|
|
LOG=/home/dank/logs/swift15_convert.log
|
|
# gate_up ~37.6 + down ~18.8 + PLE 47.7 + trunk/embeddings/head ~10 GiB (all-w4 expert table;
|
|
# the format assigns ONE encoding per expert table, so a per-tensor block-fp8
|
|
# down tier cannot be served beside a w4 gate_up tier -- see the recipe header).
|
|
MIN_MIB=${FRANK_SWIFT15_RAD_MIN_MIB:-108000}
|
|
|
|
# Gate 1: inputs. A missing Gram directory converts UNCALIBRATED with a
|
|
# per-tensor stderr note, which is silently worse than failing here.
|
|
[ -d "$CKPT" ] || { echo "no checkpoint at $CKPT" >&2; exit 1; }
|
|
[ -f "$RECIPE" ] || { echo "no recipe at $RECIPE" >&2; exit 1; }
|
|
GRAMS=$(find "$CALIB" -maxdepth 1 -name 'gram.r*.bin' 2>/dev/null | wc -l)
|
|
[ "$GRAMS" -ge 48 ] || { echo "calib dir $CALIB holds $GRAMS gram files (<48)" >&2; exit 1; }
|
|
if [ -e "$OUT" ]; then echo "$OUT already exists; move it to trash first" >&2; exit 1; fi
|
|
if [ -e /home/dank/models/rad/qwen4exp-swift15-bf16.rad ]; then
|
|
echo "the bf16 container is still on disk; delete it first (peak disk)" >&2; exit 1
|
|
fi
|
|
|
|
# Gate 2: disk. Output ~132 GiB plus convert staging, 20 GiB of slack.
|
|
FREE_MIB=$(df --output=avail -m /home/dank/models | tail -1 | tr -d ' ')
|
|
[ "$FREE_MIB" -ge $((MIN_MIB + 20480)) ] || {
|
|
echo "only ${FREE_MIB} MiB free on /home/dank/models" >&2; exit 1; }
|
|
|
|
# The recipe names $CALIB; rad-convert expands it from the environment
|
|
# (MOE-W4.md:275). The recipe's cast section must name THIS checkpoint's
|
|
# protected experts — derive-protected-experts.py rewrote it.
|
|
echo "convert: $CKPT -> $OUT (gptq calib=$CALIB, $(date -Is))" | tee "$LOG"
|
|
podman run --rm --name swift15-convert \
|
|
-v /home/dank/models:/models \
|
|
-v /home/dank/serverAppConfigs-swift15:/campaign:ro \
|
|
-v "$CALIB:/data/calib:ro" \
|
|
-e CALIB=/data/calib \
|
|
--entrypoint /opt/radiance/bin/rad-convert \
|
|
"$IMAGE" "/models/${CKPT#/home/dank/models/}" \
|
|
--recipe /campaign/"${RECIPE#/home/dank/serverAppConfigs-swift15/}" \
|
|
-o /models/rad/"$(basename "$OUT")" 2>&1 | tee -a "$LOG"
|
|
rc=${PIPESTATUS[0]}
|
|
[ "$rc" -eq 0 ] || { echo "rad-convert rc=$rc; log: $LOG" >&2; exit "$rc"; }
|
|
|
|
# Gate 3: the artifact. rad-info's recipe echo is the receipt that GPTQ ran.
|
|
SIZE_MIB=$(( $(stat -c %s "$OUT") / 1048576 ))
|
|
[ "$SIZE_MIB" -ge "$MIN_MIB" ] || {
|
|
echo "$OUT is ${SIZE_MIB} MiB < floor ${MIN_MIB}" >&2; exit 1; }
|
|
podman run --rm --entrypoint /opt/radiance/bin/rad-info \
|
|
-v /home/dank/models:/models:ro "$IMAGE" /models/rad/"$(basename "$OUT")" \
|
|
2>&1 | tee -a "$LOG" | grep -c 'gptq' >/dev/null \
|
|
|| echo "WARNING: rad-info shows no gptq rule in the recorded recipe" >&2
|
|
echo "CONVERT_DONE ${SIZE_MIB} MiB -> $OUT"
|