frank-medium: swap ROCmFPX llama.cpp runtime for vllm-radiance MXFP4
Rootless Quadlet on dankserver serving just1moremodel/Qwen3.8-27B-Uncensored-MXFP4-awq (the radiance stack's designated alternate target; ships its fp8 MTP head, no rewrite step) with the DFlash2-FP8 drafter at SPEC=7 on the 2x R9700s (TP=2, host network, :7770, alias frank-medium unchanged). - dankserver/frank-medium/: quadlet unit, container entrypoint (fork of serve-mxfp4.sh's patch block at pinned clone commit 97353293), healthcheck - dispatcher retires the root llama.cpp unit, re-tags the registry image to the localhost alias, installs the quadlet, waits on /health - planner maps dankserver/frank-medium/* to frank-medium; scripts-era mappings removed - ROCmFPX-era env/serve/unit/download scripts staged in scripts/.AGENTTRASH with .rocmfpx suffix; seams updated (frank_medium_quadlet.bats new)
This commit is contained in:
@@ -21,10 +21,10 @@ load helpers
|
||||
[[ "$output" != *"tests/homepage_pages.bats"* ]]
|
||||
}
|
||||
|
||||
@test "changed-test wrapper maps a service script to its focused tests" {
|
||||
run bash "$REPO_ROOT/scripts/test-changed.sh" --list --paths scripts/serve-frank-medium.sh
|
||||
@test "changed-test wrapper maps the frank-medium quadlet to its focused tests" {
|
||||
run bash "$REPO_ROOT/scripts/test-changed.sh" --list --paths dankserver/frank-medium/quadlet/frank-medium.container
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"tests/scripts_syntax.bats"* ]]
|
||||
[[ "$output" == *"tests/llm_units.bats"* ]]
|
||||
[[ "$output" == *"tests/llm_secrets.bats"* ]]
|
||||
[[ "$output" == *"tests/frank_medium_quadlet.bats"* ]]
|
||||
[[ "$output" == *"tests/deployment_scoping.bats"* ]]
|
||||
[[ "$output" != *"tests/llm_units.bats"* ]]
|
||||
}
|
||||
|
||||
@@ -28,23 +28,25 @@ REMOTE_DEPLOY="$REPO_ROOT/scripts/deploy-remote.sh"
|
||||
! grep -q 'frank_npu\|frank-npu' "$REMOTE_DEPLOY"
|
||||
}
|
||||
|
||||
@test "shared chat-template changes map only to the service that reads it" {
|
||||
# frank-medium reads the tracked template only when its env file points at
|
||||
# it (the GGUF's embedded template is the default); frank-large runs
|
||||
# halogen-flash-server, which owns its own chat handling. So a template
|
||||
# edit is a no-op on Dankclaw and selects frank-medium on Dankserver.
|
||||
@test "chat-template changes plan no service: the radiance runtime ships its own template" {
|
||||
# The ROCmFPX llama.cpp deployment optionally read the tracked
|
||||
# scripts/chat-template.jinja; the vllm-radiance runtime mounts its own
|
||||
# qwen-fixed-v22.3.jinja out of the pinned clone instead. Nobody reads
|
||||
# the tracked template any more, so an edit to it deploys nothing.
|
||||
run python3 "$PLANNER" --target dankclaw --paths scripts/chat-template.jinja
|
||||
[ "$status" -eq 0 ]
|
||||
[ -z "$output" ]
|
||||
|
||||
run python3 "$PLANNER" --target dankserver --paths scripts/chat-template.jinja
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" = "frank-medium" ]
|
||||
[ -z "$output" ]
|
||||
}
|
||||
|
||||
@test "deployment planner maps the dankserver model to frank-medium only" {
|
||||
@test "deployment planner maps the frank-medium service dir to frank-medium only" {
|
||||
run python3 "$PLANNER" --target dankserver --paths \
|
||||
scripts/frank-medium.service
|
||||
dankserver/frank-medium/quadlet/frank-medium.container \
|
||||
dankserver/frank-medium/radiance-entrypoint.sh \
|
||||
dankserver/frank-medium/frank-medium-healthcheck.py
|
||||
[ "$status" -eq 0 ]
|
||||
[ "$output" = "frank-medium" ]
|
||||
}
|
||||
|
||||
Executable
+127
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/env bats
|
||||
# Seam: the frank-medium quadlet on dankserver.
|
||||
# frank-medium became a rootless Quadlet container on 2026-09-15 when the
|
||||
# vllm-radiance MXFP4 stack replaced the charlie12345/ROCmFPX llama.cpp
|
||||
# runtime on the 2x Radeon AI PRO R9700. This seam pins the properties that
|
||||
# make it work and that no reviewer can see by reading the flags alone: GPU
|
||||
# device access on the fixed device indices, the upstream launcher's podman
|
||||
# posture, host networking with the fleet's client port and alias, the
|
||||
# measured KV pin for this exact hardware signature, boot persistence, and a
|
||||
# deploy handler that retires the old root unit without deleting anything.
|
||||
|
||||
load helpers
|
||||
|
||||
UNIT="$REPO_ROOT/dankserver/frank-medium/quadlet/frank-medium.container"
|
||||
ENTRYPOINT="$REPO_ROOT/dankserver/frank-medium/radiance-entrypoint.sh"
|
||||
HEALTHCHECK="$REPO_ROOT/dankserver/frank-medium/frank-medium-healthcheck.py"
|
||||
REMOTE_DEPLOY="$REPO_ROOT/scripts/deploy-remote.sh"
|
||||
|
||||
@test "frank-medium quadlet exists under dankserver/frank-medium/quadlet/" {
|
||||
[ -f "$UNIT" ]
|
||||
}
|
||||
|
||||
@test "frank-medium unit is boot-persistent (WantedBy=default.target)" {
|
||||
# Generated units cannot be enabled on the podman 5.x v1 quadlet
|
||||
# generator; [Install] plus linger is the entire boot-persistence story.
|
||||
grep -q '^WantedBy=default.target$' "$UNIT"
|
||||
}
|
||||
|
||||
@test "frank-medium unit is self-healing" {
|
||||
grep -q '^Restart=on-failure$' "$UNIT"
|
||||
grep -q '^RestartSec=' "$UNIT"
|
||||
}
|
||||
|
||||
@test "frank-medium image is pinned to an exact version tag" {
|
||||
grep -Eq '^Image=localhost/radiance-vllm:[0-9]+\.[0-9]+\.[0-9]+$' "$UNIT"
|
||||
grep -q '^Pull=never$' "$UNIT"
|
||||
}
|
||||
|
||||
@test "frank-medium can reach the GPU (kfd + DRM render node) on the fixed indices" {
|
||||
grep -q '^AddDevice=/dev/kfd$' "$UNIT"
|
||||
grep -q '^AddDevice=/dev/dri$' "$UNIT"
|
||||
grep -q '^Environment=HIP_VISIBLE_DEVICES=0,1$' "$UNIT"
|
||||
grep -q '^Environment=ROCR_VISIBLE_DEVICES=0,1$' "$UNIT"
|
||||
}
|
||||
|
||||
@test "frank-medium runs with the upstream launcher's podman posture" {
|
||||
# serve-mxfp4.sh runs the image privileged, with host IPC, an unconfined
|
||||
# seccomp profile and SYS_PTRACE; host networking carries the port.
|
||||
grep -q -- '--privileged' "$UNIT"
|
||||
grep -q -- '--ipc=host' "$UNIT"
|
||||
grep -q -- '--security-opt seccomp=unconfined' "$UNIT"
|
||||
grep -q -- '--network=host' "$UNIT"
|
||||
}
|
||||
|
||||
@test "frank-medium keeps the fleet endpoint: host-network port 7770, alias frank-medium" {
|
||||
# vLLM binds 0.0.0.0:7770 on the host network; no PublishPort exists.
|
||||
[ "$(grep -c '^PublishPort=' "$UNIT")" -eq 0 ]
|
||||
grep -q '^Environment=PORT=7770$' "$UNIT"
|
||||
grep -q '^Environment=SERVED_NAMES=frank-medium$' "$UNIT"
|
||||
}
|
||||
|
||||
@test "frank-medium pins the measured KV cache for its hardware signature" {
|
||||
# The upstream repo's shipped kv-profiles.tsv row for
|
||||
# 2x7551-32624 at maxseqs=8 chunk=8192 maxlen=262144 spec=dflash.
|
||||
# A pin is only valid at that batch shape; if the shape changes, this
|
||||
# value must be recalibrated or set to 0 (vLLM profiling).
|
||||
grep -q '^Environment=KV_MEM=18563072000$' "$UNIT"
|
||||
grep -q '^Environment=MAXSEQS=8$' "$UNIT"
|
||||
grep -q '^Environment=CHUNK=8192$' "$UNIT"
|
||||
grep -q '^Environment=MAXLEN=262144$' "$UNIT"
|
||||
grep -q '^Environment=SPEC_METHOD=dflash$' "$UNIT"
|
||||
grep -q '^Environment=SPEC=7$' "$UNIT"
|
||||
}
|
||||
|
||||
@test "frank-medium mounts the pinned radiance clone and the patched libr4d" {
|
||||
# The patches are applied at every container start from /patches; the
|
||||
# image's shipped r4d.so predates the GDN overflow fix and NaNs this
|
||||
# model, so /r4d (b9e42ab-rx6) must be mounted and copied over it.
|
||||
grep -q 'Volume=/home/dank/GitPackages/radiance-vllm-mxfp4:/patches:z$' "$UNIT"
|
||||
grep -q 'Volume=/home/dank/.cache/radiance-libr4d/b9e42ab-rx6:/r4d:z$' "$UNIT"
|
||||
}
|
||||
|
||||
@test "frank-medium entrypoint is a syntax-clean fork of the upstream launcher" {
|
||||
[ -f "$ENTRYPOINT" ]
|
||||
bash -n "$ENTRYPOINT"
|
||||
# Pinned clone: the entrypoint must name the commit it was forked from so
|
||||
# a clone update is forced through a re-diff, not drifted into silently.
|
||||
grep -q '9735329348ae1c9319f01cbe5f7004ec5f4dba63' "$ENTRYPOINT"
|
||||
}
|
||||
|
||||
@test "frank-medium healthcheck probes the serving endpoint, not the process" {
|
||||
[ -f "$HEALTHCHECK" ]
|
||||
python3 -m py_compile "$HEALTHCHECK"
|
||||
grep -q 'frank-medium-healthcheck.py' "$UNIT"
|
||||
grep -q '^HealthStartPeriod=' "$UNIT"
|
||||
}
|
||||
|
||||
@test "frank-medium unit carries no secret material" {
|
||||
! grep -Eq '^(Environment|EnvironmentFile)=.*(TOKEN|PASSWORD|SECRET|KEY)' "$UNIT"
|
||||
}
|
||||
|
||||
@test "the frank-medium checkpoint mount is the designated target" {
|
||||
grep -q '^Environment=SNAP=/models/Qwen3.8-27B-Uncensored-MXFP4-awq$' "$UNIT"
|
||||
grep -q '^Volume=/home/dank/models:/models$' "$UNIT"
|
||||
}
|
||||
|
||||
@test "the deploy handler retires the old root unit without deleting it" {
|
||||
grep -q 'retire_root_llm_medium' "$REMOTE_DEPLOY"
|
||||
grep -q 'systemctl stop frank-medium.service' "$REMOTE_DEPLOY"
|
||||
# Never `rm`: the retired ROCmFPX unit moves into the home trash so the
|
||||
# llama.cpp era stays recoverable.
|
||||
grep -q 'mv -- /etc/systemd/system/frank-medium.service' "$REMOTE_DEPLOY"
|
||||
! grep -qE '(^|[^[:alnum:]_])rm (-[a-zA-Z]+ )?/etc/systemd/system/frank-medium' "$REMOTE_DEPLOY"
|
||||
}
|
||||
|
||||
@test "the deploy handler never tries to enable a generated unit" {
|
||||
# `systemctl --user enable frank-medium.service` fails on the v1
|
||||
# generator ("transient or generated"); the deploy must install and
|
||||
# restart instead.
|
||||
! grep -q 'systemctl --user enable frank-medium.service' "$REMOTE_DEPLOY"
|
||||
grep -q 'install_quadlet frank-medium dankserver/frank-medium/quadlet frank-medium' "$REMOTE_DEPLOY"
|
||||
grep -q 'systemctl --user restart frank-medium.service' "$REMOTE_DEPLOY"
|
||||
}
|
||||
|
||||
@test "the deploy handler re-tags the registry image to the localhost alias" {
|
||||
grep -q 'podman tag docker.io/stilldeadcode/vllm-radiance:0.9.3 localhost/radiance-vllm:0.9.3' "$REMOTE_DEPLOY"
|
||||
}
|
||||
Reference in New Issue
Block a user