--- name: gguf-lora-adapter-fit-census description: "Read-only census before applying a GGUF LoRA/adapter to a llama.cpp (or fork) endpoint: Hub metadata, declared base provenance, runtime flag support, and the behavioural probe that proves the effect." --- # GGUF LoRA / adapter fit census (read-only, before you promise a file to a payload) A 3 MB adapter is a payload change: it edits the compute graph at load. Do the census before editing an endpoint's trio, and prove the EFFECT behaviourally — no metadata, card table, or health gate can see it. ## 1. Census the Hub repo first (no auth for public repos) ```bash curl -sS "https://huggingface.co/api/models//?blobs=true" | python3 -c " import json,sys; d=json.load(sys.stdin) print(d.get('pipeline_tag'), d.get('library_name')) print([t for t in d.get('tags',[])][:20]) # base_model / base_model:adapter rows matter for s in d['siblings']: print(s['rfilename'], s.get('size'), (s.get('lfs') or {}).get('oid'))" curl -sS "https://huggingface.co///raw/main/README.md" > /tmp/card.md # grep for --lora flags ``` - `base_model` / `base_model_relation: adapter` name the pack the adapter was built for. - **A file with `lfs.oid = None` is a plain git object**: pin the sha256 of the Hub's bytes, not an LFS oid. Fetcher law still applies: `curl -fsSL --fail-with-body`, byte count, sha256, `--verify-only`, no resume. ## 2. Read the adapter's own GGUF KV section (settles provenance in one read) Small python read of the KV pairs — no torch, no download beyond the adapter itself: magic `GGUF`, `u32 ver`, `u64 n_tensors`, `u64 n_kv`; key = `u64 len` + bytes; type `u32` (0 u8,1 i8,2 u16,3 i16,4 u32,5 i32,6 f32,7 bool,8 str,9 array,10 u64,11 i64,12 f64); array = `u32 elem_type` + `u64 count`. Keys worth printing: `general.type` (`adapter`), `adapter.type` (`lora`), `adapter.lora_alpha`, and whatever provenance the publisher wrote — e.g. PrismML/abliteration packs carry `prism.abliterate.base_gguf`, `base_sha256`, `direction_row`, `target_layers`, `target_embedding`, `sites`, `basis`. **Provenance is metadata, not a gate.** The loader matches **tensor names, not hashes**, so an adapter fit against a sibling quantization of the same model still applies — which is a decision to surface to the operator, not a failure to hide. Compare `base_sha256` against the sha the endpoint's own fetcher pins; if they differ, say so in the PR body, the env header and the endpoint page, and prove the effect behaviourally instead. Two publisher facts that decide whether a fork can carry the file at all: the build it was verified on, and what it deliberately does NOT touch (an embedding rank is the usual crash — `token_embd` left alone is a graph constraint, not an omission). ## 3. Ask the runtime binary, not your memory ```bash --help | grep -iE "lora|adapter" ``` Expect `--lora FNAME`, `--lora-scaled FNAME:SCALE,...`, `--lora-init-without-apply` (+ `POST /lora-adapters` for runtime scale). Prefer `--lora-scaled :` as ONE argv token so a scale can never reach the engine without its file, and follow the endpoint's existing opt-out convention (the `MMPROJ_FILE=` shape: `:`-less default so an explicitly empty value means "off, on purpose"). Gate the deployer on the file's existence with the adapter's OWN fetcher named in the error text. ## 4. Prove the effect: refusal/behaviour probe, before AND after The probe is not a bench, so the no-bench law does not block it — and the **before** half must be captured while the old shape is still live. - Same prompts, `temperature` low, both before and after; classify with a refusal-marker regex and print only the opening characters, never the generated body. - **Budget ≥ 2 048 tokens on a thinking model.** A 600-token request can be swallowed whole by the reasoning channel: `content` comes back empty with `finish_reason: length` and `reasoning_content` full — which reads exactly like a refusal that never happened. - A leading `⚠️ Disclaimer`/hedge after the adapter is style, not the circuit: judge the marker sentence, not the tone. ## 5. Post-deploy reads (the ledger is the instrument) - Boot log shows `llama_adapter_lora_init_impl: loading lora adapter from ''` and then **dumps the adapter's KV block** — the provenance mismatch is printed at every start, so the runbook should point at the journal instead of restating it. - Confirm the flag on argv: `tr '\0' ' ' < /proc/$(systemctl show -p MainPID --value)/cmdline`; confirm `systemctl show -p DropInPaths --value` is empty (a leftover bench drop-in outranks everything you just deployed). - Shape must be untouched by an adapter: `n_slots` / `n_ctx_slot` / KV lines unchanged, and `/metrics` still answering (a llama.cpp endpoint is invisible to Prometheus without `--metrics`). - Root units log to the journal; rootless podman storage is read WITHOUT sudo (`sudo podman inspect` sees a different storage namespace and reports "no such object"). ## Yields One sentence per question: does the file exist and at what size/sha; which pack it declares as its base and whether that matches the served payload; which flag the runtime actually offers; what the before/after probe classified. Anything else is a decision for the operator, and the rollback should be one env line on a file the endpoint already loads.