mirror of
https://github.com/ruvnet/RuView
synced 2026-07-22 17:23:19 +00:00
a47bb71b22
ADR-185 §13 flagged the `[aether]` wheel as linking the whole
`wifi-densepose-sensing-server` Axum/tokio/worldgraph/ruvector tree via the
non-optional deps of that crate. Hoist the pure-compute AETHER stack out so the
binding depends only on pure Rust.
New crate `wifi-densepose-aether` (std-only, ZERO external deps) holds the four
self-contained modules the AETHER surface needs — `embedding`, `graph_transformer`,
`sona`, `sparse_inference` (verified: no serde/tokio/axum/crate:: refs outside the
set; the four form a closed dependency graph). `wifi-densepose-sensing-server`
now `pub use`s them from the leaf crate, so its own code (`crate::embedding`, …)
and public API (`wifi_densepose_sensing_server::embedding`, …) are unchanged —
`main.rs`/`trainer.rs` untouched. The Python binding + parity test + `[aether]`
feature repoint at the leaf crate; the sensing-server dep is dropped from python.
MEASURED wheel size (maturin build --release --features aether --strip; each
wheel install-verified to actually contain `AetherConfig`):
BEFORE (aether -> sensing-server): 369,782 B (~361 KB)
AFTER (aether -> leaf crate): 319,719 B (~312 KB)
HONEST CORRECTION to the §9/§13 premise: the pre-hoist wheel was NOT over the
ADR-117 §5.4 5 MB budget — it was ~361 KB, ~14x under. Linker dead-code
elimination (--gc-sections on the pyo3 cdylib) already strips the unreached
server tree because the binding only reaches pure-compute symbols. So this is
"blows the budget" CLAIMED, not MEASURED. The hoist is still worthwhile and
lands the real, measured wins:
- `[aether]` build time 71s -> 12s (no server tree to compile),
- python/Cargo.lock -1238 lines (server tree no longer resolved),
- ~50 KB smaller wheel,
- honest, minimal declared dependency surface + removes the latent risk that a
future change makes some server code reachable and *then* bloats the wheel.
Verified this session (real counts):
- cargo test --features aether --test aether_parity: 2 passed / 0 failed
- pytest tests/test_aether.py (maturin develop --features aether): 9 passed
- cargo test -p wifi-densepose-sensing-server --no-default-features: 217 bin +
388 lib, 0 failed (no regression)
- cargo test -p wifi-densepose-aether: 96 passed (the relocated unit tests)
The §9/§13 wheel-size narrative in ADR-185 (owned by the ADR author) should be
corrected to reflect the measured reality — flagged to the team lead.
100 lines
3.2 KiB
Rust
100 lines
3.2 KiB
Rust
//! ADR-185 §4.1 — AETHER bit-for-bit parity: native-Rust reference half.
|
|
//!
|
|
//! Produces the golden 128-dim embedding by calling the canonical
|
|
//! `wifi-densepose-aether::embedding` code DIRECTLY (no PyO3),
|
|
//! for the committed `tests/golden/aether_input.json` fixture, and locks
|
|
//! its SHA-256 into `tests/golden/aether_embedding.sha256`.
|
|
//!
|
|
//! The pytest half (`tests/test_aether.py`) independently runs the same
|
|
//! fixture through the Python binding and asserts the identical hash —
|
|
//! together they prove the binding is byte-identical to native Rust.
|
|
//!
|
|
//! Regeneration (only when the Rust subsystem intentionally changes):
|
|
//! delete `tests/golden/aether_embedding.sha256` and re-run
|
|
//! `cargo test --features aether`.
|
|
#![cfg(feature = "aether")]
|
|
|
|
use std::fs;
|
|
use std::path::PathBuf;
|
|
|
|
use sha2::{Digest, Sha256};
|
|
use wifi_densepose_aether::embedding::{EmbeddingConfig, EmbeddingExtractor};
|
|
use wifi_densepose_aether::graph_transformer::TransformerConfig;
|
|
|
|
fn golden_dir() -> PathBuf {
|
|
PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
|
.join("tests")
|
|
.join("golden")
|
|
}
|
|
|
|
fn load_input() -> Vec<Vec<f32>> {
|
|
let raw = fs::read_to_string(golden_dir().join("aether_input.json"))
|
|
.expect("read aether_input.json fixture");
|
|
let rows: Vec<Vec<f64>> = serde_json::from_str(&raw).expect("parse aether_input.json");
|
|
rows.into_iter()
|
|
.map(|row| row.into_iter().map(|x| x as f32).collect())
|
|
.collect()
|
|
}
|
|
|
|
/// Build the extractor identically to the Python binding's default
|
|
/// construction: `AetherConfig()` + `EmbeddingExtractor(n_subcarriers=56, cfg)`.
|
|
fn embed_native(input: &[Vec<f32>]) -> Vec<f32> {
|
|
let e_config = EmbeddingConfig {
|
|
d_model: 64,
|
|
d_proj: 128,
|
|
temperature: 0.07,
|
|
normalize: true,
|
|
};
|
|
let t_config = TransformerConfig {
|
|
n_subcarriers: 56,
|
|
n_keypoints: 17,
|
|
d_model: 64,
|
|
n_heads: 4,
|
|
n_gnn_layers: 2,
|
|
};
|
|
let mut ext = EmbeddingExtractor::new(t_config, e_config);
|
|
ext.extract(input)
|
|
}
|
|
|
|
fn sha256_le(embedding: &[f32]) -> String {
|
|
let mut hasher = Sha256::new();
|
|
for &x in embedding {
|
|
hasher.update(x.to_le_bytes());
|
|
}
|
|
hasher
|
|
.finalize()
|
|
.iter()
|
|
.map(|b| format!("{b:02x}"))
|
|
.collect()
|
|
}
|
|
|
|
#[test]
|
|
fn native_embedding_is_128_dim_unit_norm() {
|
|
let emb = embed_native(&load_input());
|
|
assert_eq!(emb.len(), 128, "AETHER embedding must be 128-dim");
|
|
let norm: f32 = emb.iter().map(|x| x * x).sum::<f32>().sqrt();
|
|
assert!(
|
|
(norm - 1.0).abs() < 1e-4,
|
|
"embedding must be L2-normalized, got norm={norm}"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn native_embedding_matches_committed_golden() {
|
|
let emb = embed_native(&load_input());
|
|
let got = sha256_le(&emb);
|
|
let path = golden_dir().join("aether_embedding.sha256");
|
|
match fs::read_to_string(&path) {
|
|
Ok(expected) => assert_eq!(
|
|
got,
|
|
expected.trim(),
|
|
"native AETHER embedding hash drifted from committed golden \
|
|
(intentional? delete the .sha256 and regenerate)"
|
|
),
|
|
Err(_) => {
|
|
fs::write(&path, &got).expect("write golden sha256");
|
|
panic!("no committed golden found; wrote {got}. Re-run to verify parity.");
|
|
}
|
|
}
|
|
}
|