feat(frank-zealot): apply the refusal-direction adapter at load
Frank ordered the adapter; this adds it to the shape as one knob and one flag. - `LORA_FILE` / `LORA_SCALE` in the env, `--lora-scaled <file>:<scale>` as ONE argv token so a scale can never reach the engine without its adapter. The rollback follows the mmproj convention exactly: `LORA_FILE=` (explicitly empty) drops the flag entirely, no rebuild, and `LORA_SCALE=0` is the card's own "inert but present" value. - New fetcher `scripts/download-frank-zealot-uncensored-lora.sh`: `-f`, byte count, sha256, `--verify-only`, idempotent. The file is NOT LFS (a plain git object), so the pinned sha is the content hash, not an LFS oid. - The deployer gates on the adapter beside the pack and the projector, and its error names the ADAPTER's fetcher — sending an operator to the bonsai9 script for a 3 MB file is how a payload ships without it. - Seam: path+scale pinned as one token, the scale knob including 0, absence on the empty opt-out, a refusal to boot on a missing adapter, and the env ↔ deployer anti-drift pair extended to LORA_FILE/LLM_ZEALOT_LORA. 454/454. Provenance, stated where it will be read: the adapter's own metadata names `Ternary-Bonsai-2-9B-PTQ1_0.gguf` (3561df7a…) as the pack the direction was fitted against. This endpoint serves the PQ2_0+MTP+Q8_0 packing (c79fcdfa…), which is not that file and is not on this host. The loader matches tensor names, not hashes, so it applies — and build 10777 is the build the card verified on — but the strength is calibrated on a sibling quantization. The proof is therefore the refusal probe against the live endpoint, captured before and after, and not the card's table.
This commit is contained in:
1 parent
6248f02ca2
commit
3eaba57925
5 files changed
+220
-7
No files matched your search
@@ -1463,6 +1463,12 @@ LLM_ZEALOT_RUNTIME="${LLM_ZEALOT_RUNTIME:-/home/dank/GitPackages/llama-prism-b10
|
|||||||
# 868.32 MiB worst-case VRAM (595.29 model + 248.10 compute in the boot ledger)
|
# 868.32 MiB worst-case VRAM (595.29 model + 248.10 compute in the boot ledger)
|
||||||
# lands AFTER the engine's fit check, so it is not inside the q8_0 budget.
|
# lands AFTER the engine's fit check, so it is not inside the q8_0 budget.
|
||||||
LLM_ZEALOT_MMPROJ="${LLM_ZEALOT_MMPROJ:-/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-mmproj-Q8_0.gguf}"
|
LLM_ZEALOT_MMPROJ="${LLM_ZEALOT_MMPROJ:-/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-mmproj-Q8_0.gguf}"
|
||||||
|
# The refusal adapter is part of the payload identity now, so the deployer
|
||||||
|
# checks it beside the other two files — but it has its OWN fetcher, so a
|
||||||
|
# missing adapter must not send the operator to the bonsai9 script. Integrity
|
||||||
|
# (bytes + sha256) is the fetcher's job at download time; this gate only asks
|
||||||
|
# whether the file the env names exists, exactly like the two above.
|
||||||
|
LLM_ZEALOT_LORA="${LLM_ZEALOT_LORA:-/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-Uncensored-LoRA.gguf}"
|
||||||
|
|
||||||
deploy_llm_zealot() {
|
deploy_llm_zealot() {
|
||||||
# Refuse rather than restart-loop: a unit whose runtime or payload is
|
# Refuse rather than restart-loop: a unit whose runtime or payload is
|
||||||
@@ -1484,6 +1490,13 @@ deploy_llm_zealot() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
if [[ ! -f "$LLM_ZEALOT_LORA" ]]; then
|
||||||
|
echo "ERROR: frank-zealot refusal adapter absent at $LLM_ZEALOT_LORA" >&2
|
||||||
|
echo "frank-zealot: run scripts/download-frank-zealot-uncensored-lora.sh first;" >&2
|
||||||
|
echo "frank-zealot: the env names the adapter, so the unit would refuse to boot" >&2
|
||||||
|
echo "frank-zealot: without it — starting the unit anyway is a crash loop." >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
relink_unit frank-zealot
|
relink_unit frank-zealot
|
||||||
run_privileged systemctl daemon-reload
|
run_privileged systemctl daemon-reload
|
||||||
run_privileged systemctl enable frank-zealot.service
|
run_privileged systemctl enable frank-zealot.service
|
||||||
|
|||||||
+101
@@ -0,0 +1,101 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Fetch the refusal-direction adapter that frank-zealot applies at load:
|
||||||
|
# AtomicChat/Ternary-Bonsai-2-9B-Uncensored-LoRA-GGUF — a **3.2 MB rank-1 LoRA**
|
||||||
|
# for prism-ml/Ternary-Bonsai-2-9B, not a checkpoint. Public repo: no auth
|
||||||
|
# header, and never a token on the command line (a Bearer token is
|
||||||
|
# world-readable in /proc/<pid>/cmdline).
|
||||||
|
#
|
||||||
|
# IT IS AN EDIT INSIDE THE COMPUTE GRAPH, NOT A SECOND MODEL. The card: B = -r
|
||||||
|
# (the refusal direction, row 23 of its own probe matrix), A = P^T(s *
|
||||||
|
# H(r^T W_fold)) built from the base pack's folded input basis, applied at every
|
||||||
|
# transformer layer (`target_layers = all`, `sites = 64`), with the embedding
|
||||||
|
# deliberately untouched because an embedding LoRA crashes this fork's graph.
|
||||||
|
# `--lora-scaled <file>:<scale>` is the flag pair: scale 1 is the card's
|
||||||
|
# "held-out refusals 0 %" point, scale 0 is the plain model again.
|
||||||
|
#
|
||||||
|
# THE RUNTIME IS A GATE, NOT A PREFERENCE. The card verified the adapter on
|
||||||
|
# `prism-b10777-e3de715` — the exact build frank-zealot runs — and says older
|
||||||
|
# forks (e.g. `prism-b10709`) refuse these packs with `unsupported
|
||||||
|
# prism.hadamard.version: 2`. The fork is already pinned for the payload's
|
||||||
|
# custom tensor type 142; this adapter adds a second reason it cannot move.
|
||||||
|
#
|
||||||
|
# PROVENANCE ASYMMETRY, STATED HONESTLY. The GGUF's own metadata names the pack
|
||||||
|
# the direction was fitted against:
|
||||||
|
# prism.abliterate.base_gguf = Ternary-Bonsai-2-9B-PTQ1_0.gguf
|
||||||
|
# prism.abliterate.base_sha256 = 3561df7ac7d26a71ffa991ac2db740b10841c3a350aa2676ccd3ff5d428b4e8b
|
||||||
|
# frank-zealot serves the PQ2_0 + MTP + Q8_0-embedding packing (its sha256 is
|
||||||
|
# c79fcdfa…, see download-frank-zealot-bonsai9.sh), which is NOT that file and is
|
||||||
|
# not on this host. The adapter still applies — same tensor names, and the
|
||||||
|
# metadata is provenance rather than a checksum gate — but its strength was
|
||||||
|
# calibrated on a sibling quantization. What proves the effect here is the
|
||||||
|
# behaviour of the endpoint (a refusal probe before and after the swap), not the
|
||||||
|
# metadata and not the card's table, which was measured on PTQ1_0.
|
||||||
|
#
|
||||||
|
# Fresh downloads, no resume; -f/--fail-with-body so an HTTP error is not a
|
||||||
|
# success, then byte count and sha256 (this repo is NOT LFS — the file is a
|
||||||
|
# plain git object, so the sha below is the content hash of the Hub's bytes as
|
||||||
|
# fetched, not an LFS oid). Idempotent: a complete file is skipped.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# scripts/download-frank-zealot-uncensored-lora.sh [DEST_DIR] [--verify-only]
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
DEST=""
|
||||||
|
VERIFY_ONLY=0
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
--verify-only) VERIFY_ONLY=1 ;;
|
||||||
|
*) DEST="$arg" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
DEST="${DEST:-/home/dank/models/Bonsai2-9B-MTP}"
|
||||||
|
|
||||||
|
REPO="AtomicChat/Ternary-Bonsai-2-9B-Uncensored-LoRA-GGUF"
|
||||||
|
# name | bytes | sha256 of the Hub's bytes
|
||||||
|
FILES=(
|
||||||
|
"Ternary-Bonsai-2-9B-Uncensored-LoRA.gguf|3155424|861b9c099fb5cd81438ba85bad30590847c777b1e18112586be7f4f9ae5fb07b"
|
||||||
|
)
|
||||||
|
|
||||||
|
mkdir -p "$DEST"
|
||||||
|
status=0
|
||||||
|
for entry in "${FILES[@]}"; do
|
||||||
|
IFS='|' read -r name size sha <<<"$entry"
|
||||||
|
url="https://huggingface.co/${REPO}/resolve/main/${name}"
|
||||||
|
f="$DEST/$name"
|
||||||
|
have=0
|
||||||
|
if [[ -f "$f" ]] && [[ "$(stat -c%s "$f")" == "$size" ]]; then
|
||||||
|
if sha256sum -c --quiet <(printf '%s %s\n' "$sha" "$f"); then
|
||||||
|
have=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if (( have )); then
|
||||||
|
echo "OK $name"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if (( VERIFY_ONLY )); then
|
||||||
|
echo "MISSING $name"
|
||||||
|
status=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo "FETCHING $name (from $REPO)"
|
||||||
|
tmp="$f.part"
|
||||||
|
curl -fsSL --fail-with-body -o "$tmp" "$url"
|
||||||
|
mv "$tmp" "$f"
|
||||||
|
if [[ "$(stat -c%s "$f")" != "$size" ]]; then
|
||||||
|
echo "SIZE FAIL $name ($(stat -c%s "$f") != $size)"
|
||||||
|
status=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if ! sha256sum -c --quiet <(printf '%s %s\n' "$sha" "$f"); then
|
||||||
|
echo "SHA FAIL $name"
|
||||||
|
status=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo "VERIFIED $name"
|
||||||
|
done
|
||||||
|
if (( status == 0 )); then
|
||||||
|
echo "DOWNLOAD_DONE $DEST"
|
||||||
|
else
|
||||||
|
echo "DOWNLOAD_FAILED $DEST" >&2
|
||||||
|
fi
|
||||||
|
exit "$status"
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
# frank-zealot — llama.cpp (PrismML fork build 10777, CUDA) on the RTX 3090,
|
# frank-zealot — llama.cpp (PrismML fork build 10777, CUDA) on the RTX 3090,
|
||||||
# :7771. Payload: Ternary-Bonsai-2-9B PQ2_0 with the MTP head in the file.
|
# :7771. Payload: Ternary-Bonsai-2-9B PQ2_0 with the MTP head in the file, plus
|
||||||
|
# the refusal-direction adapter applied at load.
|
||||||
#
|
#
|
||||||
# ONE OWNER: shape, payload identity, eras, laws and every measured number
|
# ONE OWNER: shape, payload identity, eras, laws and every measured number
|
||||||
# live in serverAppConfigs-docs/LLM/frank-zealot.md. This file carries the
|
# live in serverAppConfigs-docs/LLM/frank-zealot.md. This file carries the
|
||||||
@@ -13,6 +14,17 @@ MODEL_FILE=/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-PQ2_0-MTP-Q8_0.g
|
|||||||
# Q8_0 IS MANDATORY: the publisher states the BF16 tower can crash llama-server
|
# Q8_0 IS MANDATORY: the publisher states the BF16 tower can crash llama-server
|
||||||
# under concurrent image requests, which is exactly --parallel 3.
|
# under concurrent image requests, which is exactly --parallel 3.
|
||||||
MMPROJ_FILE=/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-mmproj-Q8_0.gguf
|
MMPROJ_FILE=/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-mmproj-Q8_0.gguf
|
||||||
|
# Refusal-direction adapter (a rank-1 LoRA, 3.2 MB) applied at load; it edits
|
||||||
|
# the compute graph, it is not a second model. Scale 1 is the card's "held-out
|
||||||
|
# refusals 0 %" point. LORA_FILE="" is the documented opt-out — the plain pack
|
||||||
|
# again, no rebuild — and LORA_SCALE=0 is the same result through the flag.
|
||||||
|
# PROVENANCE ASYMMETRY: the adapter's own prism.abliterate.base_gguf names
|
||||||
|
# Ternary-Bonsai-2-9B-PTQ1_0.gguf as the pack its direction was fitted against,
|
||||||
|
# which is NOT this packing and is not on this host. The tensor names match, so
|
||||||
|
# it applies; the strength was calibrated on a sibling quantization, so the
|
||||||
|
# effect is proven by the endpoint's behaviour, never by the metadata.
|
||||||
|
LORA_FILE=/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-Uncensored-LoRA.gguf
|
||||||
|
LORA_SCALE=1
|
||||||
# Served id — the harness/family name, not a fact about the payload.
|
# Served id — the harness/family name, not a fact about the payload.
|
||||||
# Id-keyed consumers: OpenWebUI (model row, access_grant, api_configs), models.yml.
|
# Id-keyed consumers: OpenWebUI (model row, access_grant, api_configs), models.yml.
|
||||||
ALIAS=frank-zealot
|
ALIAS=frank-zealot
|
||||||
|
|||||||
@@ -33,6 +33,19 @@
|
|||||||
# what gives this endpoint eyes; MMPROJ_FILE="" is the documented text-only
|
# what gives this endpoint eyes; MMPROJ_FILE="" is the documented text-only
|
||||||
# opt-out.
|
# opt-out.
|
||||||
#
|
#
|
||||||
|
# A refusal-direction adapter rides on top of the pack (Frank, 2026-10-19):
|
||||||
|
# AtomicChat's rank-1 LoRA, applied at load by --lora-scaled. It is an edit
|
||||||
|
# inside the compute graph, not a second model — B = -r (the refusal direction),
|
||||||
|
# A built from the base pack's folded input basis, every transformer layer, the
|
||||||
|
# embedding deliberately untouched because an embedding LoRA crashes this fork's
|
||||||
|
# graph. The card verified it on prism-b10777-e3de715 — the build pinned here —
|
||||||
|
# and says older forks refuse the pack outright (`unsupported
|
||||||
|
# prism.hadamard.version: 2`), which makes the runtime lock doubly load-bearing.
|
||||||
|
# Its own metadata names the PTQ1_0 packing as the pack the direction was fitted
|
||||||
|
# against, so what proves the effect is a refusal probe against the live
|
||||||
|
# endpoint, not the metadata and not the card's table. LORA_FILE="" drops the
|
||||||
|
# flag and the endpoint is the plain pack again.
|
||||||
|
#
|
||||||
# Speculative decoding ships ON (Frank, 2026-10-19). The head is IN the file and
|
# Speculative decoding ships ON (Frank, 2026-10-19). The head is IN the file and
|
||||||
# accepts well (0.798/0.617 per position, mean length 2.41, measured 2026-10-18);
|
# accepts well (0.798/0.617 per position, mean length 2.41, measured 2026-10-18);
|
||||||
# what made it lose that evening was the bill, not the drafts — the draft context
|
# what made it lose that evening was the bill, not the drafts — the draft context
|
||||||
@@ -136,6 +149,13 @@ fi
|
|||||||
# Vision projector. No colon on purpose: an explicitly empty value means
|
# Vision projector. No colon on purpose: an explicitly empty value means
|
||||||
# "text-only, on purpose" and must NOT be replaced by the default path.
|
# "text-only, on purpose" and must NOT be replaced by the default path.
|
||||||
: "${MMPROJ_FILE=/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-mmproj-Q8_0.gguf}"
|
: "${MMPROJ_FILE=/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-mmproj-Q8_0.gguf}"
|
||||||
|
# Refusal adapter. No colon on purpose, the same convention as MMPROJ_FILE: an
|
||||||
|
# explicitly empty LORA_FILE is the documented opt-out (the plain pack again)
|
||||||
|
# and must NOT be replaced by the default path. The scale travels INSIDE the
|
||||||
|
# same argv token as the file, so LORA_SCALE only matters while LORA_FILE names
|
||||||
|
# something; 0 is the card's "switch it off without touching the file" value.
|
||||||
|
: "${LORA_FILE=/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-Uncensored-LoRA.gguf}"
|
||||||
|
: "${LORA_SCALE:=1}"
|
||||||
|
|
||||||
# Fail loudly rather than half-loading: a missing file is a download that
|
# Fail loudly rather than half-loading: a missing file is a download that
|
||||||
# has not finished, and Restart=always would turn it into a crash loop that
|
# has not finished, and Restart=always would turn it into a crash loop that
|
||||||
@@ -149,6 +169,17 @@ if [[ -n "$MMPROJ_FILE" ]]; then
|
|||||||
EXTRA_ARGS+=(--mmproj "$MMPROJ_FILE")
|
EXTRA_ARGS+=(--mmproj "$MMPROJ_FILE")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# The adapter reaches the engine as ONE token — --lora-scaled <file>:<scale> —
|
||||||
|
# so a scale can never arrive without its file. It is applied once, at load;
|
||||||
|
# nothing here hot-swaps it (--lora-init-without-apply plus POST /lora-adapters
|
||||||
|
# is that shape, and a process holding three conversations is not the place to
|
||||||
|
# re-parameterise weights mid-flight). A missing file is a fetch that never
|
||||||
|
# finished, so refuse rather than let Restart=always loop on it.
|
||||||
|
if [[ -n "$LORA_FILE" ]]; then
|
||||||
|
[[ -e "$LORA_FILE" ]] || { echo "frank-zealot: missing $LORA_FILE" >&2; exit 1; }
|
||||||
|
EXTRA_ARGS+=(--lora-scaled "${LORA_FILE}:${LORA_SCALE}")
|
||||||
|
fi
|
||||||
|
|
||||||
# Prometheus scraping is opt-IN in llama.cpp: without --metrics the server
|
# Prometheus scraping is opt-IN in llama.cpp: without --metrics the server
|
||||||
# answers 501 on /metrics, and the fleet scrape then reports the endpoint DOWN.
|
# answers 501 on /metrics, and the fleet scrape then reports the endpoint DOWN.
|
||||||
if [[ "$METRICS" = "1" ]]; then
|
if [[ "$METRICS" = "1" ]]; then
|
||||||
|
|||||||
@@ -12,7 +12,10 @@
|
|||||||
# pool (4,096 B/position, 2,352.00 MiB here), and the 786,432 pool this shape
|
# pool (4,096 B/position, 2,352.00 MiB here), and the 786,432 pool this shape
|
||||||
# replaced cannot carry a drafter at any dtype inside the 24,123 MiB the driver
|
# replaced cannot carry a drafter at any dtype inside the 24,123 MiB the driver
|
||||||
# leaves addressable. The publisher's own Q8_0 vision projector rides along (the
|
# leaves addressable. The publisher's own Q8_0 vision projector rides along (the
|
||||||
# BF16 one can crash on concurrent images). Log
|
# BF16 one can crash on concurrent images). The payload also carries a
|
||||||
|
# REFUSAL-DIRECTION ADAPTER: a rank-1 LoRA applied at load, so the seam pins the
|
||||||
|
# --lora-scaled token (path and scale together), the scale knob, and the
|
||||||
|
# empty-LORA_FILE opt-out.
|
||||||
# This seam runs the serve script against a stub engine and asserts on the
|
# This seam runs the serve script against a stub engine and asserts on the
|
||||||
# argv it actually execs, so what is pinned is the command the operator gets.
|
# argv it actually execs, so what is pinned is the command the operator gets.
|
||||||
|
|
||||||
@@ -39,8 +42,9 @@ STUB
|
|||||||
# (the env) instead of silently forking the test's filename constants.
|
# (the env) instead of silently forking the test's filename constants.
|
||||||
MODEL_STUB="$(basename "$(sed -nE 's/^MODEL_FILE=(.+)$/\1/p' "$ENV_FILE")")"
|
MODEL_STUB="$(basename "$(sed -nE 's/^MODEL_FILE=(.+)$/\1/p' "$ENV_FILE")")"
|
||||||
MM_STUB="$(basename "$(sed -nE 's/^MMPROJ_FILE=(.+)$/\1/p' "$ENV_FILE")")"
|
MM_STUB="$(basename "$(sed -nE 's/^MMPROJ_FILE=(.+)$/\1/p' "$ENV_FILE")")"
|
||||||
|
LORA_STUB="$(basename "$(sed -nE 's/^LORA_FILE=(.+)$/\1/p' "$ENV_FILE")")"
|
||||||
DRAFT_STUB="draft-assistant.gguf"
|
DRAFT_STUB="draft-assistant.gguf"
|
||||||
touch "$MODEL_DIR/$MODEL_STUB" "$MODEL_DIR/$MM_STUB" "$MODEL_DIR/$DRAFT_STUB"
|
touch "$MODEL_DIR/$MODEL_STUB" "$MODEL_DIR/$MM_STUB" "$MODEL_DIR/$LORA_STUB" "$MODEL_DIR/$DRAFT_STUB"
|
||||||
}
|
}
|
||||||
|
|
||||||
teardown() {
|
teardown() {
|
||||||
@@ -69,6 +73,8 @@ SPEC_DRAFT_N_MAX=$(sed -nE 's/^SPEC_DRAFT_N_MAX=([0-9]+)$/\1/p' "$ENV_FILE")
|
|||||||
VERBOSITY=$(sed -nE 's/^VERBOSITY=([0-9]+)$/\1/p' "$ENV_FILE")
|
VERBOSITY=$(sed -nE 's/^VERBOSITY=([0-9]+)$/\1/p' "$ENV_FILE")
|
||||||
METRICS=$(sed -nE 's/^METRICS=([0-9]+)$/\1/p' "$ENV_FILE")
|
METRICS=$(sed -nE 's/^METRICS=([0-9]+)$/\1/p' "$ENV_FILE")
|
||||||
NGL=$(sed -nE 's/^NGL=([0-9]+)$/\1/p' "$ENV_FILE")
|
NGL=$(sed -nE 's/^NGL=([0-9]+)$/\1/p' "$ENV_FILE")
|
||||||
|
LORA_FILE=$MODEL_DIR/$LORA_STUB
|
||||||
|
LORA_SCALE=$(sed -nE 's/^LORA_SCALE=(.+)$/\1/p' "$ENV_FILE")
|
||||||
EOF
|
EOF
|
||||||
run env FRANK_ZEALOT_ENV_FILE="$envf" nvidia-modprobe=true bash "$SERVE"
|
run env FRANK_ZEALOT_ENV_FILE="$envf" nvidia-modprobe=true bash "$SERVE"
|
||||||
}
|
}
|
||||||
@@ -117,7 +123,7 @@ run_stage() {
|
|||||||
grep -q 'FRANK_ZEALOT_ENV_FILE=/home/dank/serverAppConfigs/scripts/frank-zealot.env' "$UNIT"
|
grep -q 'FRANK_ZEALOT_ENV_FILE=/home/dank/serverAppConfigs/scripts/frank-zealot.env' "$UNIT"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "the shipped env points at the fork runtime and the Bonsai-2 9B MTP pair" {
|
@test "the shipped env points at the fork runtime, the MTP pair and the refusal adapter" {
|
||||||
# The payload path IS the endpoint's identity, and the runtime is part of
|
# The payload path IS the endpoint's identity, and the runtime is part of
|
||||||
# it here: the file's custom tensor type 142 + prism.hadamard.* metadata
|
# it here: the file's custom tensor type 142 + prism.hadamard.* metadata
|
||||||
# make the PrismML build the only loader, and this build must be >= b10776
|
# make the PrismML build the only loader, and this build must be >= b10776
|
||||||
@@ -127,6 +133,7 @@ run_stage() {
|
|||||||
grep -qE '^LLAMA_BIN=/home/dank/GitPackages/llama-prism-b10777/llama-server$' "$ENV_FILE"
|
grep -qE '^LLAMA_BIN=/home/dank/GitPackages/llama-prism-b10777/llama-server$' "$ENV_FILE"
|
||||||
grep -qE '^MODEL_FILE=/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-PQ2_0-MTP-Q8_0\.gguf$' "$ENV_FILE"
|
grep -qE '^MODEL_FILE=/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-PQ2_0-MTP-Q8_0\.gguf$' "$ENV_FILE"
|
||||||
grep -qE '^MMPROJ_FILE=/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-mmproj-Q8_0\.gguf$' "$ENV_FILE"
|
grep -qE '^MMPROJ_FILE=/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-mmproj-Q8_0\.gguf$' "$ENV_FILE"
|
||||||
|
grep -qE '^LORA_FILE=/home/dank/models/Bonsai2-9B-MTP/Ternary-Bonsai-2-9B-Uncensored-LoRA\.gguf$' "$ENV_FILE"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "the deployer gates on exactly the payload paths the env file ships" {
|
@test "the deployer gates on exactly the payload paths the env file ships" {
|
||||||
@@ -135,7 +142,7 @@ run_stage() {
|
|||||||
# would be gating on a file nobody reads — and a missing projector would
|
# would be gating on a file nobody reads — and a missing projector would
|
||||||
# ship a blind endpoint.
|
# ship a blind endpoint.
|
||||||
local env_v dep_v path pair
|
local env_v dep_v path pair
|
||||||
for pair in "MODEL_FILE LLM_ZEALOT_MODEL_FILE" "MMPROJ_FILE LLM_ZEALOT_MMPROJ"; do
|
for pair in "MODEL_FILE LLM_ZEALOT_MODEL_FILE" "MMPROJ_FILE LLM_ZEALOT_MMPROJ" "LORA_FILE LLM_ZEALOT_LORA"; do
|
||||||
env_v="${pair%% *}"
|
env_v="${pair%% *}"
|
||||||
dep_v="${pair##* }"
|
dep_v="${pair##* }"
|
||||||
path="$(sed -nE "s/^${env_v}=(.+)$/\1/p" "$ENV_FILE")"
|
path="$(sed -nE "s/^${env_v}=(.+)$/\1/p" "$ENV_FILE")"
|
||||||
@@ -367,6 +374,45 @@ run_stage() {
|
|||||||
! grep -qxF -- '--mmproj' <<<"$output"
|
! grep -qxF -- '--mmproj' <<<"$output"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@test "the refusal adapter reaches the engine as path and scale in ONE token" {
|
||||||
|
# --lora-scaled takes FNAME:SCALE as a single argument, so the seam pins the
|
||||||
|
# whole token. An adapter that reaches the engine without its scale — or a
|
||||||
|
# scale without its adapter — is a different payload than the one the env
|
||||||
|
# file describes, and nothing else would notice.
|
||||||
|
serve_argv
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
local scale
|
||||||
|
scale="$(sed -nE 's/^LORA_SCALE=(.+)$/\1/p' "$ENV_FILE")"
|
||||||
|
[ "$(argv_value --lora-scaled)" = "$MODEL_DIR/$LORA_STUB:$scale" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "the scale knob rides inside the token, including the card's off value" {
|
||||||
|
# Distinctive values first: proof the flag is wired to the env and not
|
||||||
|
# merely to the script's default. Scale 0 is the card's second mode — the
|
||||||
|
# direction present but inert — so the endpoint can be neutered without
|
||||||
|
# deleting a file or rebuilding anything.
|
||||||
|
serve_argv
|
||||||
|
{ echo 'LORA_SCALE=0'; } >> "$STAGE/test.env"
|
||||||
|
run_stage
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[ "$(argv_value --lora-scaled)" = "$MODEL_DIR/$LORA_STUB:0" ]
|
||||||
|
|
||||||
|
sed -i 's|^LORA_SCALE=.*|LORA_SCALE=0.75|' "$STAGE/test.env"
|
||||||
|
run_stage
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
[ "$(argv_value --lora-scaled)" = "$MODEL_DIR/$LORA_STUB:0.75" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
@test "LORA_FILE empty opts the adapter out and leaves no trace in the argv" {
|
||||||
|
# The rollback is ABSENCE of the flag: an empty argument would have the
|
||||||
|
# engine open "" and die at load, which is the failure this seam forbids.
|
||||||
|
serve_argv
|
||||||
|
sed -i 's|^LORA_FILE=.*|LORA_FILE=|' "$STAGE/test.env"
|
||||||
|
run_stage
|
||||||
|
[ "$status" -eq 0 ]
|
||||||
|
! grep -qxF -- '--lora-scaled' <<<"$output"
|
||||||
|
}
|
||||||
|
|
||||||
@test "the card sampler's only non-metadata term reaches the argv" {
|
@test "the card sampler's only non-metadata term reaches the argv" {
|
||||||
# general.sampling.* (temperature / top_p / top_k / min_p / repeat_penalty)
|
# general.sampling.* (temperature / top_p / top_k / min_p / repeat_penalty)
|
||||||
# rides in the checkpoint and the engine reads it itself; presence penalty
|
# rides in the checkpoint and the engine reads it itself; presence penalty
|
||||||
@@ -406,23 +452,33 @@ run_stage() {
|
|||||||
grep -qxF -- '--jinja' <<<"$output"
|
grep -qxF -- '--jinja' <<<"$output"
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "the serve script refuses a missing runtime, GGUF or projector" {
|
@test "the serve script refuses a missing runtime, GGUF, projector or adapter" {
|
||||||
rm -f "$MODEL_DIR/$MM_STUB"
|
rm -f "$MODEL_DIR/$MM_STUB"
|
||||||
serve_argv
|
serve_argv
|
||||||
[ "$status" -ne 0 ]
|
[ "$status" -ne 0 ]
|
||||||
[[ "$output" == *"frank-zealot: missing"* ]]
|
[[ "$output" == *"frank-zealot: missing"* ]]
|
||||||
|
|
||||||
|
# The adapter is payload: a fetch that stopped short must not boot a
|
||||||
|
# silently-plain endpoint, and Restart=always would loop on the missing
|
||||||
|
# file until somebody reads the name in the log.
|
||||||
|
touch "$MODEL_DIR/$MM_STUB"
|
||||||
|
rm -f "$MODEL_DIR/$LORA_STUB"
|
||||||
|
serve_argv
|
||||||
|
[ "$status" -ne 0 ]
|
||||||
|
[[ "$output" == *"frank-zealot: missing $MODEL_DIR/$LORA_STUB"* ]]
|
||||||
|
|
||||||
rm -f "$RUNTIME_DIR/bin/llama-server"
|
rm -f "$RUNTIME_DIR/bin/llama-server"
|
||||||
serve_argv
|
serve_argv
|
||||||
[ "$status" -ne 0 ]
|
[ "$status" -ne 0 ]
|
||||||
[[ "$output" == *"frank-zealot: missing"* ]]
|
[[ "$output" == *"frank-zealot: missing"* ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "the deploy handler gates on binary, GGUF and projector, then MainPID-hardens health" {
|
@test "the deploy handler gates on binary, GGUF, projector and adapter, then MainPID-hardens health" {
|
||||||
grep -q 'deploy_llm_zealot' "$REMOTE_DEPLOY"
|
grep -q 'deploy_llm_zealot' "$REMOTE_DEPLOY"
|
||||||
grep -q 'LLM_ZEALOT_RUNTIME' "$REMOTE_DEPLOY"
|
grep -q 'LLM_ZEALOT_RUNTIME' "$REMOTE_DEPLOY"
|
||||||
grep -q 'LLM_ZEALOT_MODEL_FILE' "$REMOTE_DEPLOY"
|
grep -q 'LLM_ZEALOT_MODEL_FILE' "$REMOTE_DEPLOY"
|
||||||
grep -q 'LLM_ZEALOT_MMPROJ' "$REMOTE_DEPLOY"
|
grep -q 'LLM_ZEALOT_MMPROJ' "$REMOTE_DEPLOY"
|
||||||
|
grep -q 'LLM_ZEALOT_LORA' "$REMOTE_DEPLOY"
|
||||||
grep -q 'relink_unit frank-zealot' "$REMOTE_DEPLOY"
|
grep -q 'relink_unit frank-zealot' "$REMOTE_DEPLOY"
|
||||||
grep -q 'systemctl enable frank-zealot.service' "$REMOTE_DEPLOY"
|
grep -q 'systemctl enable frank-zealot.service' "$REMOTE_DEPLOY"
|
||||||
grep -q '127.0.0.1:7771/health' "$REMOTE_DEPLOY"
|
grep -q '127.0.0.1:7771/health' "$REMOTE_DEPLOY"
|
||||||
|
|||||||
Reference in new issue
Block a user