Downloads · 30 days
496
25% of all-time downloads
logic65/whittle-next-moe-test
whittle-next-moe-test is a text generation model from logic65. Use it when you need the model to write or continue text. The card lists the license as apache-2.0.
<img src="whittle.svg" width="200" align="right"/
Downloads · 30 days
496
25% of all-time downloads
All-time downloads
2K
Public
Parameters
14.8B
78.6 GB on disk
Likes
0
Public
Click a slice to open those files.
.safetensors59 GB · 75%
From the Hugging Face model README
☕ Support this work
Whittle is built by one person on a grocery budget and rented GPU hours. If this research is useful to you, or you want to see it finished: ko-fi.com/davida81328. Every hour of GPU time goes straight into the next checkpoint, and every checkpoint, table and log lands in these repos.
A training-free MoE carve of Qwen3.8-Whittle-tri-14.7B, followed by a short learned-assignment alignment pass. No expert weight was ever retrained — only which neurons sit in which expert, and the router.
Ships as Qwen3_5MoeForCausalLM, the stock architecture, so it loads in plain
transformers with no custom code and no patches.
Experimental test model — a research artifact, not an assistant; superseded by Whittle-Next-27B-A3B (the parent of the current Whittle-Qwen-3.8-35B-A3B). It is published as the record of an experiment: turning a dense model into a Mixture-of-Experts without retraining the weights, then learning the neuron→expert assignment. It has had no instruction tuning, no chat healing, and no safety work as a MoE. Expect rough edges. Do not use it in production. Use it to reproduce or extend the method.
whittle-next-moe-test-Q4_K_M.gguf: the reference carve at k=58, the one the method section describes.kd-k104/ (7 shards) and whittle-next-moe-kd-k104-Q4_K_M.gguf: a better variant that ships alongside the reference carve (added 30 Aug). It runs the same weights at k=104 with a short top-64 KD pass, and cuts the loop-test failure rate from 92.7% to 83.7% (246 paired generations, exact McNemar p = 0.0032). It is still a failing conversational model — just measurably less so. See Follow-up (30 Aug) under Measured for the full A/B.ab_significance.json, loop_test_results.json, whittle.svg.Same evaluation throughout; "baseline" is the identical carve before alignment (see How it was made).
| active experts (k) | baseline | this model (aligned) |
|---|---|---|
| 26 | CE 5.31 | CE 4.17 |
| 52 | CE 4.76, 2/5 | CE 3.94, 5/5 |
| 58 (shipped default) | CE 4.69, 4/5 | CE 3.91, 5/5 |
| 104 | CE 4.16 | CE 3.77 |
| 240 (all) | CE 3.486 | CE 3.485 |
Alignment is worth roughly 0.8 CE at every sparsity, and the aligned model at k=58 beats the un-aligned one at k=104 — better quality from half the active experts. At full k both reproduce the dense model exactly, which is the carve's correctness check.
Run with the standard Whittle loop_test.py harness against this repo's Q4_K_M on an A100,
~90 generations. These are FAILURE rates — lower is better.
| section | failed | loopy | short |
|---|---|---|---|
| single-turn 12x3 | 31/36 (86%) | 24 | 10 |
| structured 6x3 | 18/18 (100%) | 11 | 9 |
| multi-turn | 26/28 (93%) | 2 | 24 |
| late turns (>=5th) | 12/12 (100%) | 2 | 10 |
For context, the instruction-tuned Whittle v2.1 release passed at 8 / 22 / 7 / 8%.
Read this plainly: as a conversational model, this checkpoint fails. It loops and it answers too briefly. That is the expected consequence of what it is — a training-free carve plus a short alignment pass, with no instruction tuning and no chat healing as an MoE. Its strengths are narrow and real (held-out CE 3.91 at 33% active experts, 5/5 on the factual smoke battery); its conversational behaviour is not one of them. Use it to reproduce or extend the carve method, not as an assistant.
The loop-test numbers above are bad, so we tried to fix them. Five arms were measured on the same harness, same host, same Q4_K_M quantisation, in one session. The baseline was re-measured rather than quoted, and it reproduced the published table exactly (31/36, 18/18, 26/28, 12/12), so these comparisons are like-for-like.
Failures out of 94 generations — lower is better.
| arm | total | single 12×3 | struct 6×3 | multi | late ≥5th |
|---|---|---|---|---|---|
| baseline, k=58 (published) | 87 | 31/36 | 18/18 | 26/28 | 12/12 |
| + chat SFT on 90 teacher answers | 87 | 31/36 | 17/18 | 27/28 | 12/12 |
| + top-64 KD from the 27B teacher | 86 | 29/36 | 18/18 | 27/28 | 12/12 |
| k=104, no training at all | 80 | 30/36 | 16/18 | 24/28 | 10/12 |
| KD weights served at k=104 | 74 | 27/36 | 18/18 | 22/28 | 7/12 |
The result, with a significance test. Raising the number of active experts — a pure config change, no training — beat every training run we did. Going from k=58 to k=104 removed 7 failures; the KD pass on top removed 6 more. Because 94 generations is not much evidence for a ~10% shift, the best arm was re-run against the baseline over three independent seed blocks (246 paired generations) and tested with an exact paired McNemar:
| failure rate | ||
|---|---|---|
| baseline, k=58 | 228/246 = 92.7% | |
| KD weights @ k=104 | 206/246 = 83.7% | discordant 37 vs 15, p = 0.0032 |
So the effect is real. On the single 94-generation run it was not significant (p = 0.12) — worth knowing if you use this harness to gate anything. Late-turn failures fell from 12/12 to 7/12. On an 8-prompt greedy probe the same effect is visible directly: 4-gram repetition halves, 0.227 at k=58 → 0.106 at k=104 → 0.058 at full k. For this carve, conversational degeneration is a capacity problem: at 33% active FFN the model does not have enough width to stay coherent, and it loops.
The cost is compute, not parameters: k=104 activates 2048 + 104×64 = 8,704 / 17,408 ≈ 50%
of the FFN instead of 33%. The weights are identical; only down_proj is rescaled by
104/58 to match the runtime's 1/k renormalisation.
Two traps worth knowing if you fine-tune this.
Never train mlp.gate.weight. The serving semantics are baked in by scaling every router
by 1e-4 (that is what makes the top-k softmax uniform). Those weights are ~1e-4 of normal
magnitude, so any normal optimizer step re-peaks the router and down_proj × k/16 then
amplifies the damage. Same data, only the trainable set differing: routers trained → CE 4.41,
battery 1/5, rep4 0.843; routers frozen → CE 3.946, battery 4/5. Both Muon and AdamW failed
identically, so the optimizer was a red herring — the trainable set was the bug.
A short greedy probe is not a chat metric. During chat SFT, held-out CE fell monotonically (3.9522 → 3.9321) while 4-gram repetition on a 3-prompt probe swung 0.446 → 0.014 → 0.831. The checkpoint that looked repaired on the probe scored exactly the same 87/94 as the untrained baseline on the full harness. Gate on the harness, not the probe.
Where the remaining ceiling is.
Because the carve is exact at full k, the checkpoint contains its own dense teacher: set
top_k = 240 and scale the routed output by 240/58 (never the shared expert). Doing that
recovers the dense parent — and the dense parent also fails to stop on 3 of 8 prompts, answers
"write a short paragraph about why the sky appears blue" with a JSON write_file tool call, and
reads "three tips for writing clearer code" as a three.js request. The carve is faithful to a
parent that was never instruction-tuned. The dominant surviving failure is short on
multi-turn, and those answers are not truncated — they are confidently wrong and tiny
("In macOS macOS."). That is inherited, and no amount of routing or self-distillation removes
it; it needs a better parent or real instruction tuning.
Scripts for every arm (rebake_k.py, teacher_gate.py, train_kd_sharpen.py, train_chat.py,
publish_prep.py, loop_test.py) and all raw logs are in
logic65/mini-next-a100-kit (private at the time of writing).
gate/up/down slices always move
together, so the carve is a pure permutation — exact at full k.| Layers | 32 (GDN : full-attention, 3:1) |
| Hidden | 5120 |
| FFN width | 17,408 (unchanged from the dense parent) |
| Shared expert | 2048, always on |
| Routed experts | 240 × 64 |
| Active per token | 58 experts + shared = 5,760 / 17,408 ≈ 33% |
from transformers import AutoModelForCausalLM, AutoTokenizer
# the reference carve, k=58 (what the method section describes)
m = AutoModelForCausalLM.from_pretrained("logic65/whittle-next-moe-test",
dtype="bfloat16", device_map="auto")
# the better-measured variant, k=104 + top-64 KD (92.7% -> 83.7% loop-test failures)
m = AutoModelForCausalLM.from_pretrained("logic65/whittle-next-moe-test",
subfolder="kd-k104", dtype="bfloat16", device_map="auto")
GGUF: whittle-next-moe-test-Q4_K_M.gguf (k=58 reference) and
whittle-next-moe-kd-k104-Q4_K_M.gguf (k=104, recommended). Both run on stock llama.cpp.
To try another sparsity yourself, use rebake_k.py from the kit: it rescales down_proj by
k_new/k_old and rewrites num_experts_per_tok. Nothing else needs to change — the router is
already flat, and top-k selection is scale-invariant.
A CUDA GPU is required — the gated-delta-net layers use Triton kernels.
down_proj compensating). Change num_experts_per_tok and you must
rescale down_proj by k_new / 58, or the output amplitude will be wrong.Carve follows ExpertWeaver (arXiv 2602.15521); learned assignment follows DOT-MoE (arXiv 2606.01666). Parent lineage: Qwen3.8-27B (Apache-2.0) → Whittle-tri-14.7B → this.
Built by David Aylward with Claude (Anthropic) as co-author.
If this is useful to you: ko-fi.com/davida81328