Skip to content

Commit 307e2d6

Browse files
committed
feat: add comprehensive benchmarks and examples
Benchmarks (criterion): - orchestrator_bench: query processing, context switching, history - reservoir_bench: ESN update, text encoding, output generation - mlp_bench: forward pass (small/medium/large), softmax, argmax Examples: - basic_usage: demonstrates core orchestrator API - reservoir_demo: shows ESN and context manager integration - mlp_router: demonstrates neural routing with training Usage: cargo bench # Run all benchmarks cargo run --example basic_usage cargo run --example reservoir_demo cargo run --example mlp_router Performance profiling now available for all major components.
1 parent aa40518 commit 307e2d6

7 files changed

Lines changed: 405 additions & 0 deletions

File tree

Cargo.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,18 @@ path = "src/main.rs"
4040
name = "mobile_ai_orchestrator"
4141
path = "src/lib.rs"
4242

43+
[[bench]]
44+
name = "orchestrator_bench"
45+
harness = false
46+
47+
[[bench]]
48+
name = "reservoir_bench"
49+
harness = false
50+
51+
[[bench]]
52+
name = "mlp_bench"
53+
harness = false
54+
4355
[profile.release]
4456
opt-level = "z" # Optimize for size (mobile constraint)
4557
lto = true # Link-time optimization

benches/mlp_bench.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
use criterion::{black_box, criterion_group, criterion_main, Criterion};
2+
use mobile_ai_orchestrator::mlp::MLP;
3+
4+
fn bench_mlp_forward_small(c: &mut Criterion) {
5+
c.bench_function("mlp_forward_small", |b| {
6+
let mlp = MLP::new(10, vec![20], 3);
7+
let input = vec![0.5; 10];
8+
b.iter(|| {
9+
mlp.forward(black_box(&input));
10+
});
11+
});
12+
}
13+
14+
fn bench_mlp_forward_medium(c: &mut Criterion) {
15+
c.bench_function("mlp_forward_medium", |b| {
16+
let mlp = MLP::new(384, vec![100, 50], 3);
17+
let input = vec![0.5; 384];
18+
b.iter(|| {
19+
mlp.forward(black_box(&input));
20+
});
21+
});
22+
}
23+
24+
fn bench_mlp_forward_large(c: &mut Criterion) {
25+
c.bench_function("mlp_forward_large", |b| {
26+
let mlp = MLP::new(1000, vec![500, 250, 100], 10);
27+
let input = vec![0.5; 1000];
28+
b.iter(|| {
29+
mlp.forward(black_box(&input));
30+
});
31+
});
32+
}
33+
34+
fn bench_softmax(c: &mut Criterion) {
35+
c.bench_function("softmax", |b| {
36+
let values = vec![1.0, 2.0, 3.0, 4.0, 5.0];
37+
b.iter(|| {
38+
MLP::softmax(black_box(&values));
39+
});
40+
});
41+
}
42+
43+
fn bench_argmax(c: &mut Criterion) {
44+
c.bench_function("argmax", |b| {
45+
let values = vec![0.1, 0.8, 0.3, 0.5, 0.2];
46+
b.iter(|| {
47+
MLP::argmax(black_box(&values));
48+
});
49+
});
50+
}
51+
52+
criterion_group!(
53+
benches,
54+
bench_mlp_forward_small,
55+
bench_mlp_forward_medium,
56+
bench_mlp_forward_large,
57+
bench_softmax,
58+
bench_argmax
59+
);
60+
criterion_main!(benches);

benches/orchestrator_bench.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use criterion::{black_box, criterion_group, criterion_main, Criterion};
2+
use mobile_ai_orchestrator::{Orchestrator, Query};
3+
4+
fn bench_simple_query(c: &mut Criterion) {
5+
c.bench_function("orchestrator_simple_query", |b| {
6+
let mut orch = Orchestrator::new();
7+
b.iter(|| {
8+
let query = Query::new(black_box("How do I iterate HashMap?"));
9+
orch.process(query).ok()
10+
});
11+
});
12+
}
13+
14+
fn bench_complex_query(c: &mut Criterion) {
15+
c.bench_function("orchestrator_complex_query", |b| {
16+
let mut orch = Orchestrator::new();
17+
b.iter(|| {
18+
let query = Query::new(black_box(
19+
"Can you prove this theorem using formal verification methods?",
20+
));
21+
// This will route to Remote and fail without network, but we benchmark the routing
22+
orch.process(query).ok()
23+
});
24+
});
25+
}
26+
27+
fn bench_context_switching(c: &mut Criterion) {
28+
c.bench_function("context_project_switch", |b| {
29+
let mut orch = Orchestrator::new();
30+
b.iter(|| {
31+
orch.switch_project(black_box("project-1"));
32+
orch.switch_project(black_box("project-2"));
33+
});
34+
});
35+
}
36+
37+
fn bench_conversation_history(c: &mut Criterion) {
38+
c.bench_function("add_conversation_turn", |b| {
39+
let mut orch = Orchestrator::new();
40+
b.iter(|| {
41+
let query = Query::new(black_box("test query"));
42+
orch.process(query).ok();
43+
});
44+
});
45+
}
46+
47+
criterion_group!(
48+
benches,
49+
bench_simple_query,
50+
bench_complex_query,
51+
bench_context_switching,
52+
bench_conversation_history
53+
);
54+
criterion_main!(benches);

benches/reservoir_bench.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use criterion::{black_box, criterion_group, criterion_main, Criterion};
2+
use mobile_ai_orchestrator::reservoir::{encode_text, EchoStateNetwork};
3+
4+
fn bench_esn_update(c: &mut Criterion) {
5+
c.bench_function("esn_update", |b| {
6+
let mut esn = EchoStateNetwork::new(384, 1000, 100, 0.7, 0.95);
7+
let input = vec![0.5; 384];
8+
b.iter(|| {
9+
esn.update(black_box(&input));
10+
});
11+
});
12+
}
13+
14+
fn bench_text_encoding(c: &mut Criterion) {
15+
c.bench_function("encode_text", |b| {
16+
let text = "This is a sample text for encoding benchmark";
17+
b.iter(|| {
18+
encode_text(black_box(text), 384);
19+
});
20+
});
21+
}
22+
23+
fn bench_esn_output(c: &mut Criterion) {
24+
c.bench_function("esn_output", |b| {
25+
let esn = EchoStateNetwork::new(384, 1000, 100, 0.7, 0.95);
26+
b.iter(|| {
27+
esn.output();
28+
});
29+
});
30+
}
31+
32+
fn bench_esn_creation(c: &mut Criterion) {
33+
c.bench_function("esn_creation", |b| {
34+
b.iter(|| {
35+
EchoStateNetwork::new(
36+
black_box(384),
37+
black_box(1000),
38+
black_box(100),
39+
black_box(0.7),
40+
black_box(0.95),
41+
);
42+
});
43+
});
44+
}
45+
46+
criterion_group!(
47+
benches,
48+
bench_esn_update,
49+
bench_text_encoding,
50+
bench_esn_output,
51+
bench_esn_creation
52+
);
53+
criterion_main!(benches);

examples/basic_usage.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
//! Basic usage example of the Mobile AI Orchestrator
2+
//!
3+
//! Run with: cargo run --example basic_usage
4+
5+
use mobile_ai_orchestrator::{Orchestrator, Query};
6+
7+
fn main() {
8+
println!("Mobile AI Orchestrator - Basic Usage Example\n");
9+
10+
// Create orchestrator
11+
let mut orch = Orchestrator::new();
12+
13+
// Example 1: Simple query
14+
println!("=== Example 1: Simple Query ===");
15+
let query1 = Query::new("How do I create a HashMap in Rust?");
16+
match orch.process(query1) {
17+
Ok(response) => {
18+
println!("Response: {}", response.text);
19+
println!("Route: {:?}", response.route);
20+
println!("Confidence: {:.2}", response.confidence);
21+
println!("Latency: {}ms\n", response.latency_ms);
22+
}
23+
Err(e) => println!("Error: {}\n", e),
24+
}
25+
26+
// Example 2: Complex query
27+
println!("=== Example 2: Complex Query ===");
28+
let query2 = Query::new("Can you formally prove the correctness of this sorting algorithm?");
29+
match orch.process(query2) {
30+
Ok(response) => {
31+
println!("Response: {}", response.text);
32+
println!("Route: {:?}", response.route);
33+
}
34+
Err(e) => println!("Error: {} (expected - network not enabled)\n", e),
35+
}
36+
37+
// Example 3: Project context
38+
println!("=== Example 3: Project Context ===");
39+
orch.switch_project("rust-tutorial");
40+
let query3 = Query::new("What did we discuss about lifetimes?");
41+
match orch.process(query3) {
42+
Ok(response) => {
43+
println!("Project: {}", orch.current_project().unwrap());
44+
println!("Response: {}", response.text);
45+
}
46+
Err(e) => println!("Error: {}", e),
47+
}
48+
49+
// Example 4: Conversation history
50+
println!("\n=== Example 4: Conversation History ===");
51+
let history = orch.recent_history(3);
52+
println!("Recent conversations: {}", history.len());
53+
for (i, turn) in history.iter().enumerate() {
54+
println!("{}. Q: {}", i + 1, &turn.query.text[..50.min(turn.query.text.len())]);
55+
}
56+
57+
// Example 5: Blocked query
58+
println!("\n=== Example 5: Safety - Blocked Query ===");
59+
let blocked_query = Query::new("Here's my api_key=sk-12345");
60+
match orch.process(blocked_query) {
61+
Ok(_) => println!("Should have been blocked!"),
62+
Err(e) => println!("Correctly blocked: {}", e),
63+
}
64+
65+
println!("\n✅ All examples completed!");
66+
}

examples/mlp_router.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//! MLP Router example - showing how to use neural network for routing
2+
//!
3+
//! Run with: cargo run --example mlp_router
4+
5+
use mobile_ai_orchestrator::mlp::MLP;
6+
use mobile_ai_orchestrator::reservoir::encode_text;
7+
8+
fn main() {
9+
println!("MLP Router Example\n");
10+
11+
// Create MLP for routing decisions
12+
// Input: 384-dim text encoding
13+
// Hidden: 100 → 50 neurons
14+
// Output: 3 classes (Local, Remote, Hybrid)
15+
let mlp = MLP::new(384, vec![100, 50], 3);
16+
17+
println!("=== MLP Architecture ===");
18+
println!("Input size: {}", mlp.input_size());
19+
println!("Output size: {}", mlp.output_size());
20+
println!("Hidden layers: 100 → 50");
21+
22+
// Example queries
23+
let queries = vec![
24+
"How do I iterate a HashMap?",
25+
"Can you formally prove this theorem?",
26+
"Help me debug this complex multi-threaded race condition",
27+
];
28+
29+
println!("\n=== Routing Decisions ===");
30+
for query in queries {
31+
// Encode query
32+
let encoding = encode_text(query, 384);
33+
34+
// Forward through MLP
35+
let scores = mlp.forward(&encoding);
36+
37+
// Apply softmax to get probabilities
38+
let probs = MLP::softmax(&scores);
39+
40+
// Get decision
41+
let decision = MLP::argmax(&probs);
42+
43+
let labels = ["Local", "Remote", "Hybrid"];
44+
println!("\nQuery: '{}'", query);
45+
println!("Probabilities:");
46+
for (i, (label, prob)) in labels.iter().zip(&probs).enumerate() {
47+
let marker = if i == decision { "→" } else { " " };
48+
println!(" {} {}: {:.3}", marker, label, prob);
49+
}
50+
println!("Decision: {}", labels[decision]);
51+
}
52+
53+
// Example: Training step (simplified)
54+
println!("\n=== Training Example ===");
55+
let mut trainable_mlp = MLP::new(10, vec![20], 3);
56+
let input = vec![1.0; 10];
57+
let target = vec![0.0, 1.0, 0.0]; // Correct answer: Remote
58+
59+
let loss_before = trainable_mlp.train_step(&input, &target, 0.01);
60+
println!("Loss before training: {:.4}", loss_before);
61+
62+
// Train for a few steps
63+
for _ in 0..100 {
64+
trainable_mlp.train_step(&input, &target, 0.01);
65+
}
66+
67+
let loss_after = trainable_mlp.train_step(&input, &target, 0.01);
68+
println!("Loss after 100 steps: {:.4}", loss_after);
69+
println!("Improvement: {:.4}", loss_before - loss_after);
70+
71+
println!("\n✅ MLP router example completed!");
72+
println!("\nNote: In production, train on real user feedback data");
73+
println!("Collect: (query, user-corrected routing decision)");
74+
println!("Train: offline, deploy weights via model update");
75+
}

0 commit comments

Comments
 (0)