Add an MLX backend so MOSS-Music runs on Apple Silicon - #3
Open
dthinkr wants to merge 1 commit into
Open
Conversation
Port MOSS-Music-8B to MLX so it runs efficiently on Apple Silicon, where the PyTorch/MPS path falls back to CPU and is effectively unusable for local generation. The audio encoder (chunked conv stem, Whisper layers, DeepStack taps), the SwiGLU adapters and the audio-to-Qwen3 fusion are reimplemented in MLX; the Qwen3 decoder is reused from mlx-lm. The repository's own MossMusicProcessor is reused unchanged for mel features and audio-token placeholders. Includes: - HF to MLX conversion with 8-bit quantization (audio encoder kept bf16) - KV-cached generation with a UTF-8-safe incremental detokenizer and a CLI - prefill parity vs the PyTorch reference, decode-path self-consistency tests, artifact-free unit tests, and a bf16-vs-8bit eval harness - an [mlx] optional-dependency group; mlx/ mirrors the sglang/ backend layout Validation: 8-bit vs fp32 reference prefill argmax identical, logit cos 0.99999; 8-bit vs bf16 over 5 mixed-genre clips argmax 5/5, mean cos 0.99998; ~10.2 GB, ~23 tok/s on an M4 (vs PyTorch/MPS stalling at <0.3 tok/s).
Author
|
Quick note on context: I built this because I wanted to run MOSS-Music locally on an Apple Silicon Mac, and it seemed like it might be useful to others, so I'm offering it as a proposal rather than assuming you want it. It's self-contained in its own No rush on a review, take your time. Thanks for the great work on this model. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
MOSS-Music doesn't run well on Apple Silicon today. On the PyTorch/MPS path several audio-encoder ops fall back to CPU, so local generation crawls (under 0.3 tokens/sec, and it often just hangs). This PR adds an MLX backend that runs properly: on an M4 it loads in about 1.5 seconds and analyzes a song in roughly 34 seconds, using about 10 GB of memory.
The code lives in a new
mlx/folder, following the same layout as the existingsglang/backend. It reuses the repo's own audio processor and mlx-lm's Qwen3 implementation, so only the audio-specific parts (the encoder, the adapters, and the audio-to-text fusion) are reimplemented for MLX.It includes a converter that turns the HuggingFace weights into MLX format with optional 8-bit quantization (the audio encoder is kept at higher precision for quality), generation with both a command-line tool and a Python API (Chinese text streams correctly), and tests that compare the MLX output against the original PyTorch model.
On accuracy, the 8-bit MLX model predicts the same next token as the full-precision reference and the logits line up almost exactly: cosine 0.99999 against fp32, and 5 out of 5 matching top predictions across five mixed-genre clips against the bf16 model. A script in
mlx/README.mdreproduces these numbers.A few notes: 8-bit is the tested recipe, while 4-bit and 6-bit run but aren't verified yet; inference handles one audio clip at a time. Also, unrelated to this PR, the repo's
pyproject.tomlpoints to aLICENSEfile that isn't in the root while the README states Apache-2.0, so it may be worth adding one.