fix(#62): frank-dragoon's reasoning_effort contract, measured instead of assumed #63
+68
-17
@@ -16,7 +16,7 @@ providers:
|
||||
auth: none
|
||||
models:
|
||||
- id: frank-archon
|
||||
# Model id renamed from frank-archon on 2026-10-08 (official
|
||||
# Model id renamed from frank-medium on 2026-10-08 (official
|
||||
# unit-name scheme; the systemd service, scripts and runbooks keep
|
||||
# the frank-archon name — service names are unchanged).
|
||||
# Server-side compaction routes to compaction.remoteEndpoint in
|
||||
@@ -82,9 +82,11 @@ providers:
|
||||
auth: none
|
||||
models:
|
||||
- id: frank-dragoon
|
||||
# Model id renamed from frank-dragoon on 2026-10-08 (official
|
||||
# Model id renamed from frank-large on 2026-10-08 (official
|
||||
# unit-name scheme; the service/unit/scripts keep the frank-dragoon
|
||||
# name — service names are unchanged).
|
||||
# name — service names are unchanged). The pre-rename id is
|
||||
# `frank-large`, recorded here because the callsign rename overwrote
|
||||
# its own explanation and left "renamed from frank-dragoon".
|
||||
name: "frank-dragoon (dankclaw-gpu)"
|
||||
# Server-side compaction runs on the compaction.remoteEndpoint in
|
||||
# config.yml (192.168.0.143:7771 — frank-zealot's 3090); this steers the
|
||||
@@ -111,31 +113,80 @@ providers:
|
||||
maxTokens: 45056
|
||||
reasoning: true
|
||||
# VISION ON as of 2026-10-06: the v2 vision tower loads beside the
|
||||
# checkpoint (HALOGEN_VISION_TOWER; red-PNG probe verified on the
|
||||
# card). image_url content parts only — the legacy top-level
|
||||
# images field is the frank-zealot trap, do not repeat it here.
|
||||
# checkpoint (HALOGEN_VISION_TOWER; priced at 0.8 GiB in the boot
|
||||
# ledger, and re-probed 2026-10-21 — a 512 px solid-red PNG comes back
|
||||
# "Red" at 282 prompt tokens). image_url content parts only — the
|
||||
# legacy top-level images field is the frank-zealot trap, do not
|
||||
# repeat it here.
|
||||
input: [text, image]
|
||||
compat:
|
||||
# flash-server emits thinking as `reasoning_content` — same
|
||||
# field as every engine this endpoint has run, no harness
|
||||
# change needed.
|
||||
reasoningContentField: "reasoning_content"
|
||||
# Same Qwen3.8 template family (it ships inside the tokenizer
|
||||
# bundle): any reasoning_effort outside {xhigh, medium, low} is
|
||||
# rejected, not clamped — the fold stays mandatory.
|
||||
# flash-server validates reasoning_effort against its own list and
|
||||
# 400s anything else, naming it: "reasoning_effort 'maximum'
|
||||
# unsupported; use minimal|low|medium|high|xhigh|max|none" (measured
|
||||
# 2026-10-21). Every omp level is already spelled by the engine, so
|
||||
# the map is identity — it exists to record that, not to fold. An
|
||||
# earlier version rewrote high->xhigh and minimal->low to stop
|
||||
# rejections that do not exist, and the rewrite asked the engine for
|
||||
# a different thinking budget than the caller named. Levels really do
|
||||
# differ here: thinking length on one prompt at max_tokens 2048
|
||||
# measured low 766 tokens, xhigh 614, max 1049 with the block closed
|
||||
# at 1024 (reasoning_closed_at). The harness passes an unmapped level
|
||||
# through verbatim (`compat.reasoningEffortMap?.[effort] ?? effort`),
|
||||
# so removing an entry is a pass-through, never a 400.
|
||||
#
|
||||
# `max` still does not reach the engine, and the map is not why: the
|
||||
# harness clamps the requested effort to the model's own effort ladder
|
||||
# before the map applies, and its ladder for this model tops out at
|
||||
# xhigh — captured on the wire 2026-10-21, `:max` left as
|
||||
# `reasoning_effort: "xhigh"` with this identity map in place. The
|
||||
# `max` row below is the engine-side half of the contract; it takes
|
||||
# effect the moment the harness ladder gains `max`, and nothing here
|
||||
# can force it sooner.
|
||||
#
|
||||
# Thinking OFF needs an explicit mode. The default disable mode sends
|
||||
# the LOWEST effort rather than a switch — `:off` left the wire as
|
||||
# `reasoning_effort: "minimal"` (captured), and minimal still thinks:
|
||||
# a canned 26-token block on every "off" request. `none-effort` makes
|
||||
# the harness send `reasoning_effort: "none"`, which this engine
|
||||
# honours as a real switch: `reasoning_tokens: 0`, answer only, no
|
||||
# thinking block in the rendered output (both verified 2026-10-21).
|
||||
#
|
||||
# Re-measure before changing any of it. The allow-list, in the
|
||||
# engine's own words:
|
||||
# curl -s :7770/v1/chat/completions -H 'content-type: application/json' \
|
||||
# -d '{"model":"frank-dragoon","messages":[{"role":"user","content":"x"}],
|
||||
# "reasoning_effort":"maximum"}'
|
||||
# -> 400 "reasoning_effort 'maximum' unsupported; use
|
||||
# minimal|low|medium|high|xhigh|max|none"
|
||||
# and read usage.completion_tokens_details.reasoning_tokens at
|
||||
# max_tokens 2048 to see the levels separate. The wire itself is
|
||||
# settled by pointing a scratch HOME at a logging proxy on :7799 that
|
||||
# forwards to :7770 and running `omp --model …:off` — config claims
|
||||
# are worth exactly what their last capture says.
|
||||
reasoningDisableMode: none-effort
|
||||
reasoningEffortMap:
|
||||
minimal: low
|
||||
minimal: minimal
|
||||
low: low
|
||||
medium: medium
|
||||
high: xhigh
|
||||
max: xhigh
|
||||
# The card's thinking recipe, on the wire. The flash-server
|
||||
# engine HAS a server-side sampler (HALOGEN_TEMPERATURE/TOP_P/
|
||||
# TOP_K = 1.0 / 0.95 / 20 in frank-dragoon.env) — these match it,
|
||||
# so per-request values are consistent, not load-bearing.
|
||||
high: high
|
||||
xhigh: xhigh
|
||||
max: max
|
||||
# The card's thinking recipe, on the wire. The flash-server engine
|
||||
# HAS a server-side sampler (HALOGEN_TEMPERATURE/TOP_P/TOP_K =
|
||||
# 1.0 / 0.95 / 20 in frank-dragoon.env), but an omitted parameter is
|
||||
# the engine's choice, not a pinned one: top_k is sent explicitly so
|
||||
# the recipe survives someone editing HALOGEN_TOP_K. The engine
|
||||
# accepts top_k, min_p, presence_penalty and repetition_penalty
|
||||
# (measured 2026-10-21, all 200) — only the values this endpoint is
|
||||
# meant to run are pinned here.
|
||||
extraBody:
|
||||
temperature: 1.0
|
||||
top_p: 0.95
|
||||
top_k: 20
|
||||
|
||||
"llamacpp (dankclaw-3090)":
|
||||
baseUrl: http://192.168.0.143:7771/v1
|
||||
@@ -143,7 +194,7 @@ providers:
|
||||
auth: none
|
||||
models:
|
||||
- id: frank-zealot
|
||||
# Model id renamed from frank-zealot on 2026-10-08 (official
|
||||
# Model id renamed from frank-small on 2026-10-08 (official
|
||||
# unit-name scheme; the service/unit/scripts keep the
|
||||
# frank-zealot name — service names are unchanged).
|
||||
name: "frank-zealot (dankclaw-3090)"
|
||||
|
||||
@@ -20,6 +20,21 @@ This page is the bundle's **only** work log: one file, at the root. Never start
|
||||
second one in a subdirectory or under another name — `scripts/kb-lint.sh` reports any
|
||||
`log.md` that is not this one.
|
||||
|
||||
## 2026-10-21 — an effort map folding against rejections that never existed
|
||||
|
||||
`agent/models.yml` rewrote `minimal→low`, `high→xhigh` and `max→xhigh` for
|
||||
frank-dragoon to dodge 400s the engine does not send: flash-server's own error names
|
||||
its allow-list (`minimal|low|medium|high|xhigh|max|none`) and the harness passes an
|
||||
unmapped level through verbatim, so the fold only asked for a different thinking
|
||||
budget than the caller named. The map is identity now, and
|
||||
`reasoningDisableMode: none-effort` was added because the default disable mode does
|
||||
not disable — `:off` left as `reasoning_effort: "minimal"` and paid for a canned
|
||||
thinking block, where `none` returns `reasoning_tokens: 0`. Both settled by capturing
|
||||
the wire through a logging proxy rather than reading the config: a claim about what
|
||||
the harness sends is worth exactly its last capture. The same pass restored the three
|
||||
pre-callsign model ids (`frank-medium` / `frank-large` / `frank-small`) that the
|
||||
2026-10-08 rename had overwritten inside its own explanatory comments. Refs #62
|
||||
|
||||
## 2026-10-21 — a documented mode the panel never had
|
||||
|
||||
The home ultrawide had been running at 60 Hz for weeks while `desk-1-home.kdl`
|
||||
|
||||
Reference in New Issue
Block a user