--- license: apache-2.0 base_model: - meta-models/Muse-Glimmer-30B base_model_relation: finetune pipeline_tag: text-generation datasets: - Joakimpalm-Zen/Xyntetik-Kvist-14B-training-record - HuggingFaceTB/smoltalk - allenai/tulu-3-sft-mixture - Salesforce/wikitext tags: - muse-glimmer - xyntetik-kvist - width-pruning - distillation - agentic - tool-calling - preregistered - xyntetik-runner --- # Xyntetik-Kvist-14B > **Release: built to be downloaded and served with [Xyntetik Runner](https://github.com/Joakimpalm-Zen/xyntetik-runner).** > - **Measured status against the parent:** held-out KLD 0.762 and margin-qualified top-1 84.0% against the BF16 parent on 45,056 positions, its own row (the house quant bar does not apply); 57 of 60 held-out closed-loop tasks against the parent's 60; 99 of 99 tool calls valid; every preregistered envelope-gate arm passed. > - **Parent model:** [meta-models/Muse-Glimmer-30B](https://huggingface.co/meta-models/Muse-Glimmer-30B), cut by width to a dense 14B and distilled back from it; a new model, not a quantised copy > - **Collection:** [Xyntetik Kvist: distilled agents](https://huggingface.co/collections/Joakimpalm-Zen/xyntetik-kvist-distilled-agents-6ab9f930af19ca84df9ebf6b) > - **Evidence:** [training record](https://huggingface.co/datasets/Joakimpalm-Zen/Xyntetik-Kvist-14B-training-record) (dataset: preregistrations, K1 to K3 and envelope-gate records, corpus manifests, the envelope corpus, code), also copied under `evidence/` here > - **Runner compatibility:** Serves on Xyntetik Runner v0.5.7 or later; the gate arms E1, E2, E3 and E5 were measured on runner main 0bfa2ad and the serving measurements on 53b4deb, ac5418e and the v0.5.7 release binary; the first two are contained in v0.5.7. GGUF files are in [Xyntetik-Kvist-14B-GGUF](https://huggingface.co/Joakimpalm-Zen/Xyntetik-Kvist-14B-GGUF). Q8_0 (15.4 GB), Q5_0-mix (10.3 GB) and IQ4_NL-mix (7.6 GB) fit a 24 GB card whole and run GPU-resident; BF16 (28.9 GB) needs partial offload there (see Limits). **Want to build on it?** The trainers, the corpus manifests and every gate record are in the [training record](https://huggingface.co/datasets/Joakimpalm-Zen/Xyntetik-Kvist-14B-training-record). [Request a model](https://github.com/Joakimpalm-Zen/xyntetik-runner/issues/new?template=model_request.yml) · [Report your result](https://github.com/Joakimpalm-Zen/xyntetik-runner/issues/new?template=result_report.yml) · [Community results](https://github.com/Joakimpalm-Zen/xyntetik-runner/blob/main/docs/community-results.md) · [All files](https://huggingface.co/Joakimpalm-Zen)
If this file is useful to you, a contribution funds the hardware time behind the next one.
**What it is, and is not.** A 14B research student of Muse-Glimmer-30B, built for one job: running tool-calling agent loops on Xyntetik Runner from a 24 GB card. Its training budget is small: 6,000 distillation steps (98.3 M tokens, 162 hours) and 1,440 steps on agentic trajectories. It is **not a drop-in replacement** for Muse-Glimmer-30B, for Gemma, or for any general-purpose model: on held-out text it reads KLD 0.762 against its own parent, and its tool-calling result (57 of 60) holds for the study's environment and the `muse` wire format on Runner, nothing wider. Download it to serve agent loops on Runner and to read the evidence; do not download it expecting the parent's quality. Muse-Glimmer-30B's language model, cut by width to a dense student of **14,443,781,760 parameters**: all 52 layers kept, hidden width 6,656 → 5,760, FFN 19,968 → 10,240, attention heads 32 → 24, KV heads 2. It was distilled back from the frozen BF16 parent for 6,000 steps (98.3 M tokens, 162 hours), then trained for 1,440 more steps on agentic trajectories written in Runner's `muse` wire format. Text only: the parent's 1.92 B-parameter vision encoder is not carried. **The cost first.** On the study's 45,056-position held-out split this model reads **KLD 0.762 and margin-qualified top-1 84.0%** against the BF16 parent (top-1 79.2%). That is a student's own row. It is far from the house bar for quantised copies (KLD ≤ 0.05, margin-qualified top-1 ≥ 97%), which does not apply to a model with 14.4 B of the parent's 27.9 B language-model parameters and is not claimed. **Closed-loop agentic tasks:** 57 of 60 held-out environment tasks solved, scored by re-execution against ground truth, where the parent solves 60 and the student before the agentic phase solves 0. **What is claimed, and only this.** Every arm of the preregistered envelope gate passed. The model writes Runner's `muse` wire format (199 of 200 first turns well formed), its tool calls parse and validate against the offered schema (99 of 99), and it solves 57 of 60 held-out tasks of the study's executable environment end to end (57 also when a numeric task counts only with the right bolded answer). That is a tool-calling claim scoped to that environment and that serving path; see Limits and the disclosures. Nothing about tool calling is claimed from the general distillation, whose corpora held no tool-calling documents. ## Serve with `xyntetik-runner` ```sh runner -m Xyntetik-Kvist-14B-Q8_0.gguf --serve --port 8080 ``` Four files: BF16, the file the gate measured, and Q8_0, Q5_0-mix and IQ4_NL-mix, each measured against it below. The BF16 file is 28.9 GB and does not fit a 24 GB card whole; the gate served it with 38 of 52 layers on the GPU: ```sh runner -m Xyntetik-Kvist-14B-BF16.gguf --serve --port 8080 --gpu auto --gpu-layers 38 ``` For anything that may produce a tool call, keep `"repeat_penalty": 1.0`. That is Runner v0.5.7's default for this model, but a penalty set by the client acts on the schema tokens a call has to repeat (and only when sampling, at temperature above 0). Every gate number below was measured greedy (temperature 0) with the penalty at 1.0. ### Recommended: greedy, with the loop guard Runner v0.5.7 and later can close a reasoning turn that has started repeating itself (`--loop-guard`, off by default; per request `loop_guard`). This is the recommended way to serve this model: ```sh runner -m Xyntetik-Kvist-14B-Q8_0.gguf --serve --port 8080 --loop-guard ``` On the gate's 60 closed-loop tasks (this checkpoint at Q8_0 on CPU, greedy, the Runner v0.5.7 release binary) the guard leaves the score where it is: 58 of 60 with the guard and 58 of 60 without it on the same binary, failing the same two tasks. It intervened only in the one task that runs away without it, a two-decimals calc request, 5 times, and that task still did not terminate; it fired on no task that passed without it. Termination stayed at 98.3% and mean thinking tokens went from 154 to 147. On an earlier checkpoint of this study (attempt 8, runner 53b4deb) the same setting raised the score from 51 to 54 of 60 by ending 3 of its 6 runaways, so what the guard buys depends on how often a checkpoint loops; on this one its value is a bounded turn, not a better score. The guard fixes the turn, not the task. When the model loops because it does not have the answer, closing the loop leaves a wrong answer. It also cannot see a loop that spans requests: in one measured task an earlier checkpoint of this study (attempt 8) had the answer in its reasoning and still called the same tool with the same argument three times, each turn well formed on its own. Only the caller, which holds the whole conversation, can catch that. This checkpoint passes that task (task-20260915-02037, two calls). Token repetition is a serving problem with a serving fix, the guard; deciding to answer instead of calling again is a training problem, and the fix here was training on post-tool rollouts. Reasoning-channel sampling (`--reasoning-temp`) was measured too and is **not** recommended for this model: on an earlier checkpoint of this study (attempt 8, runner 53b4deb, Q8_0 on CPU, the gate's 60 tasks), reasoning temperature 0.6 with top-p 0.9, min-p 0.05 and top-k 20 supplied in the request solved 49 and 47 tasks on two seeds against 51 greedy; termination was 92% and 87% against 90%, and both seeds turned the same calc and units tasks into loops. The gate numbers below were all measured greedy **without** the guard. The guard is a serving recommendation, not part of the gate. ## Quickstart ```sh runner -m Xyntetik-Kvist-14B-Q8_0.gguf -p "The capital of France is" -n 32 ``` ```sh curl -s http://127.0.0.1:8080/v1/chat/completions -H 'Content-Type: application/json' -d '{ "messages": [{"role": "user", "content": "Find me a flight from Stockholm to Berlin on 2026-10-14."}], "tools": [{"type": "function", "function": {"name": "find_flight", "description": "Search for available flights between two cities on a given date.", "parameters": {"type": "object", "properties": { "origin": {"type": "string", "description": "Departure city"}, "destination": {"type": "string", "description": "Arrival city"}, "date": {"type": "string", "description": "Departure date, YYYY-MM-DD"}}, "required": ["origin", "destination", "date"]}}}], "max_tokens": 1024, "temperature": 0, "repeat_penalty": 1.0}' ``` On Runner v0.5.7 this returns a `find_flight` call with all three arguments filled (`finish_reason` `tool_calls`). Give the model a calculator tool for arithmetic. Without one it computes in its head and can be wrong: asked "What is 17% of 2,340?" at temperature 0 with no tools, it answered 462.6 (the answer is 397.8). ## What was changed, exactly Three stages, each with its own record. - **Width pruning (`PRUNE.json`).** Minitron-style activation importance, measured on 131,072 tokens (64 × 2,048) of the Muse-Glimmer surgery study's window-audited `corpus_run9` training split, eval split never read: hidden channels chosen globally by summed mean |x|, FFN neurons per layer by mean |h| at the `down_proj` input, attention heads per KV group by the mean norm of their `o_proj` input. The embedding and the LM head are cut on the hidden axis with the same channel set. No training. `PRUNE.json` holds every kept index, the calibration capture's SHA-256 and a hash of every tensor written. | | parent language model | this model | | --- | ---: | ---: | | embedding | 1,344,831,488 | 1,163,796,480 | | 52 decoder blocks | 25,165,117,952 | 12,116,188,800 | | LM head | 1,344,831,488 | 1,163,796,480 | | **total** | **27,854,780,928** | **14,443,781,760** (51.9% kept) | Unchanged: the tokenizer (202,048 entries, `tokenizer.json` identical to the parent's), the chat template, head dimension 128, the attention pattern (three sliding-window layers of 2,048 tokens to one global), the logit softcap. - **General distillation (`DISTILLATION.json`, `general_kd`).** 6,000 steps of 4 windows × 4,095 predicted positions, 98.28 M tokens: 40% of corpus v1 (59,946 sequences of 4,096 tokens, 245.5 M tokens, the study's 11 chat and task domains from SmolTalk and the Tulu 3 SFT mixture plus Wikitext-103, plain render, single pass). Objective: top-64 forward KL to the frozen BF16 parent with a tail bucket, through the parent's softcapped logits. All 52 blocks and the final norm trainable; embedding and LM head frozen at their pruned values. AdamW (0.9, 0.95), peak lr 1e-4, 50-step warmup, cosine to 1e-5, per-block clip 1.0, one block resident on a 24 GB GPU slice with fp32 master weights on the host. 583,591 s of wall time (162.1 h). - **Envelope phase (`DISTILLATION.json`, `envelope`).** 1,440 steps from checkpoint-06000 and its optimizer state, peak lr 3e-5, 20-step warmup, on a cosine schedule over a 1,500-step budget, seed 20260922. General steps: 4 windows of 4,096 tokens from `corpus-v3-muse` (9,325 sequences, 38.2 M tokens, the same domains with the chat rendered in Runner's `muse` template). Policy steps: 8 agentic examples of up to 1,536 tokens, drawn in proportion to their weight from the 3,954 of 3,955 assembled examples that fit the window. On an agentic example only the assistant's positions carry loss. At a decision position (whom the turn addresses, which tool, which argument keys) the target is the factored teacher: Ornith-1.0-9B's policy mass over the prefix trie of the alternatives, the remaining share filled with the parent's own top-64. Everywhere else the target is the parent's top-64 on text the parent wrote. In the last 840 steps part of the policy text is the student's own: reasoning it wrote itself at training-set states, each position still trained toward the frozen parent's top-64, so the student learns where the parent would stop inside the student's own phrasing (on-policy distillation). The 1,440 steps ran as 11 consecutive segments from checkpoint-06000, each resumed from a checkpoint of the one before, with the lr schedule continued: steps 1 to 200 (`train-w14b-envelope-a2`, trainer `b0b47549dc2ecf49…`): 1 general step per policy step; steps 201 to 350 (`train-w14b-envelope-a3`, trainer `ac3df6cd53c1c40a…`): 1 general step per policy step; steps 351 to 450 (`train-w14b-envelope-a4`, trainer `4fca29a35dc14f97…`): 2 general steps per policy step; sampling weights turn:answer ×2, flight ×2; steps 451 to 600 (`train-w14b-envelope-a5`, trainer `f28323e0fbfd42ba…`): 2 general steps per policy step; sampling weights turn:answer ×2, flight ×2; terminator positions weighted ×10; steps 601 to 720 (`train-w14b-envelope-a6`, trainer `f28323e0fbfd42ba…`): 2 general steps per policy step; sampling weights turn:answer ×2, flight ×2; terminator positions weighted ×10; policy examples `examples-muse-a6-mixed.jsonl` (on-policy: the student's own reasoning, parent targets, mixed 1:1 with the originals); steps 721 to 840 (`train-w14b-envelope-a7`, trainer `f28323e0fbfd42ba…`): 2 general steps per policy step; sampling weights turn:answer ×2, flight ×2; terminator positions weighted ×10; policy examples `examples-muse-a7-mixed.jsonl` (on-policy: the student's own reasoning, parent targets, mixed 1:1 with the originals); steps 841 to 960 (`train-w14b-envelope-a8`, trainer `f28323e0fbfd42ba…`): 2 general steps per policy step; sampling weights turn:answer ×2, flight ×2; terminator positions weighted ×10; policy examples `examples-muse-a8-mixed.jsonl` (on-policy: the student's own reasoning, parent targets, mixed 1:1 with the originals); steps 961 to 1080 (`train-w14b-envelope-a9`, trainer `f28323e0fbfd42ba…`): 2 general steps per policy step; sampling weights turn:answer ×2, flight ×2; terminator positions weighted ×10; policy examples `examples-muse-a9-mixed.jsonl` (on-policy: the student's own reasoning, parent targets, mixed 1:1 with the originals); steps 1081 to 1200 (`train-w14b-envelope-a10`, trainer `f28323e0fbfd42ba…`): 2 general steps per policy step; sampling weights turn:answer ×2, flight ×2; terminator positions weighted ×10; policy examples `examples-muse-a10-mixed.jsonl` (on-policy: the student's own reasoning, parent targets, mixed 1:1 with the originals); steps 1201 to 1320 (`train-w14b-envelope-a11`, trainer `f28323e0fbfd42ba…`): 2 general steps per policy step; sampling weights turn:answer ×2, flight ×2; terminator positions weighted ×10; policy examples `examples-muse-a11-mixed.jsonl` (on-policy: the student's own reasoning, parent targets, mixed 1:1 with the originals); steps 1321 to 1440 (`train-w14b-envelope-a12`, trainer `f28323e0fbfd42ba…`): 2 general steps per policy step; sampling weights turn:answer ×2, flight ×2; terminator positions weighted ×10; policy examples `examples-muse-a12-mixed.jsonl` (on-policy: the student's own reasoning, parent targets, mixed 1:1 with the originals). Through checkpoint-01440: 14,758,380 general positions on 901 steps and 772,568 assistant positions carrying loss on 539 policy steps. The gate was read at checkpoint-01440, step 1,440 of the 1,500 budgeted. The envelope phase ran as a chain of segments, each continuing from the previous attempt's gated checkpoint under a registered step ceiling (see the lineage above), and the released segment, attempt 12, ended at its ceiling. How the agentic examples were made. Ornith-1.0-9B explored environment tasks 0 to 2007 as state trees in its own template. The Muse parent wrote every deliberation, every argument value and every final answer, steered to each branch by a private planning note that is never rendered into the example, with the argument keys prefix-forced to the policy's. Each tool was re-executed with the parent's values, and a path stops where the result differs from the one Ornith saw. A leakage filter (a word list plus any 3-word sequence shared with the note's template) rejects rationales that quote the note. Assembly produced examples on 1,889 tree paths; after de-duplication 3,974 examples remained, and the 19 from tasks 2000 to 2007 were removed before training because E3 scores tasks 2000 to 2059: **3,955 examples** on 1,880 paths (SHA-256 `6a3b651ccceaed11…`). Before assembly resumed, 200 task ids (223 paths) were reserved for the gate and never assembled; none of them appears in the corpus (checked 2026-09-23). ## Why **Width, not depth.** Minitron (arXiv:2408.11796) found width pruning beats depth pruning at every token budget, depth-pruned models do not recover arithmetic generation even at about 100 B post-pruning tokens (arXiv:2602.01997), and the Muse-Glimmer surgery study's own N-wall (7 to 13 layers) says the same for this model. No smaller Muse-Glimmer existed, so the student had to be cut from the 30B. **A measured gap, not a copy.** 98 M distillation tokens is about 0.1% of Minitron's 94 B. Parent-equivalence was never reachable at this budget and was never the claim. The gates were written before training: K1 (the cut keeps a working model), K2 (held-out KLD halves by day 3), K3 (margin-qualified top-1 ≥ 80% after week 1 for a model release). The lean written before the run was 60 to 75% at K3; it was wrong by 9 to 24 points. **Why an envelope phase.** checkpoint-06000 passed K3 on the distribution it was trained on and was not a chat model: greedy, it looped after the first sentence and wrote ` to user.` as text instead of the recipient token, because corpus v1 is a template-free render and it had never seen `<|start|>`, `<|message|>` or `<|eot|>`. Corpus v1 and v2 also held **no tool-calling documents at all**: the tool-calling rows share an instruction preamble with rows in the eval split, and the 64-token contamination filter dropped all 83,111 of them. Corpus v3 fixes that (below, and in Limits), so every tool-call behaviour this model has comes from the envelope phase. The teacher is factored because the parent's turn decisions are diffuse where Ornith's are sharp: on 23 pilot states, parent and Ornith agree on 91% of think-first decisions (TV 0.08) and on 62% of turn decisions after their own deliberation (TV 0.53). ## Measured envelope Four instruments, kept apart: 1. **Retention (E4, and K1 to K3).** `score_student.py`: KLD student‖parent over the full vocabulary, top-1 agreement, margin-qualified top-1 (tie band 0.5 nats), top-8 overlap; the frozen BF16 parent from safetensors, the student's own head; the study's 11 held-out sequences, 45,056 positions, never trained on. PyTorch forward on the safetensors checkpoint. 2. **Closed loop (E3).** `agentic_closedloop.py --raw-muse`: the executable environment's tasks from offset 2000 (seed 20260915), up to 6 tool calls per task, success when every ground-truth value appears in the final answer. Re-execution, not a judge. 3. **Wire format, calls, repetition (E1, E2, E5).** `envelope_preflight.py`: prompts cut at user or tool-result events from the Ornith trees of the 200 reserved task ids, rendered in the `muse` template, half from states whose own trajectory went on to call a tool; greedy, 512-token cap; the special tokens read from `logprobs.token_ids`, because Runner's `/v1/completions` drops them from `text`. 4. **GGUF fidelity.** Runner's `scripts/kld-compare-raw.py`, each quantised file against this model's own BF16 GGUF. Every gate arm decodes greedily: E1, E2, E3 and E5 send `temperature: 0` on every request. Runner has no Muse sampling preset, so a request that omits `temperature` is served with the generic preset (0.80, top-p 0.95, top-k 40, min-p 0.05). The numbers below describe greedy decoding, not that default. The gate for the envelope phase was preregistered and approved on 2026-09-22 with its thresholds frozen; the headline order it fixes is the cost first, then the claim that is hardest to make. ### Retention against the parent (E4, the cost) | checkpoint | distillation tokens | KLD | top-1 | margin-q | top-8 | gate | | --- | ---: | ---: | ---: | ---: | ---: | --- | | pruned, untrained (K1) | 0 | 3.239 | 57.0% | 60.2% | 0.447 | K1 top-1 ≥ 20%: pass | | checkpoint-02500 (K2) | 41.0 M | 1.441 | 72.6% | 77.0% | 0.553 | K2 KLD ≤ 1.62: pass | | checkpoint-03500 | 57.3 M | 1.155 | 75.3% | 79.9% | 0.578 | progress read | | checkpoint-04000 | 65.5 M | 1.035 | 76.5% | 81.1% | 0.591 | progress read | | checkpoint-06000 (K3) | 98.3 M | 0.786 | 79.2% | 83.9% | 0.619 | K3 margin-q ≥ 80%: pass | | **this model, envelope checkpoint-01440 (E4)** | 98.3 M + 14.8 M | **0.762** | 79.2% | **84.0%** | 0.623 | E4 KLD ≤ 0.865 and margin-q ≥ 80%: pass | All six rows on the same 45,056 positions. The score files also carry a `verdict` field computed against the house quant bar; it reads FAIL on every row and is not the gate. Where the gap sits, per domain at checkpoint-06000: math word problems 0.30, code 0.34, rewriting 0.37, math chain-of-thought 0.48 at the good end; casual dialogue 1.03, system-prompted chat 1.06, long context 1.21, the Tulu mixture 1.49 at the other. The per-domain split was not re-measured after the envelope phase. ### Closed-loop agentic tasks (E3) E3 is the 60 tasks at offset 2000 (task-20260915-02000 to -02059), scored in full. Tasks 2000 to 2007 lie inside the range the Ornith trees covered; the 19 training examples drawn from them were removed before any envelope training (2026-09-23), so no arm is measured on training data. | arm | file served | solved | terminated in budget | schema-valid calls | unnecessary calls | calls / task | thinking tokens / task | | --- | --- | ---: | ---: | ---: | ---: | ---: | ---: | | parent (reference) | parent at Q4_K | 60 of 60 | 60 | 73 of 73 | 0 | 1.22 | 212 | | student before the envelope (control) | checkpoint-06000, BF16 | 0 of 60 | 0 | 0 of 0 | 0 | 0.00 | 0 | | **this model (treated)** | checkpoint-01440, BF16 | **57 of 60** | 58 | 64 of 64 | 0 | 1.07 | 165 | The rule: the treated model beats the control by at least 15 points and reaches at least 90% of the parent's success on the same tasks; with the parent at 60 of 60 that needs at least 54. The parent sits at the ceiling, so this arm can show the student approaching the parent and never passing it. All three arms ran on the same 24 GB GPU slice with runner main 0bfa2ad (owner decision, 2026-09-23): the parent with Runner's automatic fit, and both 14B BF16 files with 38 of their 52 blocks on the GPU (`--gpu-layers 38`). The control ran once, during attempt 11's gate, and was reused for this checkpoint's gate (the gate chain runs it only when its result file is missing). It measures the frozen checkpoint-06000, so the timing cannot move the number. The E3 rule is read in whole tasks: treated at least 54, treated minus control at least 9, and ten times treated at least nine times the parent's count. ### Wire format, tool calls and repetition (E1, E2, E5) | arm | prompts scored | E1 turns well formed | E2 calls valid | E2 turns addressed to a tool / the user | E5 turns looped | terminator not reported | | --- | ---: | ---: | ---: | ---: | ---: | ---: | | parent (reference, Q4_K) | 100 | 100 of 100 | 53 of 53 | 53 / 47 | 0 of 100 | 0 | | student before the envelope (control) | 200 | 0 of 200 | 0 of 11 | 11 / 0 (+189 other: to=example_tool_name.example_function_name