Case Study: APR CLI Commands Demo
This case study demonstrates creating test models and using all 17 apr-cli commands for model inspection, validation, transformation, testing, and inference.
The Problem
APR model files need comprehensive tooling for:
| Need | Traditional Approach | Problem |
|---|---|---|
| Inspection | Custom scripts | No standardization |
| Validation | Manual checksums | Incomplete coverage |
| Transformation | Framework-specific | Lock-in |
| Regression | Manual testing | Error-prone |
The Solution: apr-cli
The apr CLI provides 17 commands for complete model lifecycle management:
# Build the CLI
cargo build -p apr-cli
# Inspect model metadata
./target/debug/apr inspect model.apr --json
# Validate integrity (100-point QA)
./target/debug/apr validate model.apr --quality
# Quantize model
./target/debug/apr convert model.apr --quantize int8 -o model-int8.apr
Complete Example
Run: cargo run --example apr_cli_commands
//! APR CLI Commands Demo
//!
//! Demonstrates creating test models and using the apr-cli commands.
//! This example creates model files that work with all 17 apr-cli commands.
//!
//! Toyota Way Alignment:
//! - **Genchi Genbutsu**: Go and see - inspect actual model data
//! - **Jidoka**: Built-in quality - validate models automatically
//! - **Visualization**: Make problems visible with trace and debug
//!
//! Run with: `cargo run --example apr_cli_commands`
//!
//! After running, use the apr CLI on the generated files:
//! ```bash
//! cargo build -p apr-cli
//! ./target/debug/apr inspect /tmp/apr_cli_demo/demo_model.apr
//! ./target/debug/apr validate /tmp/apr_cli_demo/demo_model.apr --quality
//! ./target/debug/apr debug /tmp/apr_cli_demo/demo_model.apr --drama
//! ./target/debug/apr tensors /tmp/apr_cli_demo/demo_model.apr --stats
//! ./target/debug/apr trace /tmp/apr_cli_demo/demo_model.apr --verbose
//! ./target/debug/apr diff /tmp/apr_cli_demo/demo_model.apr /tmp/apr_cli_demo/demo_model_v2.apr
//! ./target/debug/apr probar /tmp/apr_cli_demo/demo_model.apr -o /tmp/apr_cli_demo/probar
//! ./target/debug/apr explain E002
//!
//! # Inference commands (requires --features inference):
//! cargo build -p apr-cli --features inference
//! ./target/debug/apr run /tmp/apr_cli_demo/demo_model.apr --input "[1.0, 2.0]"
//! ./target/debug/apr serve /tmp/apr_cli_demo/demo_model.apr --port 8080
//! ```
use aprender::serialization::apr::AprWriter;
use serde_json::json;
use std::fs;
use std::path::Path;
fn main() -> Result<(), String> {
println!("=== APR CLI Commands Demo ===\n");
// Create output directory
let demo_dir = Path::new("/tmp/apr_cli_demo");
fs::create_dir_all(demo_dir).map_err(|e| e.to_string())?;
// Part 1: Create a demo model
println!("--- Part 1: Creating Demo Model ---\n");
let model_path = create_demo_model(demo_dir)?;
println!("Created: {}\n", model_path.display());
// Part 2: Create a second model for diff comparison
println!("--- Part 2: Creating Second Model (for diff) ---\n");
let model_v2_path = create_demo_model_v2(demo_dir)?;
println!("Created: {}\n", model_v2_path.display());
// Part 3: Show CLI commands
println!("--- Part 3: CLI Commands Reference ---\n");
print_cli_commands(&model_path, &model_v2_path);
println!("\n=== Demo Complete! ===");
println!("\nModel files created in: {}", demo_dir.display());
println!("Build the CLI with: cargo build -p apr-cli");
println!("Then run the commands shown above.");
Ok(())
}
fn create_demo_model(dir: &Path) -> Result<std::path::PathBuf, String> {
let mut writer = AprWriter::new();
// Add model metadata
writer.set_metadata("model_type", json!("linear_regression"));
writer.set_metadata("model_name", json!("Demo Linear Regression"));
writer.set_metadata("description", json!("A demo model for CLI testing"));
writer.set_metadata("n_features", json!(2));
writer.set_metadata("n_outputs", json!(1));
writer.set_metadata("framework", json!("aprender"));
writer.set_metadata("framework_version", json!(env!("CARGO_PKG_VERSION")));
// Add hyperparameters
writer.set_metadata(
"hyperparameters",
json!({
"n_layer": 4,
"n_embd": 128,
"learning_rate": 0.01
}),
);
// Add training info
writer.set_metadata(
"training",
json!({
"dataset": "synthetic",
"n_samples": 1000,
"n_epochs": 100,
"final_loss": 0.0234
}),
);
// Add tensors (simulating a small model)
println!(" Adding tensors...");
// Weights tensor
let weights: Vec<f32> = vec![1.5, 0.8];
writer.add_tensor_f32("weights", vec![2, 1], &weights);
// Bias tensor
let bias: Vec<f32> = vec![0.5];
writer.add_tensor_f32("bias", vec![1], &bias);
// Embedding layer (to make it more interesting for trace)
let embedding: Vec<f32> = (0..128).map(|i| (i as f32) * 0.01).collect();
writer.add_tensor_f32("embedding", vec![128], &embedding);
// Layer norm weights
let ln_weight: Vec<f32> = vec![1.0; 128];
writer.add_tensor_f32("layer_norm.weight", vec![128], &ln_weight);
// Write to file
let path = dir.join("demo_model.apr");
let bytes = writer.to_bytes()?;
fs::write(&path, &bytes).map_err(|e| e.to_string())?;
println!(" Model type: Linear Regression");
println!(" Tensors: 4");
println!(" Size: {} bytes", bytes.len());
Ok(path)
}
fn create_demo_model_v2(dir: &Path) -> Result<std::path::PathBuf, String> {
let mut writer = AprWriter::new();
// Slightly different metadata
writer.set_metadata("model_type", json!("linear_regression"));
writer.set_metadata("model_name", json!("Demo Linear Regression v2"));
writer.set_metadata("description", json!("Updated model with more training"));
writer.set_metadata("n_features", json!(2));
writer.set_metadata("n_outputs", json!(1));
writer.set_metadata("framework", json!("aprender"));
writer.set_metadata("framework_version", json!(env!("CARGO_PKG_VERSION")));
// Different hyperparameters
writer.set_metadata(
"hyperparameters",
json!({
"n_layer": 4,
"n_embd": 128,
"learning_rate": 0.005 // Changed
}),
);
// More training
writer.set_metadata(
"training",
json!({
"dataset": "synthetic_extended", // Changed
"n_samples": 2000, // Changed
"n_epochs": 200, // Changed
"final_loss": 0.0156 // Improved
}),
);
// Slightly different weights (simulating retraining)
let weights: Vec<f32> = vec![1.52, 0.79]; // Slightly different
writer.add_tensor_f32("weights", vec![2, 1], &weights);
let bias: Vec<f32> = vec![0.48]; // Slightly different
writer.add_tensor_f32("bias", vec![1], &bias);
let embedding: Vec<f32> = (0..128).map(|i| (i as f32) * 0.0101).collect();
writer.add_tensor_f32("embedding", vec![128], &embedding);
let ln_weight: Vec<f32> = vec![1.0; 128];
writer.add_tensor_f32("layer_norm.weight", vec![128], &ln_weight);
let path = dir.join("demo_model_v2.apr");
let bytes = writer.to_bytes()?;
fs::write(&path, &bytes).map_err(|e| e.to_string())?;
println!(" Model type: Linear Regression v2");
println!(" Tensors: 4");
println!(" Size: {} bytes", bytes.len());
Ok(path)
}
fn print_cli_commands(model_path: &Path, model_v2_path: &Path) {
let model = model_path.display();
let model_v2 = model_v2_path.display();
let demo_dir = model_path.parent().unwrap().display();
println!("Build the CLI first:");
println!(" cargo build -p apr-cli\n");
println!("For inference commands (run, serve):");
println!(" cargo build -p apr-cli --features inference\n");
println!("=== 17 APR CLI Commands ===\n");
println!("--- Model Inspection ---\n");
println!("1. INSPECT - View model metadata:");
println!(" ./target/debug/apr inspect {model}");
println!(" ./target/debug/apr inspect {model} --json");
println!(" ./target/debug/apr inspect {model} --weights\n");
println!("2. TENSORS - List tensor info:");
println!(" ./target/debug/apr tensors {model}");
println!(" ./target/debug/apr tensors {model} --stats");
println!(" ./target/debug/apr tensors {model} --json\n");
println!("3. TRACE - Layer-by-layer analysis:");
println!(" ./target/debug/apr trace {model}");
println!(" ./target/debug/apr trace {model} --verbose");
println!(" ./target/debug/apr trace {model} --json\n");
println!("4. DEBUG - Debug output:");
println!(" ./target/debug/apr debug {model}");
println!(" ./target/debug/apr debug {model} --drama");
println!(" ./target/debug/apr debug {model} --hex --limit 64\n");
println!("--- Quality & Validation ---\n");
println!("5. VALIDATE - Check model integrity (100-point QA):");
println!(" ./target/debug/apr validate {model}");
println!(" ./target/debug/apr validate {model} --quality");
println!(" ./target/debug/apr validate {model} --strict\n");
println!("6. LINT - Best practices check:");
println!(" ./target/debug/apr lint {model}\n");
println!("7. DIFF - Compare two models:");
println!(" ./target/debug/apr diff {model} {model_v2}");
println!(" ./target/debug/apr diff {model} {model_v2} --json\n");
println!("--- Model Transformation ---\n");
println!("8. CONVERT - Quantization/optimization:");
println!(" ./target/debug/apr convert {model} --quantize int8 -o {demo_dir}/model-int8.apr");
println!(
" ./target/debug/apr convert {model} --quantize fp16 -o {demo_dir}/model-fp16.apr\n"
);
println!("9. EXPORT - Export to other formats:");
println!(
" ./target/debug/apr export {model} --format safetensors -o {demo_dir}/model.safetensors"
);
println!(" ./target/debug/apr export {model} --format gguf -o {demo_dir}/model.gguf\n");
println!("10. MERGE - Merge models:");
println!(" ./target/debug/apr merge {model} {model_v2} --strategy average -o {demo_dir}/merged.apr");
println!(" ./target/debug/apr merge {model} {model_v2} --strategy weighted -o {demo_dir}/merged.apr\n");
println!("--- Import & Interop ---\n");
println!("11. IMPORT - Import external models:");
println!(" ./target/debug/apr import ./external.safetensors -o imported.apr");
println!(" ./target/debug/apr import hf://org/repo -o model.apr --arch whisper\n");
println!("--- Testing & Regression ---\n");
println!("12. CANARY - Regression testing:");
println!(" ./target/debug/apr canary create {model} --input ref.wav --output {demo_dir}/canary.json");
println!(" ./target/debug/apr canary check {model_v2} --canary {demo_dir}/canary.json\n");
println!("13. PROBAR - Visual regression testing export:");
println!(" ./target/debug/apr probar {model} -o {demo_dir}/probar_output");
println!(" ./target/debug/apr probar {model} -o {demo_dir}/probar_output --format json\n");
println!("--- Help & Documentation ---\n");
println!("14. EXPLAIN - Get explanations:");
println!(" ./target/debug/apr explain E002");
println!(" ./target/debug/apr explain --tensor encoder.conv1.weight");
println!(" ./target/debug/apr explain --file {model}\n");
println!("--- Interactive ---\n");
println!("15. TUI - Interactive terminal UI:");
println!(" ./target/debug/apr tui {model}");
println!(" Tabs: Overview [1], Tensors [2], Stats [3], Help [?]");
println!(" Navigation: j/k or arrows, Tab to switch, q to quit\n");
println!("--- Inference (requires --features inference) ---\n");
println!("16. RUN - Run inference on a model:");
println!(" ./target/debug/apr run {model} --input \"[1.0, 2.0]\"");
println!(" ./target/debug/apr run {model} --input \"1.0,2.0\"");
println!(" ./target/debug/apr run {model} --input \"[1.0, 2.0]\" --json\n");
println!("17. SERVE - Start inference server:");
println!(" ./target/debug/apr serve {model} --port 8080");
println!(" ./target/debug/apr serve {model} --host 0.0.0.0 --port 3000");
println!(" # Then: curl http://localhost:8080/health");
println!(
" # Then: curl -X POST http://localhost:8080/predict -d '{{\"input\": [1.0, 2.0]}}'\n"
);
}
All 17 Commands
Model Inspection
1. INSPECT - View Model Metadata
apr inspect model.apr # Basic info
apr inspect model.apr --json # JSON output
apr inspect model.apr --weights # Include tensor info
Shows model type, framework, hyperparameters, and training info.
2. TENSORS - List Tensor Info
apr tensors model.apr # List all tensors
apr tensors model.apr --stats # Include statistics
apr tensors model.apr --json # JSON output
Lists tensor names, shapes, dtypes, and statistics.
3. TRACE - Layer-by-Layer Analysis
apr trace model.apr # Basic trace
apr trace model.apr --verbose # Detailed trace
apr trace model.apr --json # JSON output
Analyzes model layer by layer for debugging inference.
4. DEBUG - Debug Output
apr debug model.apr # Standard debug
apr debug model.apr --drama # Detailed drama mode
apr debug model.apr --hex --limit 64 # Hex dump
Provides detailed tensor inspection for debugging.
Quality & Validation
5. VALIDATE - Check Model Integrity
apr validate model.apr # Basic validation
apr validate model.apr --quality # 100-point QA checklist
apr validate model.apr --strict # Strict mode
Runs the 100-point quality assessment with grades A+ to F.
6. LINT - Best Practices Check
apr lint model.apr # Check best practices
Static analysis for naming conventions, metadata completeness, and efficiency.
Checks:
- Standard tensor naming patterns (layer.0.weight, not l0_w)
- Required metadata (author, license, provenance)
- Tensor alignment (64-byte boundaries)
- Compression for large tensors (>1MB)
7. DIFF - Compare Two Models
apr diff model_v1.apr model_v2.apr # Compare models
apr diff model_v1.apr model_v2.apr --json # JSON output
Shows metadata and tensor differences between model versions.
Model Transformation
8. CONVERT - Quantization/Optimization
apr convert model.apr --quantize int8 -o model-int8.apr
apr convert model.apr --quantize int4 -o model-int4.apr
apr convert model.apr --quantize fp16 -o model-fp16.apr
Applies quantization for reduced model size and faster inference.
| Quantization | Size Reduction | Accuracy Impact |
|---|---|---|
| fp16 | 50% | Minimal |
| int8 | 75% | Small |
| int4 | 87.5% | Moderate |
9. EXPORT - Export to Other Formats
apr export model.apr --format safetensors -o model.safetensors
apr export model.apr --format gguf -o model.gguf
Exports APR models to other ecosystems:
- SafeTensors - HuggingFace ecosystem
- GGUF - llama.cpp / local inference
10. MERGE - Merge Models
apr merge model1.apr model2.apr --strategy average -o merged.apr
apr merge model1.apr model2.apr --strategy weighted -o merged.apr
Combines multiple models using different strategies:
- average - Simple tensor averaging
- weighted - Weighted combination
Import & Interop
11. IMPORT - Import External Models
apr import external.safetensors -o imported.apr
apr import hf://org/repo -o model.apr --arch whisper
Imports from SafeTensors, HuggingFace Hub, and other formats.
Testing & Regression
12. CANARY - Regression Testing
# Create canary from original model
apr canary create model.apr --input ref.wav --output canary.json
# Check optimized model against canary
apr canary check model-optimized.apr --canary canary.json
Captures tensor statistics for regression testing after transformations (quantization, pruning).
Canary data includes:
- Tensor shapes and counts
- Mean, std, min, max for each tensor
- Drift tolerance checking
13. PROBAR - Visual Regression Testing
apr probar model.apr -o probar_output # Create probar suite
apr probar model.apr -o output --format json # JSON format
Exports model data for visual regression testing.
Help & Documentation
14. EXPLAIN - Get Explanations
apr explain E002 # Explain error code
apr explain --tensor encoder.conv1.weight # Explain tensor name
apr explain --file model.apr # Analyze file
Provides context-aware explanations for errors and tensor patterns.
Interactive
15. TUI - Interactive Terminal UI
apr tui model.apr # Launch interactive UI
Interactive terminal interface for model exploration with four tabs:
| Tab | Key | Description |
|---|---|---|
| Overview | 1 | Model metadata, hyperparameters, training info |
| Tensors | 2 | Tensor list with shapes, dtypes, sizes |
| Stats | 3 | Tensor statistics (mean, std, min, max, zeros, NaNs) |
| Help | ? | Keyboard shortcuts and navigation help |
Keyboard Navigation:
1,2,3,?- Switch tabs directlyTab/Shift+Tab- Cycle through tabsj/↓- Next item in listk/↑- Previous item in listq/Esc- Quit
Inference (requires --features inference)
Build with inference support:
cargo build -p apr-cli --features inference
16. RUN - Run Model Inference
apr run model.apr --input "[1.0, 2.0]" # JSON array input
apr run model.apr --input "1.0,2.0" # CSV input
apr run model.apr --input "[1.0, 2.0]" --json # JSON output
Runs inference on APR, SafeTensors, or GGUF models:
| Format | Inference Type |
|---|---|
| APR (.apr) | Full ML inference via realizar |
| SafeTensors (.safetensors) | Tensor inspection |
| GGUF (.gguf) | Model inspection (mmap) |
Input Formats:
- JSON array:
"[1.0, 2.0, 3.0]" - CSV:
"1.0,2.0,3.0"
17. SERVE - Start Inference Server
apr serve model.apr --port 8080 # Start on port 8080
apr serve model.apr --host 0.0.0.0 --port 3000 # Bind to all interfaces
Starts a REST API server for model inference:
APR Models (full inference):
# Health check
curl http://localhost:8080/health
# Run inference
curl -X POST http://localhost:8080/predict \
-H "Content-Type: application/json" \
-d '{"input": [1.0, 2.0]}'
Server Features:
/health- Health check endpoint/predict- Inference endpoint (APR models)/model- Model info endpoint (GGUF/SafeTensors)/tensors- Tensor listing (SafeTensors)- Graceful shutdown via Ctrl+C
Example Output
Running the example creates demo models:
=== APR CLI Commands Demo ===
--- Part 1: Creating Demo Model ---
Adding tensors...
Model type: Linear Regression
Tensors: 4
Size: 1690 bytes
Created: /tmp/apr_cli_demo/demo_model.apr
--- Part 2: Creating Second Model (for diff) ---
Model type: Linear Regression v2
Tensors: 4
Size: 1707 bytes
Created: /tmp/apr_cli_demo/demo_model_v2.apr
Use Cases
CI/CD Model Validation
# In CI pipeline
apr validate model.apr --strict --min-score 90 && apr lint model.apr
if [ $? -ne 0 ]; then
echo "Model validation failed"
exit 1
fi
Model Optimization Pipeline
# Quantize for production
apr convert model.apr --quantize int8 -o model-int8.apr
# Verify no regression
apr canary create model.apr --input test.wav --output canary.json
apr canary check model-int8.apr --canary canary.json
# Export for deployment
apr export model-int8.apr --format gguf -o model.gguf
Model Version Comparison
# Compare before/after optimization
apr diff original.apr quantized.apr --json | jq '.tensor_changes'
Debugging Inference Issues
# Layer-by-layer trace
apr trace model.apr --verbose | grep -i "nan\|inf"
# Drama mode for detailed analysis
apr debug model.apr --drama
Benefits
| Benefit | Description |
|---|---|
| Standardized | Consistent CLI for all APR models |
| Comprehensive | 17 commands cover full lifecycle |
| Scriptable | JSON output for automation |
| Debuggable | Deep inspection with drama mode |
| Validatable | 100-point QA with grades |
| Transformable | Quantization and format conversion |
| Testable | Canary regression testing |
| Inference | Run predictions and serve REST APIs |