frank-large: swap halogen Quadlet for ik_llama.cpp (3090 + Strix Halo CPU path)
This commit is contained in:
+37
-69
@@ -912,85 +912,53 @@ deploy_anubis() {
|
||||
wait_container_healthy anubis 60 || return 1
|
||||
}
|
||||
|
||||
# frank-large runs as a rootless Quadlet unit since 2026-09-11 (halogen-flash-
|
||||
# server replaced the llama.cpp/kingjones runtime). Unlike the sibling LLM
|
||||
# services it is therefore NOT a root unit: no relink_unit, no `systemctl
|
||||
# enable` (this host's quadlet generator produces units that cannot be
|
||||
# enabled — boot persistence comes from [Install] WantedBy=default.target in
|
||||
# the .container file plus linger).
|
||||
# frank-large runs as a ROOT unit again since 2026-09-15: ik_llama.cpp
|
||||
# (qwen4exp support merged upstream) replaced the halogen-flash-server
|
||||
# rootless Quadlet, and the ik server is a native binary — CUDA on the RTX
|
||||
# 3090 for dense/attention/KV, the Strix Halo CPU path for the MoE experts.
|
||||
# There is no container image to pull and no generated unit to avoid:
|
||||
# relink_unit points /etc/systemd/system/frank-large.service at the repo
|
||||
# file, and boot persistence is the unit's [Install] section.
|
||||
#
|
||||
# The llama.cpp-era ROOT unit is retired first. Its unit file is a symlink
|
||||
# into this checkout (the old relink_unit did `ln -sfn scripts/frank-large.
|
||||
# service /etc/systemd/system/`), so leaving it behind after the repo file
|
||||
# moves to the trash would leave systemd holding a dangling unit that can
|
||||
# still claim port 7770. Stop it, drop its enable symlinks, move the unit file
|
||||
# into the home trash (never rm), then reload the root manager.
|
||||
#
|
||||
# FIRST START: the container fetches ~127 GB of weights before it can serve,
|
||||
# so /health is legitimately down for the whole fetch. wait_for_health would
|
||||
# burn its budget and report a failure that is not one. The gate below
|
||||
# recognises the bootstrap (checkpoint absent) and waits for the checkpoint
|
||||
# instead, falling through to the normal health gate once it lands.
|
||||
LLM_LARGE_CHECKPOINT="${LLM_LARGE_CHECKPOINT:-/home/dank/models/halogen/qwen38-flash-next-w4b.hgn}"
|
||||
# The halogen Quadlet is retired first. Both managers must never know this
|
||||
# unit name at once (they would race for port 7770): stop the user unit,
|
||||
# poll until it is really gone, move the installed .container into the home
|
||||
# trash (never rm), then reload the user manager.
|
||||
LLM_LARGE_CHECKPOINT="${LLM_LARGE_CHECKPOINT:-/home/dank/models/mradermacher-Qwen3.8-Flash-Next-Uncensored-i1-Q4_K_M/Qwen3.8-Flash-Next-Uncensored.i1-Q4_K_M.gguf}"
|
||||
|
||||
retire_root_llm_large() {
|
||||
local trash="$HOME/.AGENTTRASH/20260911-halogen-swap/host-units"
|
||||
run_privileged systemctl stop frank-default-large 2>/dev/null || true
|
||||
run_privileged systemctl disable frank-default-large 2>/dev/null || true
|
||||
run_privileged systemctl stop frank-large.service 2>/dev/null || true
|
||||
# On this host `disable` has been observed to delete the unit file itself
|
||||
# (2026-08-26 incident, see AGENTS.md); tolerate either behaviour and keep
|
||||
# whatever remains by moving it to the trash.
|
||||
run_privileged systemctl disable frank-large.service 2>/dev/null || true
|
||||
if [[ -e /etc/systemd/system/frank-large.service || -L /etc/systemd/system/frank-large.service ]]; then
|
||||
retire_quadlet_llm_large() {
|
||||
local trash="$HOME/.AGENTTRASH/20260915-ik-swap/halogen-quadlet"
|
||||
systemctl --user stop frank-large.service 2>/dev/null || true
|
||||
# A stopping quadlet runs podman stop (SIGTERM, then SIGKILL at the
|
||||
# timeout); llama-family engines never preempt an in-flight generation.
|
||||
# Poll until the user unit is really inactive before removing its file.
|
||||
local i
|
||||
for ((i = 0; i < 30; i++)); do
|
||||
systemctl --user is-active --quiet frank-large.service 2>/dev/null || break
|
||||
sleep 2
|
||||
done
|
||||
if [[ -e "$HOME/.config/containers/systemd/frank-large.container" || -L "$HOME/.config/containers/systemd/frank-large.container" ]]; then
|
||||
mkdir -p "$trash"
|
||||
run_privileged mv -- /etc/systemd/system/frank-large.service \
|
||||
"$trash/frank-large.service"
|
||||
echo "retired root unit frank-large.service -> $trash"
|
||||
mv -- "$HOME/.config/containers/systemd/frank-large.container" \
|
||||
"$trash/frank-large.container"
|
||||
echo "retired halogen quadlet -> $trash"
|
||||
fi
|
||||
run_privileged systemctl daemon-reload
|
||||
systemctl --user daemon-reload
|
||||
}
|
||||
|
||||
deploy_llm_large() {
|
||||
retire_root_llm_large
|
||||
# Pull once, then run the localhost/-aliased tag: this host's quadlet path
|
||||
# cannot resolve registry-prefixed refs from local storage at create time
|
||||
# (same workaround as anubis/hermes).
|
||||
local image="ghcr.io/peonist-ai/halogen-flash-server:0.5.8"
|
||||
local alias="localhost/peonist-ai/halogen-flash-server:0.5.8"
|
||||
podman pull "$image"
|
||||
podman tag "$image" "$alias"
|
||||
# The weights volume: read-write, because the container downloads into it.
|
||||
mkdir -p /home/dank/models/halogen
|
||||
install_quadlet frank-large dankclaw/frank-large/quadlet frank-large
|
||||
systemctl --user restart frank-large.service
|
||||
wait_for_llm_large_ready
|
||||
retire_quadlet_llm_large
|
||||
if [[ ! -f "$LLM_LARGE_CHECKPOINT" ]]; then
|
||||
echo "ERROR: checkpoint absent at $LLM_LARGE_CHECKPOINT" >&2
|
||||
echo "frank-large: download the mradermacher i1-Q4_K_M GGUF first; refusing to start a unit that cannot load." >&2
|
||||
return 1
|
||||
fi
|
||||
relink_unit frank-large
|
||||
run_privileged systemctl enable frank-large.service
|
||||
run_privileged systemctl restart frank-large.service
|
||||
wait_for_health frank-large http://127.0.0.1:7770/health 1200
|
||||
}
|
||||
|
||||
# wait_for_llm_large_ready — bootstrap-aware gate. If the checkpoint is absent
|
||||
# the container is downloading it; wait for the file (resumable, and the unit
|
||||
# restarts it on failure) rather than gating on a /health that cannot answer
|
||||
# yet. Reports success either way, so the first deploy does not look like a
|
||||
# failure while the engine does exactly what it was told to.
|
||||
wait_for_llm_large_ready() {
|
||||
[[ -f "$LLM_LARGE_CHECKPOINT" ]] && return 0
|
||||
echo "frank-large: checkpoint absent at $LLM_LARGE_CHECKPOINT"
|
||||
echo "frank-large: first start — the container is downloading ~127 GB from"
|
||||
echo "frank-large: peonist-ai/halogen-qwen3.8-flash-next (resumes if interrupted)."
|
||||
local i
|
||||
for ((i = 1; i <= 1200; i++)); do
|
||||
if [[ -f "$LLM_LARGE_CHECKPOINT" ]]; then
|
||||
echo "frank-large: weights landed after approximately $((i * 2))s; gating on /health"
|
||||
return 0
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
echo "WARN: frank-large download still in progress after 40m — NOT a failure."
|
||||
echo "WARN: the unit keeps fetching; re-run this deploy (or re-check /health) later." >&2
|
||||
return 0
|
||||
}
|
||||
|
||||
# deploy_llm_medium — frank-medium runs as a rootless Quadlet since the
|
||||
# 2026-09-15 runtime swap to the vllm-radiance MXFP4 stack. It began the day
|
||||
# as a root llama.cpp unit (the ROCmFPX/Q8_0_ROCMFPX_AGENT deployment from
|
||||
|
||||
Reference in New Issue
Block a user