Skip to content

v0.2.0 — a second model family

Latest

Choose a tag to compare

@rayl15 rayl15 released this 05 Aug 17:23
· 23 commits to main since this release

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-mxfp4 decodes 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 python count from 516 to 248 — an earlier README reported the larger number
  • New palette: cyan on slate

Also

  • serve accepts 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.