Runbook section `2026-10-11 — unquantized KV at 2 x 200,000`: the dtype law (only bf16|fp8, no K/V split; the QSA block key is dtype-fixed, which is why bf16 costs 1.89x and not 2x), the pool formula that reproduces both live boots within 0.1%, the seqs-3-to-2 provenance (the tcclaviger fork's torch.compile constraint, not radiance's), the boot ledger, and the A/B. The A/B, fp8 control arm through a transient FRANK_ARCHON_ENV_FILE drop-in: prefill -29% (4,379 -> 3,126 cold), TTFT at the full window +25% (the 2 x 197k pair: 110.5 s -> 138.1 s), decode inside the +-3% band on two of three passes, draft acceptance UP 0.661 -> 0.740. The price is prefill, not decode. Open call for Frank: keep exact KV, or take the cheap fp8 2 x 200k fit (pool 3,648). Also corrects two stale index entries (w4dn8 said STAGED, fp8-native said ACTIVE), adds the worklog entry, and commits the verification tool as scripts/probe-frank-archon-kv.py — it carries the probe law that cost two false negatives: radiance answers in reasoning_content, so a chat probe with a small budget reads as empty content + finish_reason stop on a healthy server. Tests 368/368.
229 lines
14 KiB
Bash
229 lines
14 KiB
Bash
# frank-archon.env — radiance (StillDeadcode, Apache-2.0) serving
|
|
# ukisai/Swift1.5-Qwen3.8-Flash-Next converted to GPTQ w4 (MODEL_FILE below,
|
|
# built by scripts/convert-swift15-w4dn8.sh) on BOTH R9700s (TP=2),
|
|
# dankserver :7770.
|
|
#
|
|
# SHAPE (2026-10-11): 2 decode slots x 200,000 tokens with an UNQUANTIZED
|
|
# (bf16) KV cache — the pool is sized for the pair, and the weights slab pays
|
|
# for it (see the KV block). The fp8-native payload this file was written for
|
|
# is the rollback target and keeps its own trio under the fp8-native runbook.
|
|
#
|
|
# 2026-10-05 cutover from FreeToken (PR #587 ROCm, one card, experts in
|
|
# pinned host RAM; git tag frank-archon-freetoken-pr587-20261005 is the
|
|
# pre-cutover state — its unit/env/serve trio and Dockerfile are all in the
|
|
# tag and rebuildable). Before that: tcclaviger vLLM fork (tag
|
|
# frank-archon-vllm-shapeG-20261003).
|
|
#
|
|
# WHY RADIANCE: the engine is C++/HIP with libr4d kernels built for
|
|
# gfx1201, drives `podman run` directly from the digest-pinned
|
|
# stilldeadcode/radiance image (287 MiB; host needs only the amdgpu driver),
|
|
# and its qwen4exp plugin reads the modelopt FP8 encoding NATIVELY
|
|
# (`X.weight_scale_inv` is the scale plane — checkpoint.h). The PLE n-gram
|
|
# table (51B params, 47.7 GiB) is served from pinned host RAM via io_uring
|
|
# reads — Frank's call: "Native FP8. Experts from ram. Pin the PLE to ram."
|
|
# The 4-bit-codebook publisher shape (qwen3.8-next-flash-fp8-iq4r-moe.rad,
|
|
# --host-pool-mib 12288) remains the documented fallback if the native
|
|
# container proves unbootable.
|
|
#
|
|
# PAYLOAD: /home/dank/models/rad/qwen4exp-fp8-native.rad — a rad-convert
|
|
# NO-RECIPE pure copy of the official 131-shard checkpoint (every weight
|
|
# keeps its block-FP8 encoding; ~161 GiB). The convert runs against a
|
|
# staging dir whose config.json drops `quantization_config`: the descriptor
|
|
# string is only the plugin SELECTION key (spec §2.4 — exact match, no
|
|
# fallback), and no shipped plugin claims (qwen4exp, "fp8"); the shipped
|
|
# qwen4exp plugin claims (qwen4exp, "") which is what recipe-built
|
|
# containers carry. Per-weight encodings are data, not the descriptor —
|
|
# removing the key changes nothing about what the weights hold. Built by
|
|
# scripts/build-frank-archon-rad.sh (staging + convert + rad-info).
|
|
#
|
|
# SERVING FACTS (docs/GUIDE.md, docs/DOCKER.md, compose/flashnext.yaml):
|
|
# - The HTTP listener binds AFTER the full load (main.cpp: engine.start()
|
|
# then engine.serve()) — during load the port refuses connections, so a
|
|
# bare curl /health gate is honest. /health == /ping: 200 JSON while
|
|
# serving, 503 only while stopping (core/server/admin.cpp:385).
|
|
# - Reasoning: --reasoning-format defaults to auto, emitting thinking in
|
|
# `reasoning_content` (config.cpp). Tool calls: the qwen3.8 dialect, from
|
|
# the chat format. Both need no parser flags.
|
|
# - Sampling: the OpenAI endpoint accepts temperature, top_p, top_k, min_p,
|
|
# typical_p, presence_penalty, frequency_penalty, repetition_penalty,
|
|
# repeat_last_n, chat_template_kwargs, reasoning_effort,
|
|
# enable_thinking, preserve_thinking (core/server/oai.cpp:194-205) —
|
|
# models.yml's extraBody set is fully inside it. Unknown params are
|
|
# refused (400), which is why nothing unverified rides the wire.
|
|
# - MTP: the official checkpoint carries the mtp.* head (3,101 tensors,
|
|
# mtp_num_hidden_layers=1) and the plugin probes draft depth 3 — the
|
|
# publisher's throughput peak for this model. Stated explicitly with
|
|
# --num-speculative-tokens 3.
|
|
# - The fused TP all-reduce is declared over max-num-seqs x
|
|
# (1 + --num-speculative-tokens) rows; 2 x 3 = 6 rows, under the 25-row
|
|
# exactness bound of the wht6 wire.
|
|
# Engine pin: Codeberg tag v1.0.13 (commit 53282fa), Docker Hub tag 1.0.13,
|
|
# index digest below. REJECTED UPGRADE: 1.2.0 (sha256:665775ed1d90de6dbb
|
|
# 25558e07fc60d20328f1346f96f3c6e00845eb763f01fa, tag 1.2.0, commit
|
|
# e95d397) was benched 2026-10-06 on this exact shape (fp8-native rad,
|
|
# vram pair, spec 2, seqs 3, 43.6k greedy probe): decode 29.21 t/s and
|
|
# draft acceptance 0.7123 vs the 1.0.13 control's 30.08 and 0.7549.
|
|
# Acceptance on the greedy harness is deterministic (the control
|
|
# reproduced the recorded 0.755 exactly), so the drop is a real numerics
|
|
# change — the 1.2.0 MoE weight-rotation change (92b8aaf) is the named
|
|
# suspect; decode loss tracks the acceptance ratio (0.943 vs 0.945).
|
|
# The vram-pair translation itself is exact (1.2.0 boot ledger took
|
|
# vram_weights 25.46 GiB / vram_kv 3.46 GiB per card byte-identical to
|
|
# the 1.0.13 ledger at EVC 0.82). Re-test 1.2.0+ when the rotation change
|
|
# is untangled; 1.2.0 also REMOVED --expert-vs-cache-ratio in favour of
|
|
# the --vram-weights-mib / --vram-kv-mib pair (core/config.cpp) — this
|
|
# file already uses the pair, which BOTH pins accept (rollback symmetry).
|
|
FRANK_ARCHON_IMAGE=stilldeadcode/radiance@sha256:4c3f484564bb2872784e46b0a59cbd71becc9c1e746e301a3596ffae253c322e
|
|
# The .rad container FILE (mounted under /models) and the state dir for the
|
|
# prefix-cache disk tier (mounted rw at /data). The model dir holds ONLY
|
|
# .rad files; the raw HF download and its staging dir live beside it and
|
|
# are never mounted.
|
|
FRANK_ARCHON_MODEL_DIR=/home/dank/models/rad
|
|
FRANK_ARCHON_MODEL_FILE=qwen4exp-swift15-w4dn8-i8-hc8m.rad
|
|
FRANK_ARCHON_STATE_DIR=/home/dank/radiance-state
|
|
# The state dir's tune/ subdirectory holds rad-tune's kernel-selection
|
|
# cache (the engine's selector reads $RADIANCE_HOME/tune/<machine>.tune
|
|
# at boot; $RADIANCE_HOME defaults to /opt/radiance, in the image, so the
|
|
# cache must ride a host mount — serve script mounts it, see the runbook's
|
|
# "Tuning levers").
|
|
# Container identity is the SERVICE name (Frank's call, 2026-10-05): one
|
|
# name across systemctl and podman ps. The runtime changes; the name does
|
|
# not. The legacy list retires every predecessor identity that could hold
|
|
# the GPUs or the port.
|
|
FRANK_ARCHON_CONTAINER=frank-archon
|
|
FRANK_ARCHON_LEGACY_CONTAINERS="frank-archon-qwen frank-archon-r9v qwen-fp8 glm-probe"
|
|
# Served model id — Protoss name (wire rename 2026-10-09). The container,
|
|
# unit, scripts and this file keep the frank-archon name above; only the
|
|
# alias on the wire moved. Radiance validates the requested model name, so
|
|
# every client (harness, bench scripts, probes) MUST send this value.
|
|
FRANK_ARCHON_SERVED_NAME=frank-archon
|
|
FRANK_ARCHON_PORT=7770
|
|
# Frank's chat-template call: froggeric's fixed Qwen3.8 template (the
|
|
# repo's root chat_template.jinja, vendored here; the checkpoint's own
|
|
# template is baked into the .rad by rad-convert and this overrides it).
|
|
# Radiance derives the reasoning/tool-call reply format from it.
|
|
FRANK_ARCHON_TEMPLATE=/home/dank/serverAppConfigs/scripts/qwen38-froggeric-v22.5.jinja
|
|
|
|
# --- engine shape (the boot ledger arbitrates every number below) ---------
|
|
# Tensor parallel: BOTH R9700s. The board swap (2026-09-20, ProArt B850
|
|
# x8/x8 on root ports) made collectives legal on this host; radiance's TP
|
|
# wire is libr4d's own, not RCCL.
|
|
FRANK_ARCHON_TP=2
|
|
# Lossy WHT 6-bit wire for large all-reduces (publisher's production choice:
|
|
# +5.6-6.3% prefill, ~-1.3% 8-stream decode at TP2). min-kb stays the
|
|
# engine default.
|
|
FRANK_ARCHON_TP_WIRE=wht6
|
|
# Decode slots: TWO, so the served window is a CAPACITY CONTRACT — two
|
|
# concurrent conversations of --max-model-len fit the KV pool (see the KV
|
|
# block below). The "seqs 2 cannot boot" law is NOT radiance's: it was the
|
|
# tcclaviger vLLM fork's torch.compile shape specialization on
|
|
# query_start_loc (ConstraintViolationError, measured 2026-10-02, retired
|
|
# with that runtime). Radiance booted seqs 2 at the fp8-native first boot,
|
|
# and the 2026-10-06 decode sweep measured seqs 2 and 3 statistically tied
|
|
# (30.9-33.1 t/s, inside the +-3% noise floor). Side benefit: the fused TP
|
|
# all-reduce is declared over seqs x (1 + spec) = 6 rows, under the 25-row
|
|
# bound at which the wht6 wire stays EXACT (single-sequence decode and any
|
|
# step of <= 25 rows is bit-exact; only busier steps are lossy).
|
|
FRANK_ARCHON_MAX_SEQS=2
|
|
# Served window. Native is 262,144; 200,000 is the publisher's production
|
|
# value (compose) and what models.yml's contextWindow must quote — a longer
|
|
# prompt is refused by the engine, never truncated. The engine treats
|
|
# `kv group tokens >= max-model-len` as a HARD limit ("ONE request longer
|
|
# than N tokens is accepted by the API and then refused as too large to ever
|
|
# fit — this is a hard limit, not a backing ratio"), so the pool is sized
|
|
# for seqs x maxlen, not for one sequence.
|
|
FRANK_ARCHON_MAX_MODEL_LEN=200000
|
|
FRANK_ARCHON_PLACEMENT=expert_tiered
|
|
# Pinned host pool for the expert rows that do not fit VRAM. vram_weights and
|
|
# this pool serve the per-rank resident set TOGETHER: at the fp8-KV pair
|
|
# (26071/3543) the ledger showed the VRAM slab filled to 259 KiB of slack,
|
|
# i.e. the pair was exactly sized. Cutting vram-weights by 3.8 GiB to pay for
|
|
# the bf16 KV pool SPILLS ~3.8 GiB/rank here, so the pool moves with it —
|
|
# under-sizing it is a boot failure (36864 refused the boot in the fp8 era).
|
|
# The boot ledger's coverage line remains the referee, not this arithmetic.
|
|
FRANK_ARCHON_HOST_POOL_MIB=44928
|
|
# VRAM left unclaimed per card (publisher default 96 MiB).
|
|
FRANK_ARCHON_GPU_HEADROOM_MIB=96
|
|
# VRAM split of claimed memory per card, MiB (0 = derive from the card).
|
|
# THE CEILING, measured on this host 2026-10-11: card 31,856 MiB, a boot
|
|
# consumes 1,710 MiB OUTSIDE both budgets (driver context + activation arena
|
|
# 990 + hardware queues 100 + headroom 96 + step staging), and the fp8 pair
|
|
# settled at 1,379 MiB free — so `vram_weights + vram_kv <= 29,120 MiB` keeps
|
|
# >= 1 GiB free. The pair below is exactly that sum.
|
|
# THE PRICE, and it is paid twice: on this engine idle KV VRAM is ALSO the
|
|
# expert cache's spillover (`mover: 2275 slots can be lent out of the KV
|
|
# cache (2.69 GiB)`, `arena: lends 740 MiB while steps are <= 256 tokens`),
|
|
# so a bigger KV pool steals weight residency from the slab AND from the
|
|
# lendable cache. Priors on this card/model: stealing 2.14 GiB of weights for
|
|
# a bigger pool (MAX_MODEL_LEN 262144) cost 2.5% decode; the EVC ladder's
|
|
# other direction (0.82 -> 0.84, +2.5 GiB weights) cost 8.9%. Expect -3..-8%
|
|
# vs the fp8 control (136 t/s median at 44.5k depth, acceptance 0.7246,
|
|
# ~190 t/s on a live 512-token probe); re-tune from a boot ledger + probe,
|
|
# never from that estimate.
|
|
FRANK_ARCHON_VRAM_WEIGHTS_MIB=22208
|
|
FRANK_ARCHON_VRAM_KV_MIB=6912
|
|
# KV cache UNQUANTIZED (bf16). This engine's flag takes ONLY bf16|fp8 — there
|
|
# is ONE kv_dtype for the whole cache, so "exact K, quantized V" (llama.cpp's
|
|
# --cache-type-k/--cache-type-v pair, which is what frank-zealot runs) is
|
|
# UNSERVABLE here: the rung below bf16 is fp8 on both halves.
|
|
# Measured per-rank cost, read out of the boot ledger's group table (fp8 boot
|
|
# 2026-10-08, bf16 boot 2026-10-11):
|
|
# kv_attn 13 layers, 4-token blocks, page 26.00 KiB (fp8) -> 52.00 KiB
|
|
# kv_qsa_bkey 13 layers, 4-token blocks, page 3.25 KiB at BOTH dtypes —
|
|
# the QSA block key is an index, not attention state, and does
|
|
# NOT follow --kv-cache-dtype
|
|
# => 7.3125 KiB/token fp8, 13.8125 KiB/token bf16: bf16 costs 1.89x fp8,
|
|
# not 2x, precisely because the bkey plane is dtype-fixed.
|
|
# The dtype-INDEPENDENT terms also live in the pool: kv_gdn_state 54 MiB x 2
|
|
# copies per sequence (+ conv/tail/ple ~= 110 MiB a sequence) and the prefix
|
|
# checkpoint region 8 x 55.99 = 448 MiB. So:
|
|
# pool_mib >= tokens x 13.8125 KiB + 110 x seqs + 448
|
|
# 6912 -> (6912 - 220 - 448) x 1024 / 13.8125 = 462,946 tokens; the engine
|
|
# reported 462,752 (0.04% page rounding) — 2 x 200,000 with 62k of slack,
|
|
# and the ledger says it outright: "backs 2 sequences all at 200000 tokens
|
|
# at once, which is the worst case".
|
|
# (the fp8 pool of 3543 gave 386,904 — it never held 2 x 200k, it held 1.93
|
|
# sessions, and a third long conversation preempted to the host/disk tiers).
|
|
# Secondary cost: the prefix-cache entry grows with the attention plane
|
|
# (one entry 58.50 KiB at fp8 -> 110.50 KiB at bf16, measured on the two boot
|
|
# ledgers' `kv tier transfer` lines), so the host tier below doubles to keep
|
|
# the same number of parked conversations, out of RAM the host has
|
|
# (104 GiB available with the service loaded).
|
|
FRANK_ARCHON_KV_DTYPE=bf16
|
|
# Spec decode: the checkpoint's own MTP head at the publisher's depth-3
|
|
# operating point (probe() returns 3 when mtp_num_hidden_layers > 0; the
|
|
# flag states it so the ledger records the intent).
|
|
FRANK_ARCHON_SPEC_TOKENS=2
|
|
FRANK_ARCHON_MAX_BATCHED_TOKENS=2048
|
|
# Prefix cache tiers (publisher pattern; disk tier sized for 2 slots).
|
|
# The host tier is sized in ENTRIES, and one entry doubles with the cache
|
|
# dtype (58.50 KiB at fp8 -> 117 KiB at bf16, per the ledger's `kv tier
|
|
# transfer` line): 4096 MiB at bf16 parks ~1.4 sessions of 200k where it
|
|
# parked ~2.9 at fp8. Doubled to keep the capacity, at RAM the host has
|
|
# (104 GiB available with the service loaded).
|
|
FRANK_ARCHON_PREFIX_HOST_MIB=8192
|
|
FRANK_ARCHON_PREFIX_DISK_MIB=65536
|
|
# Frank's pin law: the PLE n-gram table (47.7 GiB) serves from pinned host
|
|
# RAM the cards read. `ram` REFUSES the start if the memlock limit is too
|
|
# small — the unit's LimitMEMLOCK=infinity is the other half of this law.
|
|
FRANK_ARCHON_NGRAM_PLACEMENT=ram
|
|
# TTM preflight: the pinned ledger (2 x 44 GiB pools + 47.7 GiB PLE + 8 GiB
|
|
# prefix host = ~147 GiB) rides TTM's shared pages, capped by ttm's
|
|
# pages_limit (the current kernel exposes NO pages_max; the cap function
|
|
# takes the min over the knobs that exist). Below the plan the load dies
|
|
# mid-pin with an allocator error instead of this named refusal — raise the
|
|
# knob first (runtime sysfs write; kernel cmdline fallback + one reboot only
|
|
# if the file is read-only), see the runbook. Cap raised 2026-10-05 to
|
|
# 52,428,800 pages = 200 GiB, which still clears this floor.
|
|
FRANK_ARCHON_TTM_MIN_MIB=150000
|
|
# Escape hatch for boot-ladder experiments. Unset -> no extra argv. Keep
|
|
# multi-flag values as one string; the serve script expands it unquoted on
|
|
# purpose.
|
|
FRANK_ARCHON_EXTRA_ARGS=
|
|
# The .rad's minimum size in MiB (deployer gate; a truncated convert is a
|
|
# guaranteed long-timeout boot instead of a fast failure). The converted
|
|
# container measured 177,109 MiB (1,857,127,997,440 B = 173.0 GiB; the
|
|
# plan-only estimate 172.76 GiB covers the data planes but not the metadata
|
|
# tail) - floor sits just under the payload.
|
|
FRANK_ARCHON_RAD_MIN_MIB=110000
|