The deepseek41 architecture exists only on Luce-Org/lucebox's feat/ds41-engine branch; main rejects the checkpoint with "unsupported model architecture 'deepseek41'". Re-aim the image build at that branch and fix the launch shape, which had been copied from the V4 DS4.md recipe: - drop --ds4-fused-decode and --ds4-fused-verify-f16-kv, and use --ds4-prefill dense: V4.1's validate_model_features refuses the V4-only prefill/fused paths (layer split and --mmproj too). - --chunk 4096 (the V4.1 dense-prefill measurement point), --max-ctx 131072 (the V4.1 default window), --prefix/--prefill-cache-slots 0 as the DS41.md bring-up recipe. - drop --cache-type-k/v: the DeepSeek4 backend ignores them; the MLA compressed caches are F16 by design. - expose BOTH R9700s and set LUCE_EXPERT_STREAM_DEVICE=1, so hip:0 owns the dense weights plus the hot expert stack while hip:1 holds the streamed-expert slot cache instead of competing with it. - quadlet: 384 routed experts per layer, Engram tables, 40 layers.
91 lines
4.5 KiB
INI
91 lines
4.5 KiB
INI
# Quadlet unit: frank-primary (rootless, boot-persistent).
|
|
#
|
|
# Install path on dankserver: ~/.config/containers/systemd/frank-primary.container
|
|
# Unit name: frank-primary.service (container name: frank-primary)
|
|
#
|
|
# The dankserver LLM endpoint (:7770, alias frank-primary): the Lucebox
|
|
# runtime (github.com/Luce-Org/lucebox, local image localhost/lucebox-rocm:
|
|
# gfx1201 built from Dockerfile.rocm with LUCE_HIP_ARCHES=gfx1201 and
|
|
# ROCM_VERSION=7.14.1-full to match the host driver's ROCm 7.x line)
|
|
# serving DeepSeek-V4.1-Flash-ROCMFP23 (377.2 GiB GGUF, 40-layer MoE,
|
|
# 384 routed experts + 1 shared per layer, top-6 routing, Engram tables at
|
|
# layers 1 and 14) on the two Radeon AI PRO R9700s (gfx1201). The model
|
|
# cannot be resident: dense weights, the compressed MLA caches and a hot
|
|
# expert stack sit on hip:0, the streamed-expert slot cache on hip:1, and
|
|
# every other routed expert is pulled out of the mmapped page cache (246 GiB
|
|
# RAM holds most of the 179 GiB expert set; the rest reads from NVMe). Lazy
|
|
# mmap page-in is the engine default — no flag.
|
|
#
|
|
# The image's entrypoint only forwards a fixed Qwen/DFlash flag set and
|
|
# cannot express the DS4 flags, so the unit bypasses it (--entrypoint) and
|
|
# runs the repo's frank-primary-entrypoint.sh, which execs the native
|
|
# luce_server with the DS4 launch shape (see that script's header).
|
|
#
|
|
# SHAPE. Host network, :7770, served model name frank-primary, OpenAI /v1
|
|
# (Chat Completions with tool metadata, Responses, Anthropic Messages,
|
|
# Open WebUI metadata) — the fleet contract is unchanged from
|
|
# frank-medium.
|
|
#
|
|
# DEVICES. /dev/kfd + /dev/dri through the amdgpu/KFD stack. Both R9700s are
|
|
# visible (indices 0 and 1; the Raphael iGPU enumerates as index 2 and stays
|
|
# out). They are NOT driven as a symmetric pair: the in-process expert-
|
|
# parallel path (LUCE_DS4_MOE_TP_INPROC) is qualified for gfx1151+gfx1201
|
|
# pairs, not gfx1201+gfx1201. Instead hip:0 owns the dense weights and the
|
|
# hot expert stack while LUCE_EXPERT_STREAM_DEVICE=1 (entrypoint) gives hip:1
|
|
# the streamed-expert slot cache, so each card carries one tier and neither
|
|
# waits on the other.
|
|
#
|
|
# MOUNTS. /models (ro — the GGUF is mmapped, nothing writes), and the
|
|
# entrypoint + healthcheck scripts straight out of this checkout
|
|
# (deploy.sh git-pulls the checkout before dispatching).
|
|
#
|
|
# IMAGE. localhost/-aliased tag: this host's podman quadlet path cannot
|
|
# resolve registry-prefixed refs from local storage at create time (same
|
|
# as frank-medium). Pull=never keeps boots off the registry.
|
|
#
|
|
# CUTOVER. This unit REPLACES frank-medium on :7770. The deploy handler
|
|
# (deploy_llm_primary in scripts/deploy-remote.sh) stops and masks the
|
|
# radiance unit before starting this one; the radiance unit is retired to
|
|
# the home trash after frank-primary is verified (trash policy, never rm).
|
|
#
|
|
# DO NOT name an environment variable TEMP, HOST or GPU_MAX_HEAP_SIZE: the
|
|
# HIP runtime reads bare TEMP for its JIT cache path (2026-08-13 incident).
|
|
[Unit]
|
|
Description=frank-primary — Lucebox DeepSeek-V4.1-Flash-ROCMFP23 on R9700 (gfx1201), experts in RAM
|
|
After=network-online.target
|
|
|
|
[Container]
|
|
ContainerName=frank-primary
|
|
Image=localhost/lucebox-rocm:gfx1201
|
|
# Host network: luce_server binds 0.0.0.0:7770 directly; no PublishPort.
|
|
AddDevice=/dev/kfd
|
|
AddDevice=/dev/dri
|
|
GroupAdd=keep-groups
|
|
PodmanArgs=--privileged --ipc=host --security-opt seccomp=unconfined --cap-add SYS_PTRACE --network=host --entrypoint /usr/local/bin/frank-primary-entrypoint.sh
|
|
# Both R9700s: hip:0 target, hip:1 the streamed-expert slot cache. Index 2,
|
|
# the Raphael iGPU, stays out.
|
|
Environment=HIP_VISIBLE_DEVICES=0,1
|
|
Environment=ROCR_VISIBLE_DEVICES=0,1
|
|
# The 377 GiB GGUF, mmapped; pages pull from disk/page cache on demand.
|
|
Volume=/home/dank/models:/models:ro
|
|
# Entrypoint + healthcheck from this checkout, mounted read-only.
|
|
Volume=/home/dank/serverAppConfigs/dankserver/frank-primary/frank-primary-entrypoint.sh:/usr/local/bin/frank-primary-entrypoint.sh:ro
|
|
Volume=/home/dank/serverAppConfigs/dankserver/frank-primary/frank-primary-healthcheck.py:/usr/local/bin/frank-primary-healthcheck.py:ro
|
|
# 200 only once the engine serves; first start page-ins the dense weights
|
|
# and builds the graphs, which takes a while. HealthCmd is split on spaces
|
|
# into an argv array by the podman 5.x v1 generator, hence the file probe.
|
|
HealthCmd=python3 /usr/local/bin/frank-primary-healthcheck.py
|
|
HealthInterval=60s
|
|
HealthTimeout=30s
|
|
HealthRetries=3
|
|
HealthStartPeriod=1800s
|
|
Pull=never
|
|
|
|
[Service]
|
|
TimeoutStartSec=1800
|
|
Restart=on-failure
|
|
RestartSec=10
|
|
|
|
[Install]
|
|
WantedBy=default.target
|