Skip to content

feat(inference): prove Gemma 4 F32 first-token parity (ST5) - #63

Merged
ezutfen merged 5 commits into
mainfrom
feat/larql-inference-trust-001a-st5
Jul 12, 2026
Merged

feat(inference): prove Gemma 4 F32 first-token parity (ST5)#63
ezutfen merged 5 commits into
mainfrom
feat/larql-inference-trust-001a-st5

Conversation

@ezutfen

@ezutfen ezutfen commented Jul 12, 2026

Copy link
Copy Markdown

LARQL-INFERENCE-TRUST-001A-ST5 — F32 CPU first-token semantic parity

Decision: GREEN — LARQL's canonical F32 CPU forward matches the pinned Transformers CPU float32 eager oracle for all four ST3 prompts.

Evidence

All four prompts: first_divergence: null, top-1 exact, top-10 overlap 10/10, logit nrmse ~1e-6 (float32 reduction-order noise):

prompt top-1 (ref==cand) top-10 overlap logit max_abs logit nrmse
raw_completion 9079==9079 10/10 5.2e-5 6.9e-7
chat 818==818 10/10 3.2e-5 4.8e-7
arithmetic 236800==236800 10/10 6.5e-5 1.1e-6
multiturn 16520==16520 10/10 3.9e-5 2.4e-7

What this PR adds

  • larql-inference::parity — trace interchange format (deterministic manifest + raw LE f32 tensors), the committed numerical comparator (coarse nrmse≤1e-4 / cosine≥0.99999; final logits + top-1 exact + top-10 overlap≥9/10), first-divergence drill-down in execution order, and LARQL F32 production-path capture.
  • larql-compute hooks — read-only on_post_ffn/on_post_ple boundary taps (zero-cost no-op defaults) + forward_raw_logits_traced reusing the canonical primitives.
  • scripts/gemma4_first_token_oracle.py — forward-only, eager, torch.float32, CPU, use_cache=false, never generate(); non-invasive pre-hook capture.
  • 9 synthetic diagnostic self-tests (section 7) + the env-gated gemma4_first_token_parity test (soft-skips CI without the 18.65 GB artifact).

Correction made (trace-proven layer-4 first divergence)

Gemma 4 global (full_attention) layers ship HF rope_type='proportional': RoPE inv_freq exponents are divided by the full head_dim (512) and zero-padded to head_dim/2, then half-split over the full head. LARQL divided by rotary_dim (128) and half-split within it — so the first global-attention layer (layer 4) diverged (cosine ~0.9997) while sliding layers (0–3) matched. Fixed by adding RopeFreqMode::{Standard, Proportional} and applying it consistently across the CPU block / decode / kv-prefill (gpu.rs CPU fallback) paths. ST4/ST4A local/global + shared-KV regressions remain green.

Validation

  • cargo fmt --all -- --check — clean
  • cargo test -p {larql-models,larql-compute,larql-inference,larql-kv,larql-vindex} — all pass, 0 failures
  • cargo clippy -p {larql-models,larql-compute,larql-inference,larql-kv,larql-vindex} --all-targets -- -D warnings — clean
  • cargo build -p larql-cli --release — passes
  • Official parity (env-gated, separate-process oracle + LARQL comparison) — GREEN

Scope exclusions

multi-token generation, sampling, KV-cached decode, Q4_K, CUDA, Vulkan, Metal, performance optimization, production quantization, multimodal inputs, tools/thinking-enabled prompts.

Recommended next slice

LARQL-INFERENCE-TRUST-001A-ST6 — Production Q4_K semantic parity against the proven F32 reference.

ezutfen added 5 commits July 12, 2026 15:32
Add the ST5 first-token semantic-parity harness and prove LARQL's
canonical F32 CPU forward matches the pinned Transformers CPU float32
eager oracle for all four ST3 prompts (first_divergence: null, top-1
exact, top-10 overlap >= 9/10, logit nrmse ~1e-6).

Trace capture + interchange format (larql-inference::parity):
- format.rs: deterministic manifest binding each tensor to (prompt,
  stage, layer, shape, dtype, element_count, sha256) with raw LE f32
  files; rejects missing/duplicate/shape/dtype/truncated/hash/non-finite.
- compare.rs: committed numerical policy (coarse nrmse<=1e-4, cosine
  >=0.99999; final logits + top-1 exact + top-10 overlap>=9/10) with
  first-divergence drill-down in execution order; f64 accumulation.
- capture.rs: runs the production forward via forward_raw_logits_traced
  and writes the last-token row of every coarse boundary.

Substrate hooks (larql-compute): LayerHook gains read-only
on_post_ffn / on_post_ple boundary taps (zero-cost no-op defaults);
forward_raw_logits_traced reuses the canonical embed/layer/ple/norm/
lm-head primitives.

Oracle (scripts/gemma4_first_token_oracle.py): forward-only, eager,
torch.float32, CPU, use_cache=false, never generate(); non-invasive
pre-hook capture.

Proportional-RoPE correction (the trace-proven layer-4 first divergence):
Gemma 4 global layers ship HF rope_type='proportional' — inv_freq
exponents over the full head_dim, zero-padded to head_dim/2, half-split
over the full head. LARQL divided by rotary_dim and half-split within
it. Add RopeFreqMode and apply it across the CPU block, decode, and
kv-prefill (gpu.rs CPU fallback) paths. Sliding layers are unaffected,
so ST4/ST4A local/global + shared-KV regressions stay green.

Tests: 9 synthetic diagnostic self-tests (ST5 section 7) + proportional
regression tests; env-gated gemma4_first_token_parity soft-skips CI.
The ST5 proportional-RoPE change added the rope_freq_mode_for_layer trait
default to config.rs; without a caller it dropped config.rs line coverage
to 89.47%, tripping the per-file 90% gate. Exercise the default (Standard)
via the generic-architecture trait-contract test.
The ST5 traced forward added forward_raw_logits_traced + TracedTail to
predict/raw.rs; exercised only by the larql-inference parity tests, it
dropped raw.rs line coverage to 77.52%, tripping the per-file 90% gate.
Add a lib unit test that runs the traced forward with a RecordHook and
asserts every per-layer boundary + tail stage matches forward_raw_logits
(same math).
The ST5 test/format additions were committed before a final per-package
rustfmt pass; cargo fmt --all and cargo fmt -p <crate> resolved a few
assert/call-chain wrappings differently. Reformat so every per-package
fmt check (the CI gate) passes alongside the workspace check.
@ezutfen
ezutfen merged commit 6e2bab4 into main Jul 12, 2026
35 of 36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant