File size: 7,858 Bytes
d4c2896 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 | #!/usr/bin/env bash
# Mini per-position curves chain (uli decision 2026-08-06, option A):
# re-runs the 20 CONFIG-WITH-DRAFTER configs (12 Qwen + 8 Gemma) on the
# stratified 180-prompt subset (acc-sample.jsonl) with FRESH dirs
# experiments/runs/curves-<name>/ to recover "acc per pos" (server.log).
#
# Why this is valid: T=0 + seed 42 + the 180 prompts are a subset of the
# 1474 (f1-sample) β generations IDENTICAL to the full run β the subset
# curve IS the curve of those prompts in the real run (deterministic
# equivalence; documented in the Methods of the post/paper).
#
# Target-solo configs are NOT included (no drafter β no curves).
# The 8 Gemma-draft configs ALREADY have complete curves (n=1474) in their
# server.log; this mini-chain re-runs them at n=180 for a uniform F1 figure
# (same n in every panel).
#
# Usage:
# DRY_RUN=1 bash scripts/run_curves_chain.sh # prints the matrix (20) and exits
# bash scripts/run_curves_chain.sh # ~15 min/config β 4.5 h total
#
# RUN ONLY WITH THE GPU FREE (after "FINAL RUN DONE" of the full chain).
set -uo pipefail
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$REPO"
source scripts/spec-env.sh
set +e # spec-env.sh enables set -e; the chain handles errors via exit codes
LOG="experiments/runs/queue-curves.log"
log() { echo "[$(date '+%F %T')] $*" | tee -a "$LOG"; }
SAMPLES="experiments/prompts/old/acc-sample.jsonl"
NTOK=256
Q="models/Qwen3-8B"
G="models/gemma-4-12b-it"
DK="models/drafts"
BENCH="python scripts/bench_accept.py"
OK_COUNT=0
FAILED_COUNT=0
SKIP_COUNT=0
OOM_OK=1
G8_CHECKED=0
# Matrix of 20 configs with drafter (spec final-run-matrix): name|target|draft|spec_type|p_min|out|extra
MATRIX=(
# Qwen3-8B (12)
"curves-qwen-q4-vanilla17b|$Q-Q4_K_M.gguf|$DK/Qwen3-1.7B-Q4_K_M.gguf|draft-simple||experiments/runs/curves-qwen-q4-vanilla17b"
"curves-qwen-q4-eagle3|$Q-Q4_K_M.gguf|$DK/Qwen3-8B-speculator.eagle3-F16.gguf|draft-eagle3||experiments/runs/curves-qwen-q4-eagle3"
"curves-qwen-q4-dflash|$Q-Q4_K_M.gguf|$DK/dflash_qwen3_8b_block7.gguf|draft-dflash||experiments/runs/curves-qwen-q4-dflash"
"curves-qwen-q4-dspark-p0|$Q-Q4_K_M.gguf|$DK/dspark_qwen3_8b_block7.gguf|draft-dspark|0.0|experiments/runs/curves-qwen-q4-dspark-p0"
"curves-qwen-q4-dspark-p2|$Q-Q4_K_M.gguf|$DK/dspark_qwen3_8b_block7.gguf|draft-dspark|0.2|experiments/runs/curves-qwen-q4-dspark-p2"
"curves-qwen-q4-dspark-p4|$Q-Q4_K_M.gguf|$DK/dspark_qwen3_8b_block7.gguf|draft-dspark|0.4|experiments/runs/curves-qwen-q4-dspark-p4"
"curves-qwen-q4-dspark-p6|$Q-Q4_K_M.gguf|$DK/dspark_qwen3_8b_block7.gguf|draft-dspark|0.6|experiments/runs/curves-qwen-q4-dspark-p6"
"curves-qwen-q5-eagle3|$Q-Q5_K_M.gguf|$DK/Qwen3-8B-speculator.eagle3-F16.gguf|draft-eagle3||experiments/runs/curves-qwen-q5-eagle3"
"curves-qwen-q5-dflash|$Q-Q5_K_M.gguf|$DK/dflash_qwen3_8b_block7.gguf|draft-dflash||experiments/runs/curves-qwen-q5-dflash"
"curves-qwen-q5-dspark-p0|$Q-Q5_K_M.gguf|$DK/dspark_qwen3_8b_block7.gguf|draft-dspark|0.0|experiments/runs/curves-qwen-q5-dspark-p0"
"curves-qwen-q8-eagle3|$Q-Q8_0.gguf|$DK/Qwen3-8B-speculator.eagle3-F16.gguf|draft-eagle3||experiments/runs/curves-qwen-q8-eagle3"
"curves-qwen-q8-dspark-p0|$Q-Q8_0.gguf|$DK/dspark_qwen3_8b_block7.gguf|draft-dspark|0.0|experiments/runs/curves-qwen-q8-dspark-p0"
# Gemma 4 12B (8)
"curves-gemma-q4-mtp|$G-Q4_K_M.gguf|$DK/mtp-gemma-4-12b-it-Q8_0.gguf|draft-mtp||experiments/runs/curves-gemma-q4-mtp"
"curves-gemma-q4-dflash-f16|$G-Q4_K_M.gguf|$DK/gemma-4-12B-it-DFlash-F16.gguf|draft-dflash||experiments/runs/curves-gemma-q4-dflash-f16"
"curves-gemma-q4-dflash-q4|$G-Q4_K_M.gguf|$DK/gemma-4-12B-it-DFlash-Q4_K_M.gguf|draft-dflash||experiments/runs/curves-gemma-q4-dflash-q4"
"curves-gemma-q4-dflash-q8|$G-Q4_K_M.gguf|$DK/gemma-4-12B-it-DFlash-Q8_0.gguf|draft-dflash||experiments/runs/curves-gemma-q4-dflash-q8"
"curves-gemma-q5-mtp|$G-Q5_K_M.gguf|$DK/mtp-gemma-4-12b-it-Q8_0.gguf|draft-mtp||experiments/runs/curves-gemma-q5-mtp"
"curves-gemma-q5-dflash-f16|$G-Q5_K_M.gguf|$DK/gemma-4-12B-it-DFlash-F16.gguf|draft-dflash||experiments/runs/curves-gemma-q5-dflash-f16"
"curves-gemma-q8-mtp|$G-Q8_0.gguf|$DK/mtp-gemma-4-12b-it-Q8_0.gguf|draft-mtp||experiments/runs/curves-gemma-q8-mtp"
"curves-gemma-q8-dflash-f16|$G-Q8_0.gguf|$DK/gemma-4-12B-it-DFlash-F16.gguf|draft-dflash||experiments/runs/curves-gemma-q8-dflash-f16|-ub 512"
)
have_file() {
local f="$1"
[ -f "$f" ] && [ "$(stat -c%s "$f" 2>/dev/null || echo 0)" -gt 100000000 ]
}
run_job() {
local name="$1" out="$2"
shift 2
local rc
log "CURVE START: $name"
$BENCH --config-name "$name" --prompts "$SAMPLES" --n-tokens "$NTOK" \
--out "$out" --resume "$@"
rc=$?
case "$rc" in
0) log "CURVE DONE: $name (exit 0)"; OK_COUNT=$((OK_COUNT + 1)) ;;
2) log "CURVE WITH FAILURES: $name (exit 2) β prompts in errors.jsonl"; FAILED_COUNT=$((FAILED_COUNT + 1)) ;;
3) log "CURVE LOCK: $name (exit 3) β another runner on this --out; skipping"; FAILED_COUNT=$((FAILED_COUNT + 1)) ;;
*) log "CURVE FAILED: $name (exit $rc)"; FAILED_COUNT=$((FAILED_COUNT + 1)) ;;
esac
return "$rc"
}
run_config() {
local entry="$1"
local name target draft stype pmin out extra
IFS='|' read -r name target draft stype pmin out extra <<< "$entry"
[ -n "$out" ] || out="experiments/runs/$name"
if ! have_file "$target" || ! have_file "$draft"; then
log "SKIP: $name (missing target/draft)"
SKIP_COUNT=$((SKIP_COUNT + 1))
return
fi
local args=(--model "$target" --draft "$draft" --spec-type "$stype")
[ -n "$pmin" ] && args+=(--spec-draft-p-min "$pmin")
[ -n "$extra" ] && args+=(--extra "$extra")
run_job "$name" "$out" "${args[@]}"
}
# OOM-CHECK before the Gemma Q8 block (worst case g8+dflash-f16, -ub 512).
oom_check_g8() {
log "OOM-CHECK: gemma q8 + dflash f16 (llama-cli -ub 512, 1 prompt n=8)"
if "$LLAMA_CPP_BIN/llama-cli" -m "$G-Q8_0.gguf" -md "$DK/gemma-4-12B-it-DFlash-F16.gguf" \
--spec-type draft-dflash -ngl 99 -ngld 99 -n 8 -p "Hello." -ub 512 \
--no-conversation --single-turn --reasoning off -c 2048 -t 8 --seed 42 \
< /dev/null > /tmp/opencode/oom-check-curves.log 2>&1; then
log "OOM-CHECK: OK (gemma q8 usable with -ub 512)"
OOM_OK=1
else
log "OOM-CHECK: FAILED β SKIP the g8 configs (see /tmp/opencode/oom-check-curves.log)"
OOM_OK=0
fi
}
log "CURVES CHAIN START β ${#MATRIX[@]} configs with drafter Γ 180 prompts (acc-sample.jsonl)"
if [ "${DRY_RUN:-0}" = "1" ]; then
echo "DRY-RUN: curves matrix (${#MATRIX[@]}):"
for entry in "${MATRIX[@]}"; do
IFS='|' read -r dname dtarget ddraft dstype dpmin dout <<< "$entry"
echo " $dname | ${ddraft:-β} | ${dstype:-β} | ${dpmin:-β}"
done
echo "DRY-RUN: end (${#MATRIX[@]} configs, ~15 min each β 4.5 h)"
exit 0
fi
T0=$(date +%s)
for entry in "${MATRIX[@]}"; do
name="${entry%%|*}"
case "$name" in
curves-gemma-q8-*)
if [ "$G8_CHECKED" -eq 0 ]; then
oom_check_g8
G8_CHECKED=1
fi
if [ "$OOM_OK" != "1" ]; then
log "SKIP: $name (OOM-CHECK g8 failed)"
SKIP_COUNT=$((SKIP_COUNT + 1))
continue
fi
;;
esac
run_config "$entry"
done
DUR=$(( $(date +%s) - T0 ))
log "CURVES CHAIN DONE (duration ${DUR}s β $((DUR / 3600))h $((DUR % 3600 / 60))m)"
log "CURVES SUMMARY: OK=$OK_COUNT FAILED=$FAILED_COUNT SKIP=$SKIP_COUNT"
if [ "$FAILED_COUNT" -eq 0 ] && [ "$SKIP_COUNT" -eq 0 ]; then
log "CURVES CHAIN: exit 0"
exit 0
fi
log "CURVES CHAIN: exit 1 (FAILED=$FAILED_COUNT SKIP=$SKIP_COUNT β check queue-curves.log)"
exit 1
|