#!/usr/bin/env bash # Serve ajgazin/Swift-1.5-Qwen3.8-27B-Uncensored-Dynamic-MTP-GGUF # (RCO-IQ3_XXS, **MTP head in the file**) as frank-small on Dankclaw's # RTX 3090 via llama.cpp (master build, CUDA sm_86). # # 2026-10-06 (Frank): TWO 131,072 conversations (262144 / 2) at the 128k # cap, ubatch 512, and MTP BACK ON (draft-mtp, depth 3 — the payload is # 1.56 GiB lighter than the IQ3_S-mtp it replaced, which is what funds # the draft ctx plus the second slot; ngram stays skipped — on a qwen35 # hybrid it disables recurrent-state rollback). The q8_0 KV contract # (FP8 class) is unchanged; the per-tensor flags stay explicit either # way. # # Architecture: qwen35 hybrid — 64 real layers, 16 full-attention + 48 # Gated DeltaNet (full_attention_interval 4), native 262144 window, plus # the blk.64 MTP head (nextn_predict_layers=1). KV lives only in the 16 # attention layers (34 KiB/token at q8_0); the DeltaNet state is per-slot # fixed size. # Vision comes from the projector file (the GGUF carries no vision # tensors; the publisher SHIPS mmproj-BF16.gguf in the same repo), so # --mmproj is what gives this endpoint eyes; MMPROJ_FILE="" is the # documented text-only opt-out. # # Sampling: llama.cpp takes it per request (the fleet harness sends its # recipe from models.yml); greedy is the harness default. # # Tunables come from frank-small.env unless FRANK_SMALL_ENV_FILE overrides. set -euo pipefail SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" ENV_FILE="${FRANK_SMALL_ENV_FILE:-$SCRIPT_DIR/frank-small.env}" if [[ -f "$ENV_FILE" ]]; then set -a # shellcheck disable=SC1090 source "$ENV_FILE" set +a fi # --- defaults (used when the env file does not set them) ------------------- : "${LLAMA_BIN:=/home/dank/GitPackages/llama-master/build-cuda/bin/llama-server}" : "${MODEL_FILE:=/home/dank/models/Swift15-UncIQ3XXS/Swift-1.5-Qwen3.8-27B-Uncensored-Dynamic-MTP-RCO-IQ3_XXS.gguf}" : "${ALIAS:=frank-small}" : "${BIND_ADDR:=0.0.0.0}" : "${LISTEN_PORT:=7771}" # ctx-size is the POOL llama.cpp divides across slots: 262144 / 2 gives # TWO 131,072 conversations — Frank's 128k cap each. 2026-10-06 (Frank): # drop MTP, drop ubatch to 512, take two slots; the fit is tight by his # explicit order (frank-small.env carries the arithmetic and the floor # violation). : "${CTX_SIZE:=262144}" : "${PARALLEL:=2}" # Compute-buffer geometry. Ubatch is a prefill knob (decode never moves). # Frank's 2026-10-06 tight-fit order ships 4096/512 (claws back ~0.3 GiB # toward the second slot); ubatch 1024 is the first A/B back if a future # boot lands with headroom (a miss fails loud at graph capture). The # logical batch is VRAM- and throughput-neutral at a fixed ubatch. : "${BATCH_SIZE:=4096}" : "${UBATCH_SIZE:=512}" # KV at FP8 class = q8_0 on llama.cpp (1.0625 B/elem => 8.5 effective bits; # there is no true fp8 KV dtype). Explicit either way so the contract is # visible in the argv. : "${CACHE_TYPE_K:=q8_0}" : "${CACHE_TYPE_V:=q8_0}" # Speculative decoding is ON by default (Frank, 2026-10-06 evening): # draft-mtp against the head that is IN the file. SPEC_TYPE none strips # BOTH speculative flags (flags move as a set) — a no-spec baseline must # not carry half a spec pair. : "${SPEC_TYPE:=draft-mtp}" : "${SPEC_DRAFT_N_MAX:=3}" : "${NGL:=99}" # Vision projector. No colon on purpose: an explicitly empty value means # "text-only, on purpose" and must NOT be replaced by the default path. : "${MMPROJ_FILE=/home/dank/models/Swift15-UncIQ3XXS/mmproj-BF16.gguf}" # 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 # reads like a runtime fault. for path in "$LLAMA_BIN" "$MODEL_FILE"; do [[ -e "$path" ]] || { echo "frank-small: missing $path" >&2; exit 1; } done EXTRA_ARGS=() if [[ -n "$MMPROJ_FILE" ]]; then [[ -e "$MMPROJ_FILE" ]] || { echo "frank-small: missing $MMPROJ_FILE" >&2; exit 1; } EXTRA_ARGS+=(--mmproj "$MMPROJ_FILE") fi # Speculative flags move as a set: they reach the argv ONLY when a drafter # is named. SPEC_TYPE=none (the shipped contract) strips both — a no-spec # baseline must not carry half a spec pair. if [[ -n "$SPEC_TYPE" && "$SPEC_TYPE" != "none" ]]; then EXTRA_ARGS+=(--spec-type "$SPEC_TYPE" --spec-draft-n-max "$SPEC_DRAFT_N_MAX") fi # The UVM device node is created lazily by nvidia-modprobe on the first CUDA # open after boot; make sure it exists before the server needs it. nvidia-modprobe -u -c=0 2>/dev/null || true # Flash attention stays pinned on: it is REQUIRED for quantized V (q8_0), # and the build carries GGML_CUDA_FA_ALL_QUANTS=ON (since 2026-09-17), so # the q8_0 KV contract in frank-small.env is a real path — without this # flag or that build option the engine silently falls back and the # contract becomes a lie. ARGS=( --model "$MODEL_FILE" --alias "$ALIAS" --host "$BIND_ADDR" --port "$LISTEN_PORT" --ctx-size "$CTX_SIZE" --parallel "$PARALLEL" --batch-size "$BATCH_SIZE" --ubatch-size "$UBATCH_SIZE" --n-gpu-layers "$NGL" --flash-attn on --cache-type-k "$CACHE_TYPE_K" --cache-type-v "$CACHE_TYPE_V" --jinja --reasoning auto --reasoning-format deepseek ) exec "$LLAMA_BIN" "${ARGS[@]}" ${EXTRA_ARGS[@]+"${EXTRA_ARGS[@]}"}