Skip to content

GPT-OSS (mixture-of-experts LLM)

OpenAI's GPT-OSS in pure Keras 3: a mixture-of-experts decoder-only language model with grouped-query attention, learned per-head attention sinks, alternating sliding-window / full causal attention, YaRN rotary positions, and top-k sparse MoE feed-forwards. One implementation runs unmodified on TensorFlow / Torch / JAX. Weights are converted on the fly from the Hugging Face repos (including their MXFP4 quantization): nothing is re-hosted.

Paper / model card: openai/gpt-oss-20b

Class Module Output
GptOssModel kerasformers.models.gpt_oss {"last_hidden_state": (B, L, embed_dim)}
GptOssGenerate kerasformers.models.gpt_oss {"logits": (B, L, vocab), "last_hidden_state": ...} + .generate()
GptOssTokenizer kerasformers.models.gpt_oss o200k_harmonyinput_ids / attention_mask

GptOssModel is a subclassed (imperative) SubclassedBaseModel whose forward runs eagerly with keras.ops; GptOssGenerate adds an (untied) LM head and greedy .generate() with a KV cache that respects each layer's sliding window.

Architecture notes

  • MoE feed-forward: a top-num_experts_per_tok (4) router selects experts whose softmax weights combine per-expert outputs. The expert activation is GPT-OSS's clamped gated-SiLU on the interleaved gate/up halves ((up+1) * gate*sigmoid(1.702*gate), clamp limit 7). Experts are evaluated densely (every expert, masked by the routing weights): exact, backend-agnostic, and fine for short prompts; long sequences over all 32/128 experts are heavy.
  • Attention sinks: a learned per-head logit is appended to the attention scores before softmax and dropped afterward, letting a head attend to "nothing".
  • Alternating attention: even layers use a sliding window of sliding_window (128) tokens; odd layers use full causal attention.
  • YaRN rotary scaling (factor 32, β_fast 32, β_slow 1, original context 4096) with the mscale cos/sin factor.
  • MXFP4: the official repos store the experts in MXFP4 (4-bit blocks + e8m0 scales). They are dequantized to float32 on load (bit-exact port of HF's convert_moe_packed_tensors), so Keras runs the experts in full precision.

Loading (on the fly, no release weights)

from kerasformers.models.gpt_oss import GptOssGenerate, GptOssTokenizer

# Downloads + converts openai/gpt-oss-20b once, then caches under
# ~/.cache/kerasformers/. (Accept the model license + set HF_TOKEN if needed.)
model = GptOssGenerate.from_weights("gpt-oss-20b")        # or "hf:openai/gpt-oss-20b"
tok = GptOssTokenizer()

inputs = tok([{"role": "user", "content": "Hello!"}])
ids = model.generate(inputs["input_ids"], max_new_tokens=64)
print(tok.decode(ids[0]))

Available variants

Variant layers experts top-k heads (Q/KV)
gpt-oss-20b 24 32 4 64 / 8
gpt-oss-120b 36 128 4 64 / 8

Verified parity

The 20B/120B checkpoints are too large to run on a dev box, so the architecture is validated against a tiny random GptOssForCausalLM (Hugging Face, eager attention) exercising the MoE router, attention sinks, the sliding window (sequence longer than the window), YaRN, and GQA:

Check Result
GptOssGenerate logits vs HF (tiny random) max |Δ| 1.8e-7, argmax 100% agree
MXFP4 dequant vs HF convert_moe_packed_tensors max |Δ| 0.0
Build + forward + .generate() on TF / Torch / JAX