Phase 2 of the world-model ingest: a generative interactive world whose every frame
is byte-exact. Genie / Oasis / Matrix / fal-WMA generate the next frame from an
action through a FLOAT network and stream the pixels, so the world is
non-reproducible, unmetered, ephemeral. Here the world model is integer:
frame_0 = g_s(z_0); z_{t+1} = clip( T( z_t ‖ action_t ) ); frame_{t+1} = g_s(z_{t+1})
BOTH the transition T and the synthesis g_s are int_hyper IntModels (WHM1: per-out
int12 weights, integer IGDN/leaky, all i64); the action is folded in as constant
input planes; the latent is clamped each step so the recurrence stays bounded. So
given (model, z_0, action trace) every frame is byte-identical on every machine.
Paired with wai.world.model's signed, replay-equivalent action trace (Phase 1),
both the trace AND the generated frames hash-converge — a generative interactive
world you can put in a receipt.
- src/int_world.rs (feature world_int = ["neural_int"]): reuses int_hyper_synth
run_net + decode for T and g_s; step() builds [c+A] input (latent ‖ dx/dy/btn
planes), runs T, clamps; decode() rolls the action trace → per-frame + clip hash.
- tools/wai_int_world_export.py: trains a small action-conditioned next-frame model
(E + recurrent T + g_s, free-rolled) on a navigable procedural world, PTQs T and
g_s to WHM1, runs an INTEGER reference decode mirroring the Rust loop → frame
hashes. float SNR 17.9 / integer 17.2 dB (PTQ ~lossless).
- examples/int_world_decode.rs + tests/int_world.rs (never-skip): the committed
tiny vector (z0 + an 8-action walk + the two models) regenerates 9 frames whose
per-frame + clip hash (1cc16522e5d57982) reproduce byte-for-byte. Rust == Python.
- wai-web: WorldModel{new,reset,step} stateful stepper (arrow-key live play) +
worldSessionHash (in-browser signed-trace replay → session hash); same pure-i64
decode in the browser.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
29 lines
1.6 KiB
Rust
29 lines
1.6 KiB
Rust
//! Decode an interactive world-model clip dir (`world_T.bin`, `world_gs.bin`,
|
|
//! `world.json`, from `tools/wai_int_world_export.py`) → RGB frames; print the clip
|
|
//! hash + frame-0 hash, optionally dump the raw frames. Proves the Rust integer world
|
|
//! decode reproduces the Python integer reference byte-for-byte.
|
|
//!
|
|
//! cargo run --release --example int_world_decode --features world_int -- <dir> [out.rgb]
|
|
|
|
use wai::int_hyper_synth::IntModel;
|
|
use wai::int_world::decode;
|
|
|
|
fn main() {
|
|
let dir = std::env::args().nth(1).expect("usage: int_world_decode <dir> [out.rgb]");
|
|
let t = IntModel::from_bytes(&std::fs::read(format!("{dir}/world_T.bin")).unwrap()).unwrap();
|
|
let gs = IntModel::from_bytes(&std::fs::read(format!("{dir}/world_gs.bin")).unwrap()).unwrap();
|
|
let j: serde_json::Value =
|
|
serde_json::from_slice(&std::fs::read(format!("{dir}/world.json")).unwrap()).unwrap();
|
|
let c = j["c"].as_u64().unwrap() as usize;
|
|
let lat = j["lat"].as_u64().unwrap() as usize;
|
|
let z0: Vec<i64> = j["z0"].as_array().unwrap().iter().map(|v| v.as_i64().unwrap()).collect();
|
|
let actions: Vec<usize> = j["actions"].as_array().unwrap().iter().map(|v| v.as_u64().unwrap() as usize).collect();
|
|
|
|
let clip = decode(&t, &gs, &z0, &actions, c, lat);
|
|
println!("frames {} {}x{} frame0 {:016x} clip {:016x}",
|
|
clip.frames.len(), clip.frame_px, clip.frame_px, clip.frame_hash(0), clip.clip_hash());
|
|
if let Some(out) = std::env::args().nth(2) {
|
|
let bytes: Vec<u8> = clip.frames.iter().flatten().copied().collect();
|
|
std::fs::write(out, bytes).unwrap();
|
|
}
|
|
}
|