Files
serverAppConfigs/serverAppConfigs-docs/LLM/frank-archon-lucebox-ds4.md
T
Frank e7f0d93c86 docs(vault): fleet-wide fact re-verification pass (67 pages)
The docs-fact census wave re-read the live hosts and re-keyed every page
it could: runtime/payload identities, ports, sizes, ledger figures, unit
state, and the retirement banners that drifted as the fleet moved. The
wave was interrupted mid-run, so this commit carries only what passed the
integrity gates: every touched page parses (front matter or H1+status
convention intact, balanced fences, no truncated tables, trailing
newline), the docs_completeness and link-integrity seams are green, and
bats is 384/384.

Numbers that this session proved on live hosts are keyed to the measured
value, not the page's earlier claim.
2026-10-18 13:15:43 -07:00

223 lines
12 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.
---
type: configuration
title: frank-archon Lucebox DeepSeek V4 Runbook
description: RETIRED 2026-09-26 frank-archon runbook (active for hours on 2026-09-26) — the Lucebox runtime (github.com/Luce-Org/lucebox, local image localhost/lucebox-rocm:gfx1201) serving DeepSeek-V4.1-Flash-ROCMFP23 (377.2 GiB GGUF, 43-layer MoE, 256 routed experts, top-6) on Dankserver's R9700 with the routed experts computed on CPU from the mmapped page cache. Replaced the same day by [[frank-archon-llamacpp-qwen38-flash-next-q8]] (llama.cpp Qwen3.8-Flash-Next Q8_0); the image is still in rootless storage but the payload is gone from the host, and frank-archon runs [[frank-archon-radiance-qwen38-iq4r]] today (2026-10-18).
tags:
- frank-archon
- dankserver
- lucebox
- deepseek-v4
- ds4
- rocmfp23
- gfx1201
- r9700
- quadlet
- moe
timestamp: 2026-09-26
---
# frank-archon Lucebox DeepSeek V4 Runbook
> [!warning] RETIRED 2026-09-26 (same day it went live)
> Replaced by [[frank-archon-llamacpp-qwen38-flash-next-q8]] — unsloth
> llama.cpp serving Qwen3.8-Flash-Next Q8_0 on both R9700s. This runtime
> served for hours; the image `localhost/lucebox-rocm:gfx1201` is still in
> dank's rootless storage, but the 378 GiB payload was deleted from the host
> (`ls /home/dank/models/` on Dankserver, 2026-10-18: `StillDeadcode`, `rad`,
> `tpl.jinja` only), and the quadlet-era repo files were deleted by `8500600`
> (2026-09-26) — they survive only in git history, not in a `.AGENTTRASH`
> directory (`dankserver/.AGENTTRASH/` holds only `20260916-vllm-radiance`).
The dankserver LLM endpoint (:7770, alias **frank-archon**) as it stood on
2026-09-26: the
[Lucebox](https://github.com/Luce-Org/lucebox) runtime serving
`Lucebox/DeepSeek-V4.1-Flash-ROCMFP23-GGUF` (377.2 GiB, 405,349,859,328
bytes, LFS oid
`2daea6ca1715bc987aae201e63445d3f7abdc2337c05f5f569f5e50237ce8be2`) on a
single Radeon AI PRO R9700 (gfx1201). It replaced
[[frank-medium-radiance-mxfp4]] (vllm-radiance TP=2), retired earlier the
same day.
## Why this shape
DeepSeek-V4.1-Flash is a 43-layer MoE: 256 routed experts + 1 shared expert
per layer, top-6 routing. The ROCMFP23 quantization is fp2 gate/up with fp3
down experts (Q2_0_ROCMFP2 type 107 + Q3_0_ROCMFPX type 104). At 377.2 GiB
the model fits neither the 63.7 GiB of combined VRAM nor the 246 GiB of RAM,
so it is served the way llama.cpp serves big models by default: the GGUF is
mmapped, pages pull from disk/page cache on demand, dense work (attention,
shared expert, embeddings, output projection) and the MLA KV cache run on
the R9700, and the routed experts are computed on CPU. The 246 GiB RAM
(upgraded for this deployment) holds the working set of active experts; the
rest streams from the 1.8 T NVMe.
Lucebox's `--ds4-fused-decode` requests a monolithic GPU load; on a model
this size that allocation fails and the backend falls back to **hybrid
expert placement + layered decode** — that fallback is the intended serving
mode here, not an error.
## Image
`localhost/lucebox-rocm:gfx1201`, built on the host from
`github.com/Luce-Org/lucebox` `Dockerfile.rocm`:
```
git clone --recurse-submodules https://github.com/Luce-Org/lucebox.git
cd lucebox
# Three local modifications (tracked at the time as
# dankserver/frank-primary/lucebox-gfx1201.patch, deleted by 8500600):
# 1. Dockerfile.rocm drops the ROCm *-dev apt packages (the 7.14.1-full
# base already ships them in /opt/rocm; the apt repo does not serve
# them) and the three runtime math libs.
# 2. Dockerfile.rocm installs the official cmake 3.31.6 binary (jammy's
# 3.22 predates the `block` command ROCm 7.14 hipblaslt-config.cmake
# requires, CMake >= 3.25).
# 3. ggml-cuda.cu: `ggml_cuda_node_launches_nothing` moved above the
# `#ifdef USE_CUDA_GRAPH` guard — `ggml_cuda_node_is_noop` calls it
# unconditionally, but the macro is never defined by the build
# system, so the in-guard definition was dead and the use failed.
git apply ../lucebox-gfx1201.patch
podman build --build-arg LUCE_HIP_ARCHES=gfx1201 \
--build-arg ROCM_VERSION=7.14.1-full \
-t localhost/lucebox-rocm:gfx1201 -f Dockerfile.rocm .
```
- The prebuilt `ghcr.io/luce-org/lucebox-hub:rocm` is **not usable as-is**:
it is built for gfx1151 + ROCm 6.4.1, and gfx1200/gfx1201 are not
code-object compatible.
- `ROCM_VERSION=7.14.1-full` matches the host driver's ROCm 7.x line (the
radiance image's core-7.14 userspace runs on this host). A 6.4.x userspace
on a 7.x driver can segfault at model load. Only `-full` tags exist for
7.14.x.
- The binary lands at `/opt/lucebox-hub/server/build/luce_server`.
## Model
`/home/dank/models/DeepSeek-V4.1-Flash/DeepSeek-V4.1-Flash-ROCMFP23.gguf`,
fetched with `huggingface_hub` (the xet-native path — plain `curl` full GETs
400 against HF's xethub CDN for this repo; see the fetch note in
`scripts/hf-fetch.sh`). Byte count and sha256 are deploy-gated in
`deploy_llm_archon`.
## Deployed flags (2026-09-26)
From `dankserver/frank-primary/frank-primary-entrypoint.sh` (deleted by `8500600`;
recover it with `git show 8500600^:dankserver/frank-primary/frank-primary-entrypoint.sh`) — the unit
bypasses the image's entrypoint, which only forwards a fixed Qwen/DFlash
flag set and cannot express the DS4 flags):
| Setting | Value |
|---|---|
| Model | `DeepSeek-V4.1-Flash-ROCMFP23.gguf` (377.2 GiB) |
| Device | `--target-device hip:0` (`HIP_VISIBLE_DEVICES=0`; the Raphael iGPU at index 2 stays out) |
| Window | `--max-ctx 131072` (the qualified Strix Halo window; DS4's MLA KV is compressed, so the pool is small) |
| Chunk | `--chunk 8192` (the qualified profile's chunk) |
| KV dtype | `--cache-type-k q4_0 --cache-type-v q4_0` (the qualified launch) |
| Decode | `--ds4-fused-decode` (falls back to hybrid expert placement on this host) |
| Prefill | `--ds4-prefill sparse` (the batched prefill; `exact` runs at token-wise decode cost) |
| Routing | `--ds4-expert-top-k 6` (the model default; do NOT reduce on adaptive qtype-105/106 artifacts — measured degenerate output at top-4, DS4.md 2026-08-05) |
| Draft | none — no DSpark draft is published for V4.1-Flash; plain autoregressive decode |
| Identity | `--model-name frank-archon`, `--host 0.0.0.0 --port 7770` |
## API surface
OpenAI Chat Completions (streaming + tool metadata), `/v1/models`,
`/health`, OpenAI Responses, Anthropic Messages, and Open WebUI model
metadata — the fleet contract is unchanged from frank-medium.
## Cutover procedure
1. Image built and model fetched (gates in `deploy_llm_archon`).
2. `deploy.sh` → `deploy_llm_archon`: stops and **masks** the radiance
unit (`frank-medium`), waits for :7770 to free, installs
`dankserver/frank-primary/quadlet/frank-primary.container` (also deleted by
`8500600`; recover it from `git show 8500600^`), starts
`frank-archon.service`, waits for health (1800 s start period — first
start page-ins the dense weights and builds the graphs).
3. Verify: `/health` 200 is not enough — a real chat completion, a tool
call, and an Open WebUI completion.
4. Retire the radiance unit to the home trash (never `rm`); the MXFP6
checkpoint payload did not stay — it is gone from the host (see Rollback).
## Rollback
Unmask and start the radiance unit (`systemctl --user unmask frank-medium &&
systemctl --user start frank-medium`) and stop/mask frank-archon. The
`localhost/radiance-vllm:0.13.0-e060895` image is still in dank's rootless
storage; the `/models/Qwen3.8-27B-PARO-MXFP6` checkpoint is not — Dankserver's
`/home/dank/models/` holds only `StillDeadcode`, `rad` and `tpl.jinja` as of
2026-10-18, so this rollback needs a re-fetch of the payload.
## Verification (2026-09-26)
_Filled in after the cutover: health, real completion, tool call, Open WebUI
completion, measured prefill/decode, `systemctl --user is-enabled/is-active`
state._
## Dual-R9700 follow-up (2026-09-28 probe era)
After this single-card runbook was retired, the DS41 engine got a dual-R9700
attempt on the `feat/ds41-engine` branch (`main` rejects the checkpoint with
`unsupported model architecture 'deepseek41'`). Findings that outlive the
probe:
**Budget both cards explicitly, or you waste half the box.** The engine
sizes the streamed-expert cache LAST, after the model, so uncapped it absorbs
every spare byte on the stream device — symptom: card1 at 33.0/34.2 GB
looking busy while card0 sits at 14.2/34.2 GB; the busy card is holding a
cache of things still streaming from NVMe. Pin all four:
| env | card | meaning |
|---|---|---|
| `LUCE_EXPERT_BUDGET_MB` | hip:0 | primary hot experts (~11.96 MiB each) |
| `LUCE_EXPERT_SECONDARY_BUDGET_MB` | hip:1 | secondary experts (needs `LUCE_DS4_MOE_TP*`) |
| `LUCE_EXPERT_STREAM_CACHE_MB` | hip:1 | cap the auto-sized stream cache |
| `LUCE_EXPERT_STREAM_DEVICE=1` | hip:1 | which card holds the slots and computes them |
Working full-card shape: 21000 + 20000 + 8000 → card0 ~28.6/31.86 GiB,
card1 ~27.3/31.86 GiB, resident experts 3,360 of 15,360.
**Expert TP DOES work on gfx1201+gfx1201.** A retired quadlet recorded
`LUCE_DS4_MOE_TP_INPROC` as "qualified for gfx1151+gfx1201, not
gfx1201+gfx1201" — that is WRONG; peer access negotiates and the secondary
tier comes up clean: `[deepseek4-moe-tp] enabled mode=in-process local=hip:0
secondary=hip:1`. It is the only lever that materially raises resident
expert count, and resident count is the entire bottleneck. Confirm every run
with `expert ownership:` and `hybrid experts ready:` lines.
**The placement file must live under the mounted models dir.** JSON
`{"owners": [...]}`, 15,360 entries indexed `layer*384+expert`, values
`primary`/`secondary`/`stream`. It is a ranking, not a promise: each device
keeps what fits its budget and demotes the rest. Anywhere outside
`/models/...` gives `cannot open expert placement` and a SILENT single-tier
fallback — a silent-wrongness failure, not a crash.
**V4.1 refuses layer split and layer-major prefill** — only `--ds4-prefill
exact` (token-by-token) is legal on a 32 GiB card and `--ds4-fused-decode`
is refused there. With ~22% of experts resident each token pulls ~187 cold
experts × ~12 MiB; if `/proc/<pid>/io` `read_bytes` climbs into terabytes
the model is larger than the box's RAM and you are in page-cache thrash at
the NVMe ceiling — a capacity verdict, not a tuning problem. Low GPU util
with a pegged link is the EXPECTED signature of PCIe-expert-stream-bound
decode, not a broken run.
**Harness traps, each of which produced a wrong number:** never `env -i` the
podman call (rootless podman runs as `dank`; `env -i HOME=/root` makes
PODMAN try `/root/.config` and die `stat /root/.config: permission denied`
before the container exists — pass container env with `-e`); never put a
large prompt on curl's argv (`Argument list too long` at ~128 KB — use
`--data-binary @file`); size prompts by growing the file until `wc -c`
reaches the byte target AND assert depth against the engine's own
`usage.prompt_tokens` (nominal 4 chars/token was really 5.73; a chunk loop
that appends a fixed ~152-byte line per nominal 200-byte chunk undershot
30%); the server runs as the container's PID 1, so tear down with
`podman rm -f`, never host `pkill`; drop page cache between arms
(`sync; echo 3 > /proc/sys/vm/drop_caches`) or the first arm reads warm and
every later one is a lie.
Read the placement log — it is the whole diagnosis
(`arch=deepseek41 layers=40 embd=5120 experts=384 used=6 ff=2304
hash_layers=0` — hash_layers=0 is correct for V4.1; `engram: layers=[1,14]
… 2 table(s) embedded (not mapped)` — the 189.13 GiB Engram tables are never
mapped, so they do not evict the expert page cache).