docs: the vault and AGENTS.md describe two Dankclaw endpoints
halogen-flash-server is ACTIVE again with its 2026-09-16 measured ledger (budget 33.5 GiB against a need of 27.2 — no clamp — and 14.7 GiB left for everything else), ik_llama.cpp is retired with its measurements kept as the record of why, and the new frank-small runbook covers the -mtp file, the 64 KiB/token KV arithmetic, the MTP contract, and the reasoning_effort trap that cost me every subagent on the endpoint. AGENTS.md: topology, Active Services, runbook index, and three new llama.cpp lessons (MTP is a property of the file; --jinja is what `tools` needs; a model's template can reject the harness's thinking level). Three pre-existing defects found while editing it: a truncated sentence mid-file, a harness path that does not exist on either server, and the benchmarking stop/mask recipe still calling frank-large a root unit. Truthfulness notes worth keeping: the co-tenant stall NOTE prints again, so the claim that it "no longer prints" is gone and the three observed block counts are recorded instead of a guessed threshold; and the Observability page says out loud why frank-large has no scrape job rather than leaving a silent absence.
This commit is contained in:
@@ -86,24 +86,34 @@ The rule is the same as for every other service: the only off-host path is a gua
|
||||
| `comfyui` | `comfyui:8188` | UI probe, no native exporter |
|
||||
| `services` | `192.168.0.143:8081`, `:3005` | SearXNG, OpenWebUI up/down probes |
|
||||
| `frank-medium` | `192.168.0.235:7770` | vLLM on Dankserver — 418 `vllm:` series |
|
||||
| `frank-large` | `192.168.0.143:7770` | llama.cpp on Dankclaw — `llamacpp:` counters |
|
||||
| `frank-small` | `192.168.0.143:7771` | llama.cpp on Dankclaw's RTX 3090 — `llamacpp:` counters, including the spec-decode pair |
|
||||
|
||||
The two LLM endpoints were added on 2026-09-16, after a night spent diagnosing
|
||||
frank-medium by hand. vLLM exports exactly what that diagnosis needed:
|
||||
`vllm:kv_cache_usage_perc` (how full the per-card pool is),
|
||||
The LLM endpoints were added on 2026-09-16, after a night spent diagnosing
|
||||
frank-medium by hand, and re-cut the same day when Dankclaw split into two
|
||||
endpoints. vLLM exports exactly what that diagnosis needed:
|
||||
`vllm:kv_cache_usage_perc` (how full the per-card pool is),
|
||||
`vllm:num_requests_waiting` (queue depth), the request-latency histograms, and
|
||||
the prefix-cache counters `vllm:prefix_cache_hits_total` /
|
||||
`vllm:prefix_cache_queries_total`, whose rates give the reuse rate that says
|
||||
whether a pinned conversation is being served warm or re-prefilled cold. What
|
||||
those numbers mean on this hardware is in [[frank-medium-radiance-mxfp4]].
|
||||
those numbers mean on this hardware is in [[frank-medium-radiance-mxfp4]];
|
||||
llama.cpp's counters (prompt and decode throughput, KV fill, and the
|
||||
`spec_decode_*` pair that proves MTP is running) are read against
|
||||
[[frank-small-qwen38-gsq-rco]].
|
||||
|
||||
Both are scraped on their LAN addresses, never on the guarded vhosts:
|
||||
Prometheus cannot solve an Anubis challenge.
|
||||
**`frank-large` is deliberately NOT scraped.** The halogen engine publishes
|
||||
`/health`, `/cache` and `/v1/*` and no Prometheus text endpoint at all, so a
|
||||
target there would be red by construction and would fire `LlmEndpointDown`
|
||||
forever — the same class of defect as the page-only probes below. Its liveness
|
||||
is on the homepage (a loopback probe) and in the engine's own boot ledger.
|
||||
|
||||
Both scraped endpoints are reached on their LAN addresses, never through the
|
||||
guarded vhosts: Prometheus cannot solve an Anubis challenge.
|
||||
|
||||
For services without a native exporter, use the Prometheus **blackbox exporter** in probe mode to assert up/down and HTTP latency. The homepage status timer probes the same endpoints from the host.
|
||||
|
||||
**Four jobs read "down" and three of them always will** (found 2026-09-16 while
|
||||
auditing why the target list was not green):
|
||||
**Four targets read "down" — three jobs, and every one of them is structural**
|
||||
(found 2026-09-16 while auditing why the target list was not green):
|
||||
|
||||
| job | error | what it means |
|
||||
|-----|-------|---------------|
|
||||
|
||||
@@ -58,25 +58,30 @@ on the selected host. The following files select the corresponding service:
|
||||
- Documentation, tests, deployment tooling, and unrelated container changes
|
||||
do not select either inference service.
|
||||
|
||||
The target-side `scripts/deploy-remote.sh` relinks the selected unit into
|
||||
`/etc/systemd/system/`, reloads systemd, enables it, restarts it, and waits for
|
||||
that service's health endpoint (`http://127.0.0.1:7770/health` for the two
|
||||
inference services; `/v1/version` for the NPU sight+sound endpoint — FLM has no
|
||||
`/health` route). The wait budget is 20 minutes because cold model loads can be
|
||||
slow. A failed handler does not advance its per-service state.
|
||||
The target-side `scripts/deploy-remote.sh` installs the selected service: for a
|
||||
**root unit** it relinks the repo file into `/etc/systemd/system/`, reloads
|
||||
systemd, enables it and restarts it (frank-small); for a **Quadlet** it retires
|
||||
the predecessor, stops the service's own unit, waits for the published port to
|
||||
clear, installs the `.container` and restarts the generated unit (frank-large).
|
||||
Each handler then waits on that service's health endpoint —
|
||||
`http://127.0.0.1:7770/health` for frank-large, `http://127.0.0.1:7771/health`
|
||||
for frank-small. The wait budget is 20 minutes because cold model loads are
|
||||
slow: halogen pins ~68 GiB of weights before it serves anything. A failed
|
||||
handler does not advance its per-service state.
|
||||
|
||||
## Unit and artifact paths
|
||||
|
||||
Both units point into the stable target checkout:
|
||||
|
||||
The units point into the stable target checkout:
|
||||
```text
|
||||
/home/dank/serverAppConfigs/scripts/frank-medium.service
|
||||
/home/dank/serverAppConfigs/scripts/frank-large.service
|
||||
/home/dank/serverAppConfigs/scripts/frank-small.service
|
||||
```
|
||||
|
||||
The unit files and serve scripts validate their model/runtime artifacts before
|
||||
starting. Keep `REMOTE_DIR` stable; moving the checkout requires updating both
|
||||
the unit absolute paths and the deployment tests in the same change.
|
||||
starting. `frank-large` is a Quadlet under `dankclaw/frank-large/quadlet/`
|
||||
rather than a unit in `scripts/`; `frank-small` keeps the unit/env/serve trio
|
||||
above. Keep `REMOTE_DIR` stable; moving the checkout requires updating both the
|
||||
unit absolute paths and the deployment tests in the same change.
|
||||
|
||||
## NPU unit
|
||||
|
||||
@@ -105,23 +110,26 @@ change in that service's inputs.
|
||||
|
||||
If the LLM handler fails after the target pull:
|
||||
|
||||
1. Inspect `sudo journalctl -u frank-medium -n 200` or
|
||||
`journalctl -u frank-large -n 200`.
|
||||
2. Confirm the model files, custom runtime binary, and chat template are
|
||||
readable by `dank`.
|
||||
1. Inspect `journalctl -u frank-small -n 200` (root unit) or
|
||||
`journalctl --user -u frank-large -n 200` (rootless Quadlet).
|
||||
2. Confirm the model files, the runtime binary and (for frank-large) the
|
||||
container image are present and readable by `dank`.
|
||||
3. Retry only the affected service:
|
||||
|
||||
```bash
|
||||
./scripts/deploy.sh dankserver --service frank-medium
|
||||
# or
|
||||
./scripts/deploy.sh dankclaw --service frank-large
|
||||
./scripts/deploy.sh dankclaw --service frank-small
|
||||
```
|
||||
|
||||
4. Verify the matching health endpoint before declaring recovery.
|
||||
|
||||
Do not stop the other host's inference service during recovery. For benchmark
|
||||
work, follow the separate stop/benchmark/restart procedure in [[Testing Policy]]
|
||||
and the repository rules.
|
||||
Do not stop the other host's inference service during recovery. The two
|
||||
Dankclaw endpoints are independent processes on different devices: restarting
|
||||
frank-large does not disturb frank-small, and the reverse holds too — with one
|
||||
exception worth knowing, that the deployer waits for port 7770 to be released
|
||||
before it starts the replacement container. For benchmark work, follow the
|
||||
separate stop/benchmark/restart procedure in [[Testing Policy]] and the
|
||||
repository rules.
|
||||
|
||||
## See Also
|
||||
|
||||
|
||||
@@ -7,10 +7,15 @@ timestamp: 2026-09-16T03:30:00-07:00
|
||||
|
||||
# frank-large — ik_llama.cpp, Qwen3.8-Flash-Next-Uncensored i1-Q4_K_M
|
||||
|
||||
**ACTIVE since 2026-09-15.** Replaced [[halogen-flash-server]] (rollback target;
|
||||
quadlet unit archived in `~/.AGENTTRASH/20260915-ik-swap/halogen-quadlet` on
|
||||
dankclaw). Serves `mradermacher/Qwen3.8-Flash-Next-Uncensored-i1-Q4_K_M`
|
||||
(111 GiB GGUF + mmproj-f16) at `192.168.0.143:7770`.
|
||||
**RETIRED 2026-09-16, after one day.** Replaced by [[halogen-flash-server]],
|
||||
which was the runtime before it as well — the fleet went ik → halogen → back.
|
||||
Its unit, env, serve script and the Qwen-Sharp template are archived in the repo
|
||||
under `scripts/.AGENTTRASH/*.ik-llama.cpp` and `*.ik-llama-qwen-sharp`, and the
|
||||
payload, build and chat template stay on disk. The measurements below are not a
|
||||
stale plan: they are the complete account of what this model costs on this
|
||||
hardware, and they are why the fleet went back. It served
|
||||
`mradermacher/Qwen3.8-Flash-Next-Uncensored` (111 GiB GGUF + mmproj-f16) at
|
||||
`192.168.0.143:7770` while it ran.
|
||||
|
||||
## Shape
|
||||
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
---
|
||||
type: reference
|
||||
title: frank-small on Dankclaw — llama.cpp, Qwen3.8-27B GSQ-RCO IQ3_S
|
||||
description: The active frank-small runbook — mainline llama.cpp on Dankclaw's RTX 3090 serving ISTA-DASLab Qwen3.8-27B-GSQ-RCO at IQ3_S with the model's own MTP head and the BF16 vision projector: identity, KV arithmetic, deployed flags, the MTP contract, the client contract, and what to check when it misbehaves.
|
||||
tags:
|
||||
- llm
|
||||
- frank-small
|
||||
- dankclaw
|
||||
- llama.cpp
|
||||
- rtx3090
|
||||
- qwen35
|
||||
- mtp
|
||||
- vision
|
||||
timestamp: 2026-09-16
|
||||
---
|
||||
|
||||
# frank-small — llama.cpp on the RTX 3090
|
||||
|
||||
> **ACTIVE since 2026-09-16.** Created when Dankclaw's inference was re-split:
|
||||
> [[halogen-flash-server]] took the gfx1151 iGPU back for `frank-large`, which
|
||||
> freed the RTX 3090 for this endpoint. Two endpoints, one host: `frank-large`
|
||||
> on `:7770`, `frank-small` on `:7771`.
|
||||
|
||||
## Identity
|
||||
|
||||
| what | value |
|
||||
|---|---|
|
||||
| runtime | mainline llama.cpp master `37b53fd` (2026-09-16), CUDA build for sm_86 |
|
||||
| binary | `/home/dank/GitPackages/llama.cpp-mainline/build-cuda/bin/llama-server` |
|
||||
| unit | **root systemd unit** `frank-small.service` (repo `scripts/frank-small.service`, `relink_unit`ed into `/etc/systemd/system/`) |
|
||||
| flags | `scripts/frank-small.env`; entrypoint `scripts/serve-frank-small.sh` |
|
||||
| endpoint | `192.168.0.143:7771`, alias `frank-small` |
|
||||
| model | `ISTA-DASLab/Qwen3.8-27B-GSQ-RCO-GGUF`, the `IQ3_S-mtp` build + BF16 mmproj |
|
||||
|
||||
It is a root unit rather than a Quadlet because the runtime is a native CUDA
|
||||
binary, not a container: there is no image to install and no generated unit to
|
||||
avoid. Boot persistence is the unit's `[Install] WantedBy=multi-user.target`;
|
||||
`Restart=on-failure` / `RestartSec=10` make it self-healing; `LimitMEMLOCK=infinity`
|
||||
covers CUDA's pinned staging buffers.
|
||||
|
||||
Build recipe (the deployed binary):
|
||||
|
||||
```bash
|
||||
cmake -B build-cuda -DCMAKE_BUILD_TYPE=Release -DGGML_NATIVE=ON \
|
||||
-DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES=86
|
||||
cmake --build build-cuda --target llama-server -j
|
||||
```
|
||||
|
||||
`GGML_CUDA_FA_ALL_QUANTS` is deliberately **off**: it is only needed for
|
||||
*quantized* KV with flash attention (see the CUDA lesson in AGENTS.md — without
|
||||
it, quantized-KV prefill collapses ~12x), and this service runs f16 KV.
|
||||
|
||||
## The model, and why the `-mtp` build specifically
|
||||
|
||||
GSQ-RCO is a **per-tensor mixed-precision** allocation produced by a
|
||||
gradient-based search under a total size budget, rather than one quantization
|
||||
type applied throughout. IQ3_S at 3.50 bpw is the release's task-lossless
|
||||
operating point: AIME25 100.00 and LiveCodeBench v6 85.71 match BF16 exactly,
|
||||
GPQA-Diamond is 0.51 behind — at 11.8 GB against 53.8 GB.
|
||||
|
||||
Two files are required, and the second suffix matters:
|
||||
|
||||
| file | size | why |
|
||||
|---|---|---|
|
||||
| `Qwen3.8-27B-GSQ-RCO-IQ3_S-mtp.gguf` | 12,120,016,960 B | the `-mtp` build **is** the MTP build: it carries the head as `blk.64.nextn.*` (`qwen35.nextn_predict_layers = 1`) |
|
||||
| `mmproj-Qwen3.8-27B-BF16.gguf` | 931,146,528 B | the vision encoder + projector (`clip.projector_type = qwen3vl_merger`, 27 blocks) |
|
||||
|
||||
Both live in `/home/dank/models/Qwen3.8-27B-GSQ-RCO-IQ3_S-mtp/`, fetched with
|
||||
`huggingface_hub` (which verifies the LFS sha256 and resumes).
|
||||
|
||||
**MTP is a property of the file, not of the flags.** `--spec-type draft-mtp`
|
||||
sets `load_mtp`, and the draft context runs on the *main model's* weights
|
||||
(`common/common.cpp` passes `shares_model` when no `--model-draft` is given;
|
||||
`common/speculative.cpp` gives it `LLAMA_CONTEXT_TYPE_MTP`). So there is no
|
||||
second copy of a 12 GiB model in VRAM, and `--model-draft` would be wrong here —
|
||||
it would load the whole file again.
|
||||
|
||||
## Architecture and the KV arithmetic
|
||||
|
||||
GGUF arch `qwen35`: 64 layers laid out as `16 x (3 x (Gated DeltaNet -> FFN) +
|
||||
1 x (Gated Attention -> FFN))`. Only the 16 full-attention layers take KV, so a
|
||||
token costs
|
||||
|
||||
```
|
||||
2 (K,V) x 4 heads x 256 head_dim x 2 B = 64 KiB at f16 (34 KiB q8_0, 18 KiB q4_0)
|
||||
```
|
||||
|
||||
and the 48 DeltaNet layers add ~0.16 GiB per sequence of constant-size state in
|
||||
f32, at any depth. The MTP draft context is `n_ctx` long over one nextn layer,
|
||||
so it costs 4 KiB/token of its own.
|
||||
|
||||
## Sizing (RTX 3090, 24576 MiB)
|
||||
|
||||
| term | GiB |
|
||||
|---|---|
|
||||
| weights | 11.29 |
|
||||
| mmproj | 0.87 |
|
||||
| MTP draft KV (131,072 x 4 KiB) | 0.50 |
|
||||
| DeltaNet state (one sequence) | 0.16 |
|
||||
| CUDA context + prefill/decode buffers | ~1.5 |
|
||||
| **KV, one slot at 131,072 x 64 KiB** | **8.00** |
|
||||
| **modelled total** | **~22.3 of 24** |
|
||||
|
||||
The binding number is the KV: about 9.5 GiB is left after the fixed terms, which
|
||||
is ~155k tokens at 64 KiB/token. Alternatives inside the same budget: `2 x
|
||||
65536` at f16, or `4 x 65536` / `1 x 262144` at q8_0 — the quantized variants
|
||||
need a rebuild with `-DGGML_CUDA_FA_ALL_QUANTS=ON`. **`--parallel N` divides
|
||||
`--ctx-size` between the slots**; it does not multiply.
|
||||
|
||||
Measured at deploy: **22,362 MiB** in use of 24,576, `n_slots = 1`,
|
||||
`n_ctx_slot = 131072`.
|
||||
|
||||
## Deployed flags
|
||||
|
||||
| flag | value | why |
|
||||
|---|---|---|
|
||||
| `CTX_SIZE` / `PARALLEL` | `131072` / `1` | one conversation per slot, full f16 precision, no KV quantization risk |
|
||||
| `CACHE_TYPE_K/V` | `f16` | quantizing would need the FA_ALL_QUANTS build for no benefit here |
|
||||
| `NGL` | `999` | every layer on the card |
|
||||
| `FLASH_ATTN` | `on` | |
|
||||
| `SPEC_TYPE` | `draft-mtp` | the model's own head; draft depth stays llama.cpp's default of 3 |
|
||||
| `BATCH_SIZE` / `UBATCH_SIZE` | `2048` / `512` | the defaults; ubatch 512 keeps the DeltaNet chunk buffers small |
|
||||
| `NUM_THREADS` / `THREAD_BATCH` | `8` / `8` | the work is on the GPU; the host CPU belongs to halogen's engine |
|
||||
| `TEMPERATURE` | `0.0` | greedy default (fleet contract) — clients that send their own values get them |
|
||||
| `REASONING_FORMAT` / `REASONING_BUDGET` | `deepseek` / `-1` | thinking into `reasoning_content`, unlimited budget (the model decides) |
|
||||
| `--jinja` | pinned | the GGUF's own template supplies `reasoning_effort`, `preserve_thinking` and the tool-call grammar. This build defaults it on; pinning it means a future default change cannot silently take tools away |
|
||||
| `--metrics` | on | Prometheus scrapes `/metrics` here (`frank-small` job) |
|
||||
|
||||
## Client contract
|
||||
|
||||
- **One slot.** A second concurrent request queues; it is not served in
|
||||
parallel, and agent fan-out through this endpoint serializes. Widen with
|
||||
`PARALLEL` (which divides the context) if that becomes the wrong trade.
|
||||
- **Thinking counts against the budget.** A request whose budget runs out
|
||||
mid-thought returns `finish_reason: "length"` with an empty `content` and the
|
||||
partial reasoning in `reasoning_content` — observed live on a vision request
|
||||
at `max_tokens: 64`. Give reasoning models a real budget.
|
||||
- **Tools work** (`tool_calls` returned; verified with a function-call round
|
||||
trip) because `--jinja` serves the model's own template. This is also what
|
||||
fixed subagents fleet-wide: the ik runtime that served `frank-large` until
|
||||
2026-09-16 rejected every request carrying `tools` with
|
||||
`500 tools param requires --jinja flag`.
|
||||
- **Images are accepted** as OpenAI `image_url` content parts with a `data:`
|
||||
URL or bare base64. This is the fleet's only image path: halogen's
|
||||
`frank-large` runs with no tower and refuses images with a named reason.
|
||||
- **`reasoning_effort` accepts only `xhigh`, `medium`, `low`.** The template
|
||||
raises on anything else — a 500, not a clamp — so the harness folds its own
|
||||
levels onto that set in `compat.reasoningEffortMap` (`high: xhigh`,
|
||||
`max: xhigh`). An unmapped level fails on the first request.
|
||||
- `/v1/models` reports `frank-small`; `/health` answers 200 once the model is
|
||||
loaded and the projector is up.
|
||||
|
||||
## Verified at deploy (2026-09-16)
|
||||
|
||||
- `systemctl is-enabled/is-active frank-small.service` → `enabled` / `active`.
|
||||
- `/v1/models` → `frank-small`; a chat completion returns `content` **and**
|
||||
`reasoning_content`.
|
||||
- A tool call returns `tool_calls` with the expected arguments.
|
||||
- Slot timing lines show `draft acceptance = 0.66-0.94, mean len = 2.95-3.83`
|
||||
— MTP is engaged, not merely configured.
|
||||
- An image request returns the right colour answer from the projector.
|
||||
- Harness routing: role `smol` lands here, role `slow` on `frank-large`, and a
|
||||
real subagent (the `task` role) completes a tool-using turn.
|
||||
|
||||
## Operate
|
||||
|
||||
```bash
|
||||
systemctl status frank-small.service # root unit
|
||||
journalctl -u frank-small.service -n 60 # load + per-request timing
|
||||
curl -s http://127.0.0.1:7771/health
|
||||
curl -s http://127.0.0.1:7771/v1/models
|
||||
curl -s http://127.0.0.1:7771/metrics | grep -E 'spec_decode|kv_cache_usage'
|
||||
nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv
|
||||
```
|
||||
|
||||
`/metrics` carries `llamacpp:spec_decode_num_{drafts,draft_tokens,accepted_tokens}_total`,
|
||||
which is the cheapest way to confirm MTP is running, and
|
||||
`llamacpp:kv_cache_usage_ratio` for how full the slot is.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| symptom | cause |
|
||||
|---|---|
|
||||
| unit restarts immediately, `frank-small: missing <path>` in the journal | the model, the projector or the binary is absent — the serve script refuses to start rather than half-load; finish the download |
|
||||
| `500 … Jinja Exception: Unexpected reasoning effort <level>` | a client sent an effort the template does not accept; map it (see the client contract) |
|
||||
| `500 tools param requires --jinja flag` | impossible here (`--jinja` is pinned) — you are looking at a *different* endpoint, most likely the retired ik runtime's logs |
|
||||
| `finish_reason: "length"` with empty content | the budget ran out inside the thinking block; raise `max_tokens` |
|
||||
| a request that waits, then answers normally | the single slot was busy (or the KV is nearly full); raise `PARALLEL` or expect serialization |
|
||||
| CUDA OOM at load | another process holds the 3090, or the KV was widened past ~9.5 GiB; check `nvidia-smi` and re-derive from the sizing table |
|
||||
|
||||
## Rollback
|
||||
|
||||
`frank-small` is a new endpoint, so rollback is retirement:
|
||||
`systemctl disable --now frank-small.service`, move
|
||||
`/etc/systemd/system/frank-small.service` into `~/.AGENTTRASH/`, and remove the
|
||||
harness provider + the `smol`/`tiny`/`task`/`vision` role entries. The old
|
||||
`frank-small` (FreeToken on Dankserver, retired 2026-09-15) is a different
|
||||
service with a different card — see [[freetoken-frank-small]].
|
||||
|
||||
## Citations
|
||||
|
||||
- [ISTA-DASLab/Qwen3.8-27B-GSQ-RCO-GGUF](https://huggingface.co/ISTA-DASLab/Qwen3.8-27B-GSQ-RCO-GGUF) — the quantized checkpoints, the `-mtp` builds and the projector
|
||||
- [Qwen/Qwen3.8-27B](https://huggingface.co/Qwen/Qwen3.8-27B) — base model: 64 layers, Gated DeltaNet/Gated Attention layout, 262,144 native context
|
||||
- [ggml-org/llama.cpp](https://github.com/ggml-org/llama.cpp) — `--spec-type draft-mtp`, the MTP context type, and the Qwen3-VL projector path
|
||||
@@ -16,10 +16,14 @@ timestamp: 2026-09-13
|
||||
|
||||
# halogen-flash-server on Dankclaw (frank-large)
|
||||
|
||||
> **ACTIVE since 2026-09-11.** Replaced the llama.cpp / kingjones30-ROCmFPX
|
||||
> STRIX deployment (see [[kingjones-strix-rocmfp4]], now the rollback target).
|
||||
> Deployed as a rootless Quadlet container,
|
||||
> `dankclaw/frank-large/quadlet/frank-large.container`, port 7770.
|
||||
> **ACTIVE again since 2026-09-16, and retuned.** It replaced the llama.cpp /
|
||||
> kingjones30-ROCmFPX STRIX deployment on 2026-09-11 (see
|
||||
> [[kingjones-strix-rocmfp4]]), was displaced for two days by ik_llama.cpp (see
|
||||
> [[frank-large-ik-uncensored]], the current rollback), and came back as the
|
||||
> shape the fleet asked for: two 200k-token conversations rather than the
|
||||
> native-context pair. Deployed as a rootless Quadlet container,
|
||||
> `dankclaw/frank-large/quadlet/frank-large.container`, port 7770. The RTX 3090
|
||||
> it does not touch now belongs to [[frank-small-qwen38-gsq-rco]].
|
||||
|
||||
The engine is a from-scratch serving runtime for the Qwen3.8-Flash-Next
|
||||
architecture on AMD's gfx1151 (Strix Halo) — the same silicon this host runs.
|
||||
@@ -77,12 +81,12 @@ upstream's defaults:
|
||||
| flag | value | why |
|
||||
|---|---|---|
|
||||
| `HALOGEN_MODEL_ID` | `frank-large` | fleet identity; no client rename |
|
||||
| `HALOGEN_CTX` | `262144` | the model's native context, and what both clients declare |
|
||||
| `HALOGEN_KV_POOL_POSITIONS` | `401408` | **trimmed 2026-09-13** from the 524,288 the doubling deployed: one full 262k conversation resident beside a ~139k one, or three at 131k, ~11.0 GiB of KV as reserved. Measured against the doubled pool the host went from 7.1 GiB / 310 contiguous 2 MiB blocks to 9.1 / 1396, and the co-tenant stall NOTE no longer prints. `HALOGEN_KV_POOL_FIT` still guards the boot, so read the ledger rather than trusting this column |
|
||||
| `HALOGEN_KV_SLOTS` | `3` | Concurrency cap — **lowered from 4 on 2026-09-12** to the real fleet size. Each slot is 111.0 MiB of O(1) state, so this freed ~111 MiB (held 103.5 → 103.4 GiB). Slots share the ONE pool and **oversubscribe** it (3 × 262144 > 401408), so admission is pool-bound: one full-length conversation plus a ~139k second, or three at 131k. This trims simultaneous requests, not how much context fits |
|
||||
| `HALOGEN_MAX_TOK` | `32768` | upstream's default, kept. The arena is 20.6 GiB here against 12.2 at 16384; it fit alongside the doubled pool only because the reserve dropped to 15, and it fits the trimmed 401,408 pool with room to spare. At 65536 the arena alone exceeds the budget and the server **will not boot** |
|
||||
| `HALOGEN_HOST_RESERVE_GIB` | `15` | **lowered from 24 (vendor default 20) on 2026-09-12** to buy the doubled pool. The only term you own in the device budget (24 → 29.5 GiB, 15 → 38.5 GiB). Against the doubled pool the ceiling was 16 — the engine needed budget ≥ 36.5, and 18 gave 35.5, silently re-clamping; at 401,408 the need is ~33.4 so the ceiling loosens, but a bigger reserve still buys nothing. Matched pair with the pool. It is **not** an allocation: raising it cannot return memory to the host, only take the pool away |
|
||||
| `HALOGEN_VISION_TOWER` | `1` | image input; the fleet's only image path since [[frank-npu]] was retired. Charges 1.97 GiB against the budget — the term missing from my first estimate |
|
||||
| `HALOGEN_CTX` | `200192` | **set 2026-09-16**: exactly half the pool, so two conversations of the full window are always resident. Not a round 200,000 — pool/2 is. The model's native window is 262,144, so this is a real reduction in the per-conversation ceiling, and a client asking for more gets a 400 (never a silent truncation). The harness declares 200192 for `frank-large` |
|
||||
| `HALOGEN_KV_POOL_POSITIONS` | `400384` | **retuned 2026-09-16** (from 401,408): 2 x 200,192. Reserves ~11.0 GiB of KV, confirmed by the boot ledger as `400384 positions, ~27.2 GiB (16.2 GiB of it for everything but the pool, at max_tok 24576)` against a 33.5 GiB device budget — **no clamp**. Slots still oversubscribe the pool for any real request (admission reserves prompt + `max_tokens`), so a near-full pair that is both generating is pool-bound. `HALOGEN_KV_POOL_FIT` guards the boot: read the ledger, not this column |
|
||||
| `HALOGEN_KV_SLOTS` | `2` | **lowered from 3 on 2026-09-16** — one slot per half of the pool, and two is the fleet's shape now that Dankclaw serves two endpoints. Each slot is 111.0 MiB of O(1) state, so this hands ~111 MiB back as well |
|
||||
| `HALOGEN_MAX_TOK` | `24576` | **halved from the 32768 default on 2026-09-16** for frank-small, its co-tenant on the same host. The arena's variable term goes `8.40 x 2 → 8.40 x 1.5`, handing ~4.2 GiB back at roughly a 4-5 % prefill cost — the same lever at 16,384 costs 8-9 %. The vendor's own notes call 24,576 the largest arena that allocated with headroom to spare, so it stays inside their tested range. 65536 still cannot boot. It sizes a per-call PREFILL CHUNK, not the prompt ceiling: a 200k conversation is prefilled in arena-sized pieces |
|
||||
| `HALOGEN_HOST_RESERVE_GIB` | `20` | **raised from 15 with the same retune**, because the arena shrank: `budget = 121.2 − 67.7 − 20 = 33.5 GiB` against a measured need of ~27.2, so the fit check kept ~6 GiB of margin and did not clamp. It is **not** an allocation: raising it cannot return memory to the host, only take the pool away (see the ceiling section below) |
|
||||
| `HALOGEN_VISION_TOWER` | *unset* | **removed 2026-09-16.** The tower charges 1.97 GiB against the same device budget as the pool and the arena, and the fleet's image path moved to [[frank-small-qwen38-gsq-rco]] (llama.cpp with `--mmproj`). This server refuses image content parts, and `models.yml` declares `frank-large` text-only to match |
|
||||
| `HALOGEN_DOWNLOAD` | `peonist-ai/halogen-qwen3.8-flash-next` | first-start fetch |
|
||||
| `HALOGEN_VERBOSE` | `1` | verbose engine logging — the fullest startup account, on permanently so an incident report needs no restart-into-debug |
|
||||
|
||||
@@ -104,10 +108,13 @@ Three numbers explain the whole box:
|
||||
**overstate free memory by the size of the model**. The server prints the
|
||||
corrected figure at startup; believe that line, not Grafana.
|
||||
- **~28 KiB per KV position** (measured: 262,144 positions = 6,656 MiB of KV,
|
||||
~7.2 GiB with block scratch), plus the prefill arena (16.7 GiB at
|
||||
`HALOGEN_MAX_TOK=32768`, 8.4 GiB at 16384). The engine's device-side budget
|
||||
stops at roughly 47 GiB on a 128 GB machine *with the weights pinned* — and
|
||||
lower on a machine carrying more besides this server, which Dankclaw is.
|
||||
~7.2 GiB with block scratch), plus the prefill arena. The 2026-09-16 ledger
|
||||
reads the two together in the engine's own words: `400384 positions, ~27.2
|
||||
GiB (16.2 GiB of it for everything but the pool, at max_tok 24576)` — so
|
||||
~11.0 GiB of pool and 16.2 GiB of arena, working slack and (no longer) a
|
||||
vision tower. The engine's device-side budget stops at roughly 47 GiB on a
|
||||
128 GB machine *with the weights pinned* — and lower on a machine carrying
|
||||
more besides this server, which Dankclaw is.
|
||||
- **`HALOGEN_HOST_RESERVE_GIB`** is what is left for the page cache the lookup
|
||||
table is read through. Too little and long prompts crawl with the disk busy
|
||||
and the process in uninterruptible sleep — that is a cache problem, not a
|
||||
@@ -128,6 +135,8 @@ startup account, including three deliberate experiments:
|
||||
| 524288 | 65536 | 24 | — | 37.3 | 46.5 | 29.5 | **OOM — will not boot** |
|
||||
| 524288 | 32768 | **15** | 14.4 | 20.6 | 37.0 | **38.5** | **deployed — both features** |
|
||||
| 524288 | 32768 | 16 | 14.4 | 20.6 | 37.0 | 37.5 | fits, footprint unchanged — see the ceiling below |
|
||||
| **400384** | **24576** | **20** | **11.0** | **16.4** | **27.2** | **33.5** | **deployed 2026-09-16 — ledger need 27.2, no clamp** |
|
||||
| 401408 | 32768 | 15 | 11.0 | 20.6 | 33.4 | 38.5 | 2026-09-13 → 09-16, superseded by the retune |
|
||||
|
||||
### The sizing rule
|
||||
|
||||
@@ -183,11 +192,14 @@ The device budget is not the whole story. Memory position by configuration
|
||||
| 524288 / 16384, reserve 24 | 94.6 | 13.8 GiB | 3742 |
|
||||
| 524288 / 32768, reserve **16** | **103.5** | **7.1 GiB** | 293 |
|
||||
| **401408 / 32768, reserve 15** | **100.0** | **9.1 GiB** | **1396** |
|
||||
| **400384 / 24576, reserve 20** | **95.4** | **14.7 GiB** | **475** |
|
||||
|
||||
At the doubled setting (2026-09-12) the server held 103.5 of 121 GiB and the
|
||||
engine volunteered a note it had not printed before (it no longer prints at
|
||||
the 401,408 trim — 9.1 GiB / 1396 blocks sits below whatever threshold
|
||||
triggers it):
|
||||
engine volunteered the stall note. It did not print it at the 401,408 trim, and
|
||||
it prints it again after the 2026-09-16 retune. Three data points, and they do
|
||||
not line up with a "free memory below X" reading: 310 blocks printed, 1396 did
|
||||
not, 475 did. So treat the note as "the machine is tight" and read the
|
||||
`host memory left` line rather than waiting to be told:
|
||||
|
||||
```
|
||||
halogen: NOTE this server now holds most of the machine, and 310 contiguous
|
||||
@@ -326,25 +338,33 @@ deployment:
|
||||
**plus** `max_tokens` positions when it is admitted; if the pool cannot hold it
|
||||
the request waits in arrival order, and after the queue timeout (3600 s) it
|
||||
gets a `503 engine_busy`. A prompt large enough that prompt + budget exceeds
|
||||
the pool can therefore never be admitted at all. With the pool at 401,408
|
||||
(since 2026-09-13) the per-conversation ceiling is still `HALOGEN_CTX`
|
||||
(262,144) — even a full-context prompt plus the 65,536 cap is 327,680 ≤
|
||||
401,408. The pool binds **how many** conversations stay resident: at 524,288
|
||||
two full-length ones fit; at 401,408 it is one full-length beside a ~139k
|
||||
second, or three at 131k. Under the pre-09-12 262,144 pool the two numbers
|
||||
were identical, which is why four concurrent 65k chats were contending for
|
||||
one conversation's worth of positions.
|
||||
the pool can therefore never be admitted at all. The 2026-09-16 shape is a
|
||||
400,384-position pool with `HALOGEN_CTX` 200,192 and two slots: two
|
||||
conversations at the ceiling fit the pool exactly, so a pair that is both
|
||||
near-full and both generating is pool-bound — the second waits for the first to
|
||||
release its region. The pool binds **how many** conversations stay resident,
|
||||
not how long one may be; the older 524,288 / 401,408 numbers live in the ledger
|
||||
tables above.
|
||||
|
||||
## Vision
|
||||
|
||||
With the tower loaded, `/v1/chat/completions` accepts the usual OpenAI image
|
||||
content part carrying a `data:` URL or bare base64 — **`http(s)` URLs are
|
||||
refused deliberately**, because fetching one would make the server issue
|
||||
outbound requests to wherever a client pointed it. One image costs about 2,040
|
||||
tokens of context and 5.5 / 11.8 / 25.3 s at 1280x800 / 1920x1080 / 2560x1440;
|
||||
text at 12 pt and above is read exactly, and a bigger frame past that point
|
||||
adds empty area rather than detail. Audio and video have no path here at all —
|
||||
that capability left with [[frank-npu]].
|
||||
**None here since 2026-09-16.** `HALOGEN_VISION_TOWER` is deliberately unset:
|
||||
the tower is a 1.97 GiB charge against the same device budget as the pool and
|
||||
the arena, and the fleet's image path moved to [[frank-small-qwen38-gsq-rco]],
|
||||
which loads the BF16 projector alongside its own weights. This server refuses
|
||||
image content parts and says why, rather than ignoring them:
|
||||
|
||||
```json
|
||||
{"error": {"message": "this server does not accept images: the engine was
|
||||
started without a vision tower (HALOGEN_VISION_TOWER)", "type":
|
||||
"invalid_request_error"}}
|
||||
```
|
||||
|
||||
The llama.cpp side handles images the same way this engine used to: a `data:`
|
||||
URL or bare base64, about 2,040 tokens of context per image, and `http(s)` URLs
|
||||
refused deliberately (fetching one would make the server issue outbound
|
||||
requests to wherever a client pointed it). Audio and video have no path
|
||||
anywhere in the fleet — that left with [[frank-npu]].
|
||||
|
||||
## Deploy and operate
|
||||
|
||||
@@ -352,17 +372,27 @@ that capability left with [[frank-npu]].
|
||||
./scripts/deploy.sh dankclaw --service frank-large
|
||||
```
|
||||
|
||||
The handler retires the llama.cpp-era **root** unit first (stops it, drops its
|
||||
enable symlinks, moves `/etc/systemd/system/frank-large.service` into the home
|
||||
trash — never `rm`), then pulls `ghcr.io/peonist-ai/halogen-flash-server:0.5.8`,
|
||||
re-tags it to the `localhost/` alias the unit references, installs the Quadlet,
|
||||
and restarts the generated unit. Boot persistence comes from
|
||||
`[Install] WantedBy=default.target` in the unit file plus linger on the deploy
|
||||
user — generated units **cannot** be `systemctl --user enable`d on this host.
|
||||
The handler retires the ik-era **root** unit first (stop, disable, move
|
||||
`/etc/systemd/system/frank-large.service` into
|
||||
`~/.AGENTTRASH/20260916-halogen-restore/host-units` — never `rm`; this host's
|
||||
`disable` may delete the file outright, which the handler now reports), stops
|
||||
the Quadlet's own unit if it is running, then pulls
|
||||
`ghcr.io/peonist-ai/halogen-flash-server:0.5.8`, re-tags it to the
|
||||
`localhost/` alias the unit references, and **waits for port 7770 to be free**
|
||||
before installing and starting anything.
|
||||
|
||||
The health gate is bootstrap-aware: while the checkpoint is absent the
|
||||
container is downloading and `/health` cannot answer, so the handler waits for
|
||||
the file instead of burning its budget and reporting a failure that is not one.
|
||||
That last gate is not paranoia. On the first cutover attempt the ik server
|
||||
logged "Deactivated successfully", and pasta — rootless podman's userspace
|
||||
network stack, which binds the published port at container CREATE — still
|
||||
reported `Address already in use` a second later, exiting the unit with code
|
||||
126. Only `Restart=on-failure` recovered it, minutes later. A deploy that
|
||||
starts a doomed container has not deployed anything, so `wait_port_free` polls
|
||||
every socket on the port (listener, accepted, TIME_WAIT) and fails loudly with
|
||||
the socket table if it never clears.
|
||||
|
||||
Boot persistence comes from `[Install] WantedBy=default.target` in the unit
|
||||
file plus linger on the deploy user — generated units **cannot** be
|
||||
`systemctl --user enable`d on this host.
|
||||
|
||||
```bash
|
||||
systemctl --user status frank-large.service # the generated unit
|
||||
@@ -404,15 +434,15 @@ in root's storage and answers "no such container".
|
||||
|
||||
## Rollback
|
||||
|
||||
The llama.cpp era is intact: the STRIX payload stays at
|
||||
`/home/dank/models/kingjones-Qwen3.8-Flash-Next-ROCmFP4-STRIX`, the
|
||||
`kingjones30/ROCmFPX` build stays at
|
||||
`/home/dank/GitPackages/kingjones-ROCmFPX/build`, and the retired unit, env and
|
||||
serve script are in `serverAppConfigs/.AGENTTRASH/` (suffixed `.llama.cpp`).
|
||||
Rolling back is a `git revert` of this change set plus a deploy — **but the
|
||||
Quadlet unit must be removed from `~/.config/containers/systemd/` first**
|
||||
(otherwise the restarted root unit and the still-installed container both
|
||||
claim port 7770). See [[kingjones-strix-rocmfp4]].
|
||||
The predecessor is intact: the ik payload stays at
|
||||
`/home/dank/models/mradermacher-Qwen3.8-Flash-Next-Uncensored-i1-Q4_K_M`, the
|
||||
ik build at `/home/dank/GitPackages/ik_llama.cpp/build`, and its unit, env,
|
||||
serve script and the Qwen-Sharp template are archived in the repo under
|
||||
`scripts/.AGENTTRASH/*.ik-llama.cpp` and `*.ik-llama-qwen-sharp`. Rolling back
|
||||
is a `git revert` of this change set plus a deploy — **but the Quadlet must be
|
||||
removed from `~/.config/containers/systemd/` first**, or the restarted root
|
||||
unit and the still-installed container both claim port 7770. The port gate in
|
||||
the handler now covers exactly that race. See [[frank-large-ik-uncensored]].
|
||||
|
||||
The `amd_iommu=off` kernel argument that came with this change is separate and
|
||||
reverts on its own — see [[dankclaw-iommu-translation-off]].
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
# LLM Fleet — Knowledge Base
|
||||
|
||||
Documentation for the LLM inference fleet on the two hosts
|
||||
(2026-09-16): charlie12345/ROCmFPX llama.cpp on Dankserver (frank-medium,
|
||||
kingjones777 Qwen3.8-27B-ROCmFPX-Q8_0-AGENT on 2x Radeon AI PRO R9700) and
|
||||
ik_llama.cpp on Dankclaw (frank-large, mradermacher Qwen3.8-Flash-Next-
|
||||
Uncensored i1-Q4_K_M on the RTX 3090 + Strix Halo hybrid).
|
||||
Documentation for the LLM inference fleet on the two hosts (2026-09-16):
|
||||
vllm-radiance on Dankserver (frank-medium, just1moremodel
|
||||
Qwen3.8-27B-Uncensored-MXFP4-awq on 2x Radeon AI PRO R9700) and TWO endpoints on
|
||||
Dankclaw — halogen-flash-server (frank-large, Qwen3.8-Flash-Next w4b on the
|
||||
gfx1151 iGPU, port 7770) and mainline llama.cpp (frank-small, ISTA-DASLab
|
||||
Qwen3.8-27B-GSQ-RCO IQ3_S with MTP and vision on the RTX 3090, port 7771).
|
||||
|
||||
> 2026-08-22: the former `vllmScripts` repository is merged into the
|
||||
> serverAppConfigs repository. This knowledge base moved from the old repo's
|
||||
@@ -18,26 +19,31 @@ graph LR
|
||||
subgraph Dankserver[AMD Dankserver - Ubuntu 26.04]
|
||||
A[2x Radeon AI PRO R9700
|
||||
gfx1201, 32 GiB each]
|
||||
B2[ROCmFPX llama.cpp
|
||||
B2[vllm-radiance MXFP4
|
||||
frank-medium, port 7770]
|
||||
C[Qwen3.8-27B-ROCmFPX-Q8_0-AGENT
|
||||
layer split, 131k ctx / 1 slot, MTP]
|
||||
C[Qwen3.8-27B-Uncensored-MXFP4-awq
|
||||
2 single-GPU replicas, 114688 ctx / 4 seqs, DFlash2]
|
||||
A --> B2 --> C
|
||||
end
|
||||
|
||||
subgraph Dankclaw[AMD Strix Halo - Ubuntu 26.04]
|
||||
E2[RTX 3090 (PCIe x4 dock) +
|
||||
gfx1151 iGPU 64 GiB unified memory]
|
||||
E[ik_llama.cpp master d85a1d7
|
||||
E[halogen-flash-server 0.5.8
|
||||
frank-large, port 7770]
|
||||
F[mradermacher Qwen3.8-Flash-Next-Uncensored
|
||||
i1-Q4_K_M GGUF, 262k ctx / 1 slot, vision]
|
||||
F[peonist-ai Qwen3.8-Flash-Next w4b
|
||||
2 x 200192 ctx over one 400384-position pool]
|
||||
G[mainline llama.cpp 37b53fd
|
||||
frank-small, port 7771]
|
||||
H[Qwen3.8-27B GSQ-RCO IQ3_S
|
||||
131072 ctx / 1 slot, MTP + vision]
|
||||
E2 --> E --> F
|
||||
E2 --> G --> H
|
||||
end
|
||||
|
||||
CLI[LLM Clients / API] -->|HTTP :7770| B2
|
||||
CLI -->|HTTP :7770| E
|
||||
```
|
||||
CLI -->|HTTP :7771| G
|
||||
|
||||
## Servers
|
||||
|
||||
@@ -59,23 +65,31 @@ i1-Q4_K_M GGUF, 262k ctx / 1 slot, vision]
|
||||
2026-09-15): charlie12345/ROCmFPX serving
|
||||
kingjones777/Qwen3.8-27B-ROCmFPX-Q8_0-AGENT-GGUF; kept as the record of the
|
||||
runtime it replaced
|
||||
- [[freetoken-frank-small]] — RETIRED 2026-09-15 with the RTX 3090: the
|
||||
FreeToken v0.1.2 frank-small runbook (batsclamp Huihui-Qwen3.6-35B-A3B-
|
||||
abliterated-FP8), kept as the retirement record
|
||||
- [[freetoken-frank-small]] — RETIRED 2026-09-15, when the RTX 3090 moved to
|
||||
frank-large: the FreeToken v0.1.2 frank-small runbook (batsclamp
|
||||
Huihui-Qwen3.6-35B-A3B-abliterated-FP8), kept as the retirement record. The
|
||||
NAME was reused on 2026-09-16 by a different service on Dankclaw — see
|
||||
[[frank-small-qwen38-gsq-rco]]
|
||||
- [[freetoken-benchmark-sweep]] — KV pool vs decode speed sweep
|
||||
(bs1/bs3/bs4/bs6, 8k–700k KV) on Dankserver RTX 3090
|
||||
- [[deployment]] — deploy and update process for both servers
|
||||
- [[frank-redo-2026-08-17]] — the 2026-08-17 topology change
|
||||
- [[frank-large-ik-uncensored]] — ACTIVE frank-large runbook since
|
||||
2026-09-15: ik_llama.cpp (root systemd unit) serving mradermacher/
|
||||
Qwen3.8-Flash-Next-Uncensored-i1-Q4_K_M on the RTX 3090 (dense/attention/
|
||||
KV) + LPDDR (experts/PLE) hybrid; measured performance envelope, the
|
||||
decode root-cause chain, tuning levers, and the co-tenancy traps
|
||||
- [[halogen-flash-server]] — RETIRED 2026-09-15 (rollback target): the
|
||||
peonist-ai halogen-flash-server 0.5.8 runbook serving
|
||||
peonist-ai/halogen-qwen3.8-flash-next (Qwen3.8-Flash-Next w4b .hgn +
|
||||
quality overlay), rootless Quadlet container on Dankclaw port 7770 —
|
||||
deployed flags, memory model, client contract, troubleshooting
|
||||
- [[halogen-flash-server]] — ACTIVE frank-large runbook again since 2026-09-16
|
||||
(rootless Quadlet, port 7770): peonist-ai halogen-flash-server 0.5.8 serving
|
||||
peonist-ai/halogen-qwen3.8-flash-next (Qwen3.8-Flash-Next w4b .hgn + quality
|
||||
overlay) on the gfx1151 iGPU — two 200k conversations over one
|
||||
400,384-position pool, deployed flags, memory model, client contract,
|
||||
troubleshooting
|
||||
- [[frank-small-qwen38-gsq-rco]] — ACTIVE frank-small runbook since 2026-09-16
|
||||
(root systemd unit, port 7771): mainline llama.cpp serving
|
||||
ISTA-DASLab/Qwen3.8-27B-GSQ-RCO IQ3_S on the RTX 3090, with the model's own
|
||||
Multi-Token Prediction head for speculative decoding and the BF16 projector
|
||||
for the fleet's image path
|
||||
- [[frank-large-ik-uncensored]] — RETIRED 2026-09-16 (rollback target): the
|
||||
ik_llama.cpp runbook (root systemd unit, 2026-09-15 → 09-16) serving
|
||||
mradermacher/Qwen3.8-Flash-Next-Uncensored-i1-Q4_K_M on the RTX 3090
|
||||
(dense/attention/KV) + LPDDR (experts/PLE) hybrid; its measured envelope and
|
||||
decode root-cause chain are the record of why the fleet went back to halogen
|
||||
- [[dankclaw-iommu-translation-off]] — why Dankclaw boots with
|
||||
`amd_iommu=off` since 2026-09-11 (13-16 % prefill, measured upstream),
|
||||
what it cost (the NPU endpoint), what was deliberately not copied from
|
||||
@@ -100,8 +114,8 @@ i1-Q4_K_M GGUF, 262k ctx / 1 slot, vision]
|
||||
- [[kairic-edge]] — the retired Kairic Edge IU4 experiment
|
||||
(deployed and reverted 2026-08-22)
|
||||
- [[Dankserver System Specs]] — the 2x R9700 box (frank-medium)
|
||||
- [[Dankclaw System Specs]] — the Strix Halo gfx1151 box (frank-large,
|
||||
on halogen-flash-server since 2026-09-11)
|
||||
- [[Dankclaw System Specs]] — the Strix Halo gfx1151 box (frank-large on
|
||||
halogen-flash-server since 2026-09-16, frank-small on the RTX 3090)
|
||||
- [[frank-npu]] — RETIRED 2026-09-11: the FLM NPU sight+sound endpoint
|
||||
on Dankclaw (Gemma4 E4B vision+audio pack, XDNA2, port 7771), kept as
|
||||
the retirement record — the IOMMU/SVA err=-19 root cause and where
|
||||
|
||||
@@ -541,3 +541,83 @@ timestamp: 2026-09-14
|
||||
Active Services section + bench-policy unit type. Committed 795b0b3;
|
||||
tests 300 ok with the single pre-existing not-ok-73 (comfyui selector
|
||||
bug, unrelated).
|
||||
|
||||
## 2026-09-16 — Dankclaw re-split: halogen returns as frank-large, llama.cpp takes the 3090 as frank-small
|
||||
- `/dankclaw/frank-large/quadlet/frank-large.container` — halogen-flash-server
|
||||
restored as the active runtime (the 09-15 ik swap never removed the file) and
|
||||
retuned to the shape Frank asked for: `HALOGEN_CTX` 262144 → **200192**,
|
||||
`HALOGEN_KV_POOL_POSITIONS` 401408 → **400384** (exactly 2 × 200192),
|
||||
`HALOGEN_KV_SLOTS` 3 → **2**, `HALOGEN_MAX_TOK` 32768 → **24576** and
|
||||
`HALOGEN_HOST_RESERVE_GIB` 15 → **20** (arena −4.2 GiB, for the co-tenant),
|
||||
`HALOGEN_VISION_TOWER` **unset** (the tower moved to frank-small). Live ledger:
|
||||
budget `121 − 67.7 − 20 = 33.5 GiB` against a need of `27.2`, so **no clamp**;
|
||||
68.0 GiB weights + 11.0 KV + 16.5 working = 95.4 GiB held, 14.7 GiB left for
|
||||
everything else (475 contiguous 2 MiB blocks). The co-tenant stall NOTE is
|
||||
back, and the boot logged 4,350 compaction stalls (285 failed) — tight and
|
||||
fragmented, not out of memory.
|
||||
- `/scripts/frank-small.env`, `frank-small.service`, `serve-frank-small.sh` (new)
|
||||
— mainline llama.cpp `37b53fd` on the RTX 3090 serving
|
||||
`ISTA-DASLab/Qwen3.8-27B-GSQ-RCO-GGUF` at IQ3_S: the `-mtp` build (the head is
|
||||
`blk.64.nextn.*` in the SAME file, so `--spec-type draft-mtp` runs the draft
|
||||
context on the main model's weights — no second copy, no `-md`) plus the BF16
|
||||
projector, 131072 ctx / 1 slot, f16 KV, `--jinja` and `--metrics` pinned, port
|
||||
7771, root systemd unit. 22,362 MiB of the card's 24,576 in use. Verified:
|
||||
`/health`, chat with `reasoning_content`, a `tool_calls` round trip, slot
|
||||
timing `draft acceptance 0.66–0.94`, and an image answered from the projector.
|
||||
- `/scripts/deploy-remote.sh` — `deploy_llm_large` flipped back to halogen
|
||||
(retire the ik ROOT unit into
|
||||
`~/.AGENTTRASH/20260916-halogen-restore/host-units`, pull + re-tag the image,
|
||||
**`wait_port_free 7770`**, install the Quadlet, start) and `deploy_llm_small`
|
||||
added (root unit, model-file gate, health on 7771). The port gate exists
|
||||
because the FIRST cutover attempt failed exactly there: pasta reported
|
||||
`Address already in use` about a second after the ik server exited, the unit
|
||||
died with code 126, and only `Restart=on-failure` recovered it. A redeploy now
|
||||
stops this service's own quadlet before waiting, or the gate would deadlock
|
||||
against itself.
|
||||
- `/scripts/deploy-plan.py`, `/scripts/deploy.sh`, `/scripts/test-changed.sh` —
|
||||
frank-small added to `SERVICE_ORDER` and the Dankclaw inventory (the stale
|
||||
`dankclaw:frank-npu` entry dropped with it); the changed-test mapping for
|
||||
`dankclaw/frank-large/*` pointed at `tests/frank_large_quadlet.bats`, retired
|
||||
on 09-15, so the wrapper had been failing on that path ever since — now
|
||||
`tests/frank_large_unit.bats`.
|
||||
- Retired to `scripts/.AGENTTRASH/`: the ik trio (`frank-large.env`,
|
||||
`frank-large.service`, `serve-frank-large.sh`), `chat-template.jinja` (only the
|
||||
ik runtime read it), and four benchmark harnesses bound to retired runtimes.
|
||||
- `/tests/frank_large_unit.bats` rewritten for the Quadlet (the `pool == 2 × ctx`
|
||||
invariant, no vision tower, the port gate) and `/tests/frank_small_unit.bats`
|
||||
added (root-unit shape, MTP-from-the-file contract, KV budget vs the card, port
|
||||
separation). One assertion failed on its first run because the negative grep
|
||||
matched a COMMENT in the serve script — the test now strips comments before
|
||||
grepping the effective flags.
|
||||
- `shared/homepage/services.json`, `shared/prometheus/prometheus.yml`,
|
||||
`rules/llm-fleet.yml`, `grafana/.../llm-fleet.json` — a frank-small card at
|
||||
`127.0.0.1:7771` and a `frank-small` scrape job at `192.168.0.143:7771`; the
|
||||
`frank-large` job **removed**, because the halogen engine has no `/metrics` at
|
||||
all (its routes are `/health`, `/cache` and `/v1/*`), so a target there would
|
||||
have been red by construction; the dashboard's endpoint picker had been sourced
|
||||
from a vLLM-only metric, so a llama.cpp job could never be selected. Live: 11
|
||||
targets, 7 up, 4 down (comfyui, gitea, services — all structural), and all
|
||||
three LLM homepage cards up.
|
||||
- Harness (`~/.omp/agent/models.yml` + `config.yml`, dev box) — third provider
|
||||
`llamacpp (dankclaw-3090)` for `:7771`; `frank-large` ctx 262144 → 200192 and
|
||||
`input: [text]`; roles `smol`, `tiny`, `task`, `vision` → frank-small (the
|
||||
image path and the small/fast roles), `slow`/`plan`/`designer`/`advisor` →
|
||||
frank-large. Two failures found by driving it, both fixed: (1) frank-small's
|
||||
template accepts only `xhigh|medium|low` for `reasoning_effort` and 500s on
|
||||
anything else, and subagents run at `high` — every subagent on that endpoint
|
||||
died until `compat.reasoningEffortMap` folded the levels onto that set; (2) the
|
||||
ik runtime that had been serving `frank-large` rejected every request carrying
|
||||
`tools` (`500 tools param requires --jinja flag`), which is what killed a
|
||||
monitoring subagent earlier in the day. Both endpoints now answer tool calls,
|
||||
and a subagent completes a tool-using turn.
|
||||
- Docs: `frank-small-qwen38-gsq-rco.md` (new runbook),
|
||||
`halogen-flash-server.md` re-activated with the 09-16 ledger,
|
||||
`frank-large-ik-uncensored.md` marked retired, LLM index, deployment flow,
|
||||
Observability and AGENTS.md topology/sections/lessons. Three AGENTS.md defects
|
||||
found on the way: a truncated sentence mid-file ("There is **no audio"), a
|
||||
harness path that does not exist (`/home/dank/.omp/agent/models.yml` — the
|
||||
harness runs on the dev box), and the benchmarking stop/mask recipe still
|
||||
describing frank-large as a root unit.
|
||||
- Deploy: `./scripts/deploy.sh dankclaw --service frank-large --service
|
||||
frank-small` — per-service health gates, then the e2e gate PASSED (31 passed,
|
||||
1 flaky-retried). Suite: 323 seams ok, 0 failures.
|
||||
|
||||
Reference in New Issue
Block a user