Skip to content

feat: GGUF load guard for MLX engines - #423

Merged
dahai80 merged 1 commit into
mainfrom
feat/gguf-load-guard
Aug 8, 2026
Merged

feat: GGUF load guard for MLX engines#423
dahai80 merged 1 commit into
mainfrom
feat/gguf-load-guard

Conversation

@dahai80

@dahai80 dahai80 commented Aug 8, 2026

Copy link
Copy Markdown
Owner

What

mlx-lm / mlx-vlm / mlx-embeddings have no GGUF load path (mx.save_gguf is one-way export). Loading a .gguf file or a GGUF-only directory crashes inside mlx_lm.load with an opaque error. This adds a shared guard that detects GGUF targets up front and raises a clear, actionable GGUFLoadError.

This closes the "GGUF 加载桥" action item from the competitor audit reports (fusion-mlx_vs_*.md): rapid-mlx has GGUF identification in its download gate; fusion-mlx had zero — now it has a load-time guard with a helpful message.

How

New fusion_mlx/engine/gguf_guard.pyassert_not_gguf(model_name, engine_kind) called before every load entry:

Engine file Load lib Sites
engines/batched.py mlx_lm.load 1 (LLM)
engines/vlm.py mlx_vlm.load 1 (VLM)
engines/embedding.py mlx_embeddings.load 1
engines/reranker.py mlx_lm.load + mlx_embeddings.load 3

Guard inspects local filesystem targets only (HF repo ids pass through to mlx_lm, which handles remote resolution). GGUF-only targets (.gguf file, or dir with .gguf weights but no config.json/safetensors) raise GGUFLoadError pointing the user at mlx-community/<model>-mlx repos or POST /v1/convert. Non-GGUF targets are a no-op.

Verification

  • ruff check: clean
  • black --check: clean
  • pytest tests/unit/test_gguf_guard.py10 passed
  • Full suite pytest tests/unit/8120 passed, 0 failed (was 8110; +10 new tests; 282 skipped = 3.4%)
  • Quarantined debt tests (test_no_mllm_flag, test_batched_engine_output_router) fail identically with/without this change — pre-existing debt, unrelated

Scope

Purely additive: +159 lines, 0 deletions. No public API signatures changed. The duplicate-engine tech debt (engine/batched/ vs engines/batched.py) is tracked separately in #422 — not mixed into this PR (risk asymmetry).

🤖 Generated with Claude Code

mlx-lm/mlx-vlm/mlx-embeddings have no GGUF load path (mx.save_gguf is
one-way export). Loading a .gguf file or GGUF-only dir crashes inside
mlx_lm.load with an opaque error. Add a shared guard
(fusion_mlx/engine/gguf_guard.py) called before every load entry:

- engines/batched.py  (LLM, mlx_lm.load)
- engines/vlm.py      (VLM, mlx_vlm.load)
- engines/embedding.py (Embedding, mlx_embeddings.load)
- engines/reranker.py  (Reranker, 3 sites: _load_causal_lm /
  _load_jina_reranker / embedding fallback)

Guard inspects the local filesystem target only (HF repo ids pass
through to mlx_lm). GGUF-only targets raise GGUFLoadError with an
actionable message pointing at mlx-community repos or POST /v1/convert.
Non-GGUF targets are a no-op.

10 unit tests cover: direct .gguf file, GGUF-only dir, MLX dir, GGUF
dir with config.json, empty name, nonexistent path, HF repo id,
convert-endpoint message, no-op normal path.

Closes audit action item from fusion-mlx_vs_*.md reports.
Duplicate-engine debt tracked separately in #422.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@dahai80
dahai80 merged commit 4a19fda into main Aug 8, 2026
5 checks passed
@dahai80
dahai80 deleted the feat/gguf-load-guard branch August 8, 2026 03:29
dahai80 added a commit that referenced this pull request Aug 8, 2026
* chore: bump version 0.8.11 → 0.8.12

Patch: GGUF load guard (#423), Wan2 staged VAE Stream fix (#419),
DPO logprobs TypeError fix (#421).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* style: black-format training/reward.py (CI lint fix)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant