Validate MLX model repositories before loading them.
Project description
mlx-model-doctor
Validate an MLX / Hugging Face model repository before you load it.
A model repo can be broken in ways you only discover halfway through load(): a config.json that's missing or internally inconsistent, a missing tokenizer file, a model.safetensors.index.json that points at shards that aren't there, quantization metadata that uses a mode or group size MLX rejects, a chat template that's absent or whose stop token has a typo, a corrupt safetensors header, a quantized layer whose packed weight and scales shapes disagree, or a model that simply won't fit in the memory you have. mlx-model-doctor checks those up front and prints a report, so a bad repo fails fast with a clear reason instead of a confusing crash.
The checks read repository metadata and the safetensors header — config.json, the tokenizer files, the safetensors index, quantization fields, and the tensor map (dtypes, shapes, byte-offsets) parsed from the header alone. They need no GPU or MLX and never download the weights; on the Hub the header arrives over a small HTTP range request, so the checks stay cheap to run anywhere. An optional --smoke check loads the model through mlx-lm (Apple Silicon) under a memory cap, to confirm it loads and generates.
mlx-model-doctor check local ./my-model
mlx-model-doctor check hf mlx-community/Llama-3.2-3B-Instruct-4bit
See EXAMPLES.md for real, dated transcripts of every command.
Install
pip install mlx-model-doctor
# With the optional mlx-lm smoke check (Apple Silicon):
pip install "mlx-model-doctor[mlx-lm]"
Or with uv:
uv add mlx-model-doctor
uv add "mlx-model-doctor[mlx-lm]"
Verify the install:
mlx-model-doctor version
mlx-model-doctor --help
Requires Python ≥ 3.11. The static checks are pure Python (huggingface-hub + safetensors); only the optional --smoke runtime check needs mlx-lm and Apple Silicon.
What it checks
The built-in text plugin runs these against a model repository, broadly in this order:
- Required files —
config.jsonis present and readable. - Config consistency —
config.jsonparses, and itsmodel_typeis set. - Tokenizer — the tokenizer files a text model needs are present, and the special-token configuration is coherent.
- Chat template — a chat/instruct model declares a chat template (in
tokenizer_config.jsonor achat_template.jinja), and the end-of-turn token its template emits is a registered special token. A typo'd stop token loads fine and then never stops generating. - Safetensors index — when the weights are sharded,
model.safetensors.index.jsonis valid and every shard it references exists. - Tensor header — read the safetensors header itself (the tensor map: dtypes, shapes, byte-offsets; no weight download) to catch a corrupt header (overlapping or out-of-bounds tensor offsets), a weight map that points at tensors no shard contains, a declared tied embedding that contradicts the stored weights, and an MLX-quantized layer whose packed-weight and scales shapes don't agree. These run by default; pass
--skip-weightsto skip them for a faster config-only pass. - Quantization metadata — quantization fields are present and use a valid MLX mode with a valid group size and bit width (
affine,mxfp4,mxfp8,nvfp4). This reads the metadata, not the tensors. - Generation tokens — the
eos/pad/bostoken IDs are present and agree acrossconfig.json,generation_config.json, andtokenizer_config.json. - Memory budget — an estimate of the memory the model needs at your context length, compared against a budget you pass with
--max-memory.
Each check returns a result with a status (pass / warn / fail / skip), a message, and — when something is wrong — a remediation hint. The report aggregates them, and the process exit code reflects the worst result under your fail policy.
Python API
from mlx_model_doctor import check_local_model, check_hf_model
report = check_local_model("./my-model")
print(report.summary) # {"pass": 9, "warn": 1, "fail": 0, "skip": 2}
for result in report.results:
print(result.status, result.check_id, result.message)
# Hugging Face repos (hits the Hub):
report = check_hf_model("mlx-community/Llama-3.2-3B-Instruct-4bit")
DoctorReport renders to text, JSON, or Markdown (render_text / render_json / render_markdown), and the result objects are frozen dataclasses, so the output is stable to diff in CI.
Commands
| Command | What it does |
|---|---|
version |
Print the version plus the active Python, virtualenv, and dependency status. |
man |
Print usage examples and the exit-code table. |
plugins |
List registered check plugins (text today). |
check local <path> |
Validate a model directory on disk. |
check hf <repo_id> |
Validate a model repository on the Hugging Face Hub (network). |
sample hf |
Survey likely-MLX repos for an author and validate a deterministic sample. |
check accepts --format {text,json,markdown}, --output <file>, --max-memory <e.g. 32gb>, --context-length <n>, --fail-on {error,warn,never}, --skip-weights (skip the tensor-header checks for a faster config-only pass), and --smoke.
Exit codes: 0 checks passed (under the fail policy), 1 checks found failures, 2 tool error — a bad target, a missing dependency, or zero checks run.
The Hugging Face path
check hf and sample hf talk to the Hub through huggingface-hub. They read repository metadata (the file list, sizes, the small text files, and the safetensors header over a range request) rather than downloading the weights, but they do need network access, and an auth or rate-limit problem surfaces as a clear tool error rather than a stack trace. sample hf is a survey: it lists an author's repos, keeps the ones that look like MLX models, validates a deterministic sample of them, and reports each as its own batch item — a per-model failure is recorded and the run continues.
Status
Alpha (0.3.0). The static check local path and the report/CLI surface are solid and well tested. 0.3.0 reads the safetensors header (no weight download) to add four tensor-level checks — offset corruption, weight-map parameter sanity, tied-embedding consistency, and MLX quantized-layer shape consistency — which run by default (--skip-weights opts out). The Hugging Face path (check hf, sample hf) is implemented and tested offline against fakes; its live behavior is exercised by opt-in network tests. The API may still shift before 1.0 — pin a version if you depend on it.
License
Apache-2.0. See LICENSE and NOTICE. Validating a model repository does not touch the model's own weights or license; those belong to their respective authors.
Acknowledgements
- Apple ML Explore for MLX and
mlx-lm. - Hugging Face for the Hub client and
safetensors.
Sister projects
Other MLX libraries for Apple Silicon:
- mlx-taef — tiny autoencoders for fast diffusion-latent previews and low-memory decode (FLUX / SD).
- mlx-teacache — TeaCache residual caching to skip redundant FLUX denoising steps.
By Denis Ineshin · ineshin.space
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mlx_model_doctor-0.4.0.tar.gz.
File metadata
- Download URL: mlx_model_doctor-0.4.0.tar.gz
- Upload date:
- Size: 177.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b82ba6089b52cb0f562a760ddadd3209f36148f0919d2ae126b2e4de7da4ea44
|
|
| MD5 |
d0e6fa07ac43082c1e8aed2d2c67ad31
|
|
| BLAKE2b-256 |
d7a98e112c5fb8abaaf59871518af59f21d03d335932769c5a24819f19e992a8
|
Provenance
The following attestation bundles were made for mlx_model_doctor-0.4.0.tar.gz:
Publisher:
release.yml on IonDen/mlx-model-doctor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mlx_model_doctor-0.4.0.tar.gz -
Subject digest:
b82ba6089b52cb0f562a760ddadd3209f36148f0919d2ae126b2e4de7da4ea44 - Sigstore transparency entry: 1750565629
- Sigstore integration time:
-
Permalink:
IonDen/mlx-model-doctor@3f8b3cc7150467e2257b9b0b4c0aca439c22f640 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/IonDen
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3f8b3cc7150467e2257b9b0b4c0aca439c22f640 -
Trigger Event:
push
-
Statement type:
File details
Details for the file mlx_model_doctor-0.4.0-py3-none-any.whl.
File metadata
- Download URL: mlx_model_doctor-0.4.0-py3-none-any.whl
- Upload date:
- Size: 58.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03ef0a5eec844b11d7ac0f3ce445222c8a75481416d88506014955231494ad71
|
|
| MD5 |
a616f43ab0eee5e45ddb4df52e9f5900
|
|
| BLAKE2b-256 |
15cfe0437f145111ffeca513856b46431f53fed93b374d3284eee3d8851f38d7
|
Provenance
The following attestation bundles were made for mlx_model_doctor-0.4.0-py3-none-any.whl:
Publisher:
release.yml on IonDen/mlx-model-doctor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mlx_model_doctor-0.4.0-py3-none-any.whl -
Subject digest:
03ef0a5eec844b11d7ac0f3ce445222c8a75481416d88506014955231494ad71 - Sigstore transparency entry: 1750565661
- Sigstore integration time:
-
Permalink:
IonDen/mlx-model-doctor@3f8b3cc7150467e2257b9b0b4c0aca439c22f640 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/IonDen
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3f8b3cc7150467e2257b9b0b4c0aca439c22f640 -
Trigger Event:
push
-
Statement type: