Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion backend/requirements-mlx.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ miniaudio>=1.59
# mlx_audio.stt.load) works fine on transformers 4.57.x in practice.
#
# Install it via `pip install --no-deps mlx-audio==0.4.1` after this file
# (see .github/workflows/release.yml). Most other mlx-audio runtime deps
# (see .github/workflows/release.yml and the setup-python recipe in the
# justfile). Most other mlx-audio runtime deps
# (huggingface_hub, librosa, mlx-lm, numba, numpy, protobuf, pyloudnorm,
# sounddevice, tqdm) are already in requirements.txt or pulled in by
# other engines.
55 changes: 55 additions & 0 deletions backend/tests/test_mlx_smoke.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""
Smoke test for the MLX backend dependencies on Apple Silicon.

Guards the `--no-deps` install of mlx-audio/mlx-lm done by `just setup-python`
and release.yml: those packages skip their declared dependencies (transformers
>=5.x conflict), so a missing transitive dep only surfaces at import time.
This test fails fast if the MLX STT/TTS entry points the backend uses stop
importing (e.g. the `miniaudio` regression from issue #505).

Usage:
python -m pytest backend/tests/test_mlx_smoke.py -v
"""

import platform
import sys

import pytest

pytestmark = pytest.mark.skipif(
not (sys.platform == "darwin" and platform.machine() == "arm64"),
reason="MLX packages are only installed on Apple Silicon macOS",
)


def test_mlx_core_runs():
"""The MLX runtime itself works (Metal array op)."""
import mlx.core as mx

assert mx.array([1, 2]).sum().item() == 3


def test_mlx_audio_tts_entry_point():
"""`from mlx_audio.tts import load` — used by MLXBackend.load_model_async."""
from mlx_audio.tts import load

assert callable(load)


def test_mlx_audio_stt_entry_point():
"""`from mlx_audio.stt import load` — used by the Whisper MLX STT path.

Importing mlx_audio.stt also pulls in miniaudio, so this catches the
ModuleNotFoundError from issue #505 on fresh installs.
"""
from mlx_audio.stt import load

assert callable(load)


def test_mlx_lm_entry_points():
"""`mlx_lm.load` / `mlx_lm.generate` — used by qwen_llm_backend."""
from mlx_lm import generate, load

assert callable(load)
assert callable(generate)
6 changes: 6 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ setup-python:
if [ "$(uname -m)" = "arm64" ] && [ "$(uname)" = "Darwin" ]; then
echo "Detected Apple Silicon — installing MLX dependencies..."
{{ pip }} install -r {{ backend_dir }}/requirements-mlx.txt
# mlx-lm and mlx-audio declare transformers>=5.x, which conflicts with
# our transformers<=4.57.x cap, so install them --no-deps (their other
# runtime deps are covered by requirements.txt / requirements-mlx.txt —
# see the note in requirements-mlx.txt and .github/workflows/release.yml)
{{ pip }} install --no-deps mlx-lm==0.31.1
{{ pip }} install --no-deps mlx-audio==0.4.1
fi
{{ pip }} install git+https://github.com/QwenLM/Qwen3-TTS.git
{{ pip }} install pyinstaller ruff pytest pytest-asyncio -q
Expand Down