Spaces:
Running
Running
| #!/usr/bin/env python3 | |
| """Gradio Space for MiMo-V2.5-ASR MLX.""" | |
| from __future__ import annotations | |
| import os | |
| import time | |
| from functools import lru_cache | |
| from pathlib import Path | |
| os.environ.setdefault("HF_HUB_ENABLE_HF_TRANSFER", "1") | |
| def _install_gxx_wrapper() -> None: | |
| """Make MLX CPU JIT tolerate GCC's built-in _Float* typedefs on Spaces.""" | |
| wrapper_dir = Path("/tmp/mimo_mlx_bin") | |
| wrapper_dir.mkdir(parents=True, exist_ok=True) | |
| wrapper = wrapper_dir / "g++" | |
| if not wrapper.exists(): | |
| wrapper.write_text("#!/usr/bin/env bash\nexec /usr/bin/g++ -fpermissive \"$@\"\n", encoding="utf-8") | |
| wrapper.chmod(0o755) | |
| os.environ["PATH"] = f"{wrapper_dir}:{os.environ.get('PATH', '')}" | |
| _install_gxx_wrapper() | |
| import gradio as gr | |
| from mlx_audio.stt import load | |
| MODEL_ID = os.environ.get("MIMO_MLX_MODEL", "mlx-community/MiMo-V2.5-ASR-MLX") | |
| MODEL_DIR = os.environ.get("MIMO_MLX_MODEL_DIR", "/models/MiMo-V2.5-ASR-MLX") | |
| AUDIO_TOKENIZER_DIR = os.environ.get( | |
| "MIMO_AUDIO_TOKENIZER_DIR", | |
| "/models/MiMo-Audio-Tokenizer", | |
| ) | |
| LANGUAGES = {"Auto": None, "Chinese": "zh", "English": "en"} | |
| def _model_source() -> str: | |
| if os.path.exists(os.path.join(MODEL_DIR, "config.json")): | |
| return MODEL_DIR | |
| return MODEL_ID | |
| def load_asr_model(): | |
| kwargs = {} | |
| if os.path.exists(os.path.join(AUDIO_TOKENIZER_DIR, "config.json")): | |
| kwargs["audio_tokenizer_dir"] = AUDIO_TOKENIZER_DIR | |
| return load(_model_source(), **kwargs) | |
| def transcribe(audio_path: str | None, language_label: str, max_tokens: int): | |
| if not audio_path: | |
| return "", "Upload or record an audio file." | |
| start = time.perf_counter() | |
| was_loaded = load_asr_model.cache_info().currsize > 0 | |
| load_start = time.perf_counter() | |
| model = load_asr_model() | |
| load_elapsed = time.perf_counter() - load_start | |
| infer_start = time.perf_counter() | |
| result = model.generate( | |
| audio_path, | |
| language=LANGUAGES.get(language_label), | |
| max_tokens=int(max_tokens), | |
| ) | |
| infer_elapsed = time.perf_counter() - infer_start | |
| total_elapsed = time.perf_counter() - start | |
| load_text = "cached" if was_loaded else f"{load_elapsed:.2f}s" | |
| status = ( | |
| f"Done. elapsed={total_elapsed:.2f}s, " | |
| f"model_load={load_text}, infer={infer_elapsed:.2f}s" | |
| ) | |
| return result.text, status | |
| with gr.Blocks(title="MiMo-V2.5-ASR MLX") as demo: | |
| gr.Markdown("# MiMo-V2.5-ASR MLX") | |
| gr.Markdown( | |
| "This Space uses MLX CPU fallback on Linux. It can verify that the model " | |
| "loads, but full ASR on cpu-basic may exceed the request timeout. " | |
| "Run locally on Apple Silicon for the intended MLX GPU path." | |
| ) | |
| with gr.Row(): | |
| with gr.Column(): | |
| audio = gr.Audio(label="Audio", type="filepath", sources=["upload", "microphone"]) | |
| language = gr.Radio( | |
| choices=list(LANGUAGES.keys()), | |
| value="Auto", | |
| label="Language", | |
| ) | |
| max_tokens = gr.Slider(1, 128, value=16, step=1, label="Max Tokens") | |
| button = gr.Button("Transcribe", variant="primary") | |
| with gr.Column(): | |
| transcript = gr.Textbox(label="Transcript", lines=8) | |
| status = gr.Textbox(label="Status") | |
| button.click(transcribe, [audio, language, max_tokens], [transcript, status]) | |
| if __name__ == "__main__": | |
| demo.queue(max_size=4, default_concurrency_limit=1).launch() | |