cargo install aprender # CPU ONLY - no GPU backend is compiled in
cargo install aprender --features cuda # NVIDIA GPU acceleration
cargo install aprender --features full # everything (training, visualization, zram)
apr pull qwen2.5-coder-1.5b
apr run qwen2.5-coder-1.5b "What is 2+2?"For release notes see GitHub Releases.
A complete ML framework in pure Rust. One cargo install, one apr binary,
the full model lifecycle — inference, training, quantization, profiling,
publishing — all backed by YAML provable contracts that fail CI on drift.
| Metric | Count | Source of truth |
|---|---|---|
| Workspace crates | 79 workspace crates | cargo metadata --no-deps (NOT ls crates/ — 4 are excluded, 1 has no Cargo.toml) |
| Provable contracts | 1837 provable contracts | contracts/census.json .n_files — the set pv lint walks (pv census, ONT-001 ONT-1; regenerated by make contracts, written by make readme-sync, guarded by scripts/check_readme_claims.sh) |
| CLI commands | 111 CLI commands | contracts/apr-cli-commands-v1.yaml §commands (parse the list; apr --help prints 112 because it lists help itself, and grep -c '^ - name:' gives 117 — other same-indent name: keys exist in the file) |
| Book CLI chapters | 113 chapters | ls book/src/cli/*.md |
| Book lib chapters | 72 chapters | ls book/src/lib/*.md (parity with pub mod) |
These numbers are enforced by contracts/readme-claims-v1.yaml.
Drift between this table and live repo state fails bash scripts/check_readme_claims.sh
→ see FALSIFY-README-001..006.
Verified matrix for 0.69.1, from the ladder receipts:
A pass cell means apr run completed on that host without falling back and its golden output matched. It does not mean chat, code and serve passed: the ladder records those verbs but its green does not read them.
A non-pass cell names the gates the receipt records, which is not always the cause: a reason apr qa computed in the same run is not carried here unless the receipt accounts for it (qa_rc is the tell).
| Model rung | gx10 | lambda |
|---|---|---|
qwen2-1.5b-q4km |
pass | pass |
qwen3-1.7b-q4km |
pass | pass |
qwen3-8b-q4km |
pass | pass |
qwen35-0.8b-q4km |
pass | pass |
qwen35-2b-q4km |
pass | pass |
qwen35-4b-q4km |
pass | pass |
qwen35-9b-q4km |
pass | pass |
qwen35-27b-q4km |
FAIL | pass |
inv:Qwen3-30B-A3B-Instruct-2507-Q4_K_M.gguf |
FAIL | FAIL |
inv:Qwen3-Coder-30B-A3B-Instruct-Q4_K_M.gguf |
FAIL | FAIL |
inv:qwen2.5-coder-0.5b-instruct-q4_k_m.gguf |
pass | pass |
inv:qwen2.5-coder-1.5b-instruct-fp16.apr |
pass | — |
inv:qwen2.5-coder-1.5b-instruct-q4_k_m.apr |
pass | — |
inv:qwen2.5-coder-1.5b-instruct-q4_k_m.gguf |
pass | pass |
inv:qwen2.5-coder-1.5b-instruct-q4k.apr |
pass | pass |
inv:qwen2.5-coder-32b-instruct-q4_k_m.gguf |
pass | — |
inv:qwen2.5-coder-7b-instruct-q4_k_m.gguf |
pass | pass |
inv:Qwen2.5-0.5B-Instruct-IQ3_M.gguf |
— | pass |
inv:Qwen2.5-0.5B-Instruct-IQ4_XS.gguf |
— | pass |
inv:Qwen2.5-0.5B-Instruct-f16.gguf |
— | FAIL |
inv:Qwen3.5-0.8B-IQ4_XS.gguf |
— | FAIL |
inv:Qwen3.5-0.8B-UD-IQ2_XXS.gguf |
— | FAIL |
inv:Qwen3.5-35B-A3B-UD-IQ4_XS.gguf |
— | FAIL |
inv:Qwen3.5-4B-UD-Q4_K_XL.gguf |
— | pass |
inv:qwen2.5-coder-0.5b-instruct.apr |
— | FAIL |
inv:qwen2.5-coder-1.5b-instruct-q4k-v2.apr |
— | pass |
inv:qwen2.5-coder-1.5b-instruct-st.apr |
— | pass |
inv:qwen2.5-coder-1.5b-q4k.apr |
— | pass |
inv:tinyllama-1.1b-chat-v1.0.Q4_K_M.gguf |
— | pass |
- gx10: 17 rung(s), 17 required, 3 not green —
apr 0.69.1 (9b7739951) - lambda: 26 rung(s), 26 required, 7 not green —
apr 0.69.1 (9b7739951)
| Stage | Commands |
|---|---|
| Inference | apr run, apr chat, apr serve |
| Training | apr finetune, apr train, apr pretrain, apr distill |
| Model ops | apr convert, apr quantize, apr merge, apr export, apr compile |
| Inspection | apr inspect, apr validate, apr tensors, apr diff, apr trace, apr lint |
| Profiling | apr profile, apr bench, apr qa |
| Registry | apr pull, apr list, apr rm, apr publish, apr registry |
| GPU | apr gpu, apr parity, apr ptx |
| Observability | apr tui, apr monitor, apr cbtop |
End-to-end recipes (data prep → train → quantize → publish → serve) live in
paiml/apr-cookbook — 1,825 worked examples (apr-cookbook, 2026-09-12),
with local book/src/ walkthroughs. The count is the
[[example]] entries the cookbook declares, pinned and gated by
contracts/readme-claims-v1.yaml — it lives in another
repository, so it carries the date it was measured rather than pretending to be live.
git clone https://github.com/paiml/apr-cookbook
cd apr-cookbook
cargo run --example bundle_static_model # any example
mdbook serve book # walkthrough docscargo install aprender # installs the `apr` binary
apr --versionEight beats, one narrative, every core command group. Anchored on the Qwen
series so the story scales from a 494-MB safetensors model to a 30 B-parameter
MoE GGUF. Every beat is a falsifier in
contracts/qwen-story-v1.yaml; the runnable
form is scripts/qwen-story.sh; nightly cron is
.github/workflows/qwen-story-daily.yml;
the dogfood gate is /apr-dogfood Gate 18.
# Reproduce locally (uses ~/models cache; ~3-5 min on RTX 4090):
bash scripts/qwen-story.shapr pull hf://Qwen/Qwen2.5-Coder-0.5B-Instruct # 494 MB safetensors
apr list # confirm cachedapr qa qwen2.5-coder-1.5b-instruct-q4k # 12 falsifiable gates
apr validate qwen2.5-coder-1.5b-instruct-q4k --quality # scores the checks that ran
apr lint qwen2.5-coder-1.5b-instruct-q4k # best-practice signalsapr inspect --json qwen2.5-coder-1.5b-instruct-q4k # arch, params, tensors
apr tensors --json qwen2.5-coder-1.5b-instruct-q4k # 339 tensors with shapes
apr tree qwen2.5-coder-1.5b-instruct-q4k # layer architectureapr export qwen2.5-coder-1.5b-instruct-q4k --format gguf -o roundtrip.gguf
apr diff qwen2.5-coder-1.5b-instruct-q4k roundtrip.gguf # tensor-by-tensor delta
apr convert model.safetensors --quantize q4_k -o quantized.aprapr run qwen2.5-coder-1.5b-instruct-q4k "fn sum(a: i32, b: i32) -> i32 {" --max-tokens 16
apr chat qwen2.5-coder-1.5b-instruct-q4k # interactive REPL
apr code -p "review this Python function" --max-turns 1 # agent mode (PMAT-182)apr serve run qwen2.5-coder-1.5b-instruct-q4k --port 8080
curl -s localhost:8080/v1/chat/completions \
-H 'Content-Type: application/json' \
-d '{"model":"qwen","messages":[{"role":"user","content":"What is 2+2?"}],"max_tokens":8}'
# → {"choices":[{"message":{"content":"2 + 2 equals 4."}}],...}apr profile qwen2.5-coder-7b-instruct-q4_k_m # Roofline analysis
apr gpu --json # VRAM, sm_*, cuda version
apr serve plan qwen2.5-coder-7b-instruct-q4_k_m # capacity plan before runapr inspect --json Qwen3-Coder-30B-A3B-Instruct # arch=qwen3moe, 30 B params
apr tensors --json Qwen3-Coder-30B-A3B-Instruct # 579 tensors (MoE expert layout)0.69.1 does not support
qwen3moeon CUDA. Mixture-of-experts models (Qwen3-30B-A3B-Instruct-2507,Qwen3-Coder-30B-A3B-Instruct) run on the CPU only:apr run <model>works, andapr run --gpu <model>refuses before loading, naming the architecture and exiting 12 rather than generating on the CPU and reporting a fallback. The MoE GPU forward is #3714 and lands in 0.70.0. Introspection above (inspect,tensors) is unaffected — it reads the header, not a forward.
# Publish a derived model to HuggingFace Hub (see SPEC-HF-PUBLISH-001 for the 12-file pipeline)
apr stamp ckpt.apr --tokenizer /path/to/qwen-tokenizer --license Apache-2.0 -o staging/model.apr
apr export staging/model.apr --format gguf --quantize int4 -o staging/model-q4k.gguf
apr publish staging/ paiml/my-model-v1 --library-name aprender --license Apache-2.0When run with PMAT_HUNT=1 (default), each beat emits a manifest of high-risk
untested code in the command modules it just exercised. A nightly cron opens an
issue when this manifest grows so untested branches in command handlers can't
accumulate quietly. See contracts/qwen-story-v1.yaml.
Publishing a model? See SPEC-HF-PUBLISH-001 for the 12-file integration pipeline, three-path verification protocol, and HF API gotchas (NDJSON commits, LFS batch sizing, Q4_K stride constraints).
[dependencies]
aprender = "0.35"use aprender::linear_regression::LinearRegression;
use aprender::traits::Estimator;
let model = LinearRegression::new();
model.fit(&x_train, &y_train)?;
let predictions = model.predict(&x_test)?;Algorithms: Linear/Logistic Regression, Decision Trees, Random Forest, GBM, Naive Bayes, KNN, SVM, K-Means, PCA, ARIMA, ICA, GLMs, graph algorithms, Bayesian inference, text + audio processing.
Monorepo, flat crates/aprender-* layout (same pattern as
Polars,
Burn,
Nushell):
paiml/aprender/
├── Cargo.toml # Workspace root + `cargo install aprender`
├── crates/
│ ├── aprender-core/ # ML library (use aprender::*)
│ ├── apr-cli/ # CLI logic (count in the table above)
│ ├── aprender-compute/ # SIMD/GPU compute kernels
│ ├── aprender-gpu/ # CUDA PTX
│ ├── aprender-serve/ # Inference server
│ ├── aprender-train/ # Training loops
│ ├── aprender-orchestrate/ # Agents + RAG
│ ├── aprender-contracts/ # Provable contracts engine
│ ├── aprender-profile/ # Profiling
│ ├── aprender-db/ aprender-graph/ aprender-rag/
│ └── ... (**84** directories — NOT the crate count: see the table above)
├── contracts/ # provable YAML contracts (count in the table above)
└── book/ # mdBook documentation
Every published throughput or comparator figure lives with the run that produced
it. The measurement ledger is evidence/parity/LEDGER.md;
the rules a figure must satisfy before it may be quoted anywhere — including on
this page — are in
docs/specifications/PP-LLAMA-001-MASTER.md.
This section carried a three-row table of tok/s figures until 2026-09-02. None
of the three cited a receipt, and the RTX 4090 row asserted a rate the tree's own
paired measurement contradicts, so all three are withdrawn rather than restated
(PP-LLAMA-001 §2.1, PP-12). A withdrawal that reprints the number leaves the
number on the page.
The harnesses that reproduce the comparisons, without their numbers: candle-vs-apr for inference and ground-truth-apr-ludwig for training. A figure from either belongs on this page only once it carries a receipt in the ledger.
Every CLI command and kernel is bound to a YAML contract with equations, preconditions, postconditions, and falsification tests:
equations:
validate_exit_code:
formula: exit_code = if score < 50 then 5 else 0
invariants:
- score < 50 implies exit_code != 0
falsification_tests:
- id: FALSIFY-CLI-001
prediction: apr validate bad-model.apr exits non-zeroThe tree carries 1837 contracts across inference, training, quantization, attention, FFN, tokenization, model formats, CLI safety — and this README itself.
| Old | New | Status |
|---|---|---|
trueno = "0.18" |
aprender-compute = "0.33" |
Shim available |
entrenar = "0.7" |
aprender-train = "0.33" |
Shim available |
realizar = "0.8" |
aprender-serve = "0.33" |
Shim available |
batuta = "0.7" |
aprender-orchestrate = "0.33" |
Shim available |
Old repositories are archived. All development happens here.
git clone https://github.com/paiml/aprender
cd aprender
cargo test --workspace --lib
cargo check --workspace
apr --help
bash scripts/check_readme_claims.sh # README contract gateMIT