fleet redo 2026-08-17: retire PP+NPU, new topology

- Move all previous scripts to old/scripts/ (retired PP/NPU-era)
- frank-default-large: llama.cpp FastMTP on dankserver (HauhauCS
  Qwen3.8-27B IQ4_XS + FastMTP 32K draft + ngram-mod, K q8_0/V f16,
  128K ctx, batch 2048/ubatch 1024, port 7770)
- frank-default-small: vLLM ROCm on dankclaw (Avesed Qwen3.6-35B-A3B
  INT8 W8A8, full 262144 ctx, no KV quant, 4 seqs, batch 16384,
  ngram spec, port 52625)
- retarget deploy.sh (dankserver/dankclaw, inline sudo, no helpers)
- docs: deployment + index + AGENTS.md + README for new topology,
  superseded banners on retired docs, add frank-redo-2026-08-17 runbook
This commit is contained in:
Frank
2026-08-17 15:23:46 -07:00
parent 136ee080c9
commit d9af7f1d19
45 changed files with 961 additions and 469 deletions
+77 -55
View File
@@ -2,48 +2,44 @@
## Overview
This project manages deployment scripts for the LLM inference fleet.
Dankclaw runs a llama.cpp pipeline-parallel head serving
Qwen3.8-27B-Uncensored Q6_K (imatrix): MTP draft (standalone
`-draft-Q8_0` sidecar, `--spec-draft-n-max 4`) over the `--spec-default`
ngram-mod fallback, 1 slot at 262144 context (pool 262144), tensors
split 0.68/0.32 (45 of 65 blocks) to the Dankserver RTX 3090 `ggml-rpc`
worker, KV q8_0/f16 (mismatched, FA retained via the
GGML_CUDA_FA_ALL_QUANTS rebuild), head GPU side on ROCm0 (no `--device`
flag), port 7770.
The Dankclaw NPU endpoint (FastFlowLM, `frank-default-small`, port 52625)
serves Qwythos-9B-Claude-Mythos-5-1M (abliterated) as registry tag
`qwythos:9b` at 262144 ctx (swapped in 2026-08-17; previously
`qwen3.6-moe:35b-a3b`; the old llama.cpp 35B service on Dankserver is
stopped). **Boot policy (2026-08-17):** only `frank-default-large` and
`frank-pp-worker` are enabled for boot. The NPU unit `frank-default-small`
is disabled; the running service keeps serving until stopped or rebooted.
See [docs/deployment.md](docs/deployment.md) for the deployment
process, the boot policy, and the re-enable recipes.
This project manages deployment scripts for the LLM inference fleet on two
local machines. Topology (2026-08-17 redo):
| Target | Host | Runtime | Service | Model | Port |
|--------|------|---------|---------|-------|------|
| Dankserver | dank@dankserver | llama.cpp (patched FastMTP build) | frank-default-large | HauhauCS Qwen3.8-27B-Uncensored-Aggressive IQ4_XS + FastMTP 32K draft + ngram-mod | 7770 |
| Dankclaw | dank@dankclaw | vLLM (ROCm, /home/dank/vllm-venv) | frank-default-small | Avesed Qwen3.6-35B-A3B INT8 W8A8, ngram spec | 52625 |
The 2026-08-17 redo retired the pipeline-parallel split and the FastFlowLM
NPU endpoint. The RTX 3090 now runs the whole 27B model standalone
(no RPC worker). Dankclaw runs vLLM on the Strix Halo iGPU (gfx1151).
The old scripts live in `old/scripts/` for reference; they describe the
retired PP topology.
**Sibling project:** [../serverAppConfigs](../serverAppConfigs) manages the
Podman app stack on the same hosts (OpenWebUI, Gitea, observability). Its
OpenWebUI consumes the `:7770` endpoint; its Gitea instance hosts this
repository. Cross-links live in both knowledge-base indexes.
OpenWebUI consumes the `:7770` endpoint on Dankserver; its Gitea instance
hosts this repository.
## Benchmarking Policy (MANDATORY)
**STOP the production service BEFORE running any benchmark on a target.**
These servers serve real users (about 3 people). Running a bench while the
service is up starves the GPU and corrupts results. Restart the service
when the bench finishes. The users will call if they need the model.
when the bench finishes.
Rules:
1. Stop the service before any benchmark: `systemctl stop frank-default-large`
(Dankclaw) or `systemctl stop frank-default-small` (Dankclaw NPU). Use the
passwordless helper or the password `Assface.3241` with `sudo -S`.
2. Run the bench on a scratch port (never the service port 7770).
3. Restart the service when the bench completes: `systemctl start <svc>`.
4. Verify health before reporting: `curl http://127.0.0.1:7770/health`.
Do not skip this policy. A stale GPU contention or a dead production box is
worse than a slow bench.
1. Stop the service before any benchmark:
`sudo systemctl stop frank-default-large` (Dankserver) or
`sudo systemctl stop frank-default-small` (Dankclaw). Use the password
`Assface.3241` with `sudo -S` when no tty is available.
2. Run the bench on a scratch port (never the service ports 7770/52625).
3. Restart the service when the bench completes:
`sudo systemctl start <svc>`.
4. Verify health before reporting:
`curl http://192.168.0.235:7770/health` or
`curl http://192.168.0.143:52625/health`.
## Git Workflow
@@ -63,11 +59,15 @@ All script edits must flow through git. Do not edit files on the remote machine
Use `scripts/deploy.sh` to deploy committed changes to a target. It pushes `main`, pulls on the target, restarts the service, and checks the health endpoint.
```
./scripts/deploy.sh dankclaw # PP head (frank-default-large, port 7770)
./scripts/deploy.sh dankserver # PP worker (frank-pp-worker, RPC 50052)
./scripts/deploy.sh dankclaw --dry-run # preview without changes
FRANK_SUDO_PW=... ./scripts/deploy.sh dankserver # llama.cpp FastMTP, port 7770
FRANK_SUDO_PW=... ./scripts/deploy.sh dankclaw # vLLM, port 52625
./scripts/deploy.sh dankserver --dry-run # preview without changes
```
Set `FRANK_SUDO_PW` for headless runs (remote sudo reads it from stdin).
The passwordless restart helpers installed for the retired topology are
obsolete; `deploy.sh` no longer uses them.
Deployment workflow:
```mermaid
@@ -79,25 +79,45 @@ graph LR
E --> F[health check]
```
Target map:
| Target | Host | Runtime | Service | Port |
|--------|------|---------|---------|------|
| Dankclaw | dank@dankclaw | llama.cpp PP head (Qwen3.8-27B-Uncensored Q6_K, split 0.68/0.32 to the Dankserver worker via RPC, standalone MTP draft + ngram-mod, q8_0/f16 KV) | frank-default-large | 7770 |
| Dankclaw | dank@dankclaw | FastFlowLM NPU (XDNA2 50 TOPS, qwythos:9b Q4NX 7.76 GB, 262144 ctx; see [[FastFlowLM NPU Inference]]) — disabled for boot since 2026-08-17 | frank-default-small | 52625 |
| Dankserver | dank@dankserver | ggml-rpc worker (RTX 3090, receives the head's tensor share) | frank-pp-worker | 50052 |
> Warning: `deploy.sh dankserver` is currently broken. It targets the
> removed `frank-default-small` unit. Restart the worker with
> `sudo systemctl restart frank-pp-worker` until the script is fixed.
## Runtime & Troubleshooting
### FastMTP patched llama.cpp (Dankserver)
The HauhauCS FastMTP draft sidecar requires a llama.cpp build from commit
`4df29be4f4c3673f428170fda944a5b19f743bb8` plus the
`HauhauCS-FastMTP-llama.cpp.patch` (from the HF repo). The build lives at
`/home/dank/llama.cpp-fastmtp/build` on Dankserver. Loading the draft with
a stock binary fails with `expected 5120, 248320, got 5120, 32768`. Do not
rebuild from another commit without re-applying the patch. See the
HauhauCS HF repo README for the exact build recipe.
### vLLM ROCm install (Dankclaw)
vLLM runs from `/home/dank/vllm-venv` (Python 3.12). Install recipe:
```
uv venv --python /usr/bin/python3.12 /home/dank/vllm-venv
uv pip install --python /home/dank/vllm-venv vllm --torch-backend=auto
```
`--torch-backend=auto` resolves the AMD ROCm wheel set (torch +
amd-torch-device-gfx1151 + the vllm rocm variant) from the AMD index.
The model cache is the default HF cache
(`/home/dank/.cache/huggingface`); the HF token lives at
`~/.cache/huggingface/token`. The retired CIRU package
(`/home/dank/ling3-ciru`) documents a source-build fallback for gfx1151.
### Env var naming rule — HIP runtime collision
The ROCm HIP runtime reads the bare environment variables `TEMP`, `HOST`, and `GPU_MAX_HEAP_SIZE`. The serve scripts export the env file with `set -a`. A tunable named `TEMP` leaks into HIP. On 2026-08-13 `TEMP=1.0` made HIP use the path `1.0` for its JIT kernel cache, then segfaulted every model load. Commit `227ce01` fixed it by renaming the sampling variable to `TEMPERATURE`.
The ROCm HIP runtime reads the bare environment variables `TEMP`, `HOST`,
and `GPU_MAX_HEAP_SIZE`. The serve scripts export the env file with
`set -a`. A tunable named `TEMP` leaks into HIP. On 2026-08-13
`TEMP=1.0` made HIP use the path `1.0` for its JIT kernel cache, then
segfaulted every model load. Commit `227ce01` fixed it by renaming the
sampling variable to `TEMPERATURE`.
Never name a tunable `TEMP`, `HOST`, or `GPU_MAX_HEAP_SIZE`. Check for collisions with this command:
Never name a tunable `TEMP`, `HOST`, or `GPU_MAX_HEAP_SIZE`. Check for
collisions with this command:
```
strings /opt/rocm-*/lib/libamdhip64.so.* | grep -xE "TEMP|HOST|GPU_MAX_HEAP_SIZE"
@@ -121,25 +141,27 @@ graph TD
2. Run the serve script directly. Then run the raw binary with the same flags. A different outcome isolates the env file sourcing.
3. Run gdb for the backtrace with this command:
```
gdb -batch -ex run -ex "bt 25" --args bash scripts/serve-pp-head.sh
gdb -batch -ex run -ex "bt 25" --args bash scripts/serve-frank-large.sh
```
`llama-server` buffers its timed stdout. On SIGSEGV the log tail is lost. Trust gdb, not the log.
4. Kernel spam about `amdgpu: SVM mapping failed` is a symptom, not the root cause. Investigate other causes before assuming memory pressure.
### Operational quirks
- `sudo` on both boxes needs a tty. The remote sudo steps in `deploy.sh` fail non-interactively. Use `echo '<password>' | sudo -S <command>`.
- Passwordless restarts: each target has a root-owned helper and a sudoers NOPASSWD drop-in (`/etc/sudoers.d/frank-*`). The Dankclaw helper `/usr/local/sbin/frank-restart-large.sh` is correct for the PP head. The Dankserver helper `frank-restart-small.sh` is **obsolete** — it restarts the removed `frank-default-small` unit. Restart the worker with `sudo systemctl restart frank-pp-worker`. The sudoers rules match commands exactly: no extra arguments (for example, `--no-pager` breaks the `systemctl status` rule). See [docs/deployment.md](docs/deployment.md).
- `sudo` on both boxes needs a tty. Remote sudo steps fail non-interactively. Use `echo '<password>' | sudo -S <command>`.
- Never run `pkill -f` with a pattern that appears in your own command line. It kills your ssh session. Use `pkill -x <exact-name>`.
- Model load is slow: about 3 minutes warm, 8-17 minutes cold (measured 17 minutes on 2026-08-13 after a cache drop). Health returns `503 Loading model` the whole time. That is normal. Do not kill the process. `deploy.sh` waits up to 20 minutes on Dankclaw (see `HEALTH_WAIT`).
- Page-cache state confounds crash tests. Cold-cache loads are slow and survive. Warm-cache loads crash fast. Control for it when testing. `deploy.sh` drops caches on Dankclaw before restart (see `DROP_CACHES`); manual restarts must run `sync && echo 3 | sudo tee /proc/sys/vm/drop_caches` first.
- Model load is slow: Dankserver ~5 minutes cold (15.7 GB IQ4_XS through RAM, `--no-mmap`); Dankclaw vLLM ~5-10 minutes (38 GB checkpoint). Health returns 503 while loading. Do not kill the process. `deploy.sh` waits up to 10 minutes on Dankserver and 20 minutes on Dankclaw (see `HEALTH_WAIT`).
- A client abort and a server release look different in the journal. A client abort logs `W srv stop: cancel task, id_task = N`. A natural stop (EOS or limit) logs only `slot release` with `truncated = 0`. The server never preempts a running generation; when all slots are busy, new tasks defer into a queue. See the 2026-08-13 incident in [docs/deployment.md](docs/deployment.md).
- Dankserver crash signature (historical): the retired 35B service aborted under parallel load with `CUDA error: an unsupported value or parameter was passed to the function` in `cublasSgemm_v2` at `ggml-cuda.cu:1541`, then `status=6/ABRT`, then `503 Loading model` for ~5 minutes (llama.cpp b10121, driver 595.84). Root cause was never determined; the service is retired. Do not confuse that crash with speculative decoding. See [docs/dankserver-vram-growth.md](docs/dankserver-vram-growth.md).
- DFlash premature EOS under parallel load (historical): on Dankclaw, `draft-dflash` ended a generating slot ~1s after a new task landed with high prompt-cache reuse (LCP ~0.99), with `finish_reason "stop"` and no `cancel task` log — a DFlash shared-draft-context bug. DFlash and DSpark are retired from Dankclaw. Production uses the standalone MTP draft over the ngram-mod fallback at PARALLEL=1 on ROCm0. See [docs/qwen3.8-spec-matrix.md](docs/qwen3.8-spec-matrix.md).
- Retired hardware history: the Dankserver 35B cuBLAS crash and the DFlash premature-EOS bug are historical; see [docs/dankserver-vram-growth.md](docs/dankserver-vram-growth.md) and [docs/qwen3.8-spec-matrix.md](docs/qwen3.8-spec-matrix.md). The FastFlowLM NPU endpoint is retired; see [docs/FastFlowLM NPU Inference.md](docs/FastFlowLM%20NPU%20Inference.md).
### Dankclaw memory model
The GPU budget on Dankclaw is the rocm-smi figure: 96 GiB addressable VRAM (SVM). The GPU node reports `local_mem_size 0`, so all allocations are GTT/SVM-backed. Trust rocm-smi and the runtime. Do not use `free` or `dmidecode` for the GPU budget; they show the CPU-side carve-out. This is intentional. Do not change it.
The GPU budget on Dankclaw is the rocm-smi figure: 64 GiB VRAM reported
by rocm-smi (SVM-backed; the docs' older 96 GiB figure was the addressable
SVM pool). The GPU node reports `local_mem_size 0`, so all allocations are
GTT/SVM-backed. Trust rocm-smi and the runtime. Do not use `free` or
`dmidecode` for the GPU budget; they show the CPU-side carve-out. This is
intentional. Do not change it.
## Why
+16 -24
View File
@@ -1,45 +1,37 @@
# vLLM Scripts
Deployment scripts for the LLM inference fleet: a llama.cpp
pipeline-parallel Qwen3.8-27B split across two machines, plus the
FastFlowLM NPU endpoint on Dankclaw.
Deployment scripts for the LLM inference fleet (2026-08-17 topology):
llama.cpp FastMTP on Dankserver and vLLM ROCm on Dankclaw.
## Targets
| Host | User | Codename | Architecture |
|------|------|----------|--------------|
| dankserver | dank | Dankserver | NVIDIA RTX 3090 + 62 GB RAM |
| dankclaw | dank | Dankclaw | AMD Strix Halo APU (shared memory) |
| Host | User | Codename | GPU |
|------|------|----------|-----|
| dankserver | dank | Dankserver | NVIDIA RTX 3090 24 GB + 62 GB RAM |
| dankclaw | dank | Dankclaw | AMD Strix Halo iGPU gfx1151 (unified memory) |
## Active Services
| Service | Host | Runtime | Model | Port |
|---------|------|---------|-------|------|
| frank-default-large | dankclaw | llama.cpp PP head (RPC to Dankserver) | Qwen3.8-27B-Uncensored Q6_K, standalone MTP draft | 7770 |
| frank-pp-worker | dankserver | ggml-rpc worker (RTX 3090) | receives the head's tensor share | 50052 |
| frank-default-large | dankserver | llama.cpp (patched FastMTP build) | HauhauCS Qwen3.8-27B-Uncensored-Aggressive IQ4_XS, FastMTP 32K draft + ngram-mod, K q8_0 / V f16 KV, 128K ctx | 7770 |
| frank-default-small | dankclaw | vLLM ROCm (vllm-venv) | Avesed Qwen3.6-35B-A3B INT8 W8A8, full 262144 ctx, no KV quantization, 4 seqs, ngram spec | 52625 |
Boot policy (2026-08-17): only these two units are enabled. The
FastFlowLM NPU endpoint (`frank-default-small`, qwythos:9b, port 52625)
is disabled for boot; re-enable it from `scripts/frank-default-small.service`
if needed. Retired units: the Dankserver llama.cpp 35B service,
`llamaserver`, `ollama`, `vllm-awq-qwen36`, `vllm-qwen36`,
`frank-large-ling` (Ling trial), and the vLLM-ROCm CIRU path. Their unit
files remain in `scripts/` for reference.
The 2026-08-17 redo retired the pipeline-parallel split (PP head + RPC
worker) and the FastFlowLM NPU endpoint. Their scripts are preserved in
`old/scripts/` for reference.
## Structure
- `docs/` — knowledge base: deployment runbook, PP runbook, spec matrix,
NPU notes, research archive
- `scripts/` — serve scripts, env files, systemd units, deploy and test
tools
- `docs/` — knowledge base: deployment runbook, model notes, research archive
- `scripts/` — serve scripts, env files, systemd units, deploy and test tools
- `old/scripts/` — retired PP/NPU-era scripts (reference only)
## Deployment
See [docs/deployment.md](docs/deployment.md). Run
`./scripts/deploy.sh dankclaw` for the PP head. The `dankserver` target
is broken (it targets the removed `frank-default-small` unit); restart
the worker with `sudo systemctl restart frank-pp-worker` until the
script is fixed.
`FRANK_SUDO_PW=... ./scripts/deploy.sh dankserver` for the llama.cpp box or
`FRANK_SUDO_PW=... ./scripts/deploy.sh dankclaw` for the vLLM box.
## Knowledge Base
+4
View File
@@ -1,3 +1,7 @@
> **SUPERSEDED 2026-08-17.** The Frank redo retired this topology.
> See [frank-redo-2026-08-17.md](frank-redo-2026-08-17.md) and
> [deployment.md](deployment.md) for the active configuration.
---
type: research
title: FastFlowLM NPU Inference
@@ -1,3 +1,7 @@
> **SUPERSEDED 2026-08-17.** The Frank redo retired this topology.
> See [frank-redo-2026-08-17.md](frank-redo-2026-08-17.md) and
> [deployment.md](deployment.md) for the active configuration.
# Qwen3.8-27B Pipeline-Parallel Deployment (Dankclaw + Dankserver)
Split Qwen3.8-27B across the Strix Halo iGPU (head) and the RTX
+4
View File
@@ -1,3 +1,7 @@
> **SUPERSEDED 2026-08-17.** The Frank redo retired this topology.
> See [frank-redo-2026-08-17.md](frank-redo-2026-08-17.md) and
> [deployment.md](deployment.md) for the active configuration.
---
type: reference
title: Dankserver VRAM and RAM Growth Under Load
+64 -179
View File
@@ -8,43 +8,8 @@ Two servers run LLM inference services. Each server pulls its scripts from this
| Target | Host | Runtime | Service | Port |
|--------|------|---------|---------|------|
| Dankclaw | dank@dankclaw | llama.cpp PP head (Qwen3.8-27B-Uncensored Q6_K, split 0.68 to the Dankserver worker) | frank-default-large | 7770 |
| Dankclaw | dank@dankclaw | FastFlowLM NPU (qwythos:9b, 262144 ctx) | frank-default-small | 52625 |
| Dankserver | dank@dankserver | ggml-rpc worker (RTX 3090) | frank-pp-worker | 50052 |
The `frank-default-small` (NPU) unit is not in `deploy.sh` and is disabled for boot (see Boot Policy below). If the unit is still loaded (pre-reboot), restart it by hand with `sudo systemctl restart frank-default-small`. After a reboot, re-enable the unit first (see Boot Policy).
## Boot Policy (2026-08-17)
Only the pipeline-parallel pair starts at boot: `frank-default-large` (Dankclaw head) and `frank-pp-worker` (Dankserver worker). Every other inference unit is disabled. This was set on 2026-08-17.
Disabled units:
| Machine | Unit | Fate |
|---------|------|------|
| Dankclaw | `frank-default-small` (FastFlowLM NPU, port 52625) | Disabled; unit file removed from `/etc/systemd/system`. The service keeps running until stopped or rebooted. |
| Dankclaw | `frank-large-ling` (Ling trial) | Disabled. |
| Dankclaw | `vllm-thinkingcap` | Disabled (already). |
| Dankserver | `frank-default-small` (old llama.cpp 35B) | Disabled; unit file removed. |
| Dankserver | `llamaserver`, `ollama`, `vllm-awq-qwen36`, `vllm-qwen36` | Disabled. |
`systemctl disable` removes the symlinked unit file from `/etc/systemd/system` when the file is a symlink. The repo copies stay intact. To restore a disabled service, re-symlink the unit and enable it:
```
sudo ln -sf /home/dank/<repo>/scripts/<unit>.service /etc/systemd/system/<unit>.service
sudo systemctl daemon-reload
sudo systemctl enable <unit>
```
The NPU re-enable recipe uses the Dankclaw repo path `/home/dank/vllmScripts/scripts/frank-default-small.service`.
The Dankserver helper `frank-restart-small.sh` targets the removed `frank-default-small` unit. Do not use it. Restart the PP worker with an explicit command:
```
sudo systemctl restart frank-pp-worker
```
`scripts/deploy.sh dankserver` also targets the removed unit. Do not run it until the script is retargeted to `frank-pp-worker`. The `dankclaw` target works: it restarts the PP head through `frank-restart-large.sh`.
| Dankserver | dank@dankserver | llama.cpp FastMTP (Qwen3.8-27B IQ4_XS + FastMTP 32K draft + ngram-mod) | frank-default-large | 7770 |
| Dankclaw | dank@dankclaw | vLLM ROCm (Avesed Qwen3.6-35B-A3B INT8 W8A8, ngram spec) | frank-default-small | 52625 |
## Workflow
@@ -70,22 +35,22 @@ graph LR
The `scripts/deploy.sh` script executes steps 4 through 6. Run it from the repository root.
Run this command to deploy to Dankclaw:
```
./scripts/deploy.sh dankclaw
```
Run this command to deploy to Dankserver:
```
./scripts/deploy.sh dankserver
FRANK_SUDO_PW=... ./scripts/deploy.sh dankserver
```
Run this command to deploy to Dankclaw:
```
FRANK_SUDO_PW=... ./scripts/deploy.sh dankclaw
```
Add the `--dry-run` flag to preview without making changes:
```
./scripts/deploy.sh dankclaw --dry-run
./scripts/deploy.sh dankserver --dry-run
```
The script does these actions:
@@ -93,153 +58,81 @@ The script does these actions:
1. Verifies that the local working tree has no uncommitted changes.
2. Pushes the `main` branch to origin.
3. Pulls the repository on the target machine.
4. Restarts the service. When the passwordless helper is installed (see below), it runs the helper with plain `sudo`. Otherwise it falls back to the inline sudo commands (unit symlink, cache drop, daemon-reload, restart).
4. Symlinks the systemd unit, reloads systemd, enables, and restarts the service.
5. Waits for the health endpoint to respond (over ssh).
Set `FRANK_SUDO_PW` when running headless on a target that does not yet have the passwordless helper, so that remote sudo reads the password from stdin:
Set `FRANK_SUDO_PW` when running headless, so that remote sudo reads the
password from stdin (`sudo -S`). The passwordless restart helpers from the
retired topology are obsolete and are not used.
Health endpoints:
- Dankserver: `http://127.0.0.1:7770/health`
- Dankclaw: `http://127.0.0.1:52625/health`
## Manual Update
### Update Dankserver (frank-default-large)
Run these commands on Dankserver:
```
FRANK_SUDO_PW=... ./scripts/deploy.sh dankclaw
cd /home/dank/vLLM
git pull origin main
sudo ln -sf /home/dank/vLLM/scripts/frank-default-large.service /etc/systemd/system/frank-default-large.service
sudo systemctl daemon-reload
sudo systemctl restart frank-default-large
curl -sf http://127.0.0.1:7770/health
```
## Passwordless Restart
Each target has a root-owned helper script that performs the full restart. The user `dank` runs it with `sudo` and no password via a sudoers drop-in.
| Target | Helper | Sudoers drop-in |
|--------|--------|-----------------|
| Dankclaw | `/usr/local/sbin/frank-restart-large.sh` | `/etc/sudoers.d/frank-large` |
| Dankserver | `/usr/local/sbin/frank-restart-small.sh` (obsolete, see below) | `/etc/sudoers.d/frank-small` |
The Dankclaw helper does these steps:
1. Runs `sync`.
2. Drops the page caches with `echo 3 > /proc/sys/vm/drop_caches`.
3. Symlinks the systemd unit.
4. Reloads systemd.
5. Enables and restarts the service.
The Dankserver helper `frank-restart-small.sh` is obsolete: it restarts the removed `frank-default-small` unit. Do not use it. The sudoers drop-in does not cover `frank-pp-worker`, so the worker restart needs the password (or a new helper). Restart the worker with `sudo systemctl restart frank-pp-worker`.
The sudoers drop-in contains exactly two rules:
```
dank ALL=(root) NOPASSWD: /usr/local/sbin/frank-restart-large.sh
dank ALL=(root) NOPASSWD: /usr/bin/systemctl status frank-default-large
```
Rules match the command and its arguments exactly. Do not append extra arguments. For example, `sudo systemctl status frank-default-large --no-pager` fails; use the exact form instead. Install or replace the helper and drop-in only through `sudo` on the target, and validate with `sudo visudo -c`.
To test that the setup works, run this command:
```
sudo -n /usr/local/sbin/frank-restart-large.sh
```
### Update Dankclaw
1. Pull the repository.
2. Symlink the unit file, if it changed.
3. Drop the page caches.
4. Reload and restart the service.
### Update Dankclaw (frank-default-small)
Run these commands on Dankclaw:
```
cd /home/dank/vllmScripts
git pull origin main
sudo ln -sf /home/dank/vllmScripts/scripts/frank-default-large.service /etc/systemd/system/frank-default-large.service
sync && echo 3 | sudo tee /proc/sys/vm/drop_caches
sudo ln -sf /home/dank/vllmScripts/scripts/frank-default-small.service /etc/systemd/system/frank-default-small.service
sudo systemctl daemon-reload
sudo systemctl restart frank-default-large
curl -sf http://127.0.0.1:7770/health
sudo systemctl restart frank-default-small
curl -sf http://127.0.0.1:52625/health
```
### Update Dankserver
Run these commands on Dankserver to update and restart the PP worker:
```
cd /home/dank/vLLM
git pull origin main
sudo ln -sf /home/dank/vLLM/scripts/frank-pp-worker.service /etc/systemd/system/frank-pp-worker.service
sudo systemctl daemon-reload
sudo systemctl restart frank-pp-worker
```
The worker has no HTTP health endpoint. Verify the listener instead:
```
ss -tln | grep :50052
```
The old passwordless helper `frank-restart-small.sh` targets the removed `frank-default-small` unit. Do not use it. See Boot Policy.
## Service Units
### Dankclaw — frank-default-large
### Dankserver — frank-default-large
The active service on Dankclaw is the llama.cpp **pipeline-parallel
head**. It serves `Qwen3.8-27B-Uncensored-Q6_K.gguf` (JonathanColetti,
imatrix) under the alias `frank-default-large` on port 7770. The head
splits the tensors `0.68,0.32` to the `ggml-rpc` worker on Dankserver
(RTX 3090, port 50052): 45 of 65 blocks (0-44) on the 3090 — the
maximum for this config (measured 2026-08-17; see the PP doc).
Speculative decoding runs **MTP** with a standalone draft head
(`--spec-draft-model`, `Qwen3.8-27B-Uncensored-draft-Q8_0.gguf`, n_max
4) plus the `--spec-default` ngram-mod fallback (48/64/24). The head GPU
side runs **ROCm0** (no `--device` flag; default device selection puts
RPC first and picks ROCm for the iGPU). **1 slot** at 262144 context
(pool 262144, `n_ctx_slot = 262144`), KV cache **K q8_0 + V f16**
(mismatched, 784 MiB per FA layer; RPC0 8624 + ROCm0 3920 MiB) with
Flash Attention retained via the GGML_CUDA_FA_ALL_QUANTS rebuild, full
layer offload (`--gpu-layers all`, `--fit off`), batch 8192 / ubatch
256, `--direct-io`. The unit file is
The active service on Dankserver is llama.cpp serving
`Qwen3.8-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS.gguf` under the alias
`frank-default-large` on port 7770. It runs the patched FastMTP build
(`/home/dank/llama.cpp-fastmtp/build/bin/llama-server`, commit 4df29be +
the HauhauCS patch) with the FastMTP 32K draft sidecar (`--spec-type
draft-mtp`, `--spec-draft-n-max 2`, `--spec-draft-ngl all`) and the
ngram-mod fallback. Context 131072 (128K, single slot), KV K q8_0 + V f16,
batch 2048 / ubatch 1024, `--no-mmap`, full GPU offload. The unit file is
`scripts/frank-default-large.service`. It launches through
`scripts/serve-pp-head.sh`, which reads tunables from
`scripts/serve-frank-large.sh`, which reads tunables from
`scripts/frank-default-large.env`.
> Note: 2026-08-17 — the Q6_K swap: model + standalone draft head,
> mismatched q8_0/f16 KV with FA (both binaries rebuilt with
> GGML_CUDA_FA_ALL_QUANTS at 9b05354ec), split 0.68 (was 0.53 with the
> Q8_K_XL). Worker at 23854/24576 MiB, ~273 MiB free. MTP acceptance
> 0.75-0.83 (mean len 4.0-4.3), stronger than the old bundled head.
### Dankclaw — frank-default-small
> Note: 2026-08-17 — single-slot config: `PARALLEL=1`, pool 262144
> (was 2 slots x 200700 at 401400), split 0.53 (was 0.40). The 3090
> landed at 23460/24576 MiB, ~667 MiB free. Same-day incident: a full
> Dankserver disk corrupted the worker RPC tensor cache -> degenerate
> output; fixed by clearing the cache + freeing the disk. Guard:
> `scripts/prune-rpc-cache.sh` (cron, 40 GiB cap).
> Note: 2026-08-16 — the pipeline-parallel split was promoted to
> production as `frank-default-large` (renamed from `frank-pp-head`);
> the standalone single-node service retired. MTP was re-enabled at
> `n_max 4` over the ngram-mod fallback. See
> [[Pipeline Parallelism/Qwen3.8 PP Deployment]] for the runbook.
> Note: 2026-08-15 — the spec went DSpark (crashed under two concurrent 16k
> prompts on ROCm, `ROCm error: an illegal memory access`, status 6/ABRT) →
> `--spec-default` (ngram-mod, parallel-safe, PARALLEL=2). The backend went
> ROCm → Vulkan0 after a 262k-ctx bench showed Vulkan decodes 48% faster
> (5.68 vs 3.83 t/s). That Vulkan0 verdict applied to the standalone
> configuration; the PP head runs ROCm0 by default (HIP registers before
> Vulkan). See [[qwen3.8-spec-matrix]] for both decisions and the bench
> table. Also retired earlier: the vLLM-ROCm CIRU INT4 Ling-3.0-flash
> runtime, and the llama-serve/vLLM units on Dankclaw.
### Dankserver — old llama.cpp 35B service (retired 2026-08-16)
Dankserver previously ran `frank-default-small`: llama.cpp serving the HauhauCS Qwen3.6-35B-A3B uncensored `Q6_K_P` (ngram-mod spec, 4 slots x 175104 ctx, 36 of 40 MoE expert layers on CPU, mmproj vision). The service was verified `inactive` on 2026-08-16, and its unit file was removed on 2026-08-17 under the boot policy. The name `frank-default-small` now belongs to the FastFlowLM NPU endpoint on Dankclaw (see [[FastFlowLM NPU Inference]]). The RTX 3090 now runs the PP worker. See git history for the full retired configuration.
The active service on Dankclaw is vLLM (ROCm) serving
`Avesed/Qwen3.6-35B-A3B-INT8-W8A8` under the served model name
`frank-default-small` on port 52625. Full 262144 context, unquantized KV
cache, `--max-num-seqs 4`, `--max-num-batched-tokens 16384`, ngram
speculative decoding, `--reasoning-parser qwen3`. The unit file is
`scripts/frank-default-small.service`. It launches through
`scripts/serve-frank-small.sh`, which reads tunables from
`scripts/frank-default-small.env`.
## Validation
The deploy script checks the health endpoint after a restart. For deeper checks, run the validation script on the target.
Run this command on Dankserver to test vLLM throughput:
The deploy script checks the health endpoint after a restart. For deeper checks, run a completion request against the endpoint:
```
./scripts/validate-vllm.sh
curl -s http://127.0.0.1:7770/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"frank-default-large","messages":[{"role":"user","content":"Say OK"}]}'
```
## Troubleshooting
@@ -248,32 +141,24 @@ If the health check fails after a deploy:
1. Read the service logs with `journalctl -u <service> -n 200`.
2. Confirm that the model files exist in the cache.
3. Confirm that the GPU has free memory.
3. Confirm that the GPU has free memory (`nvidia-smi` on Dankserver, `rocm-smi` on Dankclaw).
4. Check the service status with `systemctl status <service>`.
## Incident: HIP Runtime Crash From the `TEMP` Env Variable (2026-08-13)
On 2026-08-13 the `frank-default-large` service crash-looped for hours. Every restart died with SIGSEGV about 20 seconds into model load, at a fixed offset in `libamdhip64` (NULL refcount unref during `ggml_backend_cuda_buffer_set_tensor`). The kernel log showed bursts of `amdgpu: SVM mapping failed, exceeds resident system memory limit`, which pointed at memory but was a red herring.
On 2026-08-13 the old `frank-default-large` service crash-looped for hours on Dankclaw. Root cause: the env files exported `TEMP=1.0` (a sampling default). The ROCm HIP runtime reads `TEMP` as its JIT kernel-cache directory, used the path `1.0`, failed, and segfaulted on a NULL object. Fix: rename the sampling variable to `TEMPERATURE` (commit `227ce01`).
Root cause: the env files exported `TEMP=1.0` (a sampling default added in commit `db3eb01`). The ROCm HIP runtime reads the `TEMP` environment variable as its JIT kernel-cache directory. HIP then used the path `1.0`, failed, and segfaulted on a NULL object. The crash was deterministic whenever the serve script sourced the env file, and absent when it did not.
Fix: rename the sampling variable to `TEMPERATURE` in the env files and serve scripts (commit `227ce01`). The serve script still passes `--temp "$TEMPERATURE"` to `llama-server`, so sampling defaults are unchanged.
If a service segfaults at load with no obvious cause, compare the exported env against the HIP runtime's env reads. Check with `strings /opt/rocm-*/lib/libamdhip64.so.* | grep -xE "TEMP|HOST|..."`. Do not name any tunable `TEMP`, `HOST`, or `GPU_MAX_HEAP_SIZE`.
If a service segfaults at load with no obvious cause, compare the exported env against the HIP runtime's env reads. Do not name any tunable `TEMP`, `HOST`, or `GPU_MAX_HEAP_SIZE`.
## Incident: Jobs "Released Prematurely" Under Parallel Load (2026-08-13)
A user reported that a streaming job on `frank-default-large` was released early when another job started. The suspicion was speculative decoding. The investigation found three facts:
1. **The server does not preempt.** `llama-server` defers a new task into a queue when all slots are busy. It never releases a running generation to make room. Verified empirically with concurrent streaming jobs.
2. **The releases were client-side aborts.** The pi coding agent aborts a stream when the user interrupts it. The client records `stopReason: "aborted"`; the server logs `W srv stop: cancel task, id_task = N`. A natural stop (EOS or limit) logs only `slot release` with `truncated = 0`.
3. **Dankserver crashed under the parallel researcher load.** Five parallel research subagents hammered `frank-default-small` with back-to-back requests. The service aborted twice with `CUDA error: an unsupported value or parameter was passed to the function` in `cublasSgemm_v2` at `ggml-cuda.cu:1541`, then `status=6/ABRT`, then `503 Loading model` for ~5 minutes. That crash, not speculative decoding, killed the parallel jobs. The affected service is retired; see [[dankserver-vram-growth]] for the VRAM/RAM growth findings behind the crash class.
Historical: on the retired topology, parallel jobs on the Dankserver 35B service died with a cuBLAS crash under researcher load. The affected service is retired. A client abort logs `W srv stop: cancel task, id_task = N`; a natural stop logs only `slot release` with `truncated = 0`. The server never preempts a running generation.
## See Also
- [AGENTS.md](../AGENTS.md) — the git workflow rules
- [README.md](../README.md) — repository overview
- [index.md](index.md) — knowledge base index
- [frank-redo-2026-08-17.md](frank-redo-2026-08-17.md) — the full redo runbook
- [serverAppConfigs knowledge base](../serverAppConfigs/docs/index.md) —
the sibling Podman app stack on the same hosts; its OpenWebUI consumes
the `:7770` endpoint, and its Gitea instance hosts this repository
the sibling Podman app stack on the same hosts
+4
View File
@@ -1,3 +1,7 @@
> **SUPERSEDED 2026-08-17.** The Frank redo retired this topology.
> See [frank-redo-2026-08-17.md](frank-redo-2026-08-17.md) and
> [deployment.md](deployment.md) for the active configuration.
# frank-default-large — Backend and Spec Benchmark
This page records the benchmarks that chose the runtime for
+127
View File
@@ -0,0 +1,127 @@
# Frank Program Redo — 2026-08-17
This page records the full redo of the inference fleet on 2026-08-17.
The pipeline-parallel split and the FastFlowLM NPU endpoint were retired.
The old scripts moved to `old/scripts/` in this repository.
## New Topology
| Service | Host | Runtime | Model | Port |
|---------|------|---------|-------|------|
| frank-default-large | Dankserver | llama.cpp (patched FastMTP) | HauhauCS Qwen3.8-27B-Uncensored-Aggressive IQ4_XS | 7770 |
| frank-default-small | Dankclaw | vLLM ROCm | Avesed Qwen3.6-35B-A3B INT8 W8A8 | 52625 |
The RTX 3090 runs the whole 27B model standalone. No RPC worker, no
tensor split, no NPU.
## Models
### frank-default-large — HauhauCS/Qwen3.8-27B-Uncensored-HauhauCS-Aggressive-MTP-GGUF:IQ4_XS
- Base: Qwen3.8-27B (dense 27B, 64 layers: 48 GatedDeltaNet + 16
gated-attention, hidden 5120, 24 Q heads / 4 KV heads, head dim 256,
native 262144 ctx).
- Quant: IQ4_XS (4.60 BPW, 15.71 GB). Every GGUF in the repo preserves the
native embedded MTP/NextN head.
- FastMTP draft sidecar: `...FastMTP-32K.gguf` (903 MB). Requires the
patched llama.cpp build (commit `4df29be4f4c3673f428170fda944a5b19f743bb8`
+ `HauhauCS-FastMTP-llama.cpp.patch`). Without the patch, the draft load
fails with `expected 5120, 248320, got 5120, 32768`.
- Spec chain: FastMTP (`--spec-type draft-mtp`, `--spec-draft-n-max 2`,
`--spec-draft-ngl all`, `--spec-draft-p-min 0`) then ngram-mod fallback
(48/64/24).
### frank-default-small — Avesed/Qwen3.6-35B-A3B-INT8-W8A8
- Base: Qwen3.6-35B-A3B (hybrid MoE, 256 experts top-8, ~3B active, 40
layers: 10 blocks of 3 DeltaNet + 1 Attention, native 262144 ctx).
- Quant: compressed-tensors INT8 W8A8 (symmetric per-channel weights,
dynamic per-token activations). Expert FFNs quantized; attention, router,
DeltaNet, lm_head kept bf16. Weights ~38 GB.
- Served with vLLM ROCm, ngram speculative decoding.
## Context Math (frank-default-large, RTX 3090)
KV per token: 16 attention layers x 4 KV heads x 256 dim.
K q8_0 = 1088 B/token, V f16 = 2048 B/token, total 50176 B/token.
Budget (MiB): 24576 total - 14982 weights - 861 draft - 1024 fixed
(CUDA context, compute graph, scratch, draft KV) - headroom.
| Context | KV (MiB) | Free after load |
|---------|----------|-----------------|
| 114688 (112K) | 5488 | 2221 (2.17 GiB) |
| 122880 (120K) | 5880 | 1829 (1.79 GiB) |
| 131072 (128K) | 6272 | 1437 (1.40 GiB) |
| 147456 (144K) | 7056 | 653 (0.64 GiB) |
Production choice: **131072 (128K)** — the maximum that keeps about
1.4 GiB headroom for checkpoints. Lower `CTX_SIZE` in
`scripts/frank-default-large.env` to 122880 for ~1.8 GiB headroom.
## Install Runbook
### Dankserver (frank-default-large)
1. Stop the old worker: `sudo systemctl stop frank-pp-worker`.
2. Download the model and draft to `/home/dank/models/hauhaucs-qwen38/`.
3. Build the patched llama.cpp:
```
git clone https://github.com/ggerganov/llama.cpp /home/dank/llama.cpp-fastmtp
cd /home/dank/llama.cpp-fastmtp
git checkout 4df29be4f4c3673f428170fda944a5b19f743bb8
curl -L -o HauhauCS-FastMTP-llama.cpp.patch <HF patch URL>
git apply HauhauCS-FastMTP-llama.cpp.patch
cmake -S . -B build -DGGML_CUDA=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release -j$(nproc)
```
4. Symlink the unit, reload, enable, restart:
```
sudo ln -sf /home/dank/vLLM/scripts/frank-default-large.service /etc/systemd/system/
sudo systemctl daemon-reload && sudo systemctl enable frank-default-large
sudo systemctl restart frank-default-large
```
5. Verify: `curl -sf http://127.0.0.1:7770/health` and a chat completion.
6. Confirm VRAM headroom with `nvidia-smi`.
### Dankclaw (frank-default-small)
1. Stop the old services: `sudo systemctl stop frank-default-large
frank-default-small` (retired PP head and NPU endpoint).
2. Install uv and create the venv:
```
curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv --python /usr/bin/python3.12 /home/dank/vllm-venv
uv pip install --python /home/dank/vllm-venv vllm --torch-backend=auto
```
The resolver pulls the AMD ROCm wheel set (torch +
amd-torch-device-gfx1151 + the vllm rocm variant) from the AMD index.
3. Cache the model (default HF cache):
```
python3 -c "from huggingface_hub import snapshot_download; snapshot_download('Avesed/Qwen3.6-35B-A3B-INT8-W8A8')"
```
4. Symlink the unit, reload, enable, restart:
```
sudo ln -sf /home/dank/vllmScripts/scripts/frank-default-small.service /etc/systemd/system/
sudo systemctl daemon-reload && sudo systemctl enable frank-default-small
sudo systemctl restart frank-default-small
```
5. Verify: `curl -sf http://127.0.0.1:52625/health` and a chat completion.
## Fallback: vLLM source build for gfx1151
If the prebuilt ROCm vLLM wheel cannot run on gfx1151, build from source.
The retired CIRU package documents the proven recipe:
`/home/dank/ling3-ciru/Ling-3.0-Flash-CIRU-int4-Strix-native/scripts/build-vllm-gfx1151.sh`
(branch `ciru/ling3-gfx1151-rocm715`, index `https://rocm.nightlies.amd.com/whl-multi-arch/`).
The upstream starting point needed a five-line ROCm sampler fix to launch
on gfx1151; newer vLLM releases may already include it.
## Configuration
- `models.json` (pi): two providers — `llamacpp (dankserver)` at
http://192.168.0.235:7770/v1 and `vllm (dankclaw)` at
http://192.168.0.143:52625/v1.
- HF token: `~/.cache/huggingface/token` on both machines (mode 600).
- OpenWebUI (sibling repo): retarget `OPENAI_API_BASE_URL` to the
Dankserver endpoint.
+42 -52
View File
@@ -1,8 +1,8 @@
# vLLM Scripts — Knowledge Base
Documentation for the LLM inference fleet on two local machines:
llama.cpp production (PP head + RPC worker), the FastFlowLM NPU endpoint,
plus a vLLM research archive.
Documentation for the LLM inference fleet on two local machines
(2026-08-17 redo): llama.cpp FastMTP on Dankserver and vLLM ROCm on
Dankclaw.
## Deployment Topology
@@ -10,44 +10,47 @@ plus a vLLM research archive.
graph LR
subgraph Dankserver[NVIDIA Dankserver - Ubuntu 24.04]
A[RTX 3090 24GB + 62GB RAM]
B[ggml-rpc worker
frank-pp-worker, port 50052]
A --> B
B[llama.cpp FastMTP
frank-default-large, port 7770]
C[Qwen3.8-27B-Aggressive IQ4_XS
FastMTP 32K draft + ngram-mod, 128K ctx]
A --> B --> C
end
subgraph Dankclaw[AMD Strix Halo - Ubuntu 26.04]
D[gfx1151 APU 30GiB phys / 96GiB GPU-visible]
E[llama.cpp PP head
frank-default-large, port 7770]
F[Qwen3.8-27B-Uncensored Q6_K
split 0.68/0.32 to worker, standalone MTP draft + ngram-mod]
D[gfx1151 iGPU unified memory]
E[vLLM ROCm
frank-default-small, port 52625]
F[Avesed Qwen3.6-35B-A3B INT8 W8A8
full 262144 ctx, ngram spec, 4 seqs]
D --> E --> F
G[FastFlowLM NPU XDNA2 50 TOPS
frank-default-small, port 52625 - DISABLED for boot 2026-08-17]
H[qwythos:9b
Q4NX 7.76 GB, 262k ctx]
D --> G --> H
end
I[LLM Clients / API] -->|HTTP :7770| E
I -->|HTTP :52625| G
E -->|RPC layers 0.68| B
I[LLM Clients / API] -->|HTTP :7770| B
I -->|HTTP :52625| E
```
Boot policy (2026-08-17): only `frank-default-large` and `frank-pp-worker` are enabled. The NPU endpoint and all retired units are disabled; see [[deployment]] for the table and re-enable recipes.
## Servers
| Server | GPU | VRAM / Memory | OS |
| --------------------------------------- | ----------------------------- | ----------------------------------- | ------------ |
| [[Dankserver System Specs\|Dankserver]] | NVIDIA RTX 3090 | 24 GB VRAM, 62 GB RAM | Ubuntu 24.04 |
| [[Dankclaw System Specs\|Dankclaw]] | AMD Radeon 8060S (Strix Halo) | 30 GiB physical / 96 GiB GPU-visible | Ubuntu 26.04 |
| Server | GPU | VRAM / Memory | OS |
| --------------------------------------- | ----------------------------- | -------------------- | ------------ |
| [[Dankserver System Specs\|Dankserver]] | NVIDIA RTX 3090 | 24 GB VRAM, 62 GB RAM | Ubuntu 24.04 |
| [[Dankclaw System Specs\|Dankclaw]] | AMD Radeon 8060S (Strix Halo) | gfx1151 unified memory | Ubuntu 26.04 |
## vLLM Reference
## Active Deployment
- [[deployment]] — deploy and update process for both servers
- [[frank-redo-2026-08-17]] — the full redo: topology change, model
choices, context math, and the two install runbooks
- [[Dankserver]] — the llama.cpp FastMTP box (frank-default-large)
- [[Dankclaw]] — the vLLM ROCm box (frank-default-small)
## vLLM Reference (Dankclaw)
- [[VLLM Overview]] — installation, CLI, API, architecture, quantization, parallelism
- [[VLLM Index]] — quick reference with commands, endpoints, and parameter table
- [[deployment]] — deploy and update process for both servers
- [[Running Qwen3.6 35B A3B FP8 on Dankserver]] — Qwen3.6-35B-A3B hardware
notes and sizing (the model family served by frank-default-small)
## Memory Management
@@ -55,36 +58,23 @@ Boot policy (2026-08-17): only `frank-default-large` and `frank-pp-worker` are e
- [[Hybrid CPU GPU Processing Dankserver]] — NVIDIA GPU compute with system RAM offload
- [[Shared Memory Architecture Dankclaw]] — AMD unified memory and ROCm configuration
## Model Deployment
## Retired Topology (2026-08-17 redo)
- [[Running Qwen3.6 35B A3B FP8 on Dankserver]] — MoE model (35B total, 3B active) on RTX 3090
- [[Running Qwen3.6 27B FP8 on Dankclaw]] — Dense model (27B) on Strix Halo APU
- [[frank-default-large-benchmark]] — backend/spec benchmark; chose MTP sidecar (2026-08-14) over DFlash (parallel premature-EOS bug)
- [[qwen3.8-spec-matrix]] — Qwen3.8-27B spec history + current production state: Uncensored Q6_K + standalone MTP draft, q8_0/f16 KV with FA (FA_ALL_QUANTS rebuild), 1 slot @ 262144, split 0.68 (2026-08-17)
- [[qwen3.8-strix-optimizations]] — Qwen3.8-27B Strix speed research: ranked levers that keep UD-Q8_K_XL (PP to 3090, MTP tuning, same-bit Q8_0 A/B, prefill path, OS), quant landscape, 2026-08-16 test matrix
- [[frank-default-small-benchmark]] — ncmoe and batch/ubatch sweep that drove the Dankserver state
- [[dankserver-vram-growth]] — VRAM/RAM growth investigation behind the recurring cuBLAS crash on frank-default-small
- [[Dankclaw Improvements]] — researched enhancements: self-hosted agentic tools, runtime tuning, server/OS settings
- [[FastFlowLM NPU Inference]] — FastFlowLM (FLM), the AMD NPU-first runtime. The 50 TOPS Strix Halo NPU on Dankclaw: model fit, vendor benchmarks, verified install state, test runbook (2026-08-16)
## Speculative Decoding & Quantization
- [[DFlash DSpark Speculative Decoding]] — block diffusion (DFlash) and semi-autoregressive (DSpark) drafting on vLLM and llama.cpp
- [[Qwen3.8 PP Deployment]] — the retired pipeline-parallel head + worker
- [[qwen3.8-spec-matrix]] — Qwen3.8-27B spec history (superseded by FastMTP)
- [[FastFlowLM NPU Inference]] — the retired FastFlowLM NPU endpoint
- [[frank-default-large-benchmark]] — backend/spec benchmark behind the old head
- [[dankserver-vram-growth]] — VRAM/RAM growth behind the retired cuBLAS crash
- [[DFlash DSpark Speculative Decoding]] — retired DFlash/DSpark drafting
- [[Quantization by Hardware Architecture]] — which quant format fits which GPU/CPU
## Pipeline Parallelism
## Pipeline Parallelism (archive)
- [[Pipeline Parallelism]] — index of multi-node inference research and sample scripts
- [[Pipeline Parallelism/llama.cpp RPC]] — ggml-rpc-server + `--rpc` distributed inference
- [[Pipeline Parallelism/vLLM Pipeline Parallelism]] — vLLM PP across machines
- [[Pipeline Parallelism/Ethernet Bandwidth Math]] — bytes per token and link feasibility
- [[Pipeline Parallelism/Mixed-Vendor Experiments]] — NVIDIA + Strix Halo real-world runs
- [[Pipeline Parallelism/Expected Performance]] — estimated tok/s over 1/2.5/10 GbE
- [[Pipeline Parallelism/Sample Script Set]] — educational two-node Qwen3.6-27B Q8 split
- [[Pipeline Parallelism/Qwen3.8 PP Deployment]] — the production deployment + runbook: Qwen3.8-27B head (Strix) / worker (RTX 3090) over RPC, b10433, scripts in scripts/; split limits, FA-all-quants rebuild, cache incident (2026-08-17)
- [[Pipeline Parallelism]] — index of multi-node inference research. The PP
pair is retired; these pages are research history.
## Sibling projects
- [serverAppConfigs](../serverAppConfigs/docs/index.md) — the Podman app
stack on the same two hosts. Its OpenWebUI consumes the `:7770`
endpoint; its Gitea instance hosts this repository.
stack on the same two hosts. Its OpenWebUI consumes the `:7770` endpoint
on Dankserver; its Gitea instance hosts this repository.
+4
View File
@@ -1,3 +1,7 @@
> **SUPERSEDED 2026-08-17.** The Frank redo retired this topology.
> See [frank-redo-2026-08-17.md](frank-redo-2026-08-17.md) and
> [deployment.md](deployment.md) for the active configuration.
# Qwen3.8-27B Speculative-Decoding Matrix
This page records the speculative-decoding benchmark history and the
+196
View File
@@ -0,0 +1,196 @@
#!/usr/bin/env bash
# deploy.sh — Deploy the vllmScripts repo to a target and restart its service.
#
# This script implements the second half of the git deployment workflow from
# AGENTS.md. It assumes the local changes are committed and pushed, then:
# 1. Pulls the repo on the target
# 2. Installs / enables the systemd unit
# 3. Drops page caches (dankclaw) and restarts the service
# 4. Waits for the health endpoint and reports status
#
# Sudo: when FRANK_SUDO_PW is set, remote sudo pipes it via `sudo -S` for
# headless runs. Otherwise plain `sudo` is used (tty or passwordless config).
# Prefer the passwordless restart helpers installed on each target
# (/usr/local/sbin/frank-restart-<large|small>.sh); they cover the unit
# symlink, cache drop (dankclaw), daemon-reload, and restart in one root
# script. See docs/deployment.md -> Passwordless restart.
#
# Usage:
# ./deploy.sh <target> [--dry-run]
# FRANK_SUDO_PW=... ./deploy.sh <target>
#
# Targets:
# dankclaw - llama.cpp server (frank-default-large.service, port 7770)
# dankserver - llama.cpp server (frank-default-small.service, port 7770)
#
# Example:
# ./deploy.sh dankclaw
# ./deploy.sh dankserver --dry-run
set -euo pipefail
# ---------------------------------------------------------------------------
# Target configuration
# ---------------------------------------------------------------------------
declare -A REMOTE_USER REMOTE_HOST REMOTE_DIR SERVICE SERVICE_HEALTH DROP_CACHES HELPER HEALTH_WAIT
REMOTE_USER[dankclaw]=dank
REMOTE_HOST[dankclaw]=dankclaw
REMOTE_DIR[dankclaw]="/home/dank/vllmScripts"
SERVICE[dankclaw]="frank-default-large"
SERVICE_HEALTH[dankclaw]="http://127.0.0.1:7770/health"
# Drop page caches before restart: with the model's pages fully cached, the
# KV/graph allocation stalls at load (VRAM stuck at 28 GiB). See AGENTS.md.
DROP_CACHES[dankclaw]=1
# Passwordless restart helper (root-owned, installed via /etc/sudoers.d/frank-large).
# When present, deploy.sh uses it instead of inline sudo commands.
HELPER[dankclaw]="/usr/local/sbin/frank-restart-large.sh"
# Health wait in iterations of 2s. Cold loads after the cache drop measured
# at up to 17 minutes on 2026-08-13; 600 iterations = 20 minutes.
HEALTH_WAIT[dankclaw]=600
REMOTE_USER[dankserver]=dank
REMOTE_HOST[dankserver]=dankserver
REMOTE_DIR[dankserver]="/home/dank/vLLM"
SERVICE[dankserver]="frank-default-small"
SERVICE_HEALTH[dankserver]="http://127.0.0.1:7770/health"
DROP_CACHES[dankserver]=0
HELPER[dankserver]="/usr/local/sbin/frank-restart-small.sh"
HEALTH_WAIT[dankserver]=300
TARGET="${1:-}"
DRY_RUN=0
if [ "${2:-}" = "--dry-run" ]; then
DRY_RUN=1
fi
# ---------------------------------------------------------------------------
# Validation
# ---------------------------------------------------------------------------
if [ -z "${TARGET:-}" ]; then
echo "Usage: $0 <dankclaw|dankserver> [--dry-run]"
exit 1
fi
if [ -z "${REMOTE_HOST[$TARGET]:-}" ]; then
echo "Unknown target: $TARGET"
exit 1
fi
# ---------------------------------------------------------------------------
# Sudo wrapper (headless-friendly)
# ---------------------------------------------------------------------------
# When FRANK_SUDO_PW is set, remote sudo reads the password from stdin via
# `sudo -S`. Otherwise plain `sudo` is used (tty or passwordless config).
SUDO_PREFIX="sudo"
if [ -n "${FRANK_SUDO_PW:-}" ]; then
SUDO_PREFIX="printf '%s\n' '$FRANK_SUDO_PW' | sudo -S"
fi
# ---------------------------------------------------------------------------
# Local checks (pre-flight)
# ---------------------------------------------------------------------------
cd "$(dirname "$0")/.."
if ! git diff --quiet HEAD; then
echo "FAIL: Local working tree has uncommitted changes."
echo "Commit or stash them before deploying."
exit 1
fi
if [ "$(git rev-parse --abbrev-ref HEAD)" != "main" ]; then
echo "WARN: Not on 'main'; deploying a non-main branch."
fi
echo "=== Deploying to ${TARGET} ==="
echo " host: ${REMOTE_HOST[$TARGET]}"
echo " dir: ${REMOTE_DIR[$TARGET]}"
echo " service: ${SERVICE[$TARGET]}"
echo " health: ${SERVICE_HEALTH[$TARGET]}"
echo ""
# ---------------------------------------------------------------------------
# Push (unless dry-run)
# ---------------------------------------------------------------------------
if [ "$DRY_RUN" = "1" ]; then
echo "[dry-run] Would push local main to origin"
echo "[dry-run] Would SSH to ${REMOTE_HOST[$TARGET]} and git pull"
else
echo "[1/4] Pushing local main to origin..."
git push origin main
fi
REMOTE="$(
printf '%s@%s' "${REMOTE_USER[$TARGET]}" "${REMOTE_HOST[$TARGET]}"
)"
# ---------------------------------------------------------------------------
# Remote: pull + install + restart
# ---------------------------------------------------------------------------
DROP_CACHES_CMD=""
if [ "${DROP_CACHES[$TARGET]}" = "1" ]; then
DROP_CACHES_CMD="
echo 'Dropping page caches for reliable model load...'
${SUDO_PREFIX} sh -c 'sync; echo 3 > /proc/sys/vm/drop_caches'
"
fi
HELPER_PATH="${HELPER[$TARGET]:-}"
REMOTE_SCRIPT="
set -euo pipefail
cd '${REMOTE_DIR[$TARGET]}'
echo '[2/4] Pulling repo on ${TARGET}...'
git pull origin main
if [ -x '${HELPER_PATH}' ]; then
# Passwordless restart helper (sudoers NOPASSWD) - preferred path.
echo '[3/4] Restarting via passwordless helper ${HELPER_PATH}...'
${SUDO_PREFIX} '${HELPER_PATH}'
else
echo '[3/4] Helper not installed; using inline sudo commands...'
# Install / symlink the systemd unit
case '${TARGET}' in
dankclaw)
${SUDO_PREFIX} ln -sf '${REMOTE_DIR[$TARGET]}/scripts/frank-default-large.service' /etc/systemd/system/frank-default-large.service
;;
dankserver)
${SUDO_PREFIX} ln -sf '${REMOTE_DIR[$TARGET]}/scripts/frank-default-small.service' /etc/systemd/system/frank-default-small.service
;;
esac
${DROP_CACHES_CMD}
echo '[3/4] Reload and restart ${SERVICE[$TARGET]}...'
${SUDO_PREFIX} systemctl daemon-reload
${SUDO_PREFIX} systemctl enable '${SERVICE[$TARGET]}'
${SUDO_PREFIX} systemctl restart '${SERVICE[$TARGET]}'
fi
"
if [ "$DRY_RUN" = "1" ]; then
echo "[dry-run] Remote commands would run:"
echo "$REMOTE_SCRIPT"
else
# shellcheck disable=SC2087
ssh "$REMOTE" bash -s <<REMOTE_EOF
${REMOTE_SCRIPT}
REMOTE_EOF
fi
# ---------------------------------------------------------------------------
# Health check
# ---------------------------------------------------------------------------
if [ "$DRY_RUN" = "1" ]; then
echo "[dry-run] Would wait for health at ${SERVICE_HEALTH[$TARGET]}"
else
echo "[4/4] Waiting for health endpoint ${SERVICE_HEALTH[$TARGET]} (via ssh)..."
HEALTH_URL="${SERVICE_HEALTH[$TARGET]}"
HEALTH_ITERS="${HEALTH_WAIT[$TARGET]:-300}"
for i in $(seq 1 "$HEALTH_ITERS"); do
if ssh "$REMOTE" "curl -sf '$HEALTH_URL'" > /dev/null 2>&1; then
echo " Service healthy after approx $((i * 2))s"
echo ""
echo "=== Deploy complete: ${TARGET} ==="
exit 0
fi
sleep 2
done
echo "FAIL: Service did not become healthy in $((HEALTH_ITERS * 2))s"
exit 1
fi
+88
View File
@@ -0,0 +1,88 @@
# Head tunables — Qwen3.8-27B pipeline-parallel head (Dankclaw).
#
# The head is the LOCAL side of the split. It runs llama-server (b10433,
# HIP+Vulkan+RPC build in /home/dank/llama.cpp/build) with --rpc pointing at
# the worker on Dankserver. The model file lives on this machine only; the
# worker receives its tensor share over the network at load time.
#
# CRITICAL: this script must NOT pass --device. When --device is set,
# llama.cpp uses exactly that device list and silently drops the RPC device
# (src/llama.cpp llama_prepare_model_devices). Default device selection
# inserts RPC servers at the FRONT of the device list, so the split becomes
# [RPC0, iGPU] and --tensor-split index 0 is the worker.
#
# WARNING: do not name any variable here TEMP, HOST, or GPU_MAX_HEAP_SIZE
# (HIP runtime collision, see the 2026-08-13 TEMP incident).
MODEL_DIR=/home/dank/models
MODEL_FILE=Qwen3.8-27B-Uncensored-Q6_K.gguf
HEAD_BIN=/home/dank/llama.cpp/build/bin/llama-server
ALIAS=frank-default-large
BIND_ADDR=0.0.0.0
LISTEN_PORT=7770
# Comma-separated RPC endpoints (host:port). One worker here.
RPC_SERVERS=192.168.0.235:50052
# Model split fractions, one per device in order [RPC0, iGPU].
# 0.68,0.32 = 45 of 65 blocks on the 3090 (blocks 0-44) - the maximum
# for the Q6_K + q8_0/f16 KV config, measured 2026-08-17 phase 2:
# - KV per FA layer = 784 MiB (K 1088 B/token + V 2048 B/token @262144)
# - weights(f) = 20334 MB layer pool x f (GGUF scan, exact); embd on
# the head side (RPC0 buffer observed 10429.88 MiB at f=0.53)
# - KV-per-device count = round(f x 66) layers -> 45 layers = 11 FA
# (3..43) -> 8624 MiB. 46 layers (f>=0.7045) still 11 FA but margin
# drops to ~0.4 GiB; 48 layers (f>=0.7197) adds FA block 47 -> KV
# 9408 -> OOM by ~0.85 GiB.
# Predicted: 13430 (weights) + 8624 (KV) + ~530 (RS) + 189 (compute) =
# ~22773 MiB -> ~0.7 GiB free. Draft model runs on ROCm0 only (measured
# phase 1: 1718 MiB, no worker impact).
TENSOR_SPLIT=0.68,0.32
# Context pool. 262144 total = 1 parallel slot x 262144 per slot
# (n_ctx_seq = n_ctx / n_seq_max, llama-context.cpp:293).
CTX_SIZE=262144
PARALLEL=1
# Speculative decoding. MTP with the STANDALONE draft head (the Q6_K
# model has no bundled MTP head; the repo ships the draft sidecar) + the
# ngram-mod fallback. Set SPEC_NONE=1 for a raw baseline.
SPEC_NONE=0
SPEC_DEFAULT=1
MTP=1
SPEC_DRAFT_N_MAX=4
# Standalone MTP draft head (Q8_0 MTP-only sidecar from the same repo).
SPEC_DRAFT_MODEL=/home/dank/models/Qwen3.8-27B-Uncensored-draft-Q8_0.gguf
SPEC_NGRAM_MOD_N_MIN=48
SPEC_NGRAM_MOD_N_MAX=64
SPEC_NGRAM_MOD_N_MATCH=24
# KV on GPU: K q8_0 + V f16 (mismatched, 16 full-attention layers x 4
# heads x 256 dim: K = 1088 B/token, V = 2048 B/token -> 3136 B/token ->
# 784 MiB per FA layer at 262144, 12.25 GiB total). Mismatched K/V with
# Flash Attention requires the GGML_CUDA_FA_ALL_QUANTS rebuild (2026-08-17:
# head HIP + worker CUDA at 9b05354ec). Do not revert the binaries without
# also reverting this.
CACHE_TYPE_K=q8_0
CACHE_TYPE_V=f16
# Batch sizing: production-verified values (2026-08-14).
BATCH_SIZE=8192
UBATCH_SIZE=256
# Sampling — Qwen3.8 thinking-mode defaults.
TEMPERATURE=1.0
TOP_K=20
TOP_P=0.95
MIN_P=0.0
THREADS=12
THREADS_HTTP=1
# 4 (info): clean journal for interactive use. Raise to 10 only when
# debugging the layer split (the per-layer assignment lines are debug-level).
VERBOSITY=4
# 1: --direct-io model load. Required in practice for large models loaded
# over RPC (load hangs otherwise; visorcraft Strix RPC finding).
DIRECT_IO=1
+16
View File
@@ -0,0 +1,16 @@
[Unit]
Description=llama.cpp Qwen3.8-27B pipeline-parallel head (Strix + RPC to Dankserver) (frank-default-large)
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=dank
Group=dank
Environment="FRANK_PP_HEAD_ENV_FILE=/home/dank/vllmScripts/scripts/frank-default-large.env"
ExecStart=/home/dank/vllmScripts/scripts/serve-pp-head.sh
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
+33
View File
@@ -0,0 +1,33 @@
# Tunables for frank-default-small (FastFlowLM NPU endpoint, dankclaw)
# Runtime: FLM 1.0.1 on the XDNA2 NPU (50 TOPS). Model choice, measured
# results, and the NPU memory budget are in docs/FastFlowLM NPU Inference.md.
# The NPU allocates from the unified pool shared with frank-default-large
# (the PP head). Keep the resident footprint small enough that the head
# keeps its headroom.
#
# 2026-08-17: qwythos:9b (Huihui-Qwythos-9B-Claude-Mythos-5-1M-abliterated,
# Qwen3.5-9B hybrid linear-attention base, Q4NX, 7.76 GB) chosen after the
# user's model swap (was qwen3.6-moe:35b-a3b, which stays installed for
# rollback). FLM upgraded 0.9.45 -> 1.0.1: the pack declares flm_version
# 1.0.0 and 0.9.45 refused to serve it.
FLM_MODEL=qwythos:9b
FLM_HOST=0.0.0.0
FLM_PORT=52625
# Power mode: turbo. Smoke decode ~5-7 t/s on the 9B dense at 262k ctx
# (not benchmarked; see docs/FastFlowLM NPU Inference.md).
FLM_PMODE=turbo
# Load the ASR model (Whisper-V3-Turbo-NPU2) alongside the LLM. Exposes
# /v1/audio/transcriptions. Adds ~1 GiB to the resident footprint.
FLM_ASR=1
# Maximum context length. Qwythos-9B native max is 262144 (Qwen3.5-9B
# hybrid: 8 of 32 layers are full attention, so the KV cache stays small).
# Verified 2026-08-17: loads at -c 262144 with turbo+asr on FLM 1.0.1;
# KV occupancy 0.007% at 19 tokens.
FLM_CTX_LEN=262144
# Custom-model resolution: the qwythos:9b tag and its xclbin symlinks live
# in the user config, not the system registry. Without these, flm treats
# the tag as unknown and silently serves llama3.2:1b (see the unknown-tag
# fallback in docs/FastFlowLM NPU Inference.md).
FLM_CONFIG_PATH=/home/dank/.config/flm/model_list.json
FLM_XCLBIN_PATH=/home/dank/.config/flm
+17
View File
@@ -0,0 +1,17 @@
[Unit]
Description=FastFlowLM NPU inference (frank-default-small) on Dankclaw
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=dank
Group=dank
Environment="FLM_SMALL_ENV_FILE=/home/dank/vllmScripts/scripts/frank-default-small.env"
ExecStart=/home/dank/vllmScripts/scripts/serve-flm-small.sh
LimitMEMLOCK=infinity
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
Executable → Regular
+28 -60
View File
@@ -1,62 +1,49 @@
#!/usr/bin/env bash
# deploy.sh — Deploy the vllmScripts repo to a target and restart its service.
# deploy.sh - Deploy the vllmScripts repo to a target and restart its service.
#
# This script implements the second half of the git deployment workflow from
# AGENTS.md. It assumes the local changes are committed and pushed, then:
# 1. Pulls the repo on the target
# 2. Installs / enables the systemd unit
# 3. Drops page caches (dankclaw) and restarts the service
# 2. Symlinks the systemd unit
# 3. Reloads systemd and restarts the service
# 4. Waits for the health endpoint and reports status
#
# Sudo: when FRANK_SUDO_PW is set, remote sudo pipes it via `sudo -S` for
# headless runs. Otherwise plain `sudo` is used (tty or passwordless config).
# Prefer the passwordless restart helpers installed on each target
# (/usr/local/sbin/frank-restart-<large|small>.sh); they cover the unit
# symlink, cache drop (dankclaw), daemon-reload, and restart in one root
# script. See docs/deployment.md -> Passwordless restart.
# Sudo: set FRANK_SUDO_PW so remote sudo reads the password from stdin
# (`sudo -S`). The passwordless restart helpers installed for the retired
# topology are obsolete and must not be used.
#
# Usage:
# ./deploy.sh <target> [--dry-run]
# FRANK_SUDO_PW=... ./deploy.sh <target>
#
# Targets:
# dankclaw - llama.cpp server (frank-default-large.service, port 7770)
# dankserver - llama.cpp server (frank-default-small.service, port 7770)
#
# Example:
# ./deploy.sh dankclaw
# ./deploy.sh dankserver --dry-run
# Targets (2026-08-17 topology):
# dankserver - llama.cpp FastMTP (frank-default-large.service, port 7770)
# dankclaw - vLLM ROCm (frank-default-small.service, port 52625)
set -euo pipefail
# ---------------------------------------------------------------------------
# Target configuration
# ---------------------------------------------------------------------------
declare -A REMOTE_USER REMOTE_HOST REMOTE_DIR SERVICE SERVICE_HEALTH DROP_CACHES HELPER HEALTH_WAIT
REMOTE_USER[dankclaw]=dank
REMOTE_HOST[dankclaw]=dankclaw
REMOTE_DIR[dankclaw]="/home/dank/vllmScripts"
SERVICE[dankclaw]="frank-default-large"
SERVICE_HEALTH[dankclaw]="http://127.0.0.1:7770/health"
# Drop page caches before restart: with the model's pages fully cached, the
# KV/graph allocation stalls at load (VRAM stuck at 28 GiB). See AGENTS.md.
DROP_CACHES[dankclaw]=1
# Passwordless restart helper (root-owned, installed via /etc/sudoers.d/frank-large).
# When present, deploy.sh uses it instead of inline sudo commands.
HELPER[dankclaw]="/usr/local/sbin/frank-restart-large.sh"
# Health wait in iterations of 2s. Cold loads after the cache drop measured
# at up to 17 minutes on 2026-08-13; 600 iterations = 20 minutes.
HEALTH_WAIT[dankclaw]=600
declare -A REMOTE_USER REMOTE_HOST REMOTE_DIR SERVICE SERVICE_HEALTH DROP_CACHES HEALTH_WAIT
REMOTE_USER[dankserver]=dank
REMOTE_HOST[dankserver]=dankserver
REMOTE_DIR[dankserver]="/home/dank/vLLM"
SERVICE[dankserver]="frank-default-small"
SERVICE[dankserver]="frank-default-large"
SERVICE_HEALTH[dankserver]="http://127.0.0.1:7770/health"
DROP_CACHES[dankserver]=0
HELPER[dankserver]="/usr/local/sbin/frank-restart-small.sh"
# Cold load: --no-mmap reads 15.7 GB through RAM; allow 10 minutes.
HEALTH_WAIT[dankserver]=300
REMOTE_USER[dankclaw]=dank
REMOTE_HOST[dankclaw]=dankclaw
REMOTE_DIR[dankclaw]="/home/dank/vllmScripts"
SERVICE[dankclaw]="frank-default-small"
SERVICE_HEALTH[dankclaw]="http://127.0.0.1:52625/health"
DROP_CACHES[dankclaw]=0
# vLLM loads a 38 GB checkpoint; allow 20 minutes.
HEALTH_WAIT[dankclaw]=600
TARGET="${1:-}"
DRY_RUN=0
if [ "${2:-}" = "--dry-run" ]; then
@@ -67,7 +54,7 @@ fi
# Validation
# ---------------------------------------------------------------------------
if [ -z "${TARGET:-}" ]; then
echo "Usage: $0 <dankclaw|dankserver> [--dry-run]"
echo "Usage: $0 <dankserver|dankclaw> [--dry-run]"
exit 1
fi
if [ -z "${REMOTE_HOST[$TARGET]:-}" ]; then
@@ -78,8 +65,6 @@ fi
# ---------------------------------------------------------------------------
# Sudo wrapper (headless-friendly)
# ---------------------------------------------------------------------------
# When FRANK_SUDO_PW is set, remote sudo reads the password from stdin via
# `sudo -S`. Otherwise plain `sudo` is used (tty or passwordless config).
SUDO_PREFIX="sudo"
if [ -n "${FRANK_SUDO_PW:-}" ]; then
SUDO_PREFIX="printf '%s\n' '$FRANK_SUDO_PW' | sudo -S"
@@ -131,8 +116,6 @@ ${SUDO_PREFIX} sh -c 'sync; echo 3 > /proc/sys/vm/drop_caches'
"
fi
HELPER_PATH="${HELPER[$TARGET]:-}"
REMOTE_SCRIPT="
set -euo pipefail
cd '${REMOTE_DIR[$TARGET]}'
@@ -140,27 +123,12 @@ cd '${REMOTE_DIR[$TARGET]}'
echo '[2/4] Pulling repo on ${TARGET}...'
git pull origin main
if [ -x '${HELPER_PATH}' ]; then
# Passwordless restart helper (sudoers NOPASSWD) - preferred path.
echo '[3/4] Restarting via passwordless helper ${HELPER_PATH}...'
${SUDO_PREFIX} '${HELPER_PATH}'
else
echo '[3/4] Helper not installed; using inline sudo commands...'
# Install / symlink the systemd unit
case '${TARGET}' in
dankclaw)
${SUDO_PREFIX} ln -sf '${REMOTE_DIR[$TARGET]}/scripts/frank-default-large.service' /etc/systemd/system/frank-default-large.service
;;
dankserver)
${SUDO_PREFIX} ln -sf '${REMOTE_DIR[$TARGET]}/scripts/frank-default-small.service' /etc/systemd/system/frank-default-small.service
;;
esac
${DROP_CACHES_CMD}
echo '[3/4] Reload and restart ${SERVICE[$TARGET]}...'
${SUDO_PREFIX} systemctl daemon-reload
${SUDO_PREFIX} systemctl enable '${SERVICE[$TARGET]}'
${SUDO_PREFIX} systemctl restart '${SERVICE[$TARGET]}'
fi
echo '[3/4] Symlink unit and restart ${SERVICE[$TARGET]}...'
${SUDO_PREFIX} ln -sf '${REMOTE_DIR[$TARGET]}/scripts/${SERVICE[$TARGET]}.service' /etc/systemd/system/${SERVICE[$TARGET]}.service
${DROP_CACHES_CMD}
${SUDO_PREFIX} systemctl daemon-reload
${SUDO_PREFIX} systemctl enable '${SERVICE[$TARGET]}'
${SUDO_PREFIX} systemctl restart '${SERVICE[$TARGET]}'
"
if [ "$DRY_RUN" = "1" ]; then
+31 -61
View File
@@ -1,88 +1,58 @@
# Head tunables — Qwen3.8-27B pipeline-parallel head (Dankclaw).
# Tunables for frank-default-large (llama.cpp, dankserver, RTX 3090).
#
# The head is the LOCAL side of the split. It runs llama-server (b10433,
# HIP+Vulkan+RPC build in /home/dank/llama.cpp/build) with --rpc pointing at
# the worker on Dankserver. The model file lives on this machine only; the
# worker receives its tensor share over the network at load time.
# Runtime: patched llama-server (HauhauCS FastMTP build) serving
# HauhauCS/Qwen3.8-27B-Uncensored-HauhauCS-Aggressive-MTP-GGUF IQ4_XS with
# the FastMTP 32K draft sidecar and the ngram-mod fallback. Single machine,
# no pipeline split. Alias frank-default-large, port 7770.
#
# CRITICAL: this script must NOT pass --device. When --device is set,
# llama.cpp uses exactly that device list and silently drops the RPC device
# (src/llama.cpp llama_prepare_model_devices). Default device selection
# inserts RPC servers at the FRONT of the device list, so the split becomes
# [RPC0, iGPU] and --tensor-split index 0 is the worker.
#
# WARNING: do not name any variable here TEMP, HOST, or GPU_MAX_HEAP_SIZE
# (HIP runtime collision, see the 2026-08-13 TEMP incident).
# WARNING: do not name any variable TEMP, HOST, or GPU_MAX_HEAP_SIZE. The ROCm
# HIP runtime reads those bare env vars (see the 2026-08-13 TEMP incident).
# This box is NVIDIA/CUDA, but the rule still applies to keep the env files
# portable.
# Model files (downloaded to this directory from the HF repo).
MODEL_DIR=/home/dank/models/hauhaucs-qwen38
MODEL_FILE=Qwen3.8-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS.gguf
DRAFT_FILE=Qwen3.8-27B-Uncensored-HauhauCS-Aggressive-FastMTP-32K.gguf
# Patched llama.cpp binary. The FastMTP sidecar needs the patch; see AGENTS.md.
LLAMA_BIN=/home/dank/llama.cpp-fastmtp/build/bin/llama-server
MODEL_DIR=/home/dank/models
MODEL_FILE=Qwen3.8-27B-Uncensored-Q6_K.gguf
HEAD_BIN=/home/dank/llama.cpp/build/bin/llama-server
ALIAS=frank-default-large
BIND_ADDR=0.0.0.0
LISTEN_PORT=7770
# Comma-separated RPC endpoints (host:port). One worker here.
RPC_SERVERS=192.168.0.235:50052
# Model split fractions, one per device in order [RPC0, iGPU].
# 0.68,0.32 = 45 of 65 blocks on the 3090 (blocks 0-44) - the maximum
# for the Q6_K + q8_0/f16 KV config, measured 2026-08-17 phase 2:
# - KV per FA layer = 784 MiB (K 1088 B/token + V 2048 B/token @262144)
# - weights(f) = 20334 MB layer pool x f (GGUF scan, exact); embd on
# the head side (RPC0 buffer observed 10429.88 MiB at f=0.53)
# - KV-per-device count = round(f x 66) layers -> 45 layers = 11 FA
# (3..43) -> 8624 MiB. 46 layers (f>=0.7045) still 11 FA but margin
# drops to ~0.4 GiB; 48 layers (f>=0.7197) adds FA block 47 -> KV
# 9408 -> OOM by ~0.85 GiB.
# Predicted: 13430 (weights) + 8624 (KV) + ~530 (RS) + 189 (compute) =
# ~22773 MiB -> ~0.7 GiB free. Draft model runs on ROCm0 only (measured
# phase 1: 1718 MiB, no worker impact).
TENSOR_SPLIT=0.68,0.32
# Context pool. 262144 total = 1 parallel slot x 262144 per slot
# (n_ctx_seq = n_ctx / n_seq_max, llama-context.cpp:293).
CTX_SIZE=262144
# Context, single slot. 131072 (128K) leaves ~1.4 GiB VRAM headroom on the
# 3090 with IQ4_XS + FastMTP + K q8_0 / V f16 KV. Lower to 122880 (120K) for
# ~1.8 GiB headroom. KV per token = 16 attention layers x 4 KV heads x 256
# dim: K q8_0 (1088 B/token) + V f16 (2048 B/token) = 3136 B/token/layer.
CTX_SIZE=131072
PARALLEL=1
# Speculative decoding. MTP with the STANDALONE draft head (the Q6_K
# model has no bundled MTP head; the repo ships the draft sidecar) + the
# ngram-mod fallback. Set SPEC_NONE=1 for a raw baseline.
SPEC_NONE=0
# Speculative decoding. FastMTP (MTP depth 2) with the ngram-mod fallback.
SPEC_DEFAULT=1
MTP=1
SPEC_DRAFT_N_MAX=4
# Standalone MTP draft head (Q8_0 MTP-only sidecar from the same repo).
SPEC_DRAFT_MODEL=/home/dank/models/Qwen3.8-27B-Uncensored-draft-Q8_0.gguf
SPEC_DRAFT_N_MAX=2
SPEC_DRAFT_NGL=all
SPEC_DRAFT_P_MIN=0
SPEC_NGRAM_MOD_N_MIN=48
SPEC_NGRAM_MOD_N_MAX=64
SPEC_NGRAM_MOD_N_MATCH=24
# KV on GPU: K q8_0 + V f16 (mismatched, 16 full-attention layers x 4
# heads x 256 dim: K = 1088 B/token, V = 2048 B/token -> 3136 B/token ->
# 784 MiB per FA layer at 262144, 12.25 GiB total). Mismatched K/V with
# Flash Attention requires the GGML_CUDA_FA_ALL_QUANTS rebuild (2026-08-17:
# head HIP + worker CUDA at 9b05354ec). Do not revert the binaries without
# also reverting this.
# KV quantization on GPU: K q8_0 + V f16 (user request: K=8, V=16).
CACHE_TYPE_K=q8_0
CACHE_TYPE_V=f16
# Batch sizing: production-verified values (2026-08-14).
BATCH_SIZE=8192
UBATCH_SIZE=256
# Batch sizing (user request).
BATCH_SIZE=2048
UBATCH_SIZE=1024
# Sampling — Qwen3.8 thinking-mode defaults.
# Sampling - Qwen3.8 thinking-mode defaults.
TEMPERATURE=1.0
TOP_K=20
TOP_P=0.95
MIN_P=0.0
THREADS=12
THREADS=8
THREADS_HTTP=1
# 4 (info): clean journal for interactive use. Raise to 10 only when
# debugging the layer split (the per-layer assignment lines are debug-level).
VERBOSITY=4
# 1: --direct-io model load. Required in practice for large models loaded
# over RPC (load hangs otherwise; visorcraft Strix RPC finding).
DIRECT_IO=1
+3 -3
View File
@@ -1,5 +1,5 @@
[Unit]
Description=llama.cpp Qwen3.8-27B pipeline-parallel head (Strix + RPC to Dankserver) (frank-default-large)
Description=llama.cpp Qwen3.8-27B Aggressive IQ4_XS + FastMTP (dankserver, frank-default-large)
After=network-online.target
Wants=network-online.target
@@ -7,8 +7,8 @@ Wants=network-online.target
Type=simple
User=dank
Group=dank
Environment="FRANK_PP_HEAD_ENV_FILE=/home/dank/vllmScripts/scripts/frank-default-large.env"
ExecStart=/home/dank/vllmScripts/scripts/serve-pp-head.sh
Environment="FRANK_LARGE_ENV_FILE=/home/dank/vLLM/scripts/frank-default-large.env"
ExecStart=/home/dank/vLLM/scripts/serve-frank-large.sh
Restart=on-failure
RestartSec=10
+38 -31
View File
@@ -1,33 +1,40 @@
# Tunables for frank-default-small (FastFlowLM NPU endpoint, dankclaw)
# Runtime: FLM 1.0.1 on the XDNA2 NPU (50 TOPS). Model choice, measured
# results, and the NPU memory budget are in docs/FastFlowLM NPU Inference.md.
# The NPU allocates from the unified pool shared with frank-default-large
# (the PP head). Keep the resident footprint small enough that the head
# keeps its headroom.
# Tunables for frank-default-small (vLLM, dankclaw, Strix Halo gfx1151).
#
# 2026-08-17: qwythos:9b (Huihui-Qwythos-9B-Claude-Mythos-5-1M-abliterated,
# Qwen3.5-9B hybrid linear-attention base, Q4NX, 7.76 GB) chosen after the
# user's model swap (was qwen3.6-moe:35b-a3b, which stays installed for
# rollback). FLM upgraded 0.9.45 -> 1.0.1: the pack declares flm_version
# 1.0.0 and 0.9.45 refused to serve it.
# Runtime: vLLM (ROCm) in /home/dank/vllm-venv serving
# Avesed/Qwen3.6-35B-A3B-INT8-W8A8 (compressed-tensors INT8 W8A8, MoE 35B
# total / 3B active, Qwen3.5-MoE hybrid: 30 of 40 layers are GatedDeltaNet
# linear attention). Alias frank-default-small, port 52625.
#
# The ROCm vLLM install was created with:
# uv venv --python /usr/bin/python3.12 /home/dank/vllm-venv
# uv pip install --python /home/dank/vllm-venv vllm --torch-backend=auto
# The --torch-backend=auto resolver pulls the AMD ROCm wheels (torch +
# amd-torch-device-gfx1151 + vllm rocm variant) from the AMD index.
FLM_MODEL=qwythos:9b
FLM_HOST=0.0.0.0
FLM_PORT=52625
# Power mode: turbo. Smoke decode ~5-7 t/s on the 9B dense at 262k ctx
# (not benchmarked; see docs/FastFlowLM NPU Inference.md).
FLM_PMODE=turbo
# Load the ASR model (Whisper-V3-Turbo-NPU2) alongside the LLM. Exposes
# /v1/audio/transcriptions. Adds ~1 GiB to the resident footprint.
FLM_ASR=1
# Maximum context length. Qwythos-9B native max is 262144 (Qwen3.5-9B
# hybrid: 8 of 32 layers are full attention, so the KV cache stays small).
# Verified 2026-08-17: loads at -c 262144 with turbo+asr on FLM 1.0.1;
# KV occupancy 0.007% at 19 tokens.
FLM_CTX_LEN=262144
# Custom-model resolution: the qwythos:9b tag and its xclbin symlinks live
# in the user config, not the system registry. Without these, flm treats
# the tag as unknown and silently serves llama3.2:1b (see the unknown-tag
# fallback in docs/FastFlowLM NPU Inference.md).
FLM_CONFIG_PATH=/home/dank/.config/flm/model_list.json
FLM_XCLBIN_PATH=/home/dank/.config/flm
VLLM_BIN=/home/dank/vllm-venv/bin/vllm
MODEL=Avesed/Qwen3.6-35B-A3B-INT8-W8A8
ALIAS=frank-default-small
BIND_ADDR=0.0.0.0
LISTEN_PORT=52625
# Full native context. The KV cache stays unquantized (auto = model dtype,
# bf16). Worst-case KV at 262144 x 4 sequences is ~10.7 GiB; weights are
# ~35 GiB; total fits the Strix Halo unified pool with room to spare.
MAX_MODEL_LEN=262144
KV_CACHE_DTYPE=auto
# Concurrency and batching (user request).
MAX_NUM_SEQS=4
MAX_NUM_BATCHED_TOKENS=16384
# vLLM has no separate ubatch knob. The scheduler issues one batch per step
# with up to max-num-batched-tokens tokens; the KV cache is preallocated at
# max-model-len. Set gpu-memory-utilization below 1.0 so the unified pool
# keeps headroom for the host.
GPU_MEMORY_UTILIZATION=0.92
# ngram speculative decoding (vLLM ngram proposer).
# prompt_lookup_max = ngram window; num_speculative_tokens = draft depth.
NGRAM_LOOKUP_MAX=5
NGRAM_LOOKUP_MIN=1
NUM_SPEC_TOKENS=5
+4 -4
View File
@@ -1,5 +1,5 @@
[Unit]
Description=FastFlowLM NPU inference (frank-default-small) on Dankclaw
Description=vLLM Qwen3.6-35B-A3B INT8 W8A8 ngram spec (dankclaw, frank-default-small)
After=network-online.target
Wants=network-online.target
@@ -7,9 +7,9 @@ Wants=network-online.target
Type=simple
User=dank
Group=dank
Environment="FLM_SMALL_ENV_FILE=/home/dank/vllmScripts/scripts/frank-default-small.env"
ExecStart=/home/dank/vllmScripts/scripts/serve-flm-small.sh
LimitMEMLOCK=infinity
Environment="FRANK_SMALL_ENV_FILE=/home/dank/vllmScripts/scripts/frank-default-small.env"
Environment="HF_HOME=/home/dank/.cache/huggingface"
ExecStart=/home/dank/vllmScripts/scripts/serve-frank-small.sh
Restart=on-failure
RestartSec=10
+108
View File
@@ -0,0 +1,108 @@
#!/usr/bin/env bash
# Serve the Qwen3.8-27B HauhauCS Aggressive IQ4_XS on Dankserver (RTX 3090).
#
# Runs a patched llama-server (HauhauCS FastMTP build, commit 4df29be +
# HauhauCS-FastMTP-llama.cpp.patch) with the FastMTP draft sidecar and the
# ngram-mod fallback. There is no pipeline split: the whole model lives on
# the 3090.
#
# The FastMTP draft sidecar requires the patched executable. Loading the
# draft with the stock binary fails with "expected 5120, 248320, got 5120,
# 32768" (see the HauhauCS repo README).
#
# Tunables come from frank-default-large.env in this directory unless
# FRANK_LARGE_ENV_FILE overrides that path.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="${FRANK_LARGE_ENV_FILE:-$SCRIPT_DIR/frank-default-large.env}"
if [[ -f "$ENV_FILE" ]]; then
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
fi
# --- defaults (used when the env file does not set them) -------------------
: "${MODEL_DIR:=/home/dank/models/hauhaucs-qwen38}"
: "${MODEL_FILE:=Qwen3.8-27B-Uncensored-HauhauCS-Aggressive-IQ4_XS.gguf}"
: "${DRAFT_FILE:=Qwen3.8-27B-Uncensored-HauhauCS-Aggressive-FastMTP-32K.gguf}"
: "${LLAMA_BIN:=/home/dank/llama.cpp-fastmtp/build/bin/llama-server}"
: "${ALIAS:=frank-default-large}"
: "${BIND_ADDR:=0.0.0.0}"
: "${LISTEN_PORT:=7770}"
: "${CTX_SIZE:=131072}"
: "${PARALLEL:=1}"
: "${SPEC_DEFAULT:=1}"
: "${MTP:=1}"
: "${SPEC_DRAFT_N_MAX:=2}"
: "${SPEC_DRAFT_NGL:=all}"
: "${SPEC_DRAFT_P_MIN:=0}"
: "${SPEC_NGRAM_MOD_N_MIN:=48}"
: "${SPEC_NGRAM_MOD_N_MAX:=64}"
: "${SPEC_NGRAM_MOD_N_MATCH:=24}"
: "${CACHE_TYPE_K:=q8_0}"
: "${CACHE_TYPE_V:=f16}"
: "${BATCH_SIZE:=2048}"
: "${UBATCH_SIZE:=1024}"
: "${TEMPERATURE:=1.0}"
: "${TOP_K:=20}"
: "${TOP_P:=0.95}"
: "${MIN_P:=0.0}"
: "${THREADS:=8}"
: "${THREADS_HTTP:=1}"
: "${VERBOSITY:=4}"
MODEL="$MODEL_DIR/$MODEL_FILE"
DRAFT="$MODEL_DIR/$DRAFT_FILE"
if [[ ! -f "$MODEL" ]]; then
echo "missing required file: $MODEL" >&2
exit 1
fi
if [[ ! -f "$DRAFT" ]]; then
echo "missing draft file: $DRAFT" >&2
exit 1
fi
if [[ ! -x "$LLAMA_BIN" ]]; then
echo "missing llama-server binary: $LLAMA_BIN" >&2
exit 1
fi
# --- speculative decoding: FastMTP (MTP) first, then ngram-mod fallback ----
SPEC_ARGS=()
SPEC_ARGS+=(--spec-type draft-mtp)
SPEC_ARGS+=(--spec-draft-model "$DRAFT")
SPEC_ARGS+=(--spec-draft-n-max "$SPEC_DRAFT_N_MAX")
SPEC_ARGS+=(--spec-draft-ngl "$SPEC_DRAFT_NGL")
SPEC_ARGS+=(--spec-draft-p-min "$SPEC_DRAFT_P_MIN")
if [[ "$SPEC_DEFAULT" == "1" ]]; then
SPEC_ARGS+=(--spec-default)
SPEC_ARGS+=(--spec-ngram-mod-n-min "$SPEC_NGRAM_MOD_N_MIN")
SPEC_ARGS+=(--spec-ngram-mod-n-max "$SPEC_NGRAM_MOD_N_MAX")
SPEC_ARGS+=(--spec-ngram-mod-n-match "$SPEC_NGRAM_MOD_N_MATCH")
fi
exec "$LLAMA_BIN" \
--model "$MODEL" \
"${SPEC_ARGS[@]}" \
--gpu-layers all \
--no-mmap \
--flash-attn on \
--ctx-size "$CTX_SIZE" \
--parallel "$PARALLEL" \
--cache-type-k "$CACHE_TYPE_K" \
--cache-type-v "$CACHE_TYPE_V" \
--batch-size "$BATCH_SIZE" \
--ubatch-size "$UBATCH_SIZE" \
--temp "$TEMPERATURE" \
--top-k "$TOP_K" \
--top-p "$TOP_P" \
--min-p "$MIN_P" \
--threads "$THREADS" \
--threads-http "$THREADS_HTTP" \
--jinja \
--alias "$ALIAS" \
-lv "$VERBOSITY" \
--host "$BIND_ADDR" \
--port "$LISTEN_PORT"
+53
View File
@@ -0,0 +1,53 @@
#!/usr/bin/env bash
# Serve Avesed/Qwen3.6-35B-A3B-INT8-W8A8 via vLLM on Dankclaw (Strix Halo).
#
# Runs the ROCm vLLM build in /home/dank/vllm-venv. The model is a
# compressed-tensors INT8 W8A8 quant (MoE, 35B total / 3B active). Full
# 262144 context, unquantized KV cache, 4 concurrent sequences, ngram
# speculative decoding.
#
# Tunables come from frank-default-small.env in this directory unless
# FRANK_SMALL_ENV_FILE overrides that path.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="${FRANK_SMALL_ENV_FILE:-$SCRIPT_DIR/frank-default-small.env}"
if [[ -f "$ENV_FILE" ]]; then
set -a
# shellcheck disable=SC1090
source "$ENV_FILE"
set +a
fi
# --- defaults (used when the env file does not set them) -------------------
: "${VLLM_BIN:=/home/dank/vllm-venv/bin/vllm}"
: "${MODEL:=Avesed/Qwen3.6-35B-A3B-INT8-W8A8}"
: "${ALIAS:=frank-default-small}"
: "${BIND_ADDR:=0.0.0.0}"
: "${LISTEN_PORT:=52625}"
: "${MAX_MODEL_LEN:=262144}"
: "${KV_CACHE_DTYPE:=auto}"
: "${MAX_NUM_SEQS:=4}"
: "${MAX_NUM_BATCHED_TOKENS:=16384}"
: "${GPU_MEMORY_UTILIZATION:=0.92}"
: "${NGRAM_LOOKUP_MAX:=5}"
: "${NGRAM_LOOKUP_MIN:=1}"
: "${NUM_SPEC_TOKENS:=5}"
if [[ ! -x "$VLLM_BIN" ]]; then
echo "missing vllm binary: $VLLM_BIN" >&2
exit 1
fi
exec "$VLLM_BIN" serve "$MODEL" \
--host "$BIND_ADDR" \
--port "$LISTEN_PORT" \
--served-model-name "$ALIAS" \
--max-model-len "$MAX_MODEL_LEN" \
--kv-cache-dtype "$KV_CACHE_DTYPE" \
--max-num-seqs "$MAX_NUM_SEQS" \
--max-num-batched-tokens "$MAX_NUM_BATCHED_TOKENS" \
--gpu-memory-utilization "$GPU_MEMORY_UTILIZATION" \
--speculative-config "{\"method\":\"ngram\",\"prompt_lookup_max\":$NGRAM_LOOKUP_MAX,\"prompt_lookup_min\":$NGRAM_LOOKUP_MIN,\"num_speculative_tokens\":$NUM_SPEC_TOKENS}" \
--reasoning-parser qwen3 \
--trust-remote-code