feat(llm): rename inference services dropping 'default' from names
frank-default-large -> frank-large (Dankclaw :7770), frank-default-small -> frank-small (Dankserver :7770), frank-default-sightsound -> frank-npu (Dankclaw :7771). Units, env files, serve scripts, deploy-plan mappings, deploy-remote dispatch (stop/disable old units + relink + enable new), and the test seams move together. Retired frank-default-npu.* artifacts moved to scripts/.AGENTTRASH/ (tracked-in-history; ignored on disk). Served aliases become frank-large / frank-small via --alias; the NPU endpoint serves the whole FLM registry, so its rename changes no served tags.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
Decode throughput benchmark for frank-default-large.
|
Decode throughput benchmark for frank-large.
|
||||||
Starts the server with a given --threads-batch value, sends an 8K+ token prompt,
|
Starts the server with a given --threads-batch value, sends an 8K+ token prompt,
|
||||||
generates 256 tokens, measures generation tok/s.
|
generates 256 tokens, measures generation tok/s.
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ SERVE = "/home/dank/GitPackages/ROCmFPX/build-qwen38/bin/llama-server"
|
|||||||
PORT = 7770
|
PORT = 7770
|
||||||
N_GEN = 256
|
N_GEN = 256
|
||||||
PROMPT_FILE = "/tmp/bench-prompts/prompt_code.txt"
|
PROMPT_FILE = "/tmp/bench-prompts/prompt_code.txt"
|
||||||
ENV_FILE = os.path.join(os.path.dirname(__file__), "frank-default-large.env")
|
ENV_FILE = os.path.join(os.path.dirname(__file__), "frank-large.env")
|
||||||
SERVER_DIR = os.path.dirname(SERVE)
|
SERVER_DIR = os.path.dirname(SERVE)
|
||||||
ROCM_PATH = "/opt/rocm"
|
ROCM_PATH = "/opt/rocm"
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ def wait_ready():
|
|||||||
def send_request(prompt, max_tokens=N_GEN):
|
def send_request(prompt, max_tokens=N_GEN):
|
||||||
"""Send chat completion, measure generation throughput."""
|
"""Send chat completion, measure generation throughput."""
|
||||||
body = json.dumps({
|
body = json.dumps({
|
||||||
"model": "frank-default-large",
|
"model": "frank-large",
|
||||||
"messages": [{"role": "user", "content": prompt}],
|
"messages": [{"role": "user", "content": prompt}],
|
||||||
"max_tokens": max_tokens,
|
"max_tokens": max_tokens,
|
||||||
"stream": False,
|
"stream": False,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Decode throughput benchmark for frank-default-large.
|
# Decode throughput benchmark for frank-large.
|
||||||
# Measures generation tok/s with 8K+ token prompts and 256 generated tokens.
|
# Measures generation tok/s with 8K+ token prompts and 256 generated tokens.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ run_bench() {
|
|||||||
# Warmup (small request)
|
# Warmup (small request)
|
||||||
curl -s -m 60 http://127.0.0.1:$PORT/v1/chat/completions \
|
curl -s -m 60 http://127.0.0.1:$PORT/v1/chat/completions \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"model":"frank-default-large","messages":[{"role":"user","content":"Hi"}],"max_tokens":16,"stream":false}' > /dev/null 2>&1 || true
|
-d '{"model":"frank-large","messages":[{"role":"user","content":"Hi"}],"max_tokens":16,"stream":false}' > /dev/null 2>&1 || true
|
||||||
|
|
||||||
# Build 8K prompt
|
# Build 8K prompt
|
||||||
local prompt
|
local prompt
|
||||||
@@ -75,7 +75,7 @@ print(json.dumps(' '.join(words)))
|
|||||||
t0=$(date +%s%N)
|
t0=$(date +%s%N)
|
||||||
resp=$(curl -s -m 600 http://127.0.0.1:$PORT/v1/chat/completions \
|
resp=$(curl -s -m 600 http://127.0.0.1:$PORT/v1/chat/completions \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "{\"model\":\"frank-default-large\",\"messages\":[{\"role\":\"user\",\"content\":$prompt}],\"max_tokens\":$N_GEN,\"stream\":false}" 2>&1)
|
-d "{\"model\":\"frank-large\",\"messages\":[{\"role\":\"user\",\"content\":$prompt}],\"max_tokens\":$N_GEN,\"stream\":false}" 2>&1)
|
||||||
t1=$(date +%s%N)
|
t1=$(date +%s%N)
|
||||||
|
|
||||||
if ! echo "$resp" | python3 -c "import sys,json; json.load(sys.stdin)" 2>/dev/null; then
|
if ! echo "$resp" | python3 -c "import sys,json; json.load(sys.stdin)" 2>/dev/null; then
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
Benchmark n-gram speculative decoding vs no-spec for frank-default-large.
|
Benchmark n-gram speculative decoding vs no-spec for frank-large.
|
||||||
|
|
||||||
Tests prompt-processing throughput with 16K token prompts (manageable request size).
|
Tests prompt-processing throughput with 16K token prompts (manageable request size).
|
||||||
Code-heavy prompt (high n-gram redundancy) vs prose prompt (low redundancy).
|
Code-heavy prompt (high n-gram redundancy) vs prose prompt (low redundancy).
|
||||||
@@ -103,7 +103,7 @@ def start_server(port, spec_type):
|
|||||||
def run_test(prompt_text, spec_type, port):
|
def run_test(prompt_text, spec_type, port):
|
||||||
"""Send a request and extract prompt processing metrics."""
|
"""Send a request and extract prompt processing metrics."""
|
||||||
data = json.dumps({
|
data = json.dumps({
|
||||||
"model": "frank-default-large",
|
"model": "frank-large",
|
||||||
"messages": [{"role": "user", "content": prompt_text}],
|
"messages": [{"role": "user", "content": prompt_text}],
|
||||||
"max_tokens": TEST_TOKENS,
|
"max_tokens": TEST_TOKENS,
|
||||||
"stream": False,
|
"stream": False,
|
||||||
@@ -189,7 +189,7 @@ def main():
|
|||||||
print(f" Prose: {prose_prompt_file.stat().st_size:,} bytes")
|
print(f" Prose: {prose_prompt_file.stat().st_size:,} bytes")
|
||||||
|
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
print(" N-gram Mod Benchmark — frank-default-large")
|
print(" N-gram Mod Benchmark — frank-large")
|
||||||
print(f" STRIX ROCmFP4 · 64K context · 16K prompts")
|
print(f" STRIX ROCmFP4 · 64K context · 16K prompts")
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Benchmark n-gram speculative decoding vs no-spec for frank-default-large.
|
# Benchmark n-gram speculative decoding vs no-spec for frank-large.
|
||||||
#
|
#
|
||||||
# This tests prompt-processing throughput at 64k context with two distinct
|
# This tests prompt-processing throughput at 64k context with two distinct
|
||||||
# prompts: one code-heavy and one prose-heavy. Uses llama-server on scratch
|
# prompts: one code-heavy and one prose-heavy. Uses llama-server on scratch
|
||||||
# ports with the OpenAI-compatible API to measure prompt_eval_duration_ms.
|
# ports with the OpenAI-compatible API to measure prompt_eval_duration_ms.
|
||||||
#
|
#
|
||||||
# Run on Dankclaw after stopping the production service:
|
# Run on Dankclaw after stopping the production service:
|
||||||
# sudo systemctl stop frank-default-large
|
# sudo systemctl stop frank-large
|
||||||
# ./scripts/bench-ngram-mod.sh
|
# ./scripts/bench-ngram-mod.sh
|
||||||
# sudo systemctl start frank-default-large
|
# sudo systemctl start frank-large
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
ENV_FILE="${FRANK_LARGE_ENV_FILE:-$SCRIPT_DIR/frank-default-large.env}"
|
ENV_FILE="${FRANK_LARGE_ENV_FILE:-$SCRIPT_DIR/frank-large.env}"
|
||||||
if [[ -f "$ENV_FILE" ]]; then
|
if [[ -f "$ENV_FILE" ]]; then
|
||||||
set -a; source "$ENV_FILE"; set +a
|
set -a; source "$ENV_FILE"; set +a
|
||||||
fi
|
fi
|
||||||
@@ -184,7 +184,7 @@ run_single_test() {
|
|||||||
response=$(curl -s -X POST "http://127.0.0.1:$port/v1/completions" \
|
response=$(curl -s -X POST "http://127.0.0.1:$port/v1/completions" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d "{
|
-d "{
|
||||||
\"model\": \"frank-default-large\",
|
\"model\": \"frank-large\",
|
||||||
\"prompt\": \"$prompt_text\",
|
\"prompt\": \"$prompt_text\",
|
||||||
\"max_tokens\": 128,
|
\"max_tokens\": 128,
|
||||||
\"temperature\": 0,
|
\"temperature\": 0,
|
||||||
@@ -220,7 +220,7 @@ run_single_test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
echo "╔══════════════════════════════════════════════════════════╗"
|
echo "╔══════════════════════════════════════════════════════════╗"
|
||||||
echo "║ N-gram Mod Benchmark — frank-default-large ║"
|
echo "║ N-gram Mod Benchmark — frank-large ║"
|
||||||
echo "║ STRIX ROCmFP4 · 64k context · two prompts ║"
|
echo "║ STRIX ROCmFP4 · 64k context · two prompts ║"
|
||||||
echo "╚══════════════════════════════════════════════════════════╝"
|
echo "╚══════════════════════════════════════════════════════════╝"
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import time
|
|||||||
import urllib.request
|
import urllib.request
|
||||||
import urllib.error
|
import urllib.error
|
||||||
|
|
||||||
SERVICE = "frank-default-large"
|
SERVICE = "frank-large"
|
||||||
ENV_FILE = "/home/dank/serverAppConfigs/scripts/frank-default-large.env"
|
ENV_FILE = "/home/dank/serverAppConfigs/scripts/frank-large.env"
|
||||||
ALIAS = "frank-default-large"
|
ALIAS = "frank-large"
|
||||||
DEFAULT_HOST = "localhost"
|
DEFAULT_HOST = "localhost"
|
||||||
DEFAULT_PORT = 7770
|
DEFAULT_PORT = 7770
|
||||||
DEFAULT_MAX_TOKENS = 16384
|
DEFAULT_MAX_TOKENS = 16384
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
HTTP-based prefill-throughput sweep for frank-default-large.
|
HTTP-based prefill-throughput sweep for frank-large.
|
||||||
Starts the server with a given --threads-batch value, sends a 64K-prompt via
|
Starts the server with a given --threads-batch value, sends a 64K-prompt via
|
||||||
the chat API (max_tokens=0), measures prompt_tokens/wall_time.
|
the chat API (max_tokens=0), measures prompt_tokens/wall_time.
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ def send_prefill_request():
|
|||||||
with open(PROMPT_FILE, "r") as f:
|
with open(PROMPT_FILE, "r") as f:
|
||||||
prompt = f.read()
|
prompt = f.read()
|
||||||
body = json.dumps({
|
body = json.dumps({
|
||||||
"model": "frank-default-large",
|
"model": "frank-large",
|
||||||
"messages": [{"role": "user", "content": prompt}],
|
"messages": [{"role": "user", "content": prompt}],
|
||||||
"max_tokens": 1,
|
"max_tokens": 1,
|
||||||
"stream": False
|
"stream": False
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Threads-batch sweep for frank-default-large on dankclaw
|
# Threads-batch sweep for frank-large on dankclaw
|
||||||
# Benches prefill throughput at 65536 prompt tokens across threads-batch values.
|
# Benches prefill throughput at 65536 prompt tokens across threads-batch values.
|
||||||
set -uo pipefail
|
set -uo pipefail
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ TB_LIST=(16 32 48 64 80 96 128)
|
|||||||
ENV_FILE="/home/dank/GitPackages/ROCmFPX/build-qwen38/bin"
|
ENV_FILE="/home/dank/GitPackages/ROCmFPX/build-qwen38/bin"
|
||||||
|
|
||||||
echo "========================================"
|
echo "========================================"
|
||||||
echo "THREADS-BATCH SWEEP — frank-default-large"
|
echo "THREADS-BATCH SWEEP — frank-large"
|
||||||
echo "Model: $(basename "$MODEL") ($(du -h "$MODEL" | cut -f1))"
|
echo "Model: $(basename "$MODEL") ($(du -h "$MODEL" | cut -f1))"
|
||||||
echo "Threads-batch values: ${TB_LIST[*]}"
|
echo "Threads-batch values: ${TB_LIST[*]}"
|
||||||
echo "Prompt: 65536 tokens, n-gen: 0 (prefill-only)"
|
echo "Prompt: 65536 tokens, n-gen: 0 (prefill-only)"
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Benchmark ubatch with llama-bench for frank-default-large.
|
# Benchmark ubatch with llama-bench for frank-large.
|
||||||
#
|
#
|
||||||
# This is intentionally a ubatch-only benchmark. It uses one llama-bench
|
# This is intentionally a ubatch-only benchmark. It uses one llama-bench
|
||||||
# process, an 8K prompt workload, and equal batch/ubatch values. No server
|
# process, an 8K prompt workload, and equal batch/ubatch values. No server
|
||||||
# process, HTTP requests, or log scraping are used.
|
# process, HTTP requests, or log scraping are used.
|
||||||
#
|
#
|
||||||
# Run on Dankclaw after stopping frank-default-large:
|
# Run on Dankclaw after stopping frank-large:
|
||||||
# sudo systemctl stop frank-default-large
|
# sudo systemctl stop frank-large
|
||||||
# ./scripts/bench-ubatch.sh
|
# ./scripts/bench-ubatch.sh
|
||||||
# sudo systemctl start frank-default-large
|
# sudo systemctl start frank-large
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
: "${LLAMA_BENCH:=/home/dank/GitPackages/ROCmFPX/build-strix-rocmfp4/bin/llama-bench}"
|
: "${LLAMA_BENCH:=/home/dank/GitPackages/ROCmFPX/build-strix-rocmfp4/bin/llama-bench}"
|
||||||
|
|||||||
+13
-17
@@ -58,10 +58,9 @@ SERVICE_ORDER = (
|
|||||||
"sonarr",
|
"sonarr",
|
||||||
"lidarr",
|
"lidarr",
|
||||||
"readarr",
|
"readarr",
|
||||||
"frank-default-large",
|
"frank-large",
|
||||||
"frank-default-npu",
|
"frank-npu",
|
||||||
"frank-default-sightsound",
|
"frank-small",
|
||||||
"frank-default-small",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
DANKCLAW_SERVICES = {
|
DANKCLAW_SERVICES = {
|
||||||
@@ -89,9 +88,8 @@ DANKCLAW_SERVICES = {
|
|||||||
"authentik-outpost-ldap",
|
"authentik-outpost-ldap",
|
||||||
"caddy",
|
"caddy",
|
||||||
"homepage",
|
"homepage",
|
||||||
"frank-default-large",
|
"frank-large",
|
||||||
"frank-default-npu",
|
"frank-npu",
|
||||||
"frank-default-sightsound",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DANKSERVER_SERVICES = {
|
DANKSERVER_SERVICES = {
|
||||||
@@ -109,7 +107,7 @@ DANKSERVER_SERVICES = {
|
|||||||
"sonarr",
|
"sonarr",
|
||||||
"lidarr",
|
"lidarr",
|
||||||
"readarr",
|
"readarr",
|
||||||
"frank-default-small",
|
"frank-small",
|
||||||
}
|
}
|
||||||
|
|
||||||
# FrankBook-Pro runs the *arr stack + qBittorrent inside a podman machine on
|
# FrankBook-Pro runs the *arr stack + qBittorrent inside a podman machine on
|
||||||
@@ -352,17 +350,15 @@ def services_for_path(path: str, target: str) -> set[str]:
|
|||||||
|
|
||||||
if parts[0] == "scripts":
|
if parts[0] == "scripts":
|
||||||
name = p.name
|
name = p.name
|
||||||
if name in {"frank-default-large.env", "frank-default-large.service", "serve-frank-large.sh"}:
|
if name in {"frank-large.env", "frank-large.service", "serve-frank-large.sh"}:
|
||||||
_add(services, "frank-default-large")
|
_add(services, "frank-large")
|
||||||
elif name in {"frank-default-npu.env", "frank-default-npu.service", "serve-frank-default-npu.sh"}:
|
elif name in {"frank-npu.env", "frank-npu.service", "serve-frank-npu.sh"}:
|
||||||
_add(services, "frank-default-npu")
|
_add(services, "frank-npu")
|
||||||
elif name in {"frank-default-sightsound.env", "frank-default-sightsound.service", "serve-frank-default-sightsound.sh"}:
|
elif name in {"frank-small.env", "frank-small.service", "serve-frank-small.sh"}:
|
||||||
_add(services, "frank-default-sightsound")
|
_add(services, "frank-small")
|
||||||
elif name in {"frank-default-small.env", "frank-default-small.service", "serve-frank-small.sh"}:
|
|
||||||
_add(services, "frank-default-small")
|
|
||||||
elif name == "chat-template.jinja":
|
elif name == "chat-template.jinja":
|
||||||
# Only the selected target's LLM consumes this shared template.
|
# Only the selected target's LLM consumes this shared template.
|
||||||
_add(services, "frank-default-large" if target == "dankclaw" else "frank-default-small")
|
_add(services, "frank-large" if target == "dankclaw" else "frank-small")
|
||||||
elif name in {"homepage-status.py", "homepage-status.service", "homepage-status.timer"}:
|
elif name in {"homepage-status.py", "homepage-status.service", "homepage-status.timer"}:
|
||||||
_add(services, "homepage")
|
_add(services, "homepage")
|
||||||
# Deployment/test/benchmark scripts and other repo tooling do not
|
# Deployment/test/benchmark scripts and other repo tooling do not
|
||||||
|
|||||||
+37
-33
@@ -90,13 +90,12 @@ service_is_allowed() {
|
|||||||
dankclaw:authentik-postgres|dankclaw:authentik-server|\
|
dankclaw:authentik-postgres|dankclaw:authentik-server|\
|
||||||
dankclaw:authentik-worker|dankclaw:authentik-outpost|dankclaw:authentik-outpost-ldap|dankclaw:anubis|\
|
dankclaw:authentik-worker|dankclaw:authentik-outpost|dankclaw:authentik-outpost-ldap|dankclaw:anubis|\
|
||||||
dankclaw:caddy|dankclaw:homepage|dankclaw:seerr|\
|
dankclaw:caddy|dankclaw:homepage|dankclaw:seerr|\
|
||||||
dankclaw:frank-default-large|dankclaw:frank-default-npu|\
|
dankclaw:frank-large|dankclaw:frank-npu|\
|
||||||
dankclaw:frank-default-sightsound|\
|
|
||||||
dankserver:romm-mariadb|dankserver:romm-redis|dankserver:romm|\
|
dankserver:romm-mariadb|dankserver:romm-redis|dankserver:romm|\
|
||||||
dankserver:copyparty|dankserver:jellyfin|dankserver:calibre-web|dankserver:plex|dankserver:tautulli|\
|
dankserver:copyparty|dankserver:jellyfin|dankserver:calibre-web|dankserver:plex|dankserver:tautulli|\
|
||||||
dankserver:prowlarr|dankserver:qbittorrent|dankserver:radarr|\
|
dankserver:prowlarr|dankserver:qbittorrent|dankserver:radarr|\
|
||||||
dankserver:sonarr|dankserver:lidarr|dankserver:readarr|\
|
dankserver:sonarr|dankserver:lidarr|dankserver:readarr|\
|
||||||
dankserver:frank-default-small|\
|
dankserver:frank-small|\
|
||||||
frankbook-pro:gluetun|frankbook-pro:qbittorrent|frankbook-pro:prowlarr|\
|
frankbook-pro:gluetun|frankbook-pro:qbittorrent|frankbook-pro:prowlarr|\
|
||||||
frankbook-pro:radarr|frankbook-pro:sonarr|frankbook-pro:lidarr|\
|
frankbook-pro:radarr|frankbook-pro:sonarr|frankbook-pro:lidarr|\
|
||||||
frankbook-pro:readarr)
|
frankbook-pro:readarr)
|
||||||
@@ -182,8 +181,9 @@ add_pending_services() {
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
[[ -n "$recorded" && "$recorded" != "$REVISION" ]] || continue
|
[[ -n "$recorded" && "$recorded" != "$REVISION" ]] || continue
|
||||||
if [[ "$TARGET" == dankclaw && "$service" == frank-default-small ]]; then continue; fi
|
if [[ "$TARGET" == dankclaw && "$service" == frank-small ]]; then continue; fi
|
||||||
if [[ "$TARGET" == dankserver && "$service" == frank-default-large ]]; then continue; fi
|
if [[ "$TARGET" == dankserver && "$service" == frank-large ]]; then continue; fi
|
||||||
|
if [[ "$TARGET" == dankserver && "$service" == frank-npu ]]; then continue; fi
|
||||||
if ! changed="$(python3 scripts/deploy-plan.py --target "$TARGET" \
|
if ! changed="$(python3 scripts/deploy-plan.py --target "$TARGET" \
|
||||||
--repo "$REMOTE_DIR" --base "$recorded" --head "$REVISION")"; then
|
--repo "$REMOTE_DIR" --base "$recorded" --head "$REVISION")"; then
|
||||||
echo "WARN: unable to compare state for $service; retaining it as pending" >&2
|
echo "WARN: unable to compare state for $service; retaining it as pending" >&2
|
||||||
@@ -826,40 +826,45 @@ deploy_anubis() {
|
|||||||
wait_container_healthy anubis 60 || return 1
|
wait_container_healthy anubis 60 || return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Rename cutover (2026-09-03): frank-default-large -> frank-large,
|
||||||
|
# frank-default-small -> frank-small, frank-default-sightsound -> frank-npu.
|
||||||
|
# The legacy units are stopped and disabled before the renamed unit takes the
|
||||||
|
# port so no legacy process is left holding it; stop/disable of an already
|
||||||
|
# unloaded legacy unit fail harmlessly and are tolerated.
|
||||||
deploy_llm_large() {
|
deploy_llm_large() {
|
||||||
relink_unit frank-default-large
|
run_privileged systemctl stop frank-default-large || true
|
||||||
# NPU is intentionally not restarted here. It is a separate, retired
|
run_privileged systemctl disable frank-default-large || true
|
||||||
# endpoint and its unit is only relinked when explicitly selected.
|
relink_unit frank-large
|
||||||
run_privileged systemctl daemon-reload
|
run_privileged systemctl daemon-reload
|
||||||
run_privileged systemctl enable frank-default-large
|
run_privileged systemctl enable frank-large
|
||||||
run_privileged systemctl restart frank-default-large
|
run_privileged systemctl restart frank-large
|
||||||
wait_for_health frank-default-large http://127.0.0.1:7770/health 1200
|
wait_for_health frank-large http://127.0.0.1:7770/health 1200
|
||||||
}
|
}
|
||||||
|
|
||||||
deploy_llm_small() {
|
deploy_llm_small() {
|
||||||
relink_unit frank-default-small
|
run_privileged systemctl stop frank-default-small || true
|
||||||
|
run_privileged systemctl disable frank-default-small || true
|
||||||
|
relink_unit frank-small
|
||||||
run_privileged systemctl daemon-reload
|
run_privileged systemctl daemon-reload
|
||||||
run_privileged systemctl enable frank-default-small
|
run_privileged systemctl enable frank-small
|
||||||
run_privileged systemctl restart frank-default-small
|
run_privileged systemctl restart frank-small
|
||||||
wait_for_health frank-default-small http://127.0.0.1:7770/health 1200
|
wait_for_health frank-small http://127.0.0.1:7770/health 1200
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# frank-npu is a live serving endpoint (FLM on the XDNA2 NPU), not a
|
||||||
|
# relink-only unit: it is enabled at boot and restarted on deploy. The health
|
||||||
|
# gate polls /v1/version, FLM's cheapest always-on route (there is no /health
|
||||||
|
# route in the FLM server).
|
||||||
deploy_llm_npu() {
|
deploy_llm_npu() {
|
||||||
relink_unit frank-default-npu
|
run_privileged systemctl stop frank-default-sightsound || true
|
||||||
|
run_privileged systemctl disable frank-default-sightsound || true
|
||||||
|
run_privileged systemctl stop frank-default-npu || true
|
||||||
|
run_privileged systemctl disable frank-default-npu || true
|
||||||
|
relink_unit frank-npu
|
||||||
run_privileged systemctl daemon-reload
|
run_privileged systemctl daemon-reload
|
||||||
echo "Relinked frank-default-npu; it was not restarted."
|
run_privileged systemctl enable frank-npu
|
||||||
}
|
run_privileged systemctl restart frank-npu
|
||||||
|
wait_for_health frank-npu http://127.0.0.1:7771/v1/version 300
|
||||||
# frank-default-sightsound is a live serving endpoint (FLM on the XDNA2 NPU),
|
|
||||||
# not a relink-only unit: it is enabled at boot and restarted on deploy. The
|
|
||||||
# health gate polls /v1/version, FLM's cheapest always-on route (there is no
|
|
||||||
# /health route in the FLM server).
|
|
||||||
deploy_llm_sightsound() {
|
|
||||||
relink_unit frank-default-sightsound
|
|
||||||
run_privileged systemctl daemon-reload
|
|
||||||
run_privileged systemctl enable frank-default-sightsound
|
|
||||||
run_privileged systemctl restart frank-default-sightsound
|
|
||||||
wait_for_health frank-default-sightsound http://127.0.0.1:7771/v1/version 300
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wait_for_health() {
|
wait_for_health() {
|
||||||
@@ -1045,10 +1050,9 @@ deploy_service() {
|
|||||||
;;
|
;;
|
||||||
anubis) deploy_anubis ;;
|
anubis) deploy_anubis ;;
|
||||||
seerr) deploy_seerr ;;
|
seerr) deploy_seerr ;;
|
||||||
frank-default-large) deploy_llm_large ;;
|
frank-large) deploy_llm_large ;;
|
||||||
frank-default-small) deploy_llm_small ;;
|
frank-small) deploy_llm_small ;;
|
||||||
frank-default-npu) deploy_llm_npu ;;
|
frank-npu) deploy_llm_npu ;;
|
||||||
frank-default-sightsound) deploy_llm_sightsound ;;
|
|
||||||
hermes|hermes-dashboard|hermes-webui) deploy_hermes ;;
|
hermes|hermes-dashboard|hermes-webui) deploy_hermes ;;
|
||||||
romm|romm-mariadb|romm-redis|mariadb|redis) deploy_romm_stack "$service" ;;
|
romm|romm-mariadb|romm-redis|mariadb|redis) deploy_romm_stack "$service" ;;
|
||||||
jellyfin) deploy_jellyfin ;;
|
jellyfin) deploy_jellyfin ;;
|
||||||
|
|||||||
+3
-4
@@ -34,7 +34,7 @@ Options:
|
|||||||
Examples:
|
Examples:
|
||||||
./scripts/deploy.sh dankclaw
|
./scripts/deploy.sh dankclaw
|
||||||
./scripts/deploy.sh dankclaw --service searxng
|
./scripts/deploy.sh dankclaw --service searxng
|
||||||
./scripts/deploy.sh dankserver --service frank-default-small
|
./scripts/deploy.sh dankserver --service frank-small
|
||||||
./scripts/deploy.sh dankclaw --dry-run
|
./scripts/deploy.sh dankclaw --dry-run
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
@@ -134,13 +134,12 @@ valid_service() {
|
|||||||
dankclaw:hermes-webui|dankclaw:prometheus|dankclaw:grafana|dankclaw:loki|dankclaw:alloy|\
|
dankclaw:hermes-webui|dankclaw:prometheus|dankclaw:grafana|dankclaw:loki|dankclaw:alloy|\
|
||||||
dankclaw:node-exporter|dankclaw:authentik-postgres|dankclaw:authentik-server|\
|
dankclaw:node-exporter|dankclaw:authentik-postgres|dankclaw:authentik-server|\
|
||||||
dankclaw:authentik-worker|dankclaw:authentik-outpost|dankclaw:authentik-outpost-ldap|dankclaw:anubis|dankclaw:seerr|\
|
dankclaw:authentik-worker|dankclaw:authentik-outpost|dankclaw:authentik-outpost-ldap|dankclaw:anubis|dankclaw:seerr|\
|
||||||
dankclaw:frank-default-large|dankclaw:frank-default-npu|\
|
dankclaw:frank-large|dankclaw:frank-npu|\
|
||||||
dankclaw:frank-default-sightsound|\
|
|
||||||
dankserver:romm-mariadb|dankserver:romm-redis|dankserver:romm|\
|
dankserver:romm-mariadb|dankserver:romm-redis|dankserver:romm|\
|
||||||
dankserver:copyparty|dankserver:jellyfin|dankserver:calibre-web|dankserver:plex|dankserver:tautulli|\
|
dankserver:copyparty|dankserver:jellyfin|dankserver:calibre-web|dankserver:plex|dankserver:tautulli|\
|
||||||
dankserver:qbittorrent|dankserver:radarr|dankserver:sonarr|\
|
dankserver:qbittorrent|dankserver:radarr|dankserver:sonarr|\
|
||||||
dankserver:lidarr|dankserver:readarr|dankserver:node-exporter|\
|
dankserver:lidarr|dankserver:readarr|dankserver:node-exporter|\
|
||||||
dankserver:frank-default-small|\
|
dankserver:frank-small|\
|
||||||
frankbook-pro:gluetun|frankbook-pro:qbittorrent|frankbook-pro:prowlarr|\
|
frankbook-pro:gluetun|frankbook-pro:qbittorrent|frankbook-pro:prowlarr|\
|
||||||
frankbook-pro:radarr|frankbook-pro:sonarr|frankbook-pro:lidarr|\
|
frankbook-pro:radarr|frankbook-pro:sonarr|frankbook-pro:lidarr|\
|
||||||
frankbook-pro:readarr)
|
frankbook-pro:readarr)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Download the kingjones Qwen3.8-27B-ROCmFPX-Q8_0-AGENT payload for
|
# Download the kingjones Qwen3.8-27B-ROCmFPX-Q8_0-AGENT payload for
|
||||||
# frank-default-large from HuggingFace into /home/dank/models/.../Q8_0-AGENT.
|
# frank-large from HuggingFace into /home/dank/models/.../Q8_0-AGENT.
|
||||||
#
|
#
|
||||||
# Uses the token in ~/.cache/huggingface/token so the ~28 GB main file does not
|
# Uses the token in ~/.cache/huggingface/token so the ~28 GB main file does not
|
||||||
# hit the anonymous 10 GB/30 min rate limit. Run on Dankclaw.
|
# hit the anonymous 10 GB/30 min rate limit. Run on Dankclaw.
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
[Unit]
|
|
||||||
Description=FastFlowLM NPU sight+sound inference (frank-default-sightsound) on Dankclaw
|
|
||||||
After=network-online.target
|
|
||||||
Wants=network-online.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
User=dank
|
|
||||||
Group=dank
|
|
||||||
Environment="FLM_SIGHTSOUND_ENV_FILE=/home/dank/serverAppConfigs/scripts/frank-default-sightsound.env"
|
|
||||||
ExecStart=/home/dank/serverAppConfigs/scripts/serve-frank-default-sightsound.sh
|
|
||||||
LimitMEMLOCK=infinity
|
|
||||||
Restart=on-failure
|
|
||||||
RestartSec=10
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Tunables for frank-default-large (kingjones777/Qwen3.8-Flash-Next-ROCmFP4-
|
# Tunables for frank-large (kingjones777/Qwen3.8-Flash-Next-ROCmFP4-
|
||||||
# STRIX-GGUF on the kingjones30/ROCmFPX llama.cpp runtime, Dankclaw,
|
# STRIX-GGUF on the kingjones30/ROCmFPX llama.cpp runtime, Dankclaw,
|
||||||
# Strix Halo gfx1151, unified memory).
|
# Strix Halo gfx1151, unified memory).
|
||||||
#
|
#
|
||||||
@@ -56,7 +56,7 @@ CHAT_TEMPLATE_FILE=/home/dank/serverAppConfigs/scripts/chat-template.jinja
|
|||||||
CHAT_TEMPLATE_KWARGS='{"enable_thinking":true,"preserve_thinking":true,"preserve_reasoning":true}'
|
CHAT_TEMPLATE_KWARGS='{"enable_thinking":true,"preserve_thinking":true,"preserve_reasoning":true}'
|
||||||
|
|
||||||
# Alias + network.
|
# Alias + network.
|
||||||
ALIAS=frank-default-large
|
ALIAS=frank-large
|
||||||
BIND_ADDR=0.0.0.0
|
BIND_ADDR=0.0.0.0
|
||||||
LISTEN_PORT=7770
|
LISTEN_PORT=7770
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=ROCmFPX (kingjones30 fork) llama.cpp Qwen3.8-Flash-Next ROCmFP4 STRIX 177B MoE (dankclaw, frank-default-large)
|
Description=ROCmFPX (kingjones30 fork) llama.cpp Qwen3.8-Flash-Next ROCmFP4 STRIX 177B MoE (dankclaw, frank-large)
|
||||||
After=network-online.target
|
After=network-online.target
|
||||||
Wants=network-online.target
|
Wants=network-online.target
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ Wants=network-online.target
|
|||||||
Type=simple
|
Type=simple
|
||||||
User=dank
|
User=dank
|
||||||
Group=dank
|
Group=dank
|
||||||
Environment="FRANK_LARGE_ENV_FILE=/home/dank/serverAppConfigs/scripts/frank-default-large.env"
|
Environment="FRANK_LARGE_ENV_FILE=/home/dank/serverAppConfigs/scripts/frank-large.env"
|
||||||
ExecStart=/home/dank/serverAppConfigs/scripts/serve-frank-large.sh
|
ExecStart=/home/dank/serverAppConfigs/scripts/serve-frank-large.sh
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=10
|
RestartSec=10
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
# Tunables for frank-default-sightsound (FastFlowLM NPU sight+sound endpoint, Dankclaw)
|
# Tunables for frank-npu (FastFlowLM NPU sight+sound endpoint, Dankclaw)
|
||||||
# Runtime: FLM 1.0.1 (/usr/bin/flm) on the XDNA2 NPU (50 TOPS). Model:
|
# Runtime: FLM 1.0.1 (/usr/bin/flm) on the XDNA2 NPU (50 TOPS). Model:
|
||||||
# gemma4-it:e4b = Gemma4-E4B-IT-NPU2 (8B total / ~4.5B effective params,
|
# gemma4-it:e4b = Gemma4-E4B-IT-NPU2 (8B total / ~4.5B effective params,
|
||||||
# Q4_1; vision + audio + reasoning; ~9.1 GB footprint). It is the only NPU2
|
# Q4_1; vision + audio + reasoning; ~9.1 GB footprint). It is the only NPU2
|
||||||
# model family with BOTH an image and an audio tower — the uncensored
|
# model family with BOTH an image and an audio tower — the uncensored
|
||||||
# candidate qwythos:9b is text-only and fails the audio requirement, so this
|
# candidate qwythos:9b is text-only and fails the audio requirement, so this
|
||||||
# endpoint trades "uncensored" for "sight + sound". The NPU draws from the
|
# endpoint trades "uncensored" for "sight + sound". The NPU draws from the
|
||||||
# unified RAM pool shared with frank-default-large (iGPU); ~31 GiB was
|
# unified RAM pool shared with frank-large (iGPU); ~31 GiB was
|
||||||
# available there at idle, so a 9.1 GB pack fits with headroom.
|
# available there at idle, so a 9.1 GB pack fits with headroom.
|
||||||
FLM_MODEL=qwen3.8-distilled-heretic:9b
|
FLM_MODEL=qwen3.8-distilled-heretic:9b
|
||||||
FLM_HOST=0.0.0.0
|
FLM_HOST=0.0.0.0
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=FastFlowLM NPU sight+sound inference (frank-npu) on Dankclaw
|
||||||
|
After=network-online.target
|
||||||
|
Wants=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=dank
|
||||||
|
Group=dank
|
||||||
|
Environment="FRANK_NPU_ENV_FILE=/home/dank/serverAppConfigs/scripts/frank-npu.env"
|
||||||
|
ExecStart=/home/dank/serverAppConfigs/scripts/serve-frank-npu.sh
|
||||||
|
LimitMEMLOCK=infinity
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=10
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
# Tunables for frank-default-small (batsclamp/Huihui-Qwen3.6-35B-A3B-
|
# Tunables for frank-small (batsclamp/Huihui-Qwen3.6-35B-A3B-
|
||||||
# abliterated-FP8, qwen3_5_moe hybrid MoE, Dankserver, RTX 3090).
|
# abliterated-FP8, qwen3_5_moe hybrid MoE, Dankserver, RTX 3090).
|
||||||
#
|
#
|
||||||
# Runtime: FreeToken v0.1.2 (edge-native MoE serving engine).
|
# Runtime: FreeToken v0.1.2 (edge-native MoE serving engine).
|
||||||
@@ -39,7 +39,7 @@ MODEL_DIR=/home/dank/models/huihui-qwen36-35b-a3b-abliterated-fp8
|
|||||||
FT_VENV=/home/dank/freetoken/.venv
|
FT_VENV=/home/dank/freetoken/.venv
|
||||||
CUDA_HOME_DIR=/home/dank/freetoken/.venv/lib/python3.12/site-packages/nvidia/cu13
|
CUDA_HOME_DIR=/home/dank/freetoken/.venv/lib/python3.12/site-packages/nvidia/cu13
|
||||||
|
|
||||||
ALIAS=frank-default-small
|
ALIAS=frank-small
|
||||||
BIND_ADDR=0.0.0.0
|
BIND_ADDR=0.0.0.0
|
||||||
LISTEN_PORT=7770
|
LISTEN_PORT=7770
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=FreeToken Huihui-Qwen3.6-35B-A3B-abliterated-FP8 qwen3_5_moe hybrid MoE (dankserver, frank-default-small)
|
Description=FreeToken Huihui-Qwen3.6-35B-A3B-abliterated-FP8 qwen3_5_moe hybrid MoE (dankserver, frank-small)
|
||||||
After=network-online.target
|
After=network-online.target
|
||||||
Wants=network-online.target
|
Wants=network-online.target
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ Wants=network-online.target
|
|||||||
Type=simple
|
Type=simple
|
||||||
User=dank
|
User=dank
|
||||||
Group=dank
|
Group=dank
|
||||||
Environment="FRANK_SMALL_ENV_FILE=/home/dank/serverAppConfigs/scripts/frank-default-small.env"
|
Environment="FRANK_SMALL_ENV_FILE=/home/dank/serverAppConfigs/scripts/frank-small.env"
|
||||||
ExecStart=/home/dank/serverAppConfigs/scripts/serve-frank-small.sh
|
ExecStart=/home/dank/serverAppConfigs/scripts/serve-frank-small.sh
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=10
|
RestartSec=10
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Serve kingjones777/Qwen3.8-Flash-Next-ROCmFP4-STRIX-GGUF as
|
# Serve kingjones777/Qwen3.8-Flash-Next-ROCmFP4-STRIX-GGUF as
|
||||||
# frank-default-large via the kingjones30/ROCmFPX llama.cpp runtime on
|
# frank-large via the kingjones30/ROCmFPX llama.cpp runtime on
|
||||||
# Dankclaw (Strix Halo gfx1151, unified memory).
|
# Dankclaw (Strix Halo gfx1151, unified memory).
|
||||||
#
|
#
|
||||||
# Runtime: kingjones30/ROCmFPX (fork of charlie12345/ROCmFPX with the
|
# Runtime: kingjones30/ROCmFPX (fork of charlie12345/ROCmFPX with the
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
ENV_FILE="${FRANK_LARGE_ENV_FILE:-$SCRIPT_DIR/frank-default-large.env}"
|
ENV_FILE="${FRANK_LARGE_ENV_FILE:-$SCRIPT_DIR/frank-large.env}"
|
||||||
if [[ -f "$ENV_FILE" ]]; then
|
if [[ -f "$ENV_FILE" ]]; then
|
||||||
set -a
|
set -a
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
@@ -44,7 +44,7 @@ fi
|
|||||||
: "${MMPROJ_PATH:=/home/dank/models/agentionai-Qwen3.8-Flash-Next-ROCmFP4-FAST/mmproj/mmproj-Qwen3.8-Flash-Next-f16.gguf}"
|
: "${MMPROJ_PATH:=/home/dank/models/agentionai-Qwen3.8-Flash-Next-ROCmFP4-FAST/mmproj/mmproj-Qwen3.8-Flash-Next-f16.gguf}"
|
||||||
: "${CHAT_TEMPLATE_FILE:=$SCRIPT_DIR/chat-template.jinja}"
|
: "${CHAT_TEMPLATE_FILE:=$SCRIPT_DIR/chat-template.jinja}"
|
||||||
: "${CHAT_TEMPLATE_KWARGS:={}}"
|
: "${CHAT_TEMPLATE_KWARGS:={}}"
|
||||||
: "${ALIAS:=frank-default-large}"
|
: "${ALIAS:=frank-large}"
|
||||||
: "${BIND_ADDR:=0.0.0.0}"
|
: "${BIND_ADDR:=0.0.0.0}"
|
||||||
: "${LISTEN_PORT:=7770}"
|
: "${LISTEN_PORT:=7770}"
|
||||||
: "${CTX_SIZE:=401408}"
|
: "${CTX_SIZE:=401408}"
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Serve the FastFlowLM (FLM) sight+sound endpoint — frank-default-sightsound.
|
# Serve the FastFlowLM (FLM) sight+sound endpoint — frank-npu.
|
||||||
#
|
#
|
||||||
# Runs `flm serve <tag>` on the XDNA2 NPU (50 TOPS, Dankclaw). The NPU is a
|
# Runs `flm serve <tag>` on the XDNA2 NPU (50 TOPS, Dankclaw). The NPU is a
|
||||||
# single-lane device: generations serialize in FIFO order, so this is a
|
# single-lane device: generations serialize in FIFO order, so this is a
|
||||||
# background/triage endpoint, not an interactive multi-user chat. The NPU
|
# background/triage endpoint, not an interactive multi-user chat. The NPU
|
||||||
# draws from the unified RAM pool shared with frank-default-large (the iGPU
|
# draws from the unified RAM pool shared with frank-large (the iGPU
|
||||||
# llama.cpp service); see serverAppConfigs-docs/LLM/frank-default-sightsound.md
|
# llama.cpp service); see serverAppConfigs-docs/LLM/frank-npu.md
|
||||||
# for the memory budget and the model-selection tradeoff.
|
# for the memory budget and the model-selection tradeoff.
|
||||||
#
|
#
|
||||||
# NOTE: FLM requires unlimited memlock. The unit sets LimitMEMLOCK=infinity.
|
# NOTE: FLM requires unlimited memlock. The unit sets LimitMEMLOCK=infinity.
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
ENV_FILE="${FLM_SIGHTSOUND_ENV_FILE:-$SCRIPT_DIR/frank-default-sightsound.env}"
|
ENV_FILE="${FRANK_NPU_ENV_FILE:-$SCRIPT_DIR/frank-npu.env}"
|
||||||
if [[ -f "$ENV_FILE" ]]; then
|
if [[ -f "$ENV_FILE" ]]; then
|
||||||
set -a
|
set -a
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Serve batsclamp/Huihui-Qwen3.6-35B-A3B-abliterated-FP8 as
|
# Serve batsclamp/Huihui-Qwen3.6-35B-A3B-abliterated-FP8 as
|
||||||
# frank-default-small via FreeToken on Dankserver (RTX 3090, 60 GB RAM).
|
# frank-small via FreeToken on Dankserver (RTX 3090, 60 GB RAM).
|
||||||
#
|
#
|
||||||
# Runtime: FreeToken v0.1.2 (edge-native MoE serving engine).
|
# Runtime: FreeToken v0.1.2 (edge-native MoE serving engine).
|
||||||
# - Experts live in host RAM; an LRU cache of expert slots is resident
|
# - Experts live in host RAM; an LRU cache of expert slots is resident
|
||||||
@@ -25,12 +25,12 @@
|
|||||||
# via `ft ctl cache --kv N --moe M` (grows KV by shrinking MoE; shrinking
|
# via `ft ctl cache --kv N --moe M` (grows KV by shrinking MoE; shrinking
|
||||||
# KV requires a restart due to the swap-during-rebuild memory cost).
|
# KV requires a restart due to the swap-during-rebuild memory cost).
|
||||||
#
|
#
|
||||||
# Tunables come from frank-default-small.env unless FRANK_SMALL_ENV_FILE
|
# Tunables come from frank-small.env unless FRANK_SMALL_ENV_FILE
|
||||||
# overrides that path.
|
# overrides that path.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
ENV_FILE="${FRANK_SMALL_ENV_FILE:-$SCRIPT_DIR/frank-default-small.env}"
|
ENV_FILE="${FRANK_SMALL_ENV_FILE:-$SCRIPT_DIR/frank-small.env}"
|
||||||
if [[ -f "$ENV_FILE" ]]; then
|
if [[ -f "$ENV_FILE" ]]; then
|
||||||
set -a
|
set -a
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
@@ -40,7 +40,7 @@ fi
|
|||||||
|
|
||||||
# --- defaults (used when the env file does not set them) -----------------
|
# --- defaults (used when the env file does not set them) -----------------
|
||||||
: "${MODEL_DIR:=/home/dank/models/huihui-qwen36-35b-a3b-abliterated-fp8}"
|
: "${MODEL_DIR:=/home/dank/models/huihui-qwen36-35b-a3b-abliterated-fp8}"
|
||||||
: "${ALIAS:=frank-default-small}"
|
: "${ALIAS:=frank-small}"
|
||||||
: "${BIND_ADDR:=0.0.0.0}"
|
: "${BIND_ADDR:=0.0.0.0}"
|
||||||
: "${LISTEN_PORT:=7770}"
|
: "${LISTEN_PORT:=7770}"
|
||||||
: "${FT_VENV:=/home/dank/freetoken/.venv}"
|
: "${FT_VENV:=/home/dank/freetoken/.venv}"
|
||||||
|
|||||||
@@ -160,12 +160,12 @@ for path in "${CHANGED[@]}"; do
|
|||||||
scripts/mount-entropy.sh)
|
scripts/mount-entropy.sh)
|
||||||
add_test tests/mount_entropy.bats
|
add_test tests/mount_entropy.bats
|
||||||
;;
|
;;
|
||||||
scripts/frank-default-large.env|scripts/serve-frank-large.sh)
|
scripts/frank-large.env|scripts/serve-frank-large.sh)
|
||||||
add_test tests/llm_units.bats
|
add_test tests/llm_units.bats
|
||||||
add_test tests/llm_secrets.bats
|
add_test tests/llm_secrets.bats
|
||||||
add_test tests/scripts_syntax.bats
|
add_test tests/scripts_syntax.bats
|
||||||
;;
|
;;
|
||||||
scripts/frank-default-small.env|scripts/serve-frank-small.sh)
|
scripts/frank-small.env|scripts/serve-frank-small.sh)
|
||||||
add_test tests/llm_units.bats
|
add_test tests/llm_units.bats
|
||||||
add_test tests/llm_secrets.bats
|
add_test tests/llm_secrets.bats
|
||||||
add_test tests/scripts_syntax.bats
|
add_test tests/scripts_syntax.bats
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ load helpers
|
|||||||
}
|
}
|
||||||
|
|
||||||
@test "inference restarts are absent from the top-level dispatcher" {
|
@test "inference restarts are absent from the top-level dispatcher" {
|
||||||
! grep -qE 'systemctl .*restart (frank-default-small|frank-default-large)' "$REPO_ROOT/scripts/deploy.sh"
|
! grep -qE 'systemctl .*restart (frank-small|frank-large|frank-npu)' "$REPO_ROOT/scripts/deploy.sh"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "remote runner health-checks an inference endpoint" {
|
@test "remote runner health-checks an inference endpoint" {
|
||||||
|
|||||||
@@ -18,26 +18,26 @@ REMOTE_DEPLOY="$REPO_ROOT/scripts/deploy-remote.sh"
|
|||||||
|
|
||||||
@test "deployment planner maps large-model changes to the large model only" {
|
@test "deployment planner maps large-model changes to the large model only" {
|
||||||
run python3 "$PLANNER" --target dankclaw --paths \
|
run python3 "$PLANNER" --target dankclaw --paths \
|
||||||
scripts/frank-default-large.env scripts/frank-default-large.service
|
scripts/frank-large.env scripts/frank-large.service
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
[ "$output" = "frank-default-large" ]
|
[ "$output" = "frank-large" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "shared chat-template changes map to the selected host's inference service" {
|
@test "shared chat-template changes map to the selected host's inference service" {
|
||||||
run python3 "$PLANNER" --target dankclaw --paths scripts/chat-template.jinja
|
run python3 "$PLANNER" --target dankclaw --paths scripts/chat-template.jinja
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
[ "$output" = "frank-default-large" ]
|
[ "$output" = "frank-large" ]
|
||||||
|
|
||||||
run python3 "$PLANNER" --target dankserver --paths scripts/chat-template.jinja
|
run python3 "$PLANNER" --target dankserver --paths scripts/chat-template.jinja
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
[ "$output" = "frank-default-small" ]
|
[ "$output" = "frank-small" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "deployment planner maps small-model changes to the small model only" {
|
@test "deployment planner maps small-model changes to the small model only" {
|
||||||
run python3 "$PLANNER" --target dankserver --paths \
|
run python3 "$PLANNER" --target dankserver --paths \
|
||||||
scripts/frank-default-small.service
|
scripts/frank-small.service
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
[ "$output" = "frank-default-small" ]
|
[ "$output" = "frank-small" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "documentation-only changes plan no runtime deployment" {
|
@test "documentation-only changes plan no runtime deployment" {
|
||||||
@@ -69,9 +69,9 @@ REMOTE_DEPLOY="$REPO_ROOT/scripts/deploy-remote.sh"
|
|||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
[ "$output" = "hermes" ]
|
[ "$output" = "hermes" ]
|
||||||
|
|
||||||
run python3 "$PLANNER" --target dankclaw --paths scripts/serve-frank-default-npu.sh scripts/frank-default-npu.env
|
run python3 "$PLANNER" --target dankclaw --paths scripts/serve-frank-npu.sh scripts/frank-npu.env
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
[ "$output" = "frank-default-npu" ]
|
[ "$output" = "frank-npu" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "homepage is owned by Dankclaw's consolidated proxy" {
|
@test "homepage is owned by Dankclaw's consolidated proxy" {
|
||||||
@@ -155,7 +155,7 @@ REMOTE_DEPLOY="$REPO_ROOT/scripts/deploy-remote.sh"
|
|||||||
grep -q 'deploy_llm_large' "$REMOTE_DEPLOY"
|
grep -q 'deploy_llm_large' "$REMOTE_DEPLOY"
|
||||||
grep -q 'deploy_llm_small' "$REMOTE_DEPLOY"
|
grep -q 'deploy_llm_small' "$REMOTE_DEPLOY"
|
||||||
grep -q 'deploy_service' "$REMOTE_DEPLOY"
|
grep -q 'deploy_service' "$REMOTE_DEPLOY"
|
||||||
! grep -qE 'for .*frank-default-(small|large)' "$REMOTE_DEPLOY"
|
! grep -qE 'for .*frank-(small|large|npu)-?' "$REMOTE_DEPLOY"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "remote runner rejects services belonging to the other host" {
|
@test "remote runner rejects services belonging to the other host" {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Seam: LLM systemd unit integrity.
|
# Seam: LLM systemd unit integrity.
|
||||||
# Every LLM unit (frank-default-*.service) must point at files that exist in
|
# Every LLM unit (frank-*.service) must point at files that exist in
|
||||||
# this repo. The homepage-status unit is a different pattern (it installs to
|
# this repo. The homepage-status unit is a different pattern (it installs to
|
||||||
# /usr/local/bin and runs from /srv at deploy time) and is not checked here.
|
# /usr/local/bin and runs from /srv at deploy time) and is not checked here.
|
||||||
# The units reference absolute paths on the target checkout
|
# The units reference absolute paths on the target checkout
|
||||||
@@ -50,7 +50,7 @@ unit_repo_path() {
|
|||||||
echo "$bad"
|
echo "$bad"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
done < <(find "$REPO_ROOT/scripts" -name 'frank-default-*.service' -type f | sort)
|
done < <(find "$REPO_ROOT/scripts" -name "frank-*.service" -type f | grep -v AGENTTRASH | sort)
|
||||||
[ "$any" -eq 1 ] || skip "no LLM units yet"
|
[ "$any" -eq 1 ] || skip "no LLM units yet"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ unit_repo_path() {
|
|||||||
echo "unit $(basename "$unit") env file $envfile not in repo"
|
echo "unit $(basename "$unit") env file $envfile not in repo"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
done < <(find "$REPO_ROOT/scripts" -name 'frank-default-*.service' -type f | sort)
|
done < <(find "$REPO_ROOT/scripts" -name "frank-*.service" -type f | grep -v AGENTTRASH | sort)
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "LLM serve scripts exist for every unit" {
|
@test "LLM serve scripts exist for every unit" {
|
||||||
@@ -78,5 +78,5 @@ unit_repo_path() {
|
|||||||
echo "unit $svc: ExecStart script $script not in repo"
|
echo "unit $svc: ExecStart script $script not in repo"
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
done < <(find "$REPO_ROOT/scripts" -name 'frank-default-*.service' -type f | sort)
|
done < <(find "$REPO_ROOT/scripts" -name "frank-*.service" -type f | grep -v AGENTTRASH | sort)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
# The old open-webui was a bare container on dankserver (port 3000) pointing at a
|
# The old open-webui was a bare container on dankserver (port 3000) pointing at a
|
||||||
# dead LLM backend (:9090). This unit stands one up on dankclaw on a free port
|
# dead LLM backend (:9090). This unit stands one up on dankclaw on a free port
|
||||||
# (3005), on the CPU image (dankclaw is CPU-only), wired to the live
|
# (3005), on the CPU image (dankclaw is CPU-only), wired to the live
|
||||||
# llama.cpp backend (192.168.0.143:7770, model frank-default-large).
|
# llama.cpp backend (192.168.0.143:7770, model frank-large).
|
||||||
|
|
||||||
load helpers
|
load helpers
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ QDIR="$REPO_ROOT/dankclaw/open-webui/quadlet"
|
|||||||
# gateway (10.89.3.1) lives in the rootless netns, NOT the host netns
|
# gateway (10.89.3.1) lives in the rootless netns, NOT the host netns
|
||||||
# where llama-server runs -- it refuses. The host's LAN IP reaches it
|
# where llama-server runs -- it refuses. The host's LAN IP reaches it
|
||||||
# through the rootless NAT (verified from the container, 2026-08-22).
|
# through the rootless NAT (verified from the container, 2026-08-22).
|
||||||
# 2026-08-22: frank-default-large moved from :52625 to :7770.
|
# 2026-08-22: frank-large moved from :52625 to :7770.
|
||||||
grep -qE '^Environment=OPENAI_API_BASE_URL=http://192\.168\.0\.143:7770' \
|
grep -qE '^Environment=OPENAI_API_BASE_URL=http://192\.168\.0\.143:7770' \
|
||||||
"$QDIR/open-webui.container" \
|
"$QDIR/open-webui.container" \
|
||||||
|| { echo "open-webui.container must set OPENAI_API_BASE_URL to the LLM at 192.168.0.143:7770"; return 1; }
|
|| { echo "open-webui.container must set OPENAI_API_BASE_URL to the LLM at 192.168.0.143:7770"; return 1; }
|
||||||
|
|||||||
Reference in New Issue
Block a user