openpay/ (+3 crates, ~8400 LOC, 162 tests)
op-iso8583/ ISO 8583 messages for direct acquirer / card-network
connectivity. MTIs, primary+secondary bitmaps, full
DE catalogue, BCD/ASCII/EBCDIC/LLVAR/LLLVAR codecs,
five dialects (Visa Base I, Mastercard MDS, Amex GNS,
Discover, JCB), network-management messages
(sign-on/echo/cutover), DE 55 EMV TLV.
op-mobile-wallets/ Apple Pay (ECDH-P256 + AES-256-GCM), Google Pay ECv2
(ECDH + HKDF + AES-256-CTR + HMAC), Samsung Pay. PAN
never leaves the decryption boundary as a String;
lands in VaultRef. No-PAN-leakage assertions per
wallet.
op-routing/ Least-cost routing + MCC-aware routing + intelligent
retry / soft-decline recovery. 231-MCC catalogue.
Real ISO 8583 DE-39 soft/hard decline taxonomies.
smart-byte/smart-byte-rs/ (+3 crates, ~7100 LOC, 96 tests)
smart-byte-vc/ W3C Verifiable Credentials 2.0: VCDM, presentations,
Data Integrity proofs (eddsa-jcs-2022), VC-JWT,
SD-JWT (selective disclosure), Bitstring Status
List 2021. Cargo-bridge maps VCs to Smart Byte
envelopes with SAID stability.
smart-byte-did/ W3C DID resolution: did:key (Ed25519/P-256/secp256k1),
did:web (HTTPS), did:peer (numalgo 2+4), did:jwk,
did:ion (feature-gated stub). DID URL dereferencer.
smart-byte-pq/ Post-quantum signatures: ML-DSA-44/65/87 (FIPS 204),
SLH-DSA across 12 parameter sets (FIPS 205), FN-DSA
(draft FIPS 206, feature-gated). Hybrid Ed25519 +
ML-DSA pattern for the transition. Secret-key
zeroize-on-drop.
eoc/eoc-rs/ (+3 crates, ~6450 LOC, 76 tests)
eoc-vendor-api/ NeuralBackend implementations: Anthropic, OpenAI,
Google, Mistral, Cohere, Groq, Together, Fireworks.
SSE streaming. Prompt-caching where supported.
Joule estimates per published energy coefficient
(12-model curated table).
eoc-embeddings/ 21 embedding models behind one Embedder trait:
OpenAI v3 (3), Cohere v3 (3), Voyage (5), Mistral,
Jina, plus local ONNX (BGE x3, nomic, mxbai, GTE,
E5) behind 'local' feature. Matryoshka-style
dimension projection. Per-content-hash cache.
eoc-route-learned/ RouteLLM-style matrix-factorisation router +
multinomial-logreg classifier + LinUCB / Thompson
bandits for online learning. LearnedCascade wraps
the rule-based cascade with a confidence-threshold
skip policy. Synthetic-eval accuracy: MF 0.935,
LogReg 0.980.
Quality:
- cargo check across all three workspaces: clean
- cargo clippy --all-targets -- -D warnings on every new crate: clean
- 334 new tests total; all passing
- #![forbid(unsafe_code)] across every new crate
- No unwrap/expect outside #[cfg(test)]
Rust 1.95.0 edition 2024 (inherited via root rust-toolchain.toml).
114 lines
4.2 KiB
Rust
114 lines
4.2 KiB
Rust
//! End-to-end LearnedCascade test.
|
|
//!
|
|
//! Build a real four-stage cascade, route a "novel" query through it twice
|
|
//! and compare joule cost between:
|
|
//!
|
|
//! - the baseline `Cascade` (which walks cache → kv → graph → neural), and
|
|
//! - a `LearnedCascade` whose router picks `Neural` with confidence 1.0.
|
|
//!
|
|
//! Both must produce the same answer; the learned variant must be cheaper
|
|
//! (or at worst equal) because it skips three doomed cache/kv/graph misses.
|
|
|
|
use std::collections::HashMap;
|
|
use std::sync::Arc;
|
|
|
|
use async_trait::async_trait;
|
|
use eoc_cache::LruCache;
|
|
use eoc_cascade::Cascade;
|
|
use eoc_core::{Query, Stage};
|
|
use eoc_graph::GraphStage;
|
|
use eoc_kv::{KvStage, MemoryKvBackend};
|
|
use eoc_neural::{EchoBackend, NeuralStage};
|
|
use eoc_route_learned::inference::LearnedCascade;
|
|
use eoc_route_learned::router::{LearnedRouter, RouterState, StagePrediction};
|
|
use eoc_route_learned::threshold::ThresholdPolicy;
|
|
|
|
/// A trivial router that always picks `Neural` with full confidence.
|
|
struct AlwaysNeural;
|
|
|
|
#[async_trait]
|
|
impl LearnedRouter for AlwaysNeural {
|
|
async fn route(&self, _query: &Query) -> StagePrediction {
|
|
StagePrediction::new(Stage::Neural, 1.0)
|
|
}
|
|
async fn observe(&mut self, _q: &Query, _s: Stage, _ok: bool, _j: u64) {}
|
|
fn export_state(&self) -> RouterState {
|
|
RouterState {
|
|
algorithm: "always_neural".into(),
|
|
weights_blob: vec![],
|
|
metadata: Default::default(),
|
|
}
|
|
}
|
|
fn import_state(_state: RouterState) -> eoc_route_learned::Result<Self> {
|
|
Ok(AlwaysNeural)
|
|
}
|
|
}
|
|
|
|
fn fixture() -> Cascade {
|
|
let cache = Arc::new(LruCache::new(8));
|
|
let kv_backend = Box::new(MemoryKvBackend::new());
|
|
let kv = Arc::new(KvStage::new(kv_backend));
|
|
let graph = Arc::new(GraphStage::new());
|
|
let neural = Arc::new(NeuralStage::new(Box::new(
|
|
EchoBackend::new().with_cost(50_000),
|
|
)));
|
|
Cascade::new(cache, kv, graph, neural)
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn learned_cascade_routes_to_neural_when_confident() {
|
|
let cascade = Arc::new(fixture());
|
|
let learned = LearnedCascade::new(cascade, AlwaysNeural, ThresholdPolicy::new(0.9));
|
|
let resp = learned.resolve(Query::new("novel query")).await;
|
|
assert_eq!(resp.stage, Stage::Neural);
|
|
assert!(resp.payload.contains("novel query"));
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn learned_cascade_skip_saves_joules_vs_baseline() {
|
|
// Baseline path: full cascade, neural answers — pays neural cost only.
|
|
// Both should answer with the neural stage in this fixture, so this is
|
|
// mostly a smoke test that skip-mode doesn't *increase* cost.
|
|
let baseline = fixture();
|
|
let baseline_response = baseline.resolve(Query::new("brand new prompt")).await;
|
|
|
|
let cascade = Arc::new(fixture());
|
|
let learned = LearnedCascade::new(cascade, AlwaysNeural, ThresholdPolicy::new(0.9));
|
|
let learned_response = learned.resolve(Query::new("brand new prompt")).await;
|
|
|
|
assert_eq!(learned_response.stage, Stage::Neural);
|
|
// The learned cascade can't be more expensive than the baseline.
|
|
assert!(
|
|
learned_response.joule_cost.microjoules <= baseline_response.joule_cost.microjoules + 1
|
|
);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn learned_cascade_falls_through_to_full_cascade_when_unconfident() {
|
|
/// Low-confidence router → policy says FullCascade.
|
|
struct LowConf;
|
|
#[async_trait]
|
|
impl LearnedRouter for LowConf {
|
|
async fn route(&self, _q: &Query) -> StagePrediction {
|
|
StagePrediction::new(Stage::Neural, 0.1)
|
|
}
|
|
async fn observe(&mut self, _q: &Query, _s: Stage, _ok: bool, _j: u64) {}
|
|
fn export_state(&self) -> RouterState {
|
|
RouterState {
|
|
algorithm: "low".into(),
|
|
weights_blob: vec![],
|
|
metadata: Default::default(),
|
|
}
|
|
}
|
|
fn import_state(_s: RouterState) -> eoc_route_learned::Result<Self> {
|
|
Ok(LowConf)
|
|
}
|
|
}
|
|
|
|
let cascade = Arc::new(fixture());
|
|
let learned = LearnedCascade::new(cascade, LowConf, ThresholdPolicy::new(0.9));
|
|
let resp = learned.resolve(Query::new("anything")).await;
|
|
// Baseline cascade resolves novel queries with the neural stage.
|
|
assert_eq!(resp.stage, Stage::Neural);
|
|
let _ = HashMap::<u32, u32>::new(); // suppress unused-import warnings
|
|
}
|