Files
serverAppConfigs/serverAppConfigs-docs/LLM/frank-dragoon-flash-server-v2-swift15.md
T
Frank 13162e6615 docs(frank-dragoon): native-era runbook; retire the swift15 page
New LLM/frank-dragoon-flash-server-v2-native.md carries the shape with the
three deliberate deviations from the card (served id, SPEC_ADAPT=0, engine
pin 0.16.2), the memory ledger with the PIN_TRUNK rejection, the full
measured A/B table, and the companion law (hardlinked stock peonist files,
engine-tool certified). The swift15 page is re-banned RETIRED 2026-10-06 →
10-17 with its rollback terms; both indexes and AGENTS.md (topology table,
service section, runbook index) are re-keyed, and the root index also stops
describing the halogen-27B page as ACTIVE.
2026-10-17 22:18:00 -07:00

198 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# frank-dragoon — halogen-flash-server 0.16.2, Qwen3.8-Flash-Next v2 Swift1.5 ABLITERATED (Dankclaw, Strix Halo iGPU)
**RETIRED 2026-10-06 → 2026-10-17**, superseded by the native v2 conversion:
[[frank-dragoon-flash-server-v2-native]]. Rollback target — the payload
stays on disk at `/home/dank/models/halogen-flashnext-v2/`,
`scripts/download-frank-dragoon-flashnext.sh` re-verifies it, and restoring
the era is a revert of the 2026-10-17 swap commit. The 27B payload this era
replaced stays at `/home/dank/models/halogen-qwen3.8-27b/` with
`scripts/download-frank-dragoon-halogen.sh`. Everything below is the era as
it shipped; the engine-flag detail still governs the current page.
## Why this shape exists
Frank's ask: replace the frank-dragoon model with
`https://huggingface.co/Quat3rnion/halogen-swift1.5-qwen3.8-flash-next-v2-abliterated`.
That payload is an **abliterated Swift1.5 finetune of peonist's
Qwen3.8-Flash-Next v2 checkpoint in the v2 `.hgn` format** — a file that
loads ONLY in the **halogen-flash-server** engine line, NOT in the halogen
0.1.4 container that served the 27B dense checkpoint. The model move is
therefore a **full engine migration**, and the accepted-product facts flip
twice in the fleet's favour:
- the base is **abliterated** (the 27B halogen endpoint was a finetune of
the censored `Qwen/Qwen3.8-27B`; refusals were an accepted regression there),
- **vision is back** — the v2 vision tower loads beside the checkpoint and
the engine runs it (the 27B halogen engine silently ignored its encoder),
- **MTP speculative decoding returns** with the head inside the checkpoint
itself (the 27B shipped a DFlash2 drafter instead; comparable purpose,
different file plumbing),
- the card claims **53–57 t/s greedy decode, ~1,640 t/s prefill at 34k, ~72 %
fewer thinking tokens** than the censored 27B (905 mean), and **262,144
native context**. Publisher-card numbers — verify against live traffic
before quoting further (see Verification).
The engine is **closed-source**, ships as `ghcr.io/peonist-ai/
halogen-flash-server:0.16.2` (the version the model card's quickstart pins),
digest-pinned:
```
ghcr.io/peonist-ai/halogen-flash-server@sha256:0c61bf84ac22308a53f5d1ca6b86806702d7039e5ebc51cae4c66621b92fe04a
```
(3.6 GB image; RepoDigest captured at pull 2026-10-06. Card-tested fallback
if a future pin misbehaves: 0.15.1.)
## The payload — a triangle of files, all sha256-verified at fetch
| File | Bytes | Source repo @ revision | sha256 (LFS) |
|---|---|---|---|
| `qwen38-flash-next-v2-swift15-abliterated.hgn` | 66,687,678,464 | Quat3rnion/halogen-swift1.5-qwen3.8-flash-next-v2-abliterated @ main (`69a85db`) | `9c880b8ba48deabfa06172eff1e7572e4fe465e09e97faec6e50c3f6fdcac037` |
| `qwen38-flash-next-ngram.hgn` (REQUIRED) | 51,200,246,144 | peonist-ai/halogen-qwen3.8-flash-next @ `5cc17cea` | `3450acada94e19aabad88bd49b45eb70304820949c2240fc178067b20ae5dffe` |
| `qwen38-flash-next-vision.hgn` (enabled) | 897,916,416 | peonist-ai/halogen-qwen3.8-flash-next @ `e053f488` | `d62e0ae553fe88afd3833733d4a4c669f34d20fd8dfce4b9610525bed2134b10` |
| `tokenizer/` (6 files, flat dir) | 22.4 MB total | peonist @ `e053f488` | `tokenizer.json` is LFS `0997f410…` (byte-identical to the 27B-era copy); the rest are plain git blobs, size-checked |
Payload notes worth keeping:
- The deployed checkpoint is a **compacted r2** of the card's append-only
original (89,775,868,032 B → 66,687,678,464 B): the abliteration workflow
appends and the repo's `tooling/` compact drops dead padding; live tensors
are byte-identical, the LFS sha256 is the contract, and the 24 GiB saving
is why it fits.
- **`HALOGEN_MTP_HEAD` stays UNSET**: the MTP head is INSIDE the v2
checkpoint (the separate `qwen38-flash-next-mtp.hgn` sidecar is for a
different assembly and is deliberately not fetched).
- The **n-gram lookup table is REQUIRED**. The engine reads it beside the
checkpoint (documented fallback); the card's quickstart also names it
explicitly via `HALOGEN_NGRAM_TABLE`, and the serve script passes both —
the env var is belt-and-braces over the documented beside-the-checkpoint
default, and both mechanisms resolve to the same file.
- The tokenizer is fetched fresh from peonist @ `e053f488` into
`/home/dank/models/halogen-flashnext-v2/tokenizer/` — same flat-directory,
no-symlink law as every other payload (an HF cache snapshot's symlinks
dangle inside the container mount; both the serve gate and the deployer
refuse them).
Fetch: `scripts/download-frank-dragoon-flashnext.sh` (`--verify-only` to
re-check; `-f` + exact byte counts + LFS sha256 + resolve-the-CDN-then-`-C -`
resume law throughout; no token — the repos are public).
## Shape — the knobs that are not free
`scripts/frank-dragoon.env` carries the full rationale inline; the table:
| Env | Value | Why |
|---|---|---|
| `HALOGEN_CTX` | 262144 | per-slot HARD ceiling (the checkpoint's native window; a longer prompt is a 400 naming the limit, never truncation). **RAISED from 200192 on 2026-10-07 — the 400-zone law:** the harness clamps `max_tokens = min(45056, contextWindow − est − 4096)`, its chars/4 est UNDER-counts the rendered prompt by ~3 % (measured twice: est 152,938 → server 157,388, request over room by 354; est 158,906 → server 165,301, over by 2,300), and compaction only fires at 85 % of the harness window — so with window == engine ceiling, every request in the est ~146k–184k zone was a guaranteed 400. Harness window 217,088 = ceiling − 45k absorbs the error: worst-case request ≈ 219k ≤ 262,144 (≈10 % under-count headroom) |
| `HALOGEN_KV_SLOTS` | 2 | the 27B engine's "slots>1 disables the drafter" law does NOT carry over — on this engine batching and speculation coexist (the card's quickstart ships 2 slots WITH the head). 2 slots = concurrent capacity |
| `HALOGEN_KV_POOL_POSITIONS` | 524288 | explicit form of the default (2 × ctx), so the seam test pins the product; ~28 KiB/position ⇒ 14.0 GiB KV |
| `HALOGEN_HOST_RESERVE_GIB` | 20 | keeps the host honest (the w4b-era lesson) |
| `HALOGEN_SPEC_ADAPT` | **0** | MANDATORY (card): the default adaptive policy turns the MTP head off for whole requests after low acceptance and **halves decode**. The head stays on; temp-1.0 traffic pays some acceptance for it — accepted trade |
| `HALOGEN_MAX_TOK` / `HALOGEN_MAX_TOKENS_CAP` / `HALOGEN_QUEUE_TIMEOUT` | 8192 / 65536 / 7200 | 8192 is only the per-request DEFAULT (the harness sends at most its `maxTokens` 45,056); the cap/timeout pair is COUPLED per FLAGS.md (65536 at ~10 t/s serial needs > 6550 s) |
| `HALOGEN_TEMPERATURE` / `TOP_P` / `TOP_K` | 1.0 / 0.95 / 20 | the card's thinking recipe as SERVER-SIDE defaults — the engine HAS a sampler now, so an absent temperature is no longer greedy; models.yml extraBody matches it (consistent, not load-bearing) |
| `HALOGEN_WEIGHTS_LOCK` | 1 | card's belt-and-braces; the engine pins weights by default on v2 (`HALOGEN_FLASH_PIN_TRUNK=0` is a w4b-only knob and is REFUSED by v2) |
| `HALOGEN_MODEL_ID` / publish | **frank-dragoon** / 7770:8731 | served id renamed 2026-10-09 (service/unit/env keep `frank-dragoon`); engine port 8730 never published |
| MTP depth | default 2 | FLAGS.md: 2 is best all-round, 3 for code — Frank's traffic is agent/prose |
**Memory ledger** (121.2 GiB unified, the referee is the boot ledger):
weights ~62 GiB resident + KV 14.0 + arena ~8 (`3.8 + 8.4 × 8192/16384`)
+ vision ~2 ≈ **86 GiB engine-side**, + 20 host reserve = ~106 with
~15 GiB margin over the box's baseline co-tenancy. The 51.2 GB n-gram
table rides as mmap'd page cache beside the checkpoint — the card's own
quickstart arithmetic does not bill it as resident, but WATCH the ledger
at boot and re-size if the engine prints a clamp. Prompt cache is ON by
default (`PROMPT_CACHE=2`): a follow-up turn at 100k ctx costs ~2 s
instead of ~88 s cold — the big-TTFT win the 27B engine needed a manual
`HALOGEN_CACHE_MB` pin for is built in here.
## Engine contract facts (FLAGS.md of the flash-server repo)
- OpenAI chat **and** `/v1/responses` **and** `/v1/messages` **and**
`/v1/completions`; tool calls verified on the card; `response_format`
still unsupported (no constrained decoding).
- Thinking → **`reasoning_content`** (same field as every engine this
endpoint has run); the v2 chat template rejects `reasoning_effort`
outside `xhigh|medium|low` — the models.yml fold (high→xhigh) stays
mandatory.
- Vision: OpenAI `image_url` content parts only (the fleet's standard
contract; the legacy top-level `images` field is the frank-zealot trap).
≥256 px probe images or the model answers "video".
- `HALOGEN_MAX_TOKENS_CAP` over-cap is a 400 naming the limit — never a
truncation. `max_tokens` INCLUDES thinking.
- All flags read once at startup; every flag is BITWISE except
`HALOGEN_CK_OVERLAY`, `HALOGEN_MATMUL_TUNING_FILE`,
`HALOGEN_INDEXER_BUDGET`, `HALOGEN_COMPOSABLE_CONTEXT`. Unset
`HALOGEN_CHECKPOINT` defaults to `/models/qwen38-flash-next-v2.hgn`
with the lookup table beside it.
- Prompt-lookup drafting (3,3 window) rides beside the MTP head by
default and is byte-identical to greedy verification where it fires.
- Watchdog: `HALOGEN_ENGINE_WATCHDOG_S=180` with defer-logic for memory
stalls — on a shared host the defaults are the safe choice; the
restart policy stays real through the root unit's `Restart=always`.
Kernel: `CONFIG_HSA_AMD_SVM=y` (CachyOS ships it); `amdgpu.noretry=-1`
(auto) — for this IP auto resolves to retry-on, the same effective state
the 27B engine ran on. Only revisit if the ledger shows SVM complaints.
## Mechanics
- **Root systemd unit** (`scripts/frank-dragoon.service`, `User=dank`,
`LimitMEMLOCK=infinity`, `Restart=always`, `ExecStop=podman stop -t 60
frank-dragoon-halogen`), driven by `scripts/serve-frank-dragoon.sh` — the
fleet's `podman run`-direct pattern. The script runs the container
FOREGROUND so the boot ledger (weights resident, pool fit, MTP head,
prompt cache, any clamp) lands in `/home/dank/logs/frank_dragoon.log`.
- Serve gates mirror the deployer EXACTLY (2026-10-01 crash-loop law):
image digest in podman storage, byte-exact checkpoint + n-gram table +
vision tower, flat tokenizer with all six files as regular files,
GPU nodes present.
- **Host-RAM pin-gate preflight** (added 2026-10-06): the engine
refuses to pin when `MemAvailable` is below the checkpoint (62.11 GiB)
plus a **16 GiB floor** — pinned pages cannot be swapped, and under the
floor the n-gram lookup pages in from disk on every long prompt. A
RAM-short host crash-loops the unit (each boot dies in ~5 s at the pin
gate) until the RAM clears; the 2026-10-06 cutover hit this (8 boots,
MemAvailable 74.77 GiB vs the 78.11 GiB needed, self-resolved in ~2 min
when the dying 27B engine freed RAM). The serve script now checks
`MemAvailable` BEFORE `podman run` and WAITS up to `FRANK_DRAGOON_RAM_WAIT`
(default 600 s) for the RAM to clear, so a transient dip boots once
instead of crash-looping; if it never clears it refuses loudly. The 16
GiB floor is the engine's (not `HALOGEN_HOST_RESERVE_GIB=20` — a
separate, higher, overall-budget knob).
- Engine stdout goes to the log, NOT the journal. The FIRST request after
a (re)start can sit silent ~45–60 s on this engine class (health
`engine_unresponsive`, 503s) and self-recovers — do not restart over it.
## Verification checklist (run after any redeploy)
1. Boot ledger greps in `/home/dank/logs/frank_dragoon.log`: resident
weights (~62 GiB), KV pool line, MTP/drafter line, prompt-cache line,
**no clamp named**.
2. `curl http://192.168.0.143:7770/health` → 200.
3. Text completion probe: reasoning lands in `reasoning_content`,
`timings` honest (generate ≥128 tokens; at 8 the inter_token number is
first-token noise).
4. Vision probe: a 512×512 solid-red PNG through an `image_url` part →
"Red" (≥256 px, one word expected).
5. Spec decode: `draft_n`/`draft_n_accepted` present in timings on
real-shaped traffic (SPEC_ADAPT=0 means the head is always engaged).
## Client contract (harness)
`~/.omp/agent/models.yml` — provider `llamacpp (dankclaw)` @
`http://192.168.0.143:7770/v1`: `contextWindow: 217088` — deliberately
BELOW the 262,144 engine ceiling: the 45k gap absorbs the harness's
~3 % chars/4 est under-count (see the `HALOGEN_CTX` row above) —
`maxTokens: 45056`, `input: [text, image]`,
`reasoningContentField: "reasoning_content"`, the `high→xhigh` effort
fold, `extraBody` temperature 1.0 / top_p 0.95. Compaction still rides
frank-zealot (the `compactionModel` steering is unchanged; the input
≈ 170k fits its 200,704 slot).
## Rollback
Revert the swap commit and redeploy — the 27B trio is intact on disk
(payload at `~/models/halogen-qwen3.8-27b/`, fetch script, and the halogen
0.1.4 image digest still in podman storage). The older ROCmFPX rollback
door (`build-rocmfpx.sh` pin) is untouched.