open-standards/jouleclaw/jouleclaw-rs/crates/jouleclaw-loader-gguf/tests/real_gemma4_oracle.rs
Transaction Science 8f9a42e4d4 jouleclaw Phase 2: cascade + loader-gguf + pack + history + wire
Five crates ported / designed. All 235 tests pass; 0 errors;
0 warnings outside the loader-gguf NEON-intrinsics module (suppressed
with a documented #![allow(unsafe_op_in_unsafe_fn)] — proper fix is
wrapping each intrinsic call in unsafe { }, tracked as kernel-quality
maintenance, not standards work).

jouleclaw-cascade
  Ported from pattern-lang/joule-cascade (~7044 LOC, 17 files).
  L0 (Cache), tier dispatch, 7-axis Synthesis coordinate router, cost
  model, calibration ledger (in-memory + disk), history, verification,
  body + body_safety policy gates, active-entity tracking, l2_service
  trait surface. Two tests that depended on joule-l1's lawful-primitive
  impl (which requires pattern-lang's pattern-core + cortex-ir +
  synthesizer — OpenIE IP) were removed; the L1 trait surface lives
  here and consumers plug their own lawful lexicon in.

jouleclaw-loader-gguf
  Ported from pattern-lang/joule-loader-gguf (~11605 LOC, 17 files).
  GGUF v3 parser with mmap, Llama and Gemma / Gemma 4 decoders,
  Q4_0 / Q5_K / Q8_0 / Q8_0 grouped quants, in-place KV cache,
  matmul_q8_0 with NEON intrinsics on Apple Silicon, safetensors
  reader, tokenizer + Gemma tokenizer, sample, dequant.

jouleclaw-pack (NEW)
  The .jc.toml sidecar — JouleClaw's standard-defining contribution.
  A model on disk (GGUF / safetensors / MLX) tells you tensor shapes
  and quant schemes. It does NOT tell you what one forward pass
  actually costs in joules on real hardware. The .jc.toml is a
  declared-cost contract that travels with the model:

    - per-tensor precision (FP16/BF16/FP8/INT8/NVFP4/NF4/Q4_K/...)
    - page-alignment status (mmap-zero-copy possible? on which UMA?)
    - measured J/op on a reference hardware matrix with explicit
      Provenance (HwShunt / ModelBased / Estimator)
    - drift_factor tolerance per measurement; the runtime trips
      PackError::CostDrift when measured > declared * drift_factor
      and down-weights the backend in subsequent auction rounds

  Without a declared-cost contract, "energy-optimized inference" is
  marketing. With one, it is an engineering claim any third party
  can verify against the published reference-hardware corpus.

  5 lib tests pass. ModelFormat, Precision, Alignment, MeasurementOp,
  Pack, TensorContract, Measurement, hash_model(), verify_measurement().

jouleclaw-history
  Ported from pattern-lang/joule-history (~2026 LOC, 6 files).
  Persistent resolution history: disk + in-memory + tiered
  (hot/warm/cold) + semantic. One Rust-2024 edition fix in
  tiered.rs (binding-mode pattern: |(_, &seq)| seq -> |(_, seq)| *seq).

jouleclaw-wire
  Ported from pattern-lang/joule-wire (~1129 LOC, 2 files).
  L4 wire tier — the remote frontier escape hatch. RPC client +
  transport, invoked only when the local cascade returns Unresolvable.

Phase 3 next: HAL from efficient-genai, backend-{apple,reference,
cuda,metal,rocm,vulkan}, runtime (port joule-runtime — chat/embed/
generate/streaming/PLD/drafter — needs backends to compile).

Co-Authored-By: Claude Opus 4.7 <[email protected]>
2026-05-26 11:55:46 -04:00

161 lines
6.6 KiB
Rust

//! End-to-end Gemma 4 E2B oracles. Ignored by default — they need
//! the real ~10 GB checkpoint at `models/gemma-4-E2B`.
//!
//! Every test in this file gates **correctness of the model output**
//! against the HF transformers float32 reference. There are no
//! "kernel-runs-without-panic" tests here.
//!
//! Run: `cargo test -p jouleclaw-loader-gguf --test real_gemma4_oracle -- --ignored --nocapture`
use std::io::Write;
const DIR: &str = "/Users/dcharlot/data-share/vibe-coding/pattern-lang/models/gemma-4-E2B";
const OUT: &str = "/Users/dcharlot/data-share/vibe-coding/pattern-lang/tmp/gemma4-oracle";
fn dump(name: &str, v: &[f32]) {
let mut f = std::fs::File::create(format!("{OUT}/rust_{name}.bin")).unwrap();
let mut b = Vec::with_capacity(v.len() * 4);
for x in v {
b.extend_from_slice(&x.to_le_bytes());
}
f.write_all(&b).unwrap();
}
/// Single-pass forward — every staged tensor matches HF and the
/// post-softcap top-5 ids+values are byte-equal to HF's.
#[test]
#[ignore]
fn real_gemma4_e2b_predicts_paris() {
if !std::path::Path::new(DIR).join("config.json").exists() {
eprintln!("skip: gemma-4-E2B not downloaded");
return;
}
let m = jouleclaw_loader_gguf::gemma4::Gemma4::load(DIR).expect("load");
eprintln!(
"loaded gemma4 E2B: {} layers, d={}, vocab={}",
m.cfg.n_layers, m.cfg.d_model, m.cfg.vocab
);
let ids: Vec<u32> = vec![2, 818, 5279, 529, 7001, 563];
let o = m.forward(&ids);
dump("embed", &o.embed);
dump("layer0", &o.layer0);
dump("layer14", &o.layer14);
dump("layer34", &o.layer_last);
dump("final", &o.final_norm);
dump("logits_post", &o.logits_post);
dump("logits_pre", &o.logits_pre);
dump("l0_attn", &o.l0_attn);
dump("l0_post_attn_norm", &o.l0_post_attn_norm);
dump("l0_mlp", &o.l0_mlp);
dump("l0_post_ffw_norm", &o.l0_post_ffw_norm);
dump("l0_post_ple_norm", &o.l0_post_ple_norm);
let mut idx: Vec<usize> = (0..o.logits_post.len()).collect();
idx.sort_by(|&a, &b| o.logits_post[b].partial_cmp(&o.logits_post[a]).unwrap());
let hf_top5 = [9079usize, 496, 506, 3224, 886];
assert_eq!(&idx[..5], &hf_top5, "top-5 ids diverge from HF reference");
let v0 = o.logits_post[idx[0]];
assert!(
(v0 - 22.5101).abs() < 0.05,
"top post-softcap logit {v0} != HF 22.5101 (±0.05)"
);
}
/// Greedy generation (uncached, full re-prefill per step) — 8-token
/// continuation must equal HF `generate(do_sample=False)` exactly.
#[test]
#[ignore]
fn real_gemma4_e2b_greedy_matches_hf() {
if !std::path::Path::new(DIR).join("config.json").exists() {
eprintln!("skip: gemma-4-E2B not downloaded");
return;
}
let m = jouleclaw_loader_gguf::gemma4::Gemma4::load(DIR).expect("load");
let prompt: Vec<u32> = vec![2, 818, 5279, 529, 7001, 563];
let got = m.generate(&prompt, 8);
let hf: Vec<u32> = vec![9079, 236761, 108, 818, 5279, 529, 7001, 563];
eprintln!("rust greedy +8: {got:?}");
eprintln!("HF greedy +8: {hf:?} (' Paris.\\n\\nThe capital of France is')");
assert_eq!(got, hf, "greedy decode diverges from HF reference");
}
/// KV-cached generate equals the uncached path equals HF reference.
#[test]
#[ignore]
fn real_gemma4_e2b_kvcache_parity() {
if !std::path::Path::new(DIR).join("config.json").exists() {
eprintln!("skip: gemma-4-E2B not downloaded");
return;
}
let m = jouleclaw_loader_gguf::gemma4::Gemma4::load(DIR).expect("load");
let prompt: Vec<u32> = vec![2, 818, 5279, 529, 7001, 563];
let hf: Vec<u32> = vec![9079, 236761, 108, 818, 5279, 529, 7001, 563];
let cached = m.generate_cached(&prompt, 8);
assert_eq!(cached, hf, "kv-cached decode diverges from HF reference");
let uncached = m.generate(&prompt, 8);
assert_eq!(cached, uncached, "kv-cached != uncached generate");
}
/// Per-row int8 (Q8) — token-identical to HF on the short prompt.
/// (Note: per-row Q8 *drifts* at the 8th token on the longest
/// benchmark prompt; per-group Q8 below is the production tier.)
#[test]
#[ignore]
fn real_gemma4_e2b_q8_token_identical_on_paris() {
if !std::path::Path::new(DIR).join("config.json").exists() {
eprintln!("skip: gemma-4-E2B not downloaded");
return;
}
let g = jouleclaw_loader_gguf::gemma4::Gemma4::load(DIR).expect("load f32");
let q = jouleclaw_loader_gguf::gemma4_q8::Gemma4Q8::from_gemma4(&g);
let prompt: Vec<u32> = vec![2, 818, 5279, 529, 7001, 563];
let hf: Vec<u32> = vec![9079, 236761, 108, 818, 5279, 529, 7001, 563];
let got = q.generate_cached(&prompt, 8);
eprintln!("Q8 greedy +8: {got:?}");
eprintln!("HF reference: {hf:?}");
assert_eq!(got, hf, "Q8 must match HF on Paris (max_new=8)");
}
/// Per-group int8 (Q8G) — the production tier. Token-identical to HF
/// on both Paris AND the long Jupiter prompt (where per-row Q8 drifts).
#[test]
#[ignore]
fn real_gemma4_e2b_q8g_token_identical() {
if !std::path::Path::new(DIR).join("config.json").exists() {
eprintln!("skip: gemma-4-E2B not downloaded");
return;
}
let g = jouleclaw_loader_gguf::gemma4::Gemma4::load(DIR).expect("load f32");
let q = jouleclaw_loader_gguf::gemma4_q8g::Gemma4Q8G::from_gemma4(&g);
let paris_p: Vec<u32> = vec![2, 818, 5279, 529, 7001, 563];
let paris_hf: Vec<u32> = vec![9079, 236761, 108, 818, 5279, 529, 7001, 563];
let got_paris = q.generate_cached(&paris_p, 8);
assert_eq!(got_paris, paris_hf, "Q8G must match HF on Paris (max_new=8)");
let jup_p: Vec<u32> = vec![2, 818, 7488, 13401, 528, 1023, 10321, 1458, 563];
let jup_hf: Vec<u32> = vec![52895, 236761, 1030, 563, 496, 4314, 16784, 236764];
let got_jup = q.generate_cached(&jup_p, 8);
assert_eq!(got_jup, jup_hf, "Q8G must match HF on Jupiter (max_new=8)");
}
/// Asymmetric per-row per-group int5 (Q5) — the working int4-class
/// quantization. Token-identical to HF f32 on Paris at max_new=8,
/// ~0.78 B/param (between Q4's 0.6 and Q8G's 1.08).
#[test]
#[ignore]
fn real_gemma4_e2b_q5_token_identical() {
if !std::path::Path::new(DIR).join("config.json").exists() {
eprintln!("skip: gemma-4-E2B not downloaded");
return;
}
let g = jouleclaw_loader_gguf::gemma4::Gemma4::load(DIR).expect("load f32");
let q5 = jouleclaw_loader_gguf::gemma4_q5::Gemma4Q5::from_gemma4(&g);
let prompt: Vec<u32> = vec![2, 818, 5279, 529, 7001, 563];
let hf: Vec<u32> = vec![9079, 236761, 108, 818, 5279, 529, 7001, 563];
let got = q5.generate_cached(&prompt, 8);
eprintln!("Q5 +8: {got:?}");
eprintln!("HF : {hf:?}");
assert_eq!(got, hf, "Q5 must match HF on Paris (max_new=8)");
}