Try it See it Changes Bot Pricing API
Terraform plan, for model changes

The pre-check for everyopen-weight model change.

Swap a model or checkpoint, a fine-tune or RL recipe, a parallel layout, or a serving config. Before the change takes a GPU or serves traffic, and without running the model, Neurarch answers four questions:

  1. What changed. The structure and config diff, before anything downloads weights.
  2. What it needs. Peak memory per card, the smallest card that holds it, what one run costs.
  3. Is the layout legal and balanced. TP, PP and DP divisibility, and the work and memory on each pipeline stage.
  4. Does the config match the reference. At the configuration level only; whether outputs match is the model makers' verifiers' job.
Install the bot → Paste a model, get the plan

Free to start · no account for the check · derived from the config and calibrated on measured runs, never a claim about accuracy

113 of 131 jobs that did not fit their card, flagged before launch 50 structural checks, 0.27 ms per edit 234 real checkpoints we re-derive from config
github.com/neurarch-ai/model-ci-example/pull/11

Train DocLM on 2,048-token windows #11

configs/pretrain.yaml gpu: A10G # 24 GB batch_size: 32-seq_len: 1024+seq_len: 2048 grad_accum: 1
configs/pretrain.yaml gpu: A10G # 24 GB-batch_size: 32+batch_size: 16 seq_len: 2048-grad_accum: 1+grad_accum: 2
github-actions bot commented edited

Neurarch plan · models/doc_lm.py:DocLM

no longer fits A10G 24 GB

Peak training memory: 38.4 GB at batch 32 x 2,048 tokens (weights and optimizer state 2.7 GB, activations 35.7 GB).

  • Reserved card: A10G 24 GB. Does not fit: the job needs 44.2 GB with the 1.15x allocator headroom, and the card has 24 GB.
  • vs base: +17.8 GB (base 20.6 GB at batch 32 x 1,024 tokens), no longer fits A10G 24 GB.
  • Largest batch that fits A10G 24 GB: 16 at 2,048 tokens. Batch 16 with 2 gradient-accumulation steps keeps the effective batch at 32.
  • Smallest card that holds it: L40S 48 GB.

fits A10G 24 GB

Peak training memory: 20.6 GB at batch 16 x 2,048 tokens, 2 accumulation steps for an effective batch of 32 (weights and optimizer state 2.7 GB, activations 17.8 GB).

  • Reserved card: A10G 24 GB. Fits: the job needs 23.7 GB of its 24 GB with the 1.15x allocator headroom.
  • vs base: same peak (base 20.6 GB at batch 32 x 1,024 tokens).
  • Cost: about $23.78 and 21.6 h on A10G 24 GB for 3 epochs over 400,000 samples.

Structural checks. Will it run: yes. 113 layers, 135.8M params.

What it needs, on a real pull request: the comment as the bot wrote and then rewrote it. One line moved the job past the card it reserves; the plan named the batch that fits and the second push took it. Open the pull request →
Why one line in a config is worth a plan

seq_len: 1024 -> 2048 is one line in a pull request. The batch stays at 32 and the job still reserves one A10G 24 GB, so on the face of it nothing about the run changes, and the model still runs.

Activations scale with the tokens in a batch. The training peak goes from 20.6 GB to 38.4 GB, +17.8 GB, and with the 1.15x allocator headroom the job needs 44.2 GB of a 24 GB card. None of that is in the diff, and none of it is in review. On the cluster it is an out-of-memory error after the reservation is taken, or a bigger card requested to be safe.

The plan names the change that keeps the run the same: batch 16 is the largest that fits, and 2 gradient-accumulation steps keep the effective batch at 32. The second push does exactly that and the comment goes green, on the card the job already reserves.

See it in action

Four answers, each one real output

Every terminal here is what the command printed, captured by a script and committed. Nothing is typed by hand.

1What changed

A public model cut its context under everyone who pulls main. Not rare: of the 406 most-downloaded Hugging Face models with a config, 23% changed a structural key after release (Neurarch, from each repository's config.json history, read 2026-10-17).

2024-09-18structuralchange tracker Qwen2.5-7B-Instruct: context window 131072 to 32768 tokens; rope_scaling removed (was {"factor":4,"original_max_position_embeddings":32768,"typ...); positions are no longer scaled (2024-09-18).
Qwen/Qwen2.5-7B-Instruct · commit a306ca6 · "update config.json" · 2024-09-18- "max_position_embeddings": 131072+ "max_position_embeddings": 32768- "rope_scaling": {"factor":4,"original_max_position_embeddings":32768,"type":"yarn"}

Both keys are ones the graph reads (max_position_embeddings, rope_scaling), so this is a structural change, not metadata. A job that pulls main picks it up with no change in its own repository, and nothing errors until the next launch. The row is the tracker's own (it reads every tracked repository's history daily); the diff is the Hub's commit, fetched at both revisions. The CLI does not diff two revisions; under them, what it says about a vLLM launch still set to the old length:

terminal
$ npx neurarch@0.3.0 serve-check Qwen/Qwen2.5-7B-Instruct --gpu h100 -- vllm serve Qwen/Qwen2.5-7B-Instruct --max-model-len 131072  Qwen/Qwen2.5-7B-Instruct on vLLM  TP 1 x PP 1 x DP 1, 1 x h100-sxm (sm90), dtype bf16, weights unquantized, KV cache auto  served length 131072 (--max-model-len 131072); the model's derived maximum 32768  (the engine version and the defaults it assumed, and memory per GPU, then:)  block Served length 131072 is past the model's 32768-token context        The engine refuses to start ("User-specified max_model_len (131072) is greater than the derived max_model_len (32768)") unless VLLM_ALLOW_LONG_MAX_MODEL_LEN=1 is set, and with it set, positions past the trained length are extrapolated.        fix: Serve at most 32768, or add rope scaling where the model card supports it, with the card's own original length (e.g. --hf-overrides '{"rope_scaling":{"rope_type":"yarn","factor":F,"original_max_position_embeddings":N}}', with N x F >= 131072; N is the native length the card states, which can be below max_position_embeddings).  (two info lines, then:)  checked: gpu-count, tp-heads, tp-kv-heads, context, quant-support, weights-vs-checkpoint, memory, memory-fit, chat-template, samplerexit 1

The tracker behind that row follows 471 open-weight models; 410 have a readable history, and it has recorded 586 changes to their config, tokenizer, chat template and generation defaults. A chat template edit is rendered both ways on three fixed conversations: 125 changed the text the model is sent, 40 were cosmetic. It also reads the licence on each card: the licence id itself switched 41 times, across 35 models. The same record as Renovate, OSV and badge feeds →

Real output of neurarch 0.3.0, the release on npm, captured 2026-10-19. config.json before the commit → Every tracked change →

2What it needs

The pull request at the top is this answer on a real change. The memory number behind it, against the GPU and against accelerate: three AdamW steps per run on Modal, torch.cuda.max_memory_allocated as the truth, some runs sized to land near the card on purpose.

Every run that did not run out of memory, 148 points per method

0.10.1111010100100 exact bert-base, batch 32 on A10G: measured 2.27 GB, Neurarch held out 2.27 GB, accelerate 0.50 GBbst, batch 32 on A10G: measured 2.59 GB, Neurarch held out 2.46 GB, accelerate 2.06 GBclip-vit-b32, batch 32 on A10G: measured 3.57 GB, Neurarch held out 3.84 GB, accelerate 2.42 GBcnn-lstm-1d, batch 32 on A10G: measured 1.23 GB, Neurarch held out 0.32 GB, accelerate 0.00 GBcolbert, batch 32 on A10G: measured 1.54 GB, Neurarch held out 1.82 GB, accelerate 1.21 GBdin, batch 32 on A10G: measured 2.58 GB, Neurarch held out 2.44 GB, accelerate 2.05 GBdlrm, batch 32 on A10G: measured 1.30 GB, Neurarch held out 1.23 GB, accelerate 1.03 GBdreamer-v3, batch 32 on A10G: measured 0.29 GB, Neurarch held out 0.28 GB, accelerate 0.22 GBeeg-conformer, batch 32 on A10G: measured 0.20 GB, Neurarch held out 0.21 GB, accelerate 0.00 GBeegnet, batch 32 on A10G: measured 0.06 GB, Neurarch held out 0.05 GB, accelerate 0.00 GBijepa, batch 32 on A10G: measured 1.60 GB, Neurarch held out 1.66 GB, accelerate 0.65 GBmatryoshka-embed, batch 32 on A10G: measured 3.24 GB, Neurarch held out 2.57 GB, accelerate 0.88 GBmind, batch 32 on A10G: measured 2.58 GB, Neurarch held out 2.44 GB, accelerate 2.05 GBncf, batch 32 on A10G: measured 0.72 GB, Neurarch held out 0.67 GB, accelerate 0.56 GBneumf, batch 32 on A10G: measured 1.98 GB, Neurarch held out 2.03 GB, accelerate 1.69 GBpatch-tst, batch 32 on A10G: measured 0.08 GB, Neurarch held out 0.06 GB, accelerate 0.01 GBresnet-block, batch 32 on A10G: measured 0.04 GB, Neurarch held out 0.03 GB, accelerate 0.00 GBrqvae-semantic-id, batch 32 on A10G: measured 0.05 GB, Neurarch held out 0.02 GB, accelerate 0.02 GBsim, batch 32 on A10G: measured 2.58 GB, Neurarch held out 2.47 GB, accelerate 2.05 GBsimple-cnn, batch 32 on A10G: measured 0.04 GB, Neurarch held out 0.02 GB, accelerate 0.01 GBsimple-rnn, batch 32 on A10G: measured 0.09 GB, Neurarch held out 0.24 GB, accelerate 0.02 GBsli-rec, batch 32 on A10G: measured 1.30 GB, Neurarch held out 1.23 GB, accelerate 1.02 GBt5-small, batch 32 on A10G: measured 2.21 GB, Neurarch held out 2.92 GB, accelerate 0.91 GBtiger, batch 32 on A10G: measured 0.12 GB, Neurarch held out 0.08 GB, accelerate 0.02 GBtransformer-block, batch 32 on A10G: measured 1.45 GB, Neurarch held out 1.35 GB, accelerate 0.11 GBtwo-tower, batch 32 on A10G: measured 1.43 GB, Neurarch held out 1.34 GB, accelerate 1.13 GBunet, batch 32 on A10G: measured 6.97 GB, Neurarch held out 10.5 GB, accelerate 0.01 GBvit-b16, batch 32 on A10G: measured 0.58 GB, Neurarch held out 0.55 GB, accelerate 0.14 GBwide-and-deep, batch 32 on A10G: measured 0.09 GB, Neurarch held out 0.07 GB, accelerate 0.06 GBbert-base, batch 8 on A10G: measured 0.89 GB, Neurarch held out 1.01 GB, accelerate 0.50 GBbst, batch 8 on A10G: measured 2.59 GB, Neurarch held out 2.46 GB, accelerate 2.06 GBclip-vit-b32, batch 8 on A10G: measured 3.07 GB, Neurarch held out 3.14 GB, accelerate 2.42 GBcnn-lstm-1d, batch 8 on A10G: measured 0.81 GB, Neurarch held out 0.08 GB, accelerate 0.00 GBcolbert, batch 8 on A10G: measured 1.53 GB, Neurarch held out 1.54 GB, accelerate 1.21 GBdiffusion-unet, batch 8 on A10G: measured 17.5 GB, Neurarch held out 12.3 GB, accelerate 0.11 GBdin, batch 8 on A10G: measured 2.58 GB, Neurarch held out 2.44 GB, accelerate 2.05 GBdit-xl2, batch 8 on A10G: measured 12.2 GB, Neurarch held out 17.5 GB, accelerate 10.7 GBdlrm, batch 8 on A10G: measured 1.30 GB, Neurarch held out 1.23 GB, accelerate 1.03 GBdreamer-v3, batch 8 on A10G: measured 0.28 GB, Neurarch held out 0.27 GB, accelerate 0.22 GBeeg-conformer, batch 8 on A10G: measured 0.07 GB, Neurarch held out 0.05 GB, accelerate 0.00 GBeegnet, batch 8 on A10G: measured 0.03 GB, Neurarch held out 0.01 GB, accelerate 0.00 GBgpt2, batch 8 on A10G: measured 5.25 GB, Neurarch held out 4.94 GB, accelerate 1.35 GBijepa, batch 8 on A10G: measured 0.74 GB, Neurarch held out 1.00 GB, accelerate 0.65 GBllama3-block, batch 8 on A10G: measured 14.3 GB, Neurarch held out 16.1 GB, accelerate 11.2 GBmatryoshka-embed, batch 8 on A10G: measured 1.37 GB, Neurarch held out 1.43 GB, accelerate 0.88 GBmind, batch 8 on A10G: measured 2.58 GB, Neurarch held out 2.44 GB, accelerate 2.05 GBncf, batch 8 on A10G: measured 0.72 GB, Neurarch held out 0.67 GB, accelerate 0.56 GBneumf, batch 8 on A10G: measured 1.98 GB, Neurarch held out 2.03 GB, accelerate 1.69 GBpatch-tst, batch 8 on A10G: measured 0.04 GB, Neurarch held out 0.02 GB, accelerate 0.01 GBresnet-block, batch 8 on A10G: measured 0.03 GB, Neurarch held out 0.01 GB, accelerate 0.00 GBrqvae-semantic-id, batch 8 on A10G: measured 0.04 GB, Neurarch held out 0.02 GB, accelerate 0.02 GBsim, batch 8 on A10G: measured 2.58 GB, Neurarch held out 2.45 GB, accelerate 2.05 GBsimple-cnn, batch 8 on A10G: measured 0.03 GB, Neurarch held out 0.02 GB, accelerate 0.01 GBsimple-rnn, batch 8 on A10G: measured 0.05 GB, Neurarch held out 0.07 GB, accelerate 0.02 GBsli-rec, batch 8 on A10G: measured 1.30 GB, Neurarch held out 1.22 GB, accelerate 1.02 GBswin-tiny, batch 8 on A10G: measured 5.80 GB, Neurarch held out 6.08 GB, accelerate 0.45 GBt5-small, batch 8 on A10G: measured 1.00 GB, Neurarch held out 1.56 GB, accelerate 0.91 GBtiger, batch 8 on A10G: measured 0.05 GB, Neurarch held out 0.03 GB, accelerate 0.02 GBtransformer-block, batch 8 on A10G: measured 0.46 GB, Neurarch held out 0.44 GB, accelerate 0.11 GBtwo-tower, batch 8 on A10G: measured 1.43 GB, Neurarch held out 1.34 GB, accelerate 1.13 GBunet, batch 8 on A10G: measured 1.76 GB, Neurarch held out 2.64 GB, accelerate 0.01 GBvideo-dit, batch 8 on A10G: measured 5.04 GB, Neurarch held out 5.44 GB, accelerate 1.59 GBvit-b16, batch 8 on A10G: measured 0.27 GB, Neurarch held out 0.26 GB, accelerate 0.14 GBwide-and-deep, batch 8 on A10G: measured 0.09 GB, Neurarch held out 0.07 GB, accelerate 0.06 GBbert-base, batch 96 on A10G: measured 5.97 GB, Neurarch held out 5.61 GB, accelerate 0.50 GBbst, batch 96 on A10G: measured 2.59 GB, Neurarch held out 2.47 GB, accelerate 2.06 GBclip-vit-b32, batch 96 on A10G: measured 6.36 GB, Neurarch held out 5.73 GB, accelerate 2.42 GBcnn-lstm-1d, batch 96 on A10G: measured 2.31 GB, Neurarch held out 0.93 GB, accelerate 0.00 GBcolbert, batch 96 on A10G: measured 2.55 GB, Neurarch held out 2.55 GB, accelerate 1.21 GBdin, batch 96 on A10G: measured 2.58 GB, Neurarch held out 2.44 GB, accelerate 2.05 GBdlrm, batch 96 on A10G: measured 1.30 GB, Neurarch held out 1.23 GB, accelerate 1.03 GBdreamer-v3, batch 96 on A10G: measured 0.29 GB, Neurarch held out 0.32 GB, accelerate 0.22 GBeeg-conformer, batch 96 on A10G: measured 0.54 GB, Neurarch held out 0.63 GB, accelerate 0.00 GBeegnet, batch 96 on A10G: measured 0.13 GB, Neurarch held out 0.14 GB, accelerate 0.00 GBijepa, batch 96 on A10G: measured 3.86 GB, Neurarch held out 3.42 GB, accelerate 0.65 GBmatryoshka-embed, batch 96 on A10G: measured 8.23 GB, Neurarch held out 5.58 GB, accelerate 0.88 GBmind, batch 96 on A10G: measured 2.58 GB, Neurarch held out 2.44 GB, accelerate 2.05 GBncf, batch 96 on A10G: measured 0.72 GB, Neurarch held out 0.67 GB, accelerate 0.56 GBneumf, batch 96 on A10G: measured 1.98 GB, Neurarch held out 2.03 GB, accelerate 1.69 GBpatch-tst, batch 96 on A10G: measured 0.20 GB, Neurarch held out 0.16 GB, accelerate 0.01 GBresnet-block, batch 96 on A10G: measured 0.15 GB, Neurarch held out 0.10 GB, accelerate 0.00 GBrqvae-semantic-id, batch 96 on A10G: measured 0.07 GB, Neurarch held out 0.02 GB, accelerate 0.02 GBsim, batch 96 on A10G: measured 2.58 GB, Neurarch held out 2.51 GB, accelerate 2.05 GBsimple-cnn, batch 96 on A10G: measured 0.05 GB, Neurarch held out 0.04 GB, accelerate 0.01 GBsimple-rnn, batch 96 on A10G: measured 0.20 GB, Neurarch held out 0.66 GB, accelerate 0.02 GBsli-rec, batch 96 on A10G: measured 1.30 GB, Neurarch held out 1.24 GB, accelerate 1.02 GBt5-small, batch 96 on A10G: measured 5.45 GB, Neurarch held out 6.56 GB, accelerate 0.91 GBtiger, batch 96 on A10G: measured 0.30 GB, Neurarch held out 0.19 GB, accelerate 0.02 GBtransformer-block, batch 96 on A10G: measured 4.10 GB, Neurarch held out 3.79 GB, accelerate 0.11 GBtwo-tower, batch 96 on A10G: measured 1.43 GB, Neurarch held out 1.34 GB, accelerate 1.13 GBvit-b16, batch 96 on A10G: measured 1.45 GB, Neurarch held out 1.33 GB, accelerate 0.14 GBwide-and-deep, batch 96 on A10G: measured 0.09 GB, Neurarch held out 0.07 GB, accelerate 0.06 GBbert-base, batch 32 on H100: measured 2.32 GB, Neurarch held out 2.27 GB, accelerate 0.50 GBbst, batch 32 on H100: measured 2.64 GB, Neurarch held out 2.46 GB, accelerate 2.06 GBclip-vit-b32, batch 32 on H100: measured 3.60 GB, Neurarch held out 3.84 GB, accelerate 2.42 GBcnn-lstm-1d, batch 32 on H100: measured 1.27 GB, Neurarch held out 0.32 GB, accelerate 0.00 GBcolbert, batch 32 on H100: measured 1.59 GB, Neurarch held out 1.82 GB, accelerate 1.21 GBdin, batch 32 on H100: measured 2.63 GB, Neurarch held out 2.44 GB, accelerate 2.05 GBdit-xl2, batch 32 on H100: measured 25.6 GB, Neurarch held out 30.8 GB, accelerate 10.7 GBdlrm, batch 32 on H100: measured 1.35 GB, Neurarch held out 1.23 GB, accelerate 1.03 GBdreamer-v3, batch 32 on H100: measured 0.34 GB, Neurarch held out 0.28 GB, accelerate 0.22 GBeeg-conformer, batch 32 on H100: measured 0.25 GB, Neurarch held out 0.21 GB, accelerate 0.00 GBeegnet, batch 32 on H100: measured 0.11 GB, Neurarch held out 0.05 GB, accelerate 0.00 GBgpt2, batch 32 on H100: measured 17.7 GB, Neurarch held out 14.9 GB, accelerate 1.35 GBijepa, batch 32 on H100: measured 1.64 GB, Neurarch held out 1.66 GB, accelerate 0.65 GBllama3-block, batch 32 on H100: measured 29.1 GB, Neurarch held out 23.9 GB, accelerate 11.2 GBmatryoshka-embed, batch 32 on H100: measured 3.29 GB, Neurarch held out 2.57 GB, accelerate 0.88 GBmind, batch 32 on H100: measured 2.63 GB, Neurarch held out 2.44 GB, accelerate 2.05 GBncf, batch 32 on H100: measured 0.77 GB, Neurarch held out 0.67 GB, accelerate 0.56 GBneumf, batch 32 on H100: measured 2.03 GB, Neurarch held out 2.03 GB, accelerate 1.69 GBpatch-tst, batch 32 on H100: measured 0.13 GB, Neurarch held out 0.06 GB, accelerate 0.01 GBqwen2-vl, batch 32 on H100: measured 41.1 GB, Neurarch held out 45.3 GB, accelerate 24.8 GBresnet-block, batch 32 on H100: measured 0.11 GB, Neurarch held out 0.03 GB, accelerate 0.00 GBrqvae-semantic-id, batch 32 on H100: measured 0.10 GB, Neurarch held out 0.02 GB, accelerate 0.02 GBsim, batch 32 on H100: measured 2.63 GB, Neurarch held out 2.47 GB, accelerate 2.05 GBsimple-cnn, batch 32 on H100: measured 0.09 GB, Neurarch held out 0.02 GB, accelerate 0.01 GBsimple-rnn, batch 32 on H100: measured 0.16 GB, Neurarch held out 0.24 GB, accelerate 0.02 GBsli-rec, batch 32 on H100: measured 1.35 GB, Neurarch held out 1.23 GB, accelerate 1.02 GBswin-tiny, batch 32 on H100: measured 21.8 GB, Neurarch held out 22.7 GB, accelerate 0.45 GBt5-small, batch 32 on H100: measured 2.26 GB, Neurarch held out 2.92 GB, accelerate 0.91 GBtiger, batch 32 on H100: measured 0.17 GB, Neurarch held out 0.08 GB, accelerate 0.02 GBtransformer-block, batch 32 on H100: measured 1.50 GB, Neurarch held out 1.35 GB, accelerate 0.11 GBtwo-tower, batch 32 on H100: measured 1.48 GB, Neurarch held out 1.34 GB, accelerate 1.13 GBunet, batch 32 on H100: measured 7.02 GB, Neurarch held out 10.5 GB, accelerate 0.01 GBvideo-dit, batch 32 on H100: measured 16.0 GB, Neurarch held out 16.1 GB, accelerate 1.59 GBvit-b16, batch 32 on H100: measured 0.64 GB, Neurarch held out 0.55 GB, accelerate 0.14 GBwide-and-deep, batch 32 on H100: measured 0.14 GB, Neurarch held out 0.07 GB, accelerate 0.06 GBcnn-lstm-1d, batch 1024 on L4: measured 18.1 GB, Neurarch held out 9.90 GB, accelerate 0.00 GBdeepseek-v3-s, batch 4 on L4: measured 10.8 GB, Neurarch held out 10.6 GB, accelerate 6.00 GBdeepseek-v3-s, batch 8 on L4: measured 16.4 GB, Neurarch held out 14.1 GB, accelerate 6.00 GBdit-xl2, batch 16 on L4: measured 16.7 GB, Neurarch held out 21.9 GB, accelerate 10.7 GBdit-xl2, batch 20 on L4: measured 19.0 GB, Neurarch held out 24.1 GB, accelerate 10.7 GBeeg-conformer, batch 3072 on L4: measured 15.7 GB, Neurarch held out 20.0 GB, accelerate 0.00 GBeeg-conformer, batch 4096 on L4: measured 19.5 GB, Neurarch held out 26.7 GB, accelerate 0.00 GBllama3-block, batch 4 on L4: measured 14.2 GB, Neurarch held out 14.8 GB, accelerate 11.2 GBllama3-block, batch 16 on L4: measured 18.9 GB, Neurarch held out 18.7 GB, accelerate 11.2 GBqwen3-8b-r, batch 1 on L4: measured 13.2 GB, Neurarch held out 14.5 GB, accelerate 10.4 GBqwen3-8b-r, batch 2 on L4: measured 15.2 GB, Neurarch held out 16.5 GB, accelerate 10.4 GBqwen3-8b-r, batch 3 on L4: measured 18.3 GB, Neurarch held out 18.5 GB, accelerate 10.4 GBsimple-rnn, batch 6144 on L4: measured 10.6 GB, Neurarch held out 41.2 GB, accelerate 0.02 GBswin-tiny, batch 24 on L4: measured 16.4 GB, Neurarch held out 17.2 GB, accelerate 0.45 GBt5-small, batch 320 on L4: measured 16.8 GB, Neurarch held out 19.3 GB, accelerate 0.91 GBunet, batch 48 on L4: measured 10.4 GB, Neurarch held out 15.8 GB, accelerate 0.01 GBunet, batch 64 on L4: measured 13.9 GB, Neurarch held out 21.1 GB, accelerate 0.01 GBunet, batch 96 on L4: measured 20.8 GB, Neurarch held out 31.6 GB, accelerate 0.01 GBvideo-dit, batch 24 on L4: measured 12.3 GB, Neurarch held out 12.5 GB, accelerate 1.59 GBvideo-dit, batch 32 on L4: measured 15.9 GB, Neurarch held out 16.1 GB, accelerate 1.59 GBvideo-dit, batch 40 on L4: measured 19.5 GB, Neurarch held out 19.6 GB, accelerate 1.59 GB measured peak, GB predicted peak, GB
Neurarch, held out by architecture accelerate estimate-memory, float32 log scale; under 0.1 GB drawn on the axis

131 times a measured run did not fit a 16, 24, 40 or 80 GB card. How often each method said so before launch:

  1. Neurarch, held out 113 of 131
  2. accelerate, float32 8 of 131
  3. accelerate, bf16 0 of 131
6.9%median error, held out by architecture, on the 97 runs of 1 GB or more
14.0%median error on the 25 runs measured after the fit, at the edge of a 24 GB card: 6 of them fit, and it flagged 30 of the 42 times one did not
43.4%accelerate's median error on the same runs: it reads parameter bytes and counts no activations

203 measured runs, 55 of them out of memory (no peak to plot, so they live in the bars). Hover a point for the run. Every row, and how the six factors are fitted →

3Is the layout legal and balanced

Qwen3-0.6B in four pipeline stages on four L4s, blocks split evenly. Every divisibility check passes; the last stage carries the LM head and the loss and sets the pace for the other three. The check names a split, and we trained both.

terminal
$ npx neurarch@0.3.0 layout Qwen/Qwen3-0.6B --pp 4 --micro 1 --global-batch 8 --seq-len 2048 --gpu l4Parallel layout check: Qwen/Qwen3-0.6B  4 GPUs (l4, 24 GB), 28 blocks, schedule 1f1b, ZeRO 0, 8 microbatches/step, global batch 8   stage  blocks     extra      params    FLOPs/tok  ms/mb*  mem-bound  vs mean  act/mb  in-flight  peak/GPU    upper  fits  0      1-7 (7)    embedding    266M  837.1 MFLOP      76        39%    0.77x  0.7 GB          4    7.8 GB  11.2 GB  fits  1      8-14 (7)   -            110M  837.1 MFLOP      75        38%    0.76x  0.7 GB          3    4.1 GB   5.9 GB  fits  2      15-21 (7)  -            110M  837.1 MFLOP      75        38%    0.76x  0.7 GB          2    3.5 GB   4.9 GB  fits  3      22-28 (7)  head+loss    266M   1.77 GFLOP     168        48%    1.70x  0.7 GB          1    9.5 GB  13.6 GB  fits   Balance: slowest stage 3 at 1.70x the mean stage's predicted time.  Predicted step at 8 microbatches (1F1B schedule simulated op by op, a port of Primus's simulator): 1566 ms vs 1082 ms balanced, 44.7% slower than a perfect split (70.3% as microbatches grow).  Rebalanced split 9,9,9,1: 1.05x, predicted 40.2% faster per step at 8 microbatches (1117 ms); 62.1% as microbatches grow.  Bubble: 27.3% at 8 microbatches/step (17+ for under 15.0%).   warn  Stage 3 has 70.3% more predicted time than the mean stage (it also carries the LM head and the loss)  warn  Pipeline bubble is 27.3% of each step  info  Tied LM head costed on the last stage  (detail and fix under each finding, then:)  checked: tp-heads, tp-kv-heads, tp-hidden, tp-ffn, tp-node, cp-seq, batch-arithmetic, pp-over-blocks, stage-balance, pipeline-bubble, stage-memory

Forward and backward per microbatch, each stage on its own L4: what the check predicts, and what the A/B measured on the same split.

  1. stage 0 · embedding7 blocks9 blocks 7698 ms predicted7193 ms measured
  2. stage 17 blocks9 blocks 7596 ms predicted6686 ms measured
  3. stage 27 blocks9 blocks 7596 ms predicted6686 ms measured
  4. stage 3 · head+loss7 blocks1 block 168103 ms predicted15599 ms measured
predicted by the checkmeasured, isolated stage

Measured, not predicted: we trained this exact job (Qwen3-0.6B, 4 L4s, 8 microbatches, 1F1B) at both splits, twice each in separate containers. The step took 1,478 / 1,451 ms at 7,7,7,7 and 1,092 / 1,079 ms at 9,9,9,1: 34.4% and 35.3% faster. On 2 L4s, the split it picks there (18,10) ran 14.4% and 14.8% faster than the even one. One model, one card type, small scale: it says the recommendation held where we timed it, not that it holds on your cluster.

Real output of neurarch 0.3.0, the release on npm, captured 2026-10-19. Why the last stage: in 39.3% of LLM training jobs in ByteDance's straggler study, the last pipeline stage (LM head and loss) caused over half of the slowdown (OSDI 2025, arXiv 2505.05713).

4Does the config match the reference

The serving launch against the model it serves (context, tensor parallel against heads, KV cache against the batch it promises, chat template), and the training config against the data it will be fed. Read from the config and the flags, before anything is reserved.

terminal
$ npx neurarch@0.3.0 serve-check Qwen/Qwen3-8B --gpu l4 --gpus 4 -- vllm serve Qwen/Qwen3-8B --tensor-parallel-size 4 --max-model-len 65536 --max-num-seqs 256  Qwen/Qwen3-8B on vLLM  TP 4 x PP 1 x DP 1, 4 x l4 (sm89), dtype bf16, weights unquantized, KV cache auto  served length 65536 (--max-model-len 65536); the model's derived maximum 40960  (the engine version and the defaults it assumed, then:)   memory per GPU, predicted: 22.04 GiB x 0.92 = 20.28 GiB                   - weights 3.81 GiB                   - activation peak 0.58 GiB (estimate; vLLM measures this)                   - non-torch (NCCL, CUDA) 0.27 GiB (estimate; vLLM measures this)                   - CUDA graphs 0.53 GiB (estimate; vLLM measures this)                   = KV cache 15.08 GiB: 27,459 blocks of 16 tokens (36 full)                   36,864 KV bytes per token over the full-length layers; one full-length request 2.25 GiB                   vLLM would print: GPU KV cache size: 439,344 tokens; Maximum concurrency for 65,536 tokens per request: 6.70x                   weights: 2 bytes per parameter (16-bit); within 0.0% of the checkpoint's 16.4 GB                   card total: derived: nvidia-smi 23034 MiB less the 468 MiB gap measured on H100   block Served length 65536 is past the model's 40960-token context        The engine refuses to start ("User-specified max_model_len (65536) is greater than the derived max_model_len (40960)") unless VLLM_ALLOW_LONG_MAX_MODEL_LEN=1 is set, and with it set, positions past the trained length are extrapolated.        fix: Serve at most 40960, or add rope scaling where the model card supports it, with the card's own original length (e.g. --hf-overrides '{"rope_scaling":{"rope_type":"yarn","factor":F,"original_max_position_embeddings":N}}', with N x F >= 65536; N is the native length the card states, which can be below max_position_embeddings).  warn  --max-num-seqs 256, but at most 6 requests fit at the full 65536 tokens        vLLM's pool would hold 27,459 blocks of 16 tokens; a full-length request takes 4,096. Shorter requests pack more, but once long ones arrive the scheduler preempts or queues past ~6.        fix: Set the flag to what fits (6), shorten the max length, use an fp8 KV cache, or add GPUs as DP replicas.  (two info lines (reasoning parser, pad equals EOS), then:)  checked: gpu-count, tp-heads, tp-kv-heads, tp-ffn, context, quant-support, weights-vs-checkpoint, memory, memory-fit, chat-template, recipe, samplerexit 1 $ npx neurarch@0.3.0 bert-base-uncased --seq-len 1024 --tokenizer-size 30524  (parameter count, layers and structural checks, then:)  data fit checked: sequence length, tokenizer size    block Sequences of 1024 tokens are longer than the 512-row position table          Position ids past 511 index outside a learned table, so the first batch that long raises an IndexError (a device-side assert on GPU) after the reservation is taken.          fix: Truncate or chunk to 512 tokens, or pick a model whose context covers 1024.    block The tokenizer has 30524 ids and the embedding has 30522 rows          Any of the 2 ids past 30521 indexes outside the embedding. The usual cause is special tokens added to the tokenizer without resizing the model.          fix: Call model.resize_token_embeddings(len(tokenizer)) before training, and budget for the new rows.exit 1

The first command is a vLLM launch read before it runs: the length is past what the model was trained for, so vLLM refuses to start, and the flag promises 256 sequences where the KV cache holds about 6 at full length. The second is a training config read against the data: two blocks, each of which crashes on the first batch after the reservation is taken. Both exit 1, so a CI step or an admission hook can stop on them.

Real output of neurarch 0.3.0, the release on npm, captured 2026-10-19. serve-check reads vLLM, SGLang and llama.cpp launches; it compares configuration, never outputs.

Where it runs

Where the pre-check sits

The same four answers at each point a change has to pass before it takes a GPU or serves traffic. Same code behind every one.

At the scheduler The job is sized when it is submitted, before it takes a reservation. A request that cannot hold it is refused or warned, with the batch or card that fits. SkyPilot admin policy (PyPI) pip install neurarch-skypilot admin_policy: neurarch_skypilot.NeurarchPolicy SLURM cli_filter (PyPI), then in slurm.conf pip install neurarch-slurm CliFilterPlugins=cli_filter/lua neurarch-slurm --print-lua writes the plugin. It runs in the submitting client, so it tells people; it is not an enforcement boundary.
On the pull request Every model change in a pull request gets the plan as a comment, and a block fails the check. GitHub App, one click github.com/apps/neurarch-bot or a workflow step uses: neurarch-ai/neurarch-bot@v0 Install the bot →
In the coding agent The agent gets the checks as tools, and a hook stops a training launch that will not fit its card, or a vLLM or SGLang launch its config refuses. Claude Code plugin /plugin marketplace add neurarch-ai/neurarch-mcp /plugin install neurarch@neurarch-ai any MCP client npx -y neurarch-mcp MCP server →
From the command line No account. What a model needs at a batch, whether a parallel split is legal and balanced, whether a serving launch will start. on npm, 0.3.0 npx neurarch Qwen/Qwen3-8B --batch 8 npx neurarch layout Qwen/Qwen3-8B --tp 4 --pp 4 --dp 8 --global-batch 512 --seq-len 4096 npx neurarch serve-check Qwen/Qwen3-8B --gpu l4 --gpus 4 -- vllm serve Qwen/Qwen3-8B -tp 4 --max-model-len 32768 Real output above →
Over HTTP POST the graph with what the job will do: data (sequence length, tokenizer size), layout (TP, PP, DP, batch) or serve (the launch command). Arithmetic, no model call. the four answers POST /api/v1/check also POST /api/v1/plan POST /api/v1/lint API reference →
Inside your network One container answers plan, check and lint with the same code as the hosted API. It makes no outbound connection, so the documented way to run it is with the network removed. docker run --rm --network none -p 8080:8080 neurarch/verifier:local The image is not on a public registry yet: we send it, with a script that replaces every network call with one that throws and then answers a real request. How it runs →
Upstream, before you pull The change feed: every tracked open-weight model's config, tokenizer, chat template and generation defaults, diffed commit by commit from the Hub's history. What changed, for the models you did not change yourself. neurarch.com/changes Model changes → The same record for Renovate, OSV and badges ↓

Nothing to install: paste a model at /try.

For your other tools

Files other automation already reads

The pre-check and the change record, in formats a dependency bot, a scanner, code scanning and an attestation store take as they are. No account.

Find the unpinned downloads Reads .py, notebooks, YAML, shell and Dockerfiles for Hugging Face downloads with no commit pinned: from_pretrained, vllm serve, SGLang, CLI downloads, recipe keys. Aligned with Bandit's B615, plus the forms Bandit does not read. neurarch 0.3.0 npx neurarch@0.3.0 pin-check . Warns by default; pin/*: block in .neurarch.yml makes it a gate, --sarif feeds code scanning, --resolve writes the current sha into the fix. On 18 held-out public files: 0 missed, 2 wrong (both info level).
A pull request when a pinned model moves A Renovate preset with a custom datasource per tracked model. Once a revision is pinned, Renovate opens one pull request per model when its main moves, linking what changed key by key. renovate.json {"extends": ["https://www.neurarch.com/changes-feeds/renovate/preset.json"]} What it matches →
Every change as an advisory 586 OSV records, one per change event, each with a git range introduced at the commit that made it, so OSV tooling can ask whether a pinned revision carries it. 423 are marked breaking by a rule written into the feed. CC BY 4.0. OSV 1.7.0 curl -s https://www.neurarch.com/changes-feeds/advisories/x_NXMC-2025-0001.json The index →
A badge for the model you depend on A shields.io endpoint per tracked model: how many tracked keys changed since the earliest revision read, orange when any was breaking. README.md [![config changes](https://img.shields.io/endpoint?url=https%3A%2F%2Fwww.neurarch.com%2Fchanges-feeds%2Fbadge%2FNousResearch%2FHermes-3-Llama-3.1-8B.json)](https://www.neurarch.com/changes-feeds/models/NousResearch/Hermes-3-Llama-3.1-8B.html)
A pre-check record someone else can verify --attest writes an in-toto statement with in-toto's own test-result predicate; --cyclonedx writes a CycloneDX 1.6 ML-BOM fragment with the same verdicts. The subjects are the model's files hashed the way OpenSSF model signing does it, and the root digest is byte for byte the one model_signing 1.1.1 signs, so a model signature and a pre-check record point at the same bytes. Deterministic: two runs write the same file. on the main check, layout, serve-check and policy apply, neurarch 0.3.0 npx neurarch@0.3.0 serve-check Qwen/Qwen3-8B --gpu l4 --gpus 4 --attest precheck.intoto.json --cyclonedx precheck.cdx.json -- vllm serve Qwen/Qwen3-8B -tp 4 --max-model-len 32768 Sign it with actions/attest and gh attestation verify finds it. The record's schema →
One command

Point it at last month's jobs, or at an out-of-memory error

What it needs, read from what you already have. No account, no cluster access: a CSV of what each job requested, or the error text. Real output, captured once.

terminal
$ npx neurarch rightsize jobs.sample.csv# GPU right-sizing: requested vs needed **6 jobs, 174 GPU-hours, $507.85 spent; $328.53 of that was reserved capacity no job needed, claiming nothing on 1 row marked under or unknown.** 4 over, 1 right-sized, 1 under, 0 unknown.  (six rows, one per job: drawn below) $ npx neurarch oom error.txt --model FacebookAI/xlm-roberta-large --batch 1 --seq-len 128cause    too-big-for-card The job is bigger than this card: the predicted peak is 10.8 GB (12.5 GB with headroom) on a 4.29 GB card. read from  - the failing allocation asked for 0.02 GB  - the card has 4.29 GB  - 3.31 GB was held by live tensors  - 0.06 GB was reserved by PyTorch but held no tensor  - the plan predicts a 10.8 GB training peak at this batch fixes, least invasive first  1. shard the optimizer state and gradients across cards (FSDP or ZeRO), or use an 8-bit optimizer     weights, gradients and optimizer state alone are 10.7 GB, more than half the card  2. train adapters (LoRA) on a frozen base instead of every weight  (changes what is trained)     the optimizer state then covers the adapters only
  1. ft-qwen-small 8xH100 · 640 GB reserved · needed 211 GB · fits on 2xH200 (282 GB)
  2. lora-qwen-8b A100-80 · 80 GB reserved · needed 78 GB · right-sized as requested
  3. bert-classifier A100-80 · 80 GB reserved · needed 8.4 GB · fits on T4 (16 GB)
  4. tinyllama-lora H100 · 80 GB reserved · needed 35 GB · fits on L40S (48 GB)
  5. phi3-sft A100-40 · 40 GB reserved · needed 230 GB · did not fit what it asked for
  6. gpt2-pretrain 4xA100-80 · 320 GB reserved · needed 29 GB · fits on L40S (48 GB)
reserved (card GB x count) needed (predicted training peak x 1.15) needed more than it reserved GB, log scale

Real output of neurarch 0.2.0, captured 2026-10-18 on a 6-job sample CSV. "Reserved, not needed" is capacity at list price over the same hours, not a saving: a smaller card can run longer. Both commands, replayed, with the method →

pip install neurarch-trace for your own nn.Module: trace a forward pass, get the same plan
A real report

"Do I have to buy a better card?" Yes, and by how much

"How much CUDA memory is needed to train a new NER tagger?" flairNLP/flair#2364, fine-tuning xlm-roberta-large on a NVIDIA GeForce GTX 1050 Ti (4 GB). The error, verbatim:

RuntimeError: CUDA out of memory. Tried to allocate 16.00 MiB (GPU 0; 4.00 GiB total capacity; 3.08 GiB already allocated; 0 bytes free; 3.14 GiB reserved in total by PyTorch)

too-big-for-card The job is bigger than this card: the predicted peak is 10.8 GB (12.5 GB with headroom) on a 4.29 GB card.

weights, gradients, AdamW state: 10.7 GB activations at batch 1: 0.11 GB 1.15x headroom: 12.5 GB the card: 4.29 GB (4.00 GiB) held by live tensors when it failed: 3.31 GB GB

Weights, gradients and AdamW state alone are 10.7 GB on a 4.29 GB card, so no batch size makes this fit. The answer to the question in the issue is a card with at least 12.5 GB, or one of the two fixes the terminal above lists: shard the optimizer state, or train adapters on a frozen base.

The sequence length is the one input assumed (128 tokens; the issue does not state it). What the issue stated, what we assumed, and the run at 512 tokens →

Checkable

Those numbers are derived. Here is us checking them.

Every answer above is arithmetic from the config. Three places we put it next to the real thing, misses included.

Parameters, from config alone

We reconstruct 234 checkpoints people actually download from their config.json alone, no weights read, and put our parameter count next to the scalars actually in the published weight files. 65 of 81 comparable checkpoints are reproduced within 2% from config alone; the median miss is 0.3%.

CheckpointWe deriveIn the weightsDelta
Qwen2.5-7B-Instruct7.62B7.62B+0.00%
t5-small60.6M60.5M+0.11%
roberta-base124.0M124.7M-0.53%
vit-base-patch16-22485.8M86.6M-0.89%
distilbert-base-uncased66.4M67.0M-0.95%
All 234, including the 16 we miss → The misses are on the same page. They are the reason to believe the hits.

Memory, against the GPU

203 measured training runs on Modal, 55 of them out of memory. Held out by architecture, the median error on runs of 1 GB or more is 6.9%; on the 25 runs measured after the fit, near the edge of a 24 GB card, it is 14.0%. Of the 131 times a run did not fit its card, the estimate said so 113 times; accelerate estimate-memory said so 8 times. The chart · every row →

Parallel layout, one GPU per unit

The last pipeline stage (LM head and loss) against one decoder block, each timed alone on one GPU: measured over what the check predicted. 1.00 is exact.

  1. Qwen3-0.6B L4, 2048 x 1 1.23 → 1.11
  2. Qwen3-1.7B L4, 2048 x 1 1.11 → 1.09
  3. Llama-3.2-1B shape L4, 2048 x 1 1.28 → 1.16
  4. Qwen3-0.6B H100, 4096 x 4 0.72 → 0.69
  5. Llama-3.2-1B shape H100, 4096 x 4 0.99 → 0.97
the FLOPs-only cost modelthe current one, which adds memory-bound bytes at the card's bandwidth and prices each matmul by its size

Closer on every L4 row (worst miss 28.0% before, 16.0% after), and further on both H100 rows (lowest 0.72 before, 0.69 after): on H100 the large head matmul runs well above the 40% of peak the model assumes for long matmuls, so it prices the head too heavy there. Random weights built from each config, 5 runs; the direction, that the head stage is the heavy one, held on every run.

Parallel layout, the split trained both ways

Qwen3-0.6B trained with 1F1B pipeline parallelism on 2 and 4 L4s: how much faster each split's step was than the even split, measured, two runs each.

2 L4, 8 microbatches, against 14,14

  1. 18,10 its pick 14.4% / 14.8%
  2. 16,12 6.4% / 6.5%
  3. 20,8 11.9% / 14.4%
  4. 19,9 14.3% / 18.9%

2 L4, 16 microbatches, against 14,14

  1. 18,10 its pick 17.5% / 17.9%
  2. 16,12 7.7% / 7.9%
  3. 20,8 12.2% / 12.7%
  4. 19,9 16.4% / 19.1%

4 L4, 8 microbatches, against 7,7,7,7

  1. 9,9,9,1 its pick 34.4% / 35.3%
  2. 8,8,8,4 13.4% / 13.6%

4 L4, 16 microbatches, against 7,7,7,7

  1. 9,9,9,1 its pick 44.3% / 48.5%
  2. 8,8,8,4 16.2% / 20.0%
slower of the two runsfaster of the two runsthe check's pick in violet, the splits it was compared with in grey; bars start at 0%

The recommended split was faster than the even one in every run. The check picks 18,10 on 2 L4s, as it did when these ran. Setup: Qwen3-0.6B built from its config with random weights, bf16, AdamW, torch.distributed.pipelining with 1F1B, sequence 2048, micro batch 1, median of 15 steps after 5 warmup, each split run twice in separate containers. Everything here cost about $1.43 of L4 time. One small model on one card type: it says the recommendation held where we timed it, not that it holds on your cluster.

Pricing

Free under 8 GPUs. Per GPU after that.

Priced per managed GPU: a GPU that passed through the admission hook that month. Blocking is never the paywall: the CLI, the PR bot and the hook block on the free tier too. Early-access rates lock in when you subscribe.

Free

$0 forever
  • CLI, MCP server and Claude Code plugin
  • The 50 structural checks and the PR bot
  • The API, at the free quota
  • The self-hosted verifier container
  • The admission hook, free under 8 GPUs
Try it free →
Start here

Change pre-check report

$3,000 flat
  • Your configs and the last 30 days of jobs: what each asked for against what it needed, card by card
  • A pre-check of each change in that window: model or checkpoint, training recipe, parallel layout, serving config
  • Credited in full toward a subscription
Ask for the report →

Team

$15 /GPU/mo
  • Admission hook at submit: SLURM cli_filter or SkyPilot admin policy
  • The pre-check on every model change PR, in CI
  • A ledger of predicted against measured, per job
  • Change alerts for the models you run

Per managed GPU, billed annually: $180 per GPU a year, minimum 32 GPUs ($5,760 a year). Teams that only use pull requests can pay $20 per active committer a month instead.

Talk to us →

Enterprise / self-hosted

$25 /GPU/mo
  • Everything in Team
  • SSO
  • The self-hosted container inside your own network, with support, and an offline proof you can run
  • Unlimited change history for private repositories
  • Your own house rules and limits

Per managed GPU, billed annually: $300 per GPU a year.

Book a call →

Neurarch app (design canvas and agent). Free with 15 agent messages a day. Pro, $19/mo: 500 agent messages a month, Hugging Face, arXiv and code import, notebook and model-card export. Pro Plus, $39/mo: 2,000 agent and 200 Claude messages, workspaces, live training dashboard. Existing subscriptions are unchanged.

If you want the rest

The parts worth reading only if you are checking us

Where the memory number is weak, measured

Where the memory number is weak, from the same table:

  • At the edge of a card it is optimistic. Held out, it said "fits" 18 of the 131 times a run did not fit. On the 25 runs measured after the fit, chosen to land near a 24 GB card, the median miss is 14.0% on the 6 that fit, and it flagged 30 of the 42 that did not. Read it as a fit check first and a precise number second.
  • It also refuses runs that fit. 19 card checks held out, 7 of them with the measured peak within 15% of the card, inside the headroom the plan keeps.
  • Named misses. The U-Net's skip concatenations are counted as new tensors on top of the ones they join: held out, 51% over. Recurrent cells rest on three templates, so the gate-state factor is the least supported of the six: held out, the recurrent runs above 1 GB miss between 75% under and 287% over. Under 1 GB, allocator overhead dominates. Of the 18 did-not-fit checks still called "fits", 17 are at the line: the prediction with headroom lands within 20% under the card, the run needed more than that, and the out-of-memory error is often a single multi-GB allocation (a score matrix, or the logits in fp32) that a fragmented cache cannot place. The other 1: cnn-lstm-1d.
  • It predicts training under AdamW with bf16 autocast. Data loader buffers, custom kernels, activation checkpointing and multi-node communication buffers are not in the graph, so they are not in the number.

An earlier study ranked trained model designs by our static checks; it did not hold up, and we no longer sell it. The study and why it was retired →

What is actually in the box
  • The four answers, from the config and the flags. What changed, structurally and in the config; what it needs, as peak memory per card, the smallest card that holds it and what one run costs; whether a TP, PP and DP layout is legal and how the work and memory fall on each pipeline stage; whether a training config matches its data and a vLLM, SGLang or llama.cpp launch matches the model. No weights are downloaded and nothing is run.
  • A change feed for the models you did not change. Every tracked open-weight model's config, tokenizer, chat template and generation defaults, diffed commit by commit from the Hub's history, at /changes.
  • Right-sizing from what you already have. A CSV of last month's jobs, or the text of an out-of-memory error, read against the same memory estimate.
  • 50 structural checks, 43 of them on every edit in 0.27 ms (head divisibility, GQA mismatch, norm placement, dead paths, blown parameter and KV budgets) and 7 that compare a change with its base: a vocabulary resize that missed a tensor, a lost weight tie, a LoRA that targets nothing.
  • Calibrated in the open. The memory estimate against measured runs and the layout check against a pipeline trained both ways, each with its misses on the same page.
  • The design app, still here. A typed graph of 195 layer types and 75 prefab blocks with shapes propagated end to end, 48 templates, import from a Hugging Face id, PyTorch source, .onnx or .safetensors, and export to PyTorch, Keras, ONNX or a training notebook.
Your code, your keys, and what we store
  • No account is needed for the CLI, the checks, /try or the change feed.
  • The self-hosted container makes no outbound connection: a graph sent to it is checked in memory and never leaves your network.
  • A keyed API call records one anonymous structural row (a fingerprint, the layer-type histogram, the rules that fired), never the graph, parameter values or layer names. The API reference says exactly what.
  • In the app, your own Anthropic or Gemini key lives in your browser's localStorage, goes straight to the provider, never reaches our servers, and is wiped on sign-out or an account switch. The hosted agent is proxied for signed-in users so per-plan quotas can be enforced; that is the only path where a prompt touches our infrastructure.
  • Privacy policy · Security · Data policy and published datasets
Common questions

Does it run the model? No. It reads the config, the launch flags and the graph built from them, and every number is arithmetic calibrated on measured runs. That is why it can answer before a GPU is reserved, and why it says nothing about accuracy.

Does it tell me whether the outputs match the reference? No. It compares configuration: context length, heads against tensor parallel, KV cache against the batch a flag promises, the chat template. Whether outputs match is the job of the model makers' own verifiers.

How is the memory number different from accelerate estimate-memory? accelerate counts the bytes of the parameters and no activations, so on a job near the edge of a card it says "fits" when the run will not. The chart under What it needs puts both against the same measured runs.

What do I point it at? A Hugging Face id, a config.json, a launch command, a CSV of past jobs, an out-of-memory error, or your own nn.Module traced with neurarch-trace.

Can I cancel anytime? Yes, from the billing portal. Access runs to the end of the period, and there is a full refund within 7 days of a first payment.

Product tour: the four answers, in 2 minutes 23 seconds

One chapter per answer, each one real output: a context cut from the change feed and the launch it breaks, a training job sized per card and the pull request comment that went red and then green, a pipeline split with the measured A/B behind it, and a vLLM launch and a BERT fine-tune checked against their configs. Then the same checks as a Claude Code hook, a SkyPilot policy, an MCP tool and an API call. Every terminal is what the command printed.

Start free today

The CLI, the bot, the MCP server and the checks are free, and so is the admission hook under 8 GPUs.

No spam. Answer the question and a person replies. Or just open the app now →