Model Spec
ibm-granite/granite-4.2-3b @1.0.0
granite · 40 layers · hidden 2560 · 3.66 B parameters · language model
theformalera pull with "ibm-granite/granite-4.2-3b" = { version = "^1.0" }
· digest sha256:39f622ebf2401e1bd54076d… · 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 runPublisher verification
verifiedPublic audit
Lean source public; spec errors earn a bountyCompute graph
| node | layers | Op Spec | formula | constants | Lemma Hub |
|---|---|---|---|---|---|
embed | — | embed | y[t] = 1 · w[tokens[t]] | mul=1, norm=False | 0 |
layers[*].input_norm | 0, 1, …, 39 (40) | rmsnorm | y[t,i] = x[t,i] / √(Σⱼ x[t,j]² / H + ε) · w[i] | H=2560, eps=1e-05 | 0 |
layers[*].attn.qkv_proj | 0, 1, …, 39 (40) | linear | y[t,n] = Σₖ x[t,k] · w[n,k] | K=2560, N=3584 | 0 |
layers[*].attn.rope | 0, 1, …, 39 (40) | rope | rotate pairs (i, i + 32) by pos · θ^(-2i/64), i < 32; coordinates ≥ 64 unchanged | D=64, active=32, denom=64, rot=64, theta=10000000 | 0 |
layers[*].attn.core | 0, 1, …, 39 (40) | decodeGQA | o[b,h] = Σ_{s < seq_lens[b]} softmax_s(1/64 · ⟨q[b,h], k[b,s,h / 5]⟩) · v[b,s,h / 5] | D=64, heads=40, kv_heads=8, scale=1/64, window=None | 0 |
layers[*].attn.o_proj | 0, 1, …, 39 (40) | linear | y[t,n] = Σₖ x[t,k] · w[n,k] | K=2560, N=2560 | 0 |
layers[*].attn_residual | 0, 1, …, 39 (40) | residual | y = x + h | H=2560, layer_scalar=False, r=1 | 0 |
layers[*].post_attn_norm | 0, 1, …, 39 (40) | rmsnorm | y[t,i] = x[t,i] / √(Σⱼ x[t,j]² / H + ε) · w[i] | H=2560, eps=1e-05 | 0 |
layers[*].mlp.gate_up | 0, 1, …, 39 (40) | linear | y[t,n] = Σₖ x[t,k] · w[n,k] | K=2560, N=16384 | 0 |
layers[*].mlp.act | 0, 1, …, 39 (40) | siluMul | y[t,i] = silu(gate_up[t,i]) · gate_up[t,8192+i] | I=8192, act=silu | 0 |
layers[*].mlp.down | 0, 1, …, 39 (40) | linear | y[t,n] = Σₖ x[t,k] · w[n,k] | K=8192, N=2560 | 0 |
layers[*].mlp_residual | 0, 1, …, 39 (40) | residual | y = x + h | H=2560, layer_scalar=False, r=1 | 0 |
final_norm | — | rmsnorm | y[t,i] = x[t,i] / √(Σⱼ x[t,j]² / H + ε) · w[i] | H=2560, eps=1e-05 | 0 |
lm_head | — | lmHead | z = x wᵀ | mul=1, softcap=None, tied=False | 0 |
Domains
shape B ∈ [1, 256], S ∈ [1, 131072], T ∈ [1, 131072], page_size ∈ [16, 16]
value activation: |x| ≤ 65504 (bf16), norm_weight: |x| ≤ 64 (bf16), weight: |x| ≤ 64 (bf16)
value activation: |x| ≤ 65504 (bf16), norm_weight: |x| ≤ 64 (bf16), weight: |x| ≤ 64 (bf16)
Theorems (Lean kernel-checked)
forward_causal | Every model of the specification is causal (all configurations, all scalar types). | ✓ |
attnHead_local | An attention head only reads visible positions (causal mask + sliding window). | ✓ |
softmax_shift | Softmax is invariant under the subtracted reference value (max-subtraction is sound). | ✓ |
softmax_sum_one | Attention weights sum to one. | ✓ |
attnWeights_distribution | Attention weights form a probability distribution over the visible keys. | ✓ |
rope_relative | RoPE encodes relative positions: ⟨R_p q, R_p' k⟩ = ⟨R_(p-p') q, k⟩ (all RoPE variants). | ✓ |
rope_isometry | RoPE preserves inner products. | ✓ |
deltaRule_causal | The gated delta rule is causal. | ✓ |
deltaStep_read_key | The delta rule stores v under a unit key k exactly (β = 1, no decay). | ✓ |
causalConv_causal | The depthwise convolution of the Gated DeltaNet is causal. | ✓ |
runTrace_fst | The oracle's layer trace computes the specification's residual stream. | ✓ |
seqMap_eq_seqMapPar | The parallel position-wise evaluator computes the specification (@[csimp]). | ✓ |
linear_eq_linearPar | The parallel matrix-vector product computes the specification (@[csimp]). | ✓ |
registry_wellFormed | All 8 checkpoint specifications and their reduced versions are well formed. | ✓ |
reduced_same_architecture | Each reduced configuration has the architecture of its checkpoint. | ✓ |
qwen3_8_27b_pattern | Qwen3.8-27B: layer i is full attention iff i % 4 = 3. | ✓ |
gemma4_12b_pattern | Gemma 4 12B: layer i is global iff i % 6 = 5. | ✓ |
gemma4_31b_pattern | Gemma 4 31B: layer i is global iff i % 6 = 5. | ✓ |
museGlimmer_global_iff_nope | Muse Glimmer: global layers are exactly the NoPE layers. | ✓ |
qwen3_0_6b_params | Qwen3-0.6B text model has 596,049,920 parameters. | ✓ |
tiledSum_eq | Kernels: a tiled (masked) reduction equals the plain reduction, for every tile size. | ✓ |
rmsNormTiled_eq | Kernels: tiled RMSNorm = RMSNorm of the specification, for every block size and weight kind. | ✓ |
flashAttn_eq | Kernels: FlashAttention (online softmax, block skipping) = attention head of the specification. | ✓ |
flashAttn_tile_eq | Kernels: the kernels' key-block bounds (causal / sliding window) visit every visible key. | ✓ |
chunkDeltaRule_eq | Kernels: chunked (WY-form) gated delta rule = recurrent delta rule, for every chunk size. | ✓ |
Ops.gdnState_succ | Op Specs: the gated delta rule state recurrence is the iterated decode step. | ✓ |
Engine.Implements.ofLanes | Engine: the verification contract follows from a decoder, a witness and per-lane values. | ✓ |
Engine.sum_fin_trunc | Engine: lanes of a tile beyond the logical extent contribute nothing to a reduction. | ✓ |
Engine.tiled_range | Engine: a tiled loop accumulation equals the plain reduction (every tile size). | ✓ |
Engine.strided_inj3 | Engine: non-overlapping strided layouts are injective. | ✓ |
Engine.rmsnormOffset_zld | Engine: closed form of the (1 + w) RMSNorm Op Spec at integer indices. | ✓ |
Engine.linear_zld | Engine: closed form of the linear Op Spec at integer indices. | ✓ |
Engine.LemmaHub.tanh_eq_exp | Lemma Hub (built-in): tanh x = (exp 2x − 1)/(exp 2x + 1). | ✓ |
Lemmas.tiled_masked_sum | Lemma Hub (built-in): a masked tiled traversal covers [0, n) exactly once. | ✓ |
Lemmas.tiled_floor_misses | Lemma Hub (built-in): ⌊n/B⌋ tiles miss the tail when B ∤ n. | ✓ |
Lemmas.online_softmax_rescale | Lemma Hub (built-in): online softmax rescaling by exp(m − m'). | ✓ |
Lemmas.splitKV_lse_merge | Lemma Hub (built-in): split-KV merging in log-sum-exp form equals full attention. | ✓ |
Versions
| version | digest | published | |
|---|---|---|---|
| 1.0.0 | sha256:39f622ebf2401e1b… | 2026-11-01T06:23:07+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