modular/skills

debug-model

Debug a MAX model that loads, compiles, serves, and generates tokens but whose output disagrees with a reference implementation.

View source

How to use

  1. Copy the installation command and review the source package before installing it in your own agent environment.
  2. Check the source document for required tools, credentials and supported hosts.
  3. Describe your input and desired deliverable; review the output against the source material.
npx skills add https://github.com/modular/skills --skill debug-model

Before you start

  • Installation does not include a model subscription, API allowance or permission to access your files.
  • Repository stars and installation counts describe activity, not an independent quality or security test.
Original skill document

Rendered from the source repository. Headings, examples, code, tables, links, and referenced images are preserved.

Parity/coherence failure protocol

The model runs without errors but output is wrong. Scalar F.print taps hide directional bugs, and each new tap costs a full recompile. Build a per-layer tensor-dump comparator first. Every later check becomes a numpy read from disk.

Use this skill when MAX output disagrees with a PyTorch reference you can run and hook. The primary case is a custom-architecture port that serves but fails parity or coherence checks. The same protocol covers a quantized variant of a working port, a multi-GPU conversion of a working single-GPU port, and a regression after a MAX upgrade. It applies anywhere a trusted reference exists.

Don't use this skill when:

  • The server crashes on load → fix config, weights, module (import-model)
  • You haven't finished implementing the module → import-model Phase 2
  • An already-verified model needs logit-comparison tolerances tuned → that's

threshold calibration, which this skill doesn't cover

References

FileRead when
comparator-build.mdBuilding HF/MAX dumpers and the comparator
comparator-output-patterns.mdInterpreting comparator output, false cliffs, token-0 invariant
agent-workflow.mdDispatching parallel investigation agents
stacked-failures.mdA fix helped but verification still fails

For MAX's built-in runtime debugging options (NaN checks, source tracebacks, op logging), see the MAX debugging tools. max.nn.hooks.PrintHook (covered in comparator-build.md) prints layer inputs and outputs for quick triage.

Protocol

Step 0: Sanity-check HF

Run model.generate(...) on the same HF repo, prompt, and checkpoint. If HF is incoherent, fix the tokenizer or chat template first. The MAX model isn't the problem.

bash
pixi run python -c "
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM
tok = AutoTokenizer.from_pretrained('<repo>')
model = AutoModelForCausalLM.from_pretrained('<repo>', dtype=torch.float32, device_map='auto')
text = tok.apply_chat_template([{'role':'user','content':'Hello!'}], tokenize=False, add_generation_prompt=True)
out = model.generate(**tok(text, return_tensors='pt').to(model.device), max_new_tokens=32, do_sample=False)
print(tok.decode(out[0]))
"

Step 1: Build the comparator

Follow comparator-build.md. You need three artifacts: HF dumper, MAX dumper (forward() taps + standalone runner), comparator script. Cast dump tensors to FP32 inside the MAX forward().

Guard: validate the dumpers before trusting them. Run both dumpers on a ModuleV3 model that MAX already serves correctly, with the taps added to its forward(). Use olmo3, or llama3_modulev3 served with --prefer-module-v3. Expect cos ≈ 0.999 at every layer, identical prompt_tokens.npy on both sides, and post_embed cos = 1.0. Anything less means the dumpers are broken. Fix them before reading anything into a comparison on your port.

Step 2: Read comparator output, then branch

Follow comparator-output-patterns.md. Check false cliffs (wrong hidden_states indexing, missing attention_mask on decode-prefix dumps) before bisecting the model.

Choose the next step from the first comparator run that passes the guard:

  • Some layer diverges → layer hunt. Continue with Steps 3 to 5.
  • Every layer matches (cos ≥ 0.99) but generation still diverges → the

model math is likely correct. Skip to Step 6. Don't bisect layers.

  • Pattern matches a false-cliff signature → fix the dumper, re-dump,

re-read. Don't debug the model against a broken comparator.

Compute per-token and per-dim cosine slices when global cos looks ambiguous:

python
cos_per_token = [cos(h[t], m[t]) for t in range(h.shape[0])]
cos_per_dim = [cos(h[:, d], m[:, d]) for d in range(h.shape[1])]

High max_diff where HF spikes and MAX is flat usually means HF formed an attention anchor your port didn't.

Step 3: Dispatch investigation agents

Follow agent-workflow.md. One lead agent analyzes dumps and ranks hypotheses with tensor evidence. Helpers run in parallel (weight stats, code diff, kernel inspection, sub-tap prep). Don't dispatch fix-attempt agents until the lead localizes.

Step 4: Verify numerically before recompiling

For each hypothesis: read dump tensors, compute what the fix would produce, compare to HF. Match → recompile. No match → next hypothesis.

Step 5: Apply fix, re-dump, re-compare

One compile, one smoke, full comparator pass (cos > 0.99 all layers). If verification still fails, see stacked-failures.md.

Step 6: Serve vs pipeline

When teacher-forced dumps at decode step K match HF but generated text diverges, the model math is likely correct. Bisect before re-bisecting layers:

CheckPassFail →
Teacher-forced dump @ Kcos ≥ 0.99, argmax matchesSteps 1 to 5 (model bug)
Incremental pipeline decode @ Ktoken K matches HFDecode-state bug (KV, conv cache)
Serve vs pipeline @ KmatchHarness bug (tokenizer, chat template, token recovery)

Build if missing: pipeline decode compare, incremental layer dump, serve compare scripts. If teacher-forced and pipeline both pass but serve fails, don't edit the model.

from this repository

More skills

All skills
modular
Community

benchmark-model

Benchmark a model served on MAX with the max benchmark command: measure throughput (tokens/sec), latency (TTFT, TPOT, inter-token latency), and GPU utilization by driving load against a running max serve endpoint. Use this whenever the user wants to benchmark, load-test, or measure the performance of a MAX model, get tokens-per-second / TTFT / TPOT numbers, run a concurrency or request-rate sweep, compare latency vs throughput, size a deployment, or produce benchmark JSON, even if they don't say

installs
2
GitHub stars
204
Updated
Oct 22
modular
Community

eval-model

Measures the task accuracy of text models served by MAX using standard benchmarks such as GSM8K, MMLU, HellaSwag, ARC, AIME, GPQA, TruthfulQA, WinoGrande, and BABILong. Use when benchmarking a served model, comparing it with model-card or reference scores, verifying that a new MAX model produces correct answers, or running repeatable dataset evaluations against a MAX OpenAI-compatible endpoint.

installs
2
GitHub stars
204
Updated
Oct 22
modular
Community

migrate-max-v2-to-v3

Use when migrating a MAX model from the V2 graph API (max.nn, TensorValue, explicit Graph construction) to ModuleV3 (max.experimental.nn, Tensor, F.lazy() + compile()). Triggers on: "migrate to ModuleV3", "port a max.nn model to max.experimental", "convert TensorValue to Tensor", "update my model to the V3 API", "ModuleV3 migration". Workflow: read the concept map, rewrite imports and call signatures, and replace graph building with compile(weights=...). Align weight names with the new module hi

installs
2
GitHub stars
204
Updated
Oct 22
modular
Community

mojo-gpu-fundamentals

The basics of how to program GPUs using Mojo. Use this skill in addition to mojo-syntax when writing Mojo code that targets GPUs or other accelerators. Use targeting code to NVIDIA, AMD, Apple silicon GPUs, or others. Use this skill to overcome misconceptions about how Mojo GPU code is written.

installs
2
GitHub stars
204
Updated
Oct 22