MidMan AI

A coding and game-development language model built from scratch in Rust: its own tensors, its own autograd, its own training loop. No pretrained weights and no ML framework.

Try it: the lab runs the real model in your browser, compiled to WebAssembly.

What works today: the tensor library with reverse-mode autodiff, the transformer layers, the model, AdamW, and an end-to-end training loop that memorizes a task. Not started: the tokenizer, the data pipeline, checkpoints and everything after them.

Each crate page below says what the crate does, shows how to use it, and states its status. The longer design notes live in the repository's docs/ folder.

Workspace layout

18 library crates under crates/, 3 binaries under apps/, and one benchmark package under benches/. Six library crates have code today, plus midman-api; the rest are stubs with their documentation already written.

midman-foundation -> midman-model-config -> midman-tensor -> midman-nn -> midman-model -> midman-optim
                                                                               \-> midman-api (C ABI, WebAssembly)

Status: current. Dependencies point one way, and nothing depends on midman-bench or midman-api.

midman-foundation

What it does: the error type, a format-version check, and a deterministic random number generator (xoshiro256**) used for every random choice in the project.

Example: Rng::seed_from_u64(7).next_f32() always gives the same value on every platform.

Status: done and tested.

midman-model-config

What it does: the architecture description (ModelConfig), exact parameter counts, a strict text format, and six presets from 117K to 1.0B parameters.

Example: Preset::Smoke.default_config().param_count() is exactly 117,056. The lab's calculator shows these numbers live.

Status: done and tested.

midman-tensor

What it does: dense f32 tensors on the CPU with reverse-mode automatic differentiation, every operation a transformer needs, and a finite-difference gradient checker.

Example: build x.matmul(&w).silu().sum_all(), call backward(), and read the gradient of w.

Status: done and tested. Single-threaded; broadcast and softmax are measurably slower than a plain loop (see midman-bench).

midman-nn

What it does: the layers of a decoder-only transformer: linear, embedding, RMSNorm, rotary embeddings, causal grouped-query attention, a SwiGLU MLP and a decoder block. Each layer's math is also a plain function so it can be gradient-checked, and attention can return its probabilities for visualization.

Example: Attention::forward_traced returns the output and the [batch, heads, time, time] attention probabilities.

Status: done and tested. RMSNorm is much slower than a plain loop and is on the list to fix.

midman-model

What it does: MidManModel, the decoder-only transformer built from a ModelConfig. Construction fails unless the parameters add up to exactly what the config counts.

Example: model.loss(&inputs, &targets, batch, seq)?.backward()? gives gradients for every parameter. forward_traced also returns every layer's attention.

Status: done and tested, including a gradient check through the whole network and bit-for-bit reproducible training.

midman-optim

What it does: AdamW with decoupled weight decay, a warmup-and-cosine learning-rate schedule, and global gradient-norm clipping.

Example: clip_global_norm(&mut grads, 1.0)? then optimizer.step(&mut params, &grads, lr)?.

Status: done and tested against an independent implementation.

midman-api

What it does: the interface for applications that embed MidMan. Lab trains a model on a fixed task from the outside and exposes the loss, gradient norms, attention maps and embeddings. A C ABI (extern "C", opaque handles, status codes, no unwinding) wraps it, and that is exactly what the browser build exports.

Example: midman_lab_create, midman_lab_step, midman_lab_attention, then read results through midman_floats_ptr.

Status: done and tested natively and as real WebAssembly. The browser build is 256 KB with no imports and matches the native build to about one float rounding step.

midman-bench

What it does: criterion benchmarks for the crates above, with a plain reference implementation beside every kernel so a result means something.

Example: open the benchmarks page for the latest run.

Status: current. Open findings: RMSNorm, broadcast add, softmax and the AdamW step are slower than their plain-loop references.

The lab

The lab is a page that runs the real Rust code in your browser. It has a parameter calculator, training with live loss and gradient charts, attention heat maps, a rotary-embedding explorer, and an embedding plot.

How it works: midman-api is compiled to WebAssembly (a SIMD build and a plain build, chosen at load time). A small dependency-free JavaScript module wraps its C ABI. Every number on the page comes from Rust; nothing is reimplemented in JavaScript.

Status: tested end to end in CI: the real WebAssembly binary, the real page in a headless browser DOM, and agreement with the native build.

Deploying

The site is deployed to Cloudflare Pages by the deploy-site.yml workflow, by hand only: it never runs on a push. It builds the WebAssembly engine, runs the tests, builds this book, pulls the latest CI, test and benchmark results, and publishes.

Setup: the repository needs CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID secrets. The Pages project is created on the first run.

Status: written; its first run on GitHub has not happened yet.