8.6 KiB
8.6 KiB
name, description
| name | description |
|---|---|
| llamacpp-endpoint-model-swap | Swap the model on a dank-fleet llama.cpp endpoint: fetch, runtime-door census, env edit, deploy through git, rewrite the bats seam, sweep every live-path straggler, verify VRAM with the engine's own numbers. |
llama.cpp endpoint model swap (dank fleet)
Use when replacing the model/shape on a llama.cpp endpoint (frank-zealot on the RTX 3090). The engine's boot numbers are the verdict — do NOT commit to a feasibility verdict from head math; boot it and read nvidia-smi.
Sequence
- Runtime door BEFORE anything else. Histogram the GGUF's tensor types and metadata (one python range-read of the KV section): a custom type (e.g. PQ2_0 = GGML type 142 +
prism.hadamard.*) means the vendor/fork build is FORCED, not chosen — stock llama.cpp refuses it at load. Record the build identity (path, build number, commit, sha256) in the env comment; a--helpcensus on that binary is what settles flag questions (this fleet's builds have NO fp8 KV; q8_0 is the "FP8 class"). NEVERgrep -c <archname>on the packed binary to check arch support — it returns 0 for every arch. - Geometry first, from the loaded model's own log (
--log-verbosity 4, or the HFconfig.jsonundertext_configfor multimodal): layers,n_head_kv(an ARRAY — per-layer), head_dim,sliding_window_pattern,n_swa,attention_k_eq_v. KV scales only with full-attention layers; sliding layers cost a fixed ring; recurrent/linear layers (Gated DeltaNet) bill a fixed state per SLOT (~150 MiB measured), invisible to pool arithmetic. Single-value HF fields lie about per-layer heterogeneity. - Fit the KV rate law to the engine, not to arithmetic. One boot at
-lv 4printsllama_kv_cache/sched_reserveMiB lines. Master 5fc4f3c law: bytes/elem = (K + V) x2 when the file declaresattention_k_eq_v. Full cache = n_full x n_head_kv x head_dim x rate x ctx. If your formula disagrees with the printed MiB, your law is wrong. - Price the KV dtype by BOOTING the arms, at the target window. f16 may simply OOM (
cudaMalloc failedafter the engine's own fit line names the MiB it wanted); q8_0 may be the only pair that funds 2 x 200,704; q4_0 is the fallback rung. Record every arm's used/free. The mmproj lands AFTER the engine's fit projection (projected fit < settled VRAM by ~1.5x the projector file size) — quote both numbers. - Fetch with
-f+ byte-count + sha256 check into/home/dank/models/<name>/;--verify-onlymode for re-census. - Edit the repo trio (
scripts/serve-<svc>.sh,scripts/<svc>.env,~/.omp/agent/models.yml). Use the serve script's OWN variable names (CACHE_TYPE_K/CACHE_TYPE_V,BIND_ADDR,NGL) — an invented name is silently swallowed by: "${VAR:=default}"and the arm boots the DEFAULT (cost a whole trial window: aKV_CACHE_TYPEscratch env booted f16 and OOMed while reading as a model fault). Sweep the script's DEFAULTS to the new payload too: a defaulted run must land on the shipped shape, never the retired one. Spec flags move as a SET (SPEC_TYPE=nonestrips--spec-typeAND--spec-draft-*); MTP is a property of the FILE (nonextntensors = no drafter, ever).models.ymlcontextWindow= per-slot window (CTX_SIZE/PARALLEL); recomputemaxTokensfor the compaction clampmin(maxTokens, ctx - estimate - 4096). Check the payload's own template: if it readsreasoning_effort, thereasoningEffortMapfold becomes LOAD-BEARING (an unmapped level is a 500 naming Jinja, not the model) and quote the file'sgeneral.sampling.*trio inextraBody. - Rewrite the bats seam in the same commit (
tests/<svc>_unit.bats): payload trio paths, slot geometry, spec state, batch pair, verbosity, mmproj opt-out, reasoning flags — argv-asserted against the stub engine; where the contract is a repo value (batch pair, verbosity, KV dtype) assert argv == env value so a retune moves one file and a wrong-name env edit cannot pass silently. - Trial window protocol (when the shape is unproven on the card): stop the unit (trap-guarded
systemctl startrestore in the scratch script), run the arm census + behavior probes as a DETACHED script writing to/home/dank/logs/<name>.out, then before touching production CENSUS the live state:systemctl is-active,ss -ltnp | grep <port>,pgrep -x llama-server,nvidia-smi. A scratch server orphaned by a client-side timeout holds the whole card and will OOM the real boot — kill by PID (neverpkill -f llama-server). A trap restore can race your manual kill; read the script's ownRESTORElog line before assuming who did what. - Deploy through git (no direct remote edits): commit atomically on the worktree branch,
git fetch && git rebase origin/main(log.md conflicts at EOF are two waves appending — keep both), push branch (--force-with-leaseafter a rebase), then in the MAIN checkoutgit pull --ff-only+git merge --ff-only <branch>+git push origin main, thenscripts/deploy.sh <host> --service <svc>(--serviceis REPEATABLE — name the homepage too when cards changed, or the target ships the model without its docs). Adeploy.shwith no--serviceis a fleet-wide drain: never. - Verify the engine, not your math:
systemctl is-active/is-enabled+ the newDescription, the journal fit/KV/buffer ledger (projected to use N,KV buffer size,n_ctx_seq,n_slots),/v1/modelsserved alias (radiance-style echo does not apply to llama.cpp, but the alias is still the honest check),nvidia-smisettled, then live probes through the REAL request shape the harness sends (exact-instruction chat +reasoning_content,tool_callsJSON args, solid-colorimage_url>=256 px expecting the exact word,timings.predicted_per_second). Never report the FIRST request after a boot (warmup artifact). Push, and record numbers in the env comment + runbook. - Cutover every consumer, same branch: AGENTS.md (topology row,
### <svc>section, Model Config note, runbook index ACTIVE + RETIRED rows); the new docs page MUST be linked from the TOP-LEVELserverAppConfigs-docs/index.md(thedocs_completenessseam fails otherwise, not fromLLM/index.md);shared/homepage/services.json+docs.html(model link, spec line, rate, and the WARNING — a censored base breaks the "common uncensored text" equality inhomepage_config.bats, so re-key the test's premise too);serverAppConfigs-docs/Dankclaw/OpenWebUI.md+ the livemodelrowmeta.description(live DB state: snapshotwebui.db.bak-<date><letter>, UPDATE via host python3 over ssh; do NOT restartopen-webuifor a cosmetic string — it logs every family session out).
Gotchas
- A "we can rebuild the fork ourselves for provenance" claim needs the source tree AT the vendor build's commit — check
git -C <src> log --oneline -1first. A fork checkout at branch HEAD (prismat0082ac2) is NOT the vendor build (2459f68b5), so the rebuild produces a different binary, not the verified one. Also: if the vendor binary already demonstrates the requirement (KV dtype buffer math in the ledger + live probes), a rebuild buys no behavior change — offer it explicitly as provenance hardening, never do it silently. - A systemd restart reporting
inactivein the first seconds is usually model-load time; checkjournalctl -u <svc>formodel done/server is listeningbefore declaring failure. - Rollback = the previous payload stays on disk; one
MODEL_FILE+ shape edit back. Record a refusal-freedom fallback the same way (an official censored base ↔ a CRACK re-export with byte-identical header geometry is a one-line swap; prove the identity with the tensor histogram, not the card). - A thinking model can consume the whole token budget in
reasoning_content(emptycontent,finish_reason: length) — probe with a budget that clears thinking; a short-budget vision probe reads as "the model is blind". /completionat-lv 4printsfailed to parse reasoning content ...on raw prompts closing with an end-of-turn marker: cosmetic (chat path parses correctly). At ~26k+ a bare/completioncan return 0 tokens with no error — raw context has no role frame; chat is unaffected.- Bats vacuity trap:
serve_argvREWRITES$STAGE/test.envfrom the shipped env, so a test that mutates the file then callsserve_argvasserts on regenerated content — a tautology. Tests that mutate must exec via arun_stagehelper running the file as-is. env NAME=value cmdneeds valid identifiers; a flag-like token is only legal as anenvARGUMENT, not as a shell assignment prefix.- Gitea
git pushon a rebased branch is rejected non-fast-forward:--force-with-lease(your own branch), never on main.