oxidizr
App Listed
Trains GPT-style language models from a YAML config and a tokenized dataset: dense GQA transformers, Mamba 1, 2 and 3, MLA and MoE layers on CPU or CUDA. Runs the training loop, optimizer, checkpoints, evaluation and metrics on boostr, and builds speech corpora through voxr.
- Downloads
- 27
- Dependents
- Not applicable
- Stars
- 8
- Forks
- 3
- Contributors
- 2
- Commits
- 127
- Latest release
- 0.1.1 ·
About
LLM training framework in Rust. Train models from a YAML config with no Python.
Trains GPT-style language models from a YAML config and a tokenized dataset. Supports dense GQA transformers, Mamba1, Mamba2, Mamba3, MLA, and MoE layers on CPU or CUDA, built on boostr.
Docs · Crate · Config · CLI · Example · Contributing
What is oxidizr
oxidizr trains a language model from two inputs:
- A YAML config that defines the architecture, optimizer, and training schedule.
- A tokenized dataset stored as a binary file of
u32tokens.
oxidizr runs the training loop, optimizer, checkpointing, and metrics. It writes
checkpoints as .safetensors files and packages them for distribution.
- Language: training runs in Rust on boostr and numr. Training needs no Python. Only the optional
pushcommand uses Python tools, through thehfCLI. - Hardware: CPU, and NVIDIA GPUs through the
cudafeature. Multi-GPU on one machine needscuda,nccl. - Serve a trained model with blazr.
- Not supported yet: FSDP, ZeRO sharding, tensor parallelism, pipeline parallelism, and training across machines. blazr cannot serve Gated DeltaNet layers yet.
Read the full README
| Layer | Config keys | Notes |
|---|---|---|
| Dense GQA transformer | kv_heads, with kv_latent_dim unset | Grouped-query attention with RoPE and RMSNorm |
| MLA (Multi-Head Latent Attention) | kv_latent_dim, q_latent_dim, d_rope | Compressed KV cache |
| Mamba1 | mamba_layers, with mamba2_num_heads unset | Selective state-space layers |
| Mamba2 | mamba_layers, mamba2_* | State Space Duality (SSD) |
| Mamba3 | mamba3_enabled: true, mamba2_* | Trapezoidal discretization. Optional mamba3_complex_rope, mamba3_mimo_rank |
| MoE (Mixture of Experts) | num_experts, experts_per_tok, shared_expert_enabled | Top-k routing with a load-balance loss |
| Gated DeltaNet | gdn_layers, gdn | Qwen3.5 / Qwen3-Next linear attention. Mixes with Mamba and attention layers. blazr cannot serve it yet. Tested on CPU only |
Layers mix within one model. mamba_layers lists the SSM layer indices, and every other layer uses attention.
Mamba2 and Mamba3 require hidden_size * mamba2_expand == mamba2_num_heads * mamba2_head_dim. For example, 384 * 2 == 48 * 16.
Installation
oxidizr needs a Rust toolchain. It fetches boostr from crates.io. Clone and build:
git clone https://github.com/ml-rust/oxidizr
cd oxidizr
cargo build --release
Add --features cuda to the build for GPU support. The CUDA build uses the toolkit installed on the system.
Quick Start
Build the project, download the educational dataset, and start training:
git clone https://github.com/ml-rust/oxidizr
cd oxidizr
cargo build --release
pip install huggingface_hub # only to download this dataset
hf download fs90/nano-start-data-bin --local-dir data/nano-start/tokenized --repo-type dataset
cargo run --release -- train -f models/nano-start/nano-start.yaml -d data/nano-start/tokenized/combined.bin
The default build trains on CPU. Checkpoints for this config go to ./checkpoints/nano-start.
To train on a GPU, build and run with --features cuda:
cargo run --release --features cuda -- train -f models/nano-start/nano-start.yaml -d data/nano-start/tokenized/combined.bin
After training, package the model. See Model Distribution.
Bring Your Own Config and Data
Write a Config
A config has two top-level keys: model and trainer. This dense GQA example is a complete starting point:
# my-model.yaml
model:
name: my-model
hidden_size: 512
num_layers: 8
num_heads: 8
kv_heads: 4 # Fewer KV heads than query heads (GQA)
intermediate_size: 2048
vocab_size: 100315
tokenizer_vocab: cl100k_base # Must match the tokenizer that produced the data
max_seq_len: 512
rope_theta: 10000.0
trainer:
target_device: gpu
learning_rate: 0.0003
batch_size: 2
gradient_accumulation: 1
max_steps: 5000
num_epochs: 2
checkpoint_dir: "./checkpoints/my-model"
log_interval: 10
save_interval: 500
max_checkpoints: 3
load_balance_alpha: 0.0 # MoE auxiliary loss weight. Required. 0.0 disables it.
Run it:
cargo run --release -- train -f my-model.yaml -d data/my-dataset.bin
tokenizer_vocab is required. Set it to cl100k_base, o200k_base, llama3, deepseek_v3, or custom.
Key trainer fields:
| Field | Purpose |
|---|---|
learning_rate, batch_size, gradient_accumulation | Optimizer step size and batch shape |
max_steps, num_epochs | Training length |
warmup_steps, lr_schedule, min_lr_ratio | Warmup, then constant, cosine, linear or wsd decay. Logged rates are the rates each step applied |
weight_decay, weight_decay_rule, no_decay_patterns | AdamW decay coefficient, and the parameters it applies to. skip_1d (fresh-run default) skips norms, biases and SSM a_log/D. decay_all decays everything. skip_all decays nothing. A resume keeps the checkpoint's rule |
checkpoint_dir, save_interval, max_checkpoints | Checkpoint location, frequency, and retention (0 keeps all) |
log_interval | Steps between metric updates. Each update reports tokens and tokens per second over every rank |
metrics.peak_tflops | One device's peak TFLOP/s. Set, the logs report MFU. Absent, no MFU |
spike_guard | Loss-spike guard: an EMA of the step loss over window steps. A loss z_threshold std above it after min_steps losses is a spike. action: skip skips its optimizer step, warn reports it. Absent, nothing changes |
eval | Validation on holdout_rows, holdout_fraction or a data_file, every interval steps over batches batches. early_stopping (patience, min_delta) stops the run cleanly. A new best writes the best checkpoint. Absent, nothing changes |
target_device | gpu or cpu. The CLI --target-device overrides it |
load_balance_alpha | MoE load-balance loss weight |
The full key reference is in docs/configuration.md.
Behavior changes that alter what an existing config trains:
- MLA (
kv_latent_dim) appliesrope_scaling. It used to ignore it. A checkpoint trained before this change withkv_latent_dimandrope_scalingresumes with different rotary frequencies. - MLA refuses an explicit
head_dimother thanhidden_size / num_heads. - A fresh run with no
weight_decay_ruleusesskip_1d. A resume keeps the checkpoint's rule.
See Behavior Changes.
Sample Configs
Start from a file in models/. models/README.md describes each one. models/nano-start/nano-start.yaml is the educational hybrid model (Mamba2 + MLA + MoE).
Prepare the Data
oxidizr memory-maps a binary file of little-endian u32 tokens. The tokenizer must match model.tokenizer_vocab.
oxidizr tokenize writes that file from .txt and .jsonl inputs:
cargo run --release --features vocab-llama3 -- tokenize \
-i data/raw -o data/my-dataset.bin --tokenizer llama3
A vocabulary name needs its vocab-* feature. A tokenizer.json path needs none.
See Tokenization.
Pass the file with -d. Without -d, train generates 1,000,000 random tokens for a smoke test.
The oxidizr::data::create_dummy_data(vocab_size, total_tokens) function returns the same random tokens as a Vec<u32>.
CLI Reference
oxidizr <SUBCOMMAND> [OPTIONS]
| Subcommand | Purpose | Feature |
|---|---|---|
train | Train a model. oxidizr -f <config> runs train without the subcommand | none |
import | Convert a HuggingFace checkpoint to an oxidizr checkpoint (-f, -m, -d, -o) | none |
merge | Fold LoRA adapters into base weights (-f, -c, -o) | none |
pack | Package a checkpoint for distribution | none |
push | Upload a packaged model to the HuggingFace Hub | huggingface |
prep-corpus | Build a packed speech-LM corpus from audio recordings | audio |
Common train flags:
| Flag | Default | Purpose |
|---|---|---|
-f, --config <FILE> | models/nano.yaml | YAML config |
-d, --data <FILE> | 1,000,000 random tokens | Memory-mapped u32 token file |
--target-device <gpu|cpu> | Config trainer.target_device | Device. A build without cuda runs on CPU |
--batch-size, --seq-len, --grad-accum, --max-steps | Config | Override the config value. --batch-size is the batch of one GPU |
--resume <PATH|auto> | None | Resume from a .safetensors checkpoint, or the latest one. Restores weights, optimizer state and data position |
--gpus <IDS> | Config trainer.distributed.gpu_ids, else the default GPU | GPU ids, one data-parallel rank per id, for example 0,1. More than one id needs --features cuda,nccl |
--sync-backend <single|cpu|nccl> | Config trainer.distributed.backend | Gradient sync. NCCL is the only multi-GPU backend. cpu and an explicit single refuse more than one GPU |
--prefetch <N> | 0 | Batches to prefetch on a background thread |
--max-checkpoints <N> | 10 | Checkpoints to keep. 0 keeps all |
--dtype <f32|f16|bf16> | Config model.dtype (f32) | Model precision |
--checkpoint-dir <DIR> | Config trainer.checkpoint_dir | Checkpoint directory |
--headless | Off | Print JSON metrics only. Use in CI, pipes, and non-interactive shells |
--run-dir <DIR> | $OXIDIZED_RUN_DIR, else ./runs/<timestamp> | Directory for run.json, steps.json and evals.json |
Every run writes run.json to its run directory when it ends, in both output modes. It records status (completed or failed), the error text of a failed run, the final step, the last loss, and start and end times. train exits with code 1 when the run failed. steps.json holds one JSON line per log interval and one for the first step of each session.
Without --headless, train shows a progress bar. Run oxidizr <SUBCOMMAND> --help for every flag. docs/cli.md documents each subcommand.
Model Distribution
Package a checkpoint, then upload it:
oxidizr pack --checkpoint latest # Or: final, or a step number. Omit to pick interactively
cargo build --release --features huggingface
pip install huggingface_hub
oxidizr push --model hf/<username>/<model-name>
pack writes model.safetensors, config.json, and a generated README.md to hf/<username>/<model>/. It also copies training_config.json when the checkpoint has a run.json.
push runs the hf CLI, so hf must be on PATH. It accepts --private, -t, --token, and -y, --yes.
Put these values in a .env file, copied from .env.example:
HF_USERNAME=your-username
HF_TOKEN=hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Get a token from the HuggingFace token page. See hf/README.md and docs/cli.md for the full flag list.
Multi-GPU Training
A build with --features cuda,nccl trains one model on several GPUs of one machine. This is data parallelism: every GPU holds a full replica.
cargo build --release --features cuda,nccl
./target/release/oxidizr train -f models/nano.yaml --gpus 0,1
--gpus 0,1starts one rank per GPU, in one process. Rankiuses the i-th id. An id named twice is an error.batch_sizeis the batch of one GPU. One optimizer step readsbatch_size x GPUs x gradient_accumulationrows. Two GPUs atbatch_size: 4match one GPU atbatch_size: 8up to float rounding.- Each step sums the gradients of every GPU with one NCCL all-reduce. Every replica stays bit-equal.
- Rank 0 alone prints, evaluates, and writes
run.json,steps.json,evals.jsonand the checkpoints. Its early-stop decision reaches every rank. - A failure or panic on one GPU aborts the others. The run fails with the error of the rank that failed first.
- The checkpoint meta records
world_size. A resume needs the same GPU count. A checkpoint of another count is an error that names both counts. --target-device cpuwith more than one id is an error. A build withoutncclrefuses more than one id with the feature to add.
Not supported: FSDP, ZeRO sharding, tensor parallelism, pipeline parallelism, and more than one machine.
The CPU test suite runs every data-parallel path on in-process CPU ranks. The NCCL communicator, the NCCL abort, and the multi-GPU device setup are untested on real GPUs.
Tracking a Run
Each run keeps its own history in its run directory:
| File | Holds |
|---|---|
run.json | One record of the finished run |
steps.json | One JSON object per log interval |
evals.json | One JSON object per eval. Absent for a run without trainer.eval |
A build with --features tensorboard also writes TensorBoard event files of the training and eval scalars. --headless prints JSON metrics to stdout. --resume continues a run from its weights, optimizer state and data position.
Features
| Feature | Default | Enables |
|---|---|---|
f16 | On | F16 and BF16 dtypes |
cuda | Off | CUDA backend (boostr CubeCL), and GPU memory per process from NVML, loaded at run time |
tensorboard | Off | TensorBoard event files of the training and eval scalars in the run directory |
nccl | Off | Multi-GPU data parallelism over NCCL. Implies cuda |
huggingface | Off | push command |
audio | Off | prep-corpus command, with the voxr corpus pipeline and the Whisper, NeuCodec, and Silero VAD models |
vocab-<name> | Off | Bundled tokenizer vocabulary for tokenize --tokenizer <name> and prep-corpus --tokenizer <name> |
vocabs | Off | Every bundled vocabulary |
Bundled vocabulary names: cl100k, o200k, gpt-oss, phi4, olmo2, llama3, llama2, deepseek, qwen, glm, gemma2, gemma3, gemma4, kimi, mistral, modernbert.
Example: cargo build --release --features cuda,huggingface.
Development
See CONTRIBUTING.md for build, test, and lint commands, and the project layout.
Documentation: docs/README.md indexes the guides. docs/configuration.md is the config reference. docs/cli.md is the CLI reference. docs/architecture/overview.md describes the design.
Citation
@software{oxidizr,
author = {Farhan Syah},
title = {oxidizr: A Rust-based LLM training framework},
year = {2025},
url = {https://github.com/ml-rust/oxidizr}
}
Contributing
Contributions are welcome. See CONTRIBUTING.md for conventions and checks.
Questions and design discussion happen on Discord.
License
Licensed under Apache-2.0. See LICENSE.
Compatibility
- Runs on
- CUDA
What shows it
- CUDA: oxidizr feature cuda
- Native code
- Optional
- Binds native code: nvml-wrapper-sys (feature cuda)
- Python bindings
- No Python binding crate found
- License
- Apache-2.0
Compare with similar projects
Order: strongest tier first, then most downloads, then name, with unmeasured values last. A library counts downloads over 30 days. An app counts binary downloads per release. An app with none counts its crate downloads over 30 days.
| Project | Downloads | Dependents | Stars | Latest release | Runs on (GPU) | Native code | License |
|---|---|---|---|---|---|---|---|
|
Trains GPT-style language models from a YAML config and a tokenized dataset: dense GQA transformers, Mamba 1, 2 and 3, MLA and MoE layers on CPU or CUDA. Runs the training loop, optimizer, checkpoints, evaluation and metrics on boostr, and builds speech corpora through voxr. |
27 downloads over 30 days | Not applicable | 8 | 0.1.1 | CUDA | Binds native code: nvml-wrapper-sys (feature cuda) | Apache-2.0 |
|
boostr Listed
ML framework on numr for training and inference on CPU, CUDA and WebGPU: attention, quantization, inference scheduling and distributed execution. Models include LLaMA, Mamba2, Qwen3.5, Whisper, Kokoro, VITS, VoxCPM2, Silero VAD, CLAP and super-resolution. Loads SafeTensors and GGUF. |
1,265 downloads over 30 days | 7 | 20 | 0.11.2 | CUDA, WebGPU | Binds native code: ring (feature distributed) | Apache-2.0 |
|
web-rwkv Listed
An implementation of the RWKV language model in pure WebGPU. |
444 downloads over 30 days | 3 | 360 | 0.10.20 | WebGPU | Binds native code: tracy-client-sys (feature trace) | Apache-2.0 OR MIT |
|
rustyml Listed
Machine learning models, neural networks, metrics, and data utilities in Rust |
59 downloads over 30 days | 0 | 345 | 0.17.0 | GPU support unknown | No native code found | MIT |
|
rust-lstm Listed
A complete LSTM neural network library with training capabilities, multiple optimizers, and peephole variants. |
15 downloads over 30 days | 0 | 24 | 0.10.0 | GPU support unknown | No native code found | MIT |
|
A learning-focused, high-performance tensor computation library built from scratch in Rust, featuring automatic differentiation and CPU/CUDA backends. |
Not measured | Not applicable | 79 | Not measured | Not measured | Not measured | MIT |
Why ListedNo archive, New or Featured rule places it, so it is Listed.
What it lacks for Featured
- The check holds no value for Homebrew installs on request over 365 days, Repology repository families, Docker pull growth over 90 days. A gate that lacks its signal does not pass.
What else the check found
- The last activity is on 6 Nov 2026, 3 days ago. The rules expect an update within 365 days. Dormancy rule
Not measured: Homebrew installs on request over 365 days, Repology repository families, Docker pull growth over 90 days.
Check notes
- the latest release was packaged from a dirty working tree
Exact rules: Listed, Featured app. The check on applied thresholds version 9.
Every rule outcome, as the check records it
expected-interval: app: E = 365 daysdormancy: last activity 2026-11-06, 3 days ago, E = 365: activefeatured: not featured: unknown homebrew_on_request_365d, repology_families, docker_pull_growth_90dlisted: listed: no archive, new or featured rule applies
Measurements and sources
Each signal row shows the raw value, its source and the fetch date. The Sources list gathers every distinct source on this page. Movement needs more history.
Sources6 sources
- Description: written for the catalogue
- crates.io database dump, fetched
- GitHub releases, fetched
- GitHub repository, fetched
- crates.io package, fetched
- GitHub contributors, fetched
Adoption0 binary downloads per release4 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Active dependents | Not measured | Yes | ||
| New dependents (365 days) | Not measured | Yes | ||
| Peak active dependents | Not measured | Yes | ||
| Active dependents as a share of the peak | Not measured | Yes | ||
| Binary downloads per release | 0 | GitHub releases | Yes |
MaintenanceLatest human commit: 3 days ago4 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Latest human commit | 2026-11-06 | GitHub repository | Yes | |
| Latest release | 2026-11-06 | GitHub releases | Yes | |
| First release | 2025-12-04 | crates.io database dump | Yes | |
| Latest version | 0.1.1 | crates.io database dump | No | |
| Days the oldest outside issue waits for a reply | 0 | GitHub repository | Yes | |
| Maintainer replies over 365 days | 0 | GitHub repository | Yes | |
| Repository archived | false | GitHub repository | Yes | |
| Repository gone | false | GitHub repository | Yes | |
| Release commit or manifest in the repo | true | crates.io package | No | |
| Published docs | Not measured | Yes | ||
| Latest release fails cargo check | Not measured | Yes | ||
| Build check date | Not measured | Yes | ||
| Build check toolchain | Not measured | Yes |
SecurityNot measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Unpatched vulnerabilities past the grace window | Not measured | Yes | ||
| RustSec unmaintained advisory | Not measured | Yes | ||
| Deprecation notice | Not measured | Yes | ||
| Deprecated requirement | Not measured | Yes |
Distribution3 releases, 27 downloads over 30 days6 not measured
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| Releases | 3 | crates.io database dump | No | |
| Downloads over 30 days | 27 | crates.io database dump | No | |
| Binary downloads over the last 3 releases | 0 | GitHub releases | Yes | |
| Homebrew installs on request over 365 days | Not measured | Yes | ||
| Repology repository families | Not measured | Yes | ||
| Docker pull growth over 90 days | Not measured | Yes | ||
| Docker pulls at the growth baseline | Not measured | Yes | ||
| Every version a prerelease | false | crates.io database dump | Yes | |
| Every version 0.0.x | false | crates.io database dump | Yes | |
| Every version yanked | Not measured | Yes | ||
| Crate deleted from crates.io | Not measured | Yes |
Repository8 stars, 3 forks, 2 contributors, 127 commits. Stars alone never qualify a project.
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| GitHub stars | 8 | GitHub repository | Yes — one part of the repository route | |
| GitHub forks | 3 | GitHub repository | Yes — one part of the repository route | |
| Contributors with a GitHub account | 2 | GitHub contributors | Yes — one part of the repository route | |
| Commits on the default branch | 127 | GitHub repository | No | |
| Repository's main crate left out of the entry | none | crates.io database dump | Yes |
Facts that never count
| Signal | Value | Source | Fetched | Counts |
|---|---|---|---|---|
| License | Apache-2.0 | crates.io database dump | No | |
| Runs on, from listed crates and their direct dependencies | CUDA | crates.io database dump | No | |
| What shows each backend | CUDA: oxidizr feature cuda | crates.io database dump | No | |
| Native code, from listed crates and their dependencies | Binds native code: nvml-wrapper-sys (feature cuda) | crates.io database dump | No | |
| Python bindings, from direct dependencies of listed crates | No Python binding crate found | crates.io database dump | No | |
| Crates that depend on a listed crate directly | Not measured | No |
Corrections and review history
No correction applies to this entry.
Judgments
A judgment enters only through an approved issue and a merged pull request.
No judgment applies to this entry.