The Formal Era · Spec HubModelsLemma HubAdvisoriesDocs
Model Spec

google/gemma-4-12B @1.0.0

gemma4 · 48 layers · hidden 3840 · 11.91 B parameters · text-only language-model path; vision and audio towers are out of scope

theformalera pull with "google/gemma-4-12B" = { version = "^1.0" } · digest sha256:6204c6466455d92cd9e4cf5… · Lean leanprover/lean4:v4.35.0 · publisher theformalera (verified)

Trust

Conformance proof
pending (Phase 1: reference implementation export via torch.export)
Weight-level cross-check
not run
Publisher verification
verified
Public audit
Lean source public; spec errors earn a bounty

Compute graph

nodelayersOp SpecformulaconstantsLemma Hub
embed—embedy[t] = √3840 · w[tokens[t]]mul=√3840, norm=False0
layers[*].input_norm0, 1, …, 47 (48)rmsnormy[t,i] = x[t,i] / √(Σⱼ x[t,j]² / H + ε) · w[i]H=3840, eps=1e-060
layers[*].attn.qkv_proj40 layerslineary[t,n] = Σₖ x[t,k] · w[n,k]K=3840, N=81920
layers[*].attn.qk_norm40 layersrmsnormper head: y[t,i] = x[t,i] / √(Σⱼ x[t,j]² / H + ε) · w[i]D=256, eps=1e-060
layers[*].attn.v_norm40 layersrmsnormUnitper head: y[t,i] = x[t,i] / √(Σⱼ x[t,j]² / H + ε)D=256, eps=1e-060
layers[*].attn.rope40 layersroperotate pairs (i, i + 128) by pos · θ^(-2i/256), i < 128; coordinates ≥ 256 unchangedD=256, active=128, denom=256, rot=256, theta=100000
layers[*].attn.core40 layersslidingDecodeGQAo[b,h] = Σ_{s < seq_lens[b]} softmax_s(1 · ⟨q[b,h], k[b,s,h / 2]⟩) · v[b,s,h / 2] over the last 1024 positionsD=256, heads=16, kv_heads=8, scale=1, window=10240
layers[*].attn.o_proj40 layerslineary[t,n] = Σₖ x[t,k] · w[n,k]K=4096, N=38400
layers[*].post_mix_norm0, 1, …, 47 (48)rmsnormy[t,i] = x[t,i] / √(Σⱼ x[t,j]² / H + ε) · w[i]H=3840, eps=1e-060
layers[*].attn_residual0, 1, …, 47 (48)residualy = x + hH=3840, layer_scalar=False, r=10
layers[*].post_attn_norm0, 1, …, 47 (48)rmsnormy[t,i] = x[t,i] / √(Σⱼ x[t,j]² / H + ε) · w[i]H=3840, eps=1e-060
layers[*].mlp.gate_up0, 1, …, 47 (48)lineary[t,n] = Σₖ x[t,k] · w[n,k]K=3840, N=307200
layers[*].mlp.act0, 1, …, 47 (48)geluMuly[t,i] = gelu_tanh(gate_up[t,i]) · gate_up[t,15360+i]I=15360, act=gelu_pytorch_tanh0
layers[*].mlp.down0, 1, …, 47 (48)lineary[t,n] = Σₖ x[t,k] · w[n,k]K=15360, N=38400
layers[*].post_ffn_norm0, 1, …, 47 (48)rmsnormy[t,i] = x[t,i] / √(Σⱼ x[t,j]² / H + ε) · w[i]H=3840, eps=1e-060
layers[*].mlp_residual0, 1, …, 47 (48)residualy = s · (x + 1 · h)H=3840, layer_scalar=True, r=10
layers[*].attn.qkv_proj5, 11, …, 47 (8)lineary[t,n] = Σₖ x[t,k] · w[n,k]K=3840, N=87040
layers[*].attn.qk_norm5, 11, …, 47 (8)rmsnormper head: y[t,i] = x[t,i] / √(Σⱼ x[t,j]² / H + ε) · w[i]D=512, eps=1e-060
layers[*].attn.v_norm5, 11, …, 47 (8)rmsnormUnitper head: y[t,i] = x[t,i] / √(Σⱼ x[t,j]² / H + ε)D=512, eps=1e-060
layers[*].attn.rope5, 11, …, 47 (8)roperotate pairs (i, i + 256) by pos · θ^(-2i/512), i < 64; coordinates ≥ 512 unchangedD=512, active=64, denom=512, rot=512, theta=10000000
layers[*].attn.core5, 11, …, 47 (8)decodeGQAo[b,h] = Σ_{s < seq_lens[b]} softmax_s(1 · ⟨q[b,h], k[b,s,h / 16]⟩) · v[b,s,h / 16]D=512, heads=16, kv_heads=1, scale=1, window=None0
layers[*].attn.o_proj5, 11, …, 47 (8)lineary[t,n] = Σₖ x[t,k] · w[n,k]K=8192, N=38400
final_norm—rmsnormy[t,i] = x[t,i] / √(Σⱼ x[t,j]² / H + ε) · w[i]H=3840, eps=1e-060
lm_head—lmHeadz = x wᵀ, logits = 30 · tanh(z / 30)mul=1, softcap=30, tied=True0

Domains

shape B ∈ [1, 256], S ∈ [1, 262144], T ∈ [1, 262144], page_size ∈ [16, 16]
value activation: |x| ≤ 65504 (bf16), norm_weight: |x| ≤ 64 (bf16), weight: |x| ≤ 64 (bf16)

Theorems (Lean kernel-checked)

forward_causalEvery model of the specification is causal (all configurations, all scalar types).✓
attnHead_localAn attention head only reads visible positions (causal mask + sliding window).✓
softmax_shiftSoftmax is invariant under the subtracted reference value (max-subtraction is sound).✓
softmax_sum_oneAttention weights sum to one.✓
attnWeights_distributionAttention weights form a probability distribution over the visible keys.✓
rope_relativeRoPE encodes relative positions: ⟨R_p q, R_p' k⟩ = ⟨R_(p-p') q, k⟩ (all RoPE variants).✓
rope_isometryRoPE preserves inner products.✓
deltaRule_causalThe gated delta rule is causal.✓
deltaStep_read_keyThe delta rule stores v under a unit key k exactly (β = 1, no decay).✓
causalConv_causalThe depthwise convolution of the Gated DeltaNet is causal.✓
runTrace_fstThe oracle's layer trace computes the specification's residual stream.✓
seqMap_eq_seqMapParThe parallel position-wise evaluator computes the specification (@[csimp]).✓
linear_eq_linearParThe parallel matrix-vector product computes the specification (@[csimp]).✓
registry_wellFormedAll 8 checkpoint specifications and their reduced versions are well formed.✓
reduced_same_architectureEach reduced configuration has the architecture of its checkpoint.✓
qwen3_8_27b_patternQwen3.8-27B: layer i is full attention iff i % 4 = 3.✓
gemma4_12b_patternGemma 4 12B: layer i is global iff i % 6 = 5.✓
gemma4_31b_patternGemma 4 31B: layer i is global iff i % 6 = 5.✓
museGlimmer_global_iff_nopeMuse Glimmer: global layers are exactly the NoPE layers.✓
qwen3_0_6b_paramsQwen3-0.6B text model has 596,049,920 parameters.✓
tiledSum_eqKernels: a tiled (masked) reduction equals the plain reduction, for every tile size.✓
rmsNormTiled_eqKernels: tiled RMSNorm = RMSNorm of the specification, for every block size and weight kind.✓
flashAttn_eqKernels: FlashAttention (online softmax, block skipping) = attention head of the specification.✓
flashAttn_tile_eqKernels: the kernels' key-block bounds (causal / sliding window) visit every visible key.✓
chunkDeltaRule_eqKernels: chunked (WY-form) gated delta rule = recurrent delta rule, for every chunk size.✓
Ops.gdnState_succOp Specs: the gated delta rule state recurrence is the iterated decode step.✓
Engine.Implements.ofLanesEngine: the verification contract follows from a decoder, a witness and per-lane values.✓
Engine.sum_fin_truncEngine: lanes of a tile beyond the logical extent contribute nothing to a reduction.✓
Engine.tiled_rangeEngine: a tiled loop accumulation equals the plain reduction (every tile size).✓
Engine.strided_inj3Engine: non-overlapping strided layouts are injective.✓
Engine.rmsnormOffset_zldEngine: closed form of the (1 + w) RMSNorm Op Spec at integer indices.✓
Engine.linear_zldEngine: closed form of the linear Op Spec at integer indices.✓
Engine.LemmaHub.tanh_eq_expLemma Hub (built-in): tanh x = (exp 2x − 1)/(exp 2x + 1).✓
Lemmas.tiled_masked_sumLemma Hub (built-in): a masked tiled traversal covers [0, n) exactly once.✓
Lemmas.tiled_floor_missesLemma Hub (built-in): ⌊n/B⌋ tiles miss the tail when B ∤ n.✓
Lemmas.online_softmax_rescaleLemma Hub (built-in): online softmax rescaling by exp(m − m').✓
Lemmas.splitKV_lse_mergeLemma Hub (built-in): split-KV merging in log-sum-exp form equals full attention.✓

Versions

versiondigestpublished
1.0.0sha256:6204c6466455d92c…2026-11-01T06:23:02+00:00

Advisories

No advisories.

Lean 4 definitions

TheFormalEra/Ops/Attention.lean

import TheFormalEra.Ops.Basic

/-!
# Op Specs: softmax attention
-/

namespace TheFormalEra.Ops

open Finset

/-- Softmax over the reals, normalized only over visible positions -/
noncomputable def softmax {L : ℕ} (s : Fin L → ℝ) (visible : Fin L → Prop)
    [DecidablePred visible] : Fin L → ℝ :=
  fun l => if visible l then
    Real.exp (s l) / ∑ m ∈ Finset.univ.filter visible, Real.exp (s m) else 0

/-- Causal GQA: each KV head serves G query heads; pos s is the position of query s -/
noncomputable def causalGQA {S L Hkv G D : ℕ} (scale : ℝ) (pos : Fin S → ℕ)
    (q : Fin S → Fin Hkv → Fin G → Fin D → ℝ)
    (k v : Fin L → Fin Hkv → Fin D → ℝ) : Fin S → Fin Hkv → Fin G → Fin D → ℝ :=
  fun s c g d =>
    let logit : Fin L → ℝ := fun l => scale * ∑ e, q s c g e * k l c e
    ∑ l, softmax logit (fun l => l.val ≤ pos s) l * v l c d

/-- Sliding-window causal GQA: query at position `p` sees keys `l` with `p - w < l ≤ p`. -/
noncomputable def slidingGQA {S L Hkv G D : ℕ} (scale : ℝ) (window : ℕ) (pos : Fin S → ℕ)
    (q : Fin S → Fin Hkv → Fin G → Fin D → ℝ)
    (k v : Fin L → Fin Hkv → Fin D → ℝ) : Fin S → Fin Hkv → Fin G → Fin D → ℝ :=
  fun s c g d =>
    let logit : Fin L → ℝ := fun l => scale * ∑ e, q s c g e * k l c e
    ∑ l, softmax logit (fun l => l.val ≤ pos s ∧ pos s < l.val + window) l * v l c d

/-- Decode attention for one sequence of `L` cached tokens: the output of the query at the last
position `L - 1` (every cached key is visible).  Query head `c·G + g` reads KV head `c`. -/
noncomputable def decodeGQA {L Hkv G D : ℕ} (scale : ℝ) (q : Fin Hkv → Fin G → Fin D → ℝ)
    (k v : Fin L → Fin Hkv → Fin D → ℝ) : Fin Hkv → Fin G → Fin D → ℝ :=
  fun c g d => causalGQA (S := 1) scale (fun _ => L - 1) (fun _ => q) k v 0 c g d

/-- Sigmoid output gate of Gated Attention: `o ⊙ σ(gate)`. -/
noncomputable def sigmoidGate {ι : Type*} {N : ℕ} (o gate : ι → Fin N → ℝ) : ι → Fin N → ℝ :=
  fun t i => o t i * sigmoid (gate t i)

end TheFormalEra.Ops

TheFormalEra/Ops/Linear.lean

import TheFormalEra.Ops.Basic

/-!
# Op Specs: linear maps, feed-forward activations, residuals, embeddings
-/

namespace TheFormalEra.Ops

open Finset

variable {ι : Type*}

/-- `y = x Wᵀ` (bias-free `nn.Linear(K, N)`; `W` is stored `[N, K]`). -/
noncomputable def linear {K N : ℕ} (W : Fin N → Fin K → ℝ) (x : ι → Fin K → ℝ) : ι → Fin N → ℝ :=
  fun t n => ∑ k, x t k * W n k

/-- The fused gate/up projection: `[x W_gateᵀ ‖ x W_upᵀ]`, gate first. -/
noncomputable def gateUp {K I : ℕ} (Wg Wu : Fin I → Fin K → ℝ) (x : ι → Fin K → ℝ) :
    ι → Fin (2 * I) → ℝ :=
  fun t n => if h : n.val < I then linear Wg x t ⟨n.val, h⟩
    else linear Wu x t ⟨n.val - I, by omega⟩

/-- SwiGLU activation of a fused `[gate ‖ up]` row: `silu(gate) ⊙ up`. -/
noncomputable def siluMul {I : ℕ} (gu : ι → Fin (2 * I) → ℝ) : ι → Fin I → ℝ :=
  fun t i => silu (gu t ⟨i.val, by omega⟩) * gu t ⟨I + i.val, by omega⟩

/-- GeGLU (tanh) activation of a fused `[gate ‖ up]` row. -/
noncomputable def geluMul {I : ℕ} (gu : ι → Fin (2 * I) → ℝ) : ι → Fin I → ℝ :=
  fun t i => geluTanh (gu t ⟨i.val, by omega⟩) * gu t ⟨I + i.val, by omega⟩

/-- Residual connection with multiplier `r` (`r = 1` except for Granite). -/
noncomputable def residual {H : ℕ} (r : ℝ) (x h : ι → Fin H → ℝ) : ι → Fin H → ℝ :=
  fun t i => x t i + r * h t i

/-- Token embedding with multiplier `c`. -/
noncomputable def embed {V H T : ℕ} (c : ℝ) (E : Fin V → Fin H → ℝ) (tokens : Fin T → Fin V) :
    Fin T → Fin H → ℝ :=
  fun t i => c * E (tokens t) i

/-- Language-model head with logit multiplier and optional soft-capping. -/
noncomputable def lmHead {V H : ℕ} (mul : ℝ) (cap : Option ℝ) (W : Fin V → Fin H → ℝ)
    (x : ι → Fin H → ℝ) : ι → Fin V → ℝ :=
  fun t v => match cap with
    | none => mul * linear W x t v
    | some c => softcap c (mul * linear W x t v)

end TheFormalEra.Ops

TheFormalEra/Ops/Norm.lean

import TheFormalEra.Ops.Basic

/-!
# Op Specs: normalisation

Every norm normalises the last axis of a tensor whose rows are indexed by an arbitrary type
`ι` (tokens `Fin T`, or `(token, head)` pairs for per-head norms).
-/

namespace TheFormalEra.Ops

open Finset

variable {ι : Type*} {H : ℕ}

/-- `√(mean(x²) + ε)` of one row. -/
noncomputable def rms (eps : ℝ) (x : Fin H → ℝ) : ℝ := Real.sqrt ((∑ j, x j ^ 2) / (H : ℝ) + eps)

/-- RMSNorm with the weight applied as `w` (Qwen3, Granite, Gemma 4). -/
noncomputable def rmsnorm (eps : ℝ) (x : ι → Fin H → ℝ) (w : Fin H → ℝ) : ι → Fin H → ℝ :=
  fun t h => x t h / Real.sqrt ((∑ j, x t j ^ 2) / (H : ℝ) + eps) * w h

/-- RMSNorm in the Qwen3.5 family: the weight is applied as (1 + w) -/
noncomputable def rmsnormOffset (eps : ℝ) (x : ι → Fin H → ℝ) (w : Fin H → ℝ) : ι → Fin H → ℝ :=
  fun t h => x t h / Real.sqrt ((∑ j, x t j ^ 2) / (H : ℝ) + eps) * (1 + w h)

/-- RMSNorm without a weight (Gemma 4 value norm, Muse Glimmer q/k and embedding norms). -/
noncomputable def rmsnormUnit (eps : ℝ) (x : ι → Fin H → ℝ) : ι → Fin H → ℝ :=
  fun t h => x t h / Real.sqrt ((∑ j, x t j ^ 2) / (H : ℝ) + eps)

/-- Gated RMSNorm of the Gated DeltaNet output: `w ⊙ x̂ ⊙ silu(z)`. -/
noncomputable def rmsnormGated (eps : ℝ) (x z : ι → Fin H → ℝ) (w : Fin H → ℝ) : ι → Fin H → ℝ :=
  fun t h => w h * (x t h / Real.sqrt ((∑ j, x t j ^ 2) / (H : ℝ) + eps)) * silu (z t h)

/-- L2 normalisation `x / √(Σ x² + ε)` (queries and keys of the delta rule). -/
noncomputable def l2norm (eps : ℝ) (x : ι → Fin H → ℝ) : ι → Fin H → ℝ :=
  fun t h => x t h / Real.sqrt (∑ j, x t j ^ 2 + eps)

end TheFormalEra.Ops

TheFormalEra/Ops/Rope.lean

import TheFormalEra.Ops.Basic

/-!
# Op Specs: rotary position embeddings

Rotate-half RoPE on the first `rot` coordinates of every head (`rot = D` for full RoPE,
`rot = 64` of `256` for Qwen3.8's partial RoPE), with inverse frequencies
`ω_i = θ^(-2i / denom)` for `i < active` and `ω_i = 0` beyond (Gemma 4's proportional RoPE
rotates the whole head but keeps only the first `active` frequencies).
-/

namespace TheFormalEra.Ops

variable {ι : Type*} {D : ℕ}

/-- Inverse frequency of pair `i`. -/
noncomputable def invFreq (theta : ℝ) (denom active i : ℕ) : ℝ :=
  if i < active then theta ^ (-(2 * (i : ℝ) / denom)) else 0

/-- RoPE at position `pos t` of row `t`; pairs `(i, i + rot/2)` for `i < rot/2`. -/
noncomputable def rope (theta : ℝ) (rot denom active : ℕ) (pos : ι → ℕ) (x : ι → Fin D → ℝ) :
    ι → Fin D → ℝ :=
  fun t d =>
    let half := rot / 2
    if d.val < half then
      let a := (pos t : ℝ) * invFreq theta denom active d.val
      x t d * Real.cos a - (if h : d.val + half < D then x t ⟨d.val + half, h⟩ else 0) * Real.sin a
    else if d.val < 2 * half then
      let a := (pos t : ℝ) * invFreq theta denom active (d.val - half)
      x t d * Real.cos a + x t ⟨d.val - half, by omega⟩ * Real.sin a
    else x t d

/-- Standard (partial) RoPE over the first `rot` coordinates. -/
noncomputable def ropeStd (theta : ℝ) (rot : ℕ) (pos : ι → ℕ) (x : ι → Fin D → ℝ) : ι → Fin D → ℝ :=
  rope theta rot rot (rot / 2) pos x

end TheFormalEra.Ops