frank-primary: Lucebox DeepSeek-V4.1-Flash-ROCMFP23 quadlet + deploy handler

Replaces frank-medium (vllm-radiance TP=2) on :7770. The 377.2 GiB
43-layer MoE (256 routed experts, top-6) is mmapped: dense work and the
MLA KV cache on the R9700, routed experts computed on CPU from the
page cache (246 GiB RAM). The unit bypasses the image entrypoint
(Qwen/DFlash-only flag set) and execs luce_server with the DS4 launch
shape; --ds4-fused-decode's monolithic-load fallback IS the serving
mode here. deploy_llm_primary gates on image + model byte count,
stops/masks the radiance unit, waits for :7770, installs and starts.
Runbook: frank-primary-lucebox-ds4.md.
This commit is contained in:
Frank
2026-09-26 15:29:59 -07:00
parent 441c4f1c99
commit acd14ab7df
8 changed files with 352 additions and 1 deletions
+48 -1
View File
@@ -95,7 +95,7 @@ service_is_allowed() {
dankserver:copyparty|dankserver:jellyfin|dankserver:calibre-web|dankserver:calibre-server|dankserver:plex|dankserver:tautulli|\
dankserver:prowlarr|dankserver:qbittorrent|dankserver:radarr|\
dankserver:sonarr|dankserver:lidarr|dankserver:readarr|\
dankserver:frank-medium|dankserver:node-exporter|\
dankserver:frank-medium|dankserver:frank-primary|dankserver:node-exporter|\
frankbook-pro:gluetun|frankbook-pro:qbittorrent|frankbook-pro:prowlarr|\
frankbook-pro:radarr|frankbook-pro:sonarr|frankbook-pro:lidarr|\
frankbook-pro:readarr)
@@ -1331,6 +1331,52 @@ deploy_llm_medium() {
}
}
# deploy_llm_primary — frank-primary is the Lucebox DeepSeek V4 Quadlet
# (the 2026-09-26 cutover that replaces frank-medium on :7770). The model
# is a 377 GiB GGUF and the image is a local build, so the gates are:
# image present, model file present at its declared byte count (a partial
# download must never be served).
deploy_llm_primary() {
local missing=0
local model="/home/dank/models/DeepSeek-V4.1-Flash/DeepSeek-V4.1-Flash-ROCMFP23.gguf"
local want_size=405349859328
if ! podman image exists localhost/lucebox-rocm:gfx1201; then
echo "ERROR: lucebox image absent (localhost/lucebox-rocm:gfx1201)" >&2
echo "frank-primary: podman build --build-arg LUCE_HIP_ARCHES=gfx1201 --build-arg ROCM_VERSION=7.14.1-full -t localhost/lucebox-rocm:gfx1201 -f Dockerfile.rocm . (see runbook)" >&2
missing=1
fi
local got_size
got_size="$(wc -c < "$model" 2>/dev/null || echo 0)"
if [[ "$got_size" != "$want_size" ]]; then
echo "ERROR: model absent or incomplete at $model (have $got_size, want $want_size)" >&2
missing=1
fi
[[ "$missing" -eq 0 ]] || return 1
# Cutover: frank-primary takes :7770 from frank-medium. Stop and mask
# the radiance unit (masking is mandatory: Restart=on-failure would
# restart it and re-take the port). Retiring the radiance unit (moving
# it to the home trash) happens after frank-primary is verified — this
# handler only releases the port.
systemctl --user stop frank-medium 2>/dev/null || true
systemctl --user mask frank-medium
# 7770 is a host-network bind: nothing new can be created until the old
# holder released it (the same gate as the 2026-09-16 cutover).
sleep 2
wait_port_free 7770 || return 1
install_quadlet frank-primary dankserver/frank-primary/quadlet frank-primary
# No enable: generated units cannot be enabled on this host (v1 quadlet
# generator); boot persistence is the unit's [Install] WantedBy=default.target.
systemctl --user start frank-primary.service
# First start page-ins the dense weights and builds the graphs;
# HealthStartPeriod in the unit is 1800s to match.
wait_container_healthy frank-primary 1800 || {
podman logs --tail 40 frank-primary 2>&1 || true
return 1
}
}
wait_for_health() {
local service="$1" url="$2" limit="$3"
local i
@@ -1518,6 +1564,7 @@ deploy_service() {
frank-large) deploy_llm_large ;;
frank-small) deploy_llm_small ;;
frank-medium) deploy_llm_medium ;;
frank-primary) deploy_llm_primary ;;
hermes|hermes-dashboard|hermes-webui) deploy_hermes ;;
romm|romm-mariadb|romm-redis|mariadb|redis) deploy_romm_stack "$service" ;;
jellyfin) deploy_jellyfin ;;