Godwit runs a second model family. GPT-OSS-120B, GPT-OSS-20B and Qwen3-30B-A3B, from one binary, switchable at runtime from the dashboard.
That was the claim v0.1.0 could not support. The 20B ran first time with no change beyond declaring its spec, but it shares everything with the 120B — same tensor names, same RoPE, same activation, same tokeniser. Qwen3 shares almost nothing, and it broke seven things rather than the five predicted.
Models
| GPT-OSS-120B | GPT-OSS-20B | Qwen3-30B-A3B | |
|---|---|---|---|
| Layers × experts | 36 × 128 | 24 × 32 | 48 × 128 |
| Active per token | 4 | 4 | 8 |
| Install | 59.2 GiB | 11.2 GiB | 16.1 GiB |
| Resident | 5.7 GiB | 4.1 GiB | 2.5 GiB |
| Decode | 1.4 tok/s | 2.8–3.2 tok/s | 2.3 tok/s |
Measured on a 13" M4 MacBook Air, 16 GB, base 256 GB SSD.
What Qwen3 needed
Per-expert tensors instead of stacked ones, QK-norm, plain SwiGLU, plain RoPE, ChatML, no attention sinks, no biases — and MXFP4 written rather than copied, because Qwen3 ships BF16 where GPT-OSS ships already-quantised weights.
Two of those would have run without complaining:
- A zero attention sink is not the identity. The sink enters the softmax denominator as
exp(sink - max), so a sink-free model given a zero sink gains a whole unit of mass on every row. It has to be compiled out. - MXFP4 encoding has to be checked against something.
godwit check-mxfp4decodes OpenAI's shipped weights and re-encodes them, demanding byte equality across 2,073,600 blocks. It caught a floored exponent and a dropped sign bit, either of which would have written 15 GB of quietly wrong weights.
One bug worth reading about
Qwen3 first produced fluent English with correct facts and then could not stop — it would say Paris, doubt itself, and re-derive the answer until the token budget ran out. Every piece of evidence pointed at quantisation: MXFP4 costs Qwen3 18.9 dB where it costs GPT-OSS nothing, and the install verified at 18.5 dB against the checkpoint, so the weights on disk were provably right.
The fix looked like int8 experts: a 30 GB install, another two hours, and deleting the 120B to make room. All three would have been spent on a wrong diagnosis.
A NumPy reference for one attention block settled it in an hour. Attention was off by 4.9 against a bound of 0.013 — not a quantisation signature at all. The QK-norm weight was declared half in the Metal kernel where every other small trunk tensor is bfloat.
Dashboard
- Model picker in the header — switch between installs, or download one that is missing
- Reasoning streams as it arrives, rather than appearing at the end; a turn that spends its budget thinking says so instead of showing an empty reply
- Range maps build from a button, with per-topic progress
- Range map counts now require 24 activations before crediting a topic label. On the 120B that excludes 40% of plotted experts and takes the
pythoncount from 516 to 248 — an earlier README reported the larger number - New palette: cyan on slate
Also
serveaccepts the sampling flags the README always claimed it did- The installer refuses an unrecognised repository instead of silently falling back to GPT-OSS-120B
- 82 tests, up from 54
Full detail in the README and docs/DESIGN.md.