frank-primary: max-possible window (241664) + reasoning/tool contract

Night ladder result (Frank's subtract-16k method): 262144 and 245760 both OOM
at CUDA graph capture ('Tried to allocate 76.00 MiB ... 0 bytes free'), 237568
passed (KV 718,606 tokens), and the +4096 bonus step PASSED -> 241664 is max
possible and DEPLOYED at util 0.98 (KV 732,359 tokens / 3.03x concurrency at
241,664-token requests). Util stays 0.98: lowering it shrinks the engine's own
budget instead of buying slack.

Client contract restored (the GLM rollback d91379d dropped all three and the
qwen rollback inherited the gap): --reasoning-parser qwen3 fixes the malformed
thinking block (thinking was landing inline in content with a dangling
</think> and a null reasoning field), --enable-auto-tool-choice with
--tool-call-parser qwen3_xml makes tools work, and
--default-chat-template-kwargs enables enable_thinking + preserve_thinking.

Harness: contextWindow 241664 (compaction gap recomputed), preserve_thinking
moved into chat_template_kwargs.
This commit is contained in:
Frank
2026-10-01 03:08:52 -07:00
parent e8524d4046
commit 7cab15ac39
7 changed files with 210 additions and 53 deletions
+30 -10
View File
@@ -8,12 +8,12 @@
# restorable from the tag.
#
# Every number here was QUALIFIED by boot probe on 2026-10-01 (not inherited):
# * MAXLEN 262144 x SEQS 3 (786,432 tokens) at bf16 KV boots at
# KV_BYTES 11,047,010,304 PER RANK: the engine measured "KV cache size:
# 798,280 tokens; Maximum concurrency for 262,144 tokens per request:
# 3.05x". The pool holds all three full windows with an 11,848-token
# margin. Measured decode at the winner shape: 39.38/38.79/36.42 tok/s
# (166/1087/4064 ctx).
# * MAXLEN 241664 x SEQS 3 (724,992 tokens) at bf16 KV is the DEPLOYED
# shape (2026-10-01 night ladder): KV_BYTES 10,184,000,000 PER RANK,
# engine measured "KV cache size: 732,359 tokens; Maximum concurrency
# for 241,664 tokens per request: 3.03x". 262144 and 245760 both OOMed
# at graph capture (76 MiB short / 0 bytes free); 237568 passed at
# 718,606 tokens and the +4096 bonus step passed and won.
# * KV_BYTES is PER RANK. The old "7.2 GiB ceiling, 9/16 GiB OOM" law was
# the MTP4 WORKSPACE: the spec-era pool measured 729,545 tokens because
# the drafter reserved ~2.6 GiB/rank beside the pool. No-spec bf16 takes
@@ -59,12 +59,32 @@ FRANK_PRIMARY_PUBLISH=7770:7770
# hoc experiment identity (both hold the GPUs / name registrations).
FRANK_PRIMARY_LEGACY_CONTAINERS="frank-primary-r9v qwen-fp8"
# --- qualified engine shape ---------------------------------------------------
FRANK_PRIMARY_MAXLEN=262144
# --- qualified engine shape (2026-10-01 night ladder, Frank's method) ---------
# MAXLEN ladder per Frank: 262144 OOMed in graph capture (76 MiB short),
# 245760 OOMed (0 bytes free at graph capture), 237568 PASSED (718,606
# tokens / 3.0x), then the +4096 bonus attempt 241664 PASSED and is
# PRODUCTION (KV 732,359 tokens / 3.03x at 241,664-token requests).
FRANK_PRIMARY_MAXLEN=241664
FRANK_PRIMARY_SEQS=3
FRANK_PRIMARY_KV_BYTES=11047010304
FRANK_PRIMARY_KV_BYTES=10184000000
FRANK_PRIMARY_KV_DTYPE=auto
FRANK_PRIMARY_MNBT=1024
FRANK_PRIMARY_GATHER_CHUNKS=32
FRANK_PRIMARY_GATHER_LANES=64
FRANK_PRIMARY_UTIL=0.90
FRANK_PRIMARY_UTIL=0.98
# --- client contract: reasoning split, tools, preserve_thinking ----------------
# Without --reasoning-parser the engine leaves the thinking text INLINE in
# `content` with a dangling `</think>` and a null `reasoning` field (measured
# 2026-10-01: content = 'We need answer...Brief.\n</think>\n\n391') — the
# malformed thinking block clients choke on. The qwen3 parser splits it
# properly. The GLM rollback (d91379d) had dropped all three of these; the
# working values are the ones ecaad36 shipped for this model.
FRANK_PRIMARY_REASONING_PARSER=qwen3
# Tools: --enable-auto-tool-choice + the qwen3_xml parser is what makes
# tool_calls work here (without it, tool_choice auto returns 400).
FRANK_PRIMARY_TOOL_PARSER=qwen3_xml
# preserve_thinking keeps prior thinking blocks in the rendered prompt across
# turns; enable_thinking makes thinking the server-side default. Verified the
# payload's tokenizer_config template consumes both keys.
FRANK_PRIMARY_CHAT_TEMPLATE_KWARGS='{"enable_thinking": true, "preserve_thinking": true}'
+7 -1
View File
@@ -47,7 +47,10 @@ set +a
: "${FRANK_PRIMARY_MAXLEN:?FRANK_PRIMARY_MAXLEN must be set}"
: "${FRANK_PRIMARY_SEQS:?FRANK_PRIMARY_SEQS must be set}"
: "${FRANK_PRIMARY_KV_BYTES:?FRANK_PRIMARY_KV_BYTES must be set (PER RANK)}"
: "${FRANK_PRIMARY_KV_DTYPE:?FRANK_PRIMARY_KV_DTYPE must be set (fp8 = q8/q8 KV)}"
: "${FRANK_PRIMARY_KV_DTYPE:?FRANK_PRIMARY_KV_DTYPE must be set (auto = bf16 KV)}"
: "${FRANK_PRIMARY_REASONING_PARSER:?FRANK_PRIMARY_REASONING_PARSER must be set (qwen3)}"
: "${FRANK_PRIMARY_TOOL_PARSER:?FRANK_PRIMARY_TOOL_PARSER must be set (qwen3_xml)}"
: "${FRANK_PRIMARY_CHAT_TEMPLATE_KWARGS:?FRANK_PRIMARY_CHAT_TEMPLATE_KWARGS must be set}"
# Capture podman's output BEFORE grepping: under `set -o pipefail`, the
# classic `podman images | grep -q` pattern races — grep exits on its first
# match, podman dies SIGPIPE (141) writing the remaining lines, and pipefail
@@ -115,6 +118,9 @@ podman run -d --name "$FRANK_PRIMARY_CONTAINER" \
--kv-cache-memory-bytes "$FRANK_PRIMARY_KV_BYTES" \
--kv-cache-dtype "$FRANK_PRIMARY_KV_DTYPE" \
--enable-prefix-caching \
--enable-auto-tool-choice --tool-call-parser "$FRANK_PRIMARY_TOOL_PARSER" \
--reasoning-parser "$FRANK_PRIMARY_REASONING_PARSER" \
--default-chat-template-kwargs "$FRANK_PRIMARY_CHAT_TEMPLATE_KWARGS" \
--trust-remote-code \
> "$LOG" 2>&1