| """ |
| Bharat Voice Assistant on Modal β Gradio UI on A10G (~11GB VRAM) |
| ================================================================ |
| MiniCPM-o 4.5 (STT + LLM) + VoxCPM2 (TTS) in one container. |
| |
| modal deploy deploy_modal.py |
| β https://aniketchopde03--bharat-voice-ui.modal.run |
| |
| Dashboard: https://modal.com/apps/aniketchopde03/main |
| """ |
|
|
| import modal |
|
|
| app = modal.App("bharat-voice") |
|
|
| OMNI_REVISION = "4382fcae8a551b54d18f18462db974ff312aa7f3" |
| BAKE_MODELS = ( |
| 'python -c "from huggingface_hub import snapshot_download; ' |
| f"snapshot_download('openbmb/MiniCPM-o-4_5', revision='{OMNI_REVISION}', " |
| "local_dir='/models/MiniCPM-o-4_5'); " |
| "snapshot_download('openbmb/VoxCPM2', local_dir='/models/VoxCPM2')\"" |
| ) |
|
|
| web_image = ( |
| modal.Image.debian_slim(python_version="3.11") |
| .apt_install("ffmpeg", "libsndfile1", "build-essential") |
| .pip_install("torch==2.8.0", "torchaudio==2.8.0") |
| .pip_install( |
| "transformers==4.51.0", |
| "huggingface_hub>=0.33.5,<1.0", |
| "gradio>=6.0.0,<6.18.0", |
| "accelerate>=0.34.0", |
| "bitsandbytes>=0.43.0", |
| "librosa==0.9.0", |
| "setuptools>=65.0.0,<81", |
| "soundfile>=0.12.1", |
| "numpy>=1.26.0", |
| "minicpmo-utils[all]>=1.0.5", |
| "voxcpm>=2.0.3", |
| "sentencepiece>=0.2.0", |
| "fastapi[standard]", |
| ) |
| |
| .run_commands(BAKE_MODELS) |
| .env({ |
| "OMNI_MODEL_PATH": "/models/MiniCPM-o-4_5", |
| "TTS_MODEL_PATH": "/models/VoxCPM2", |
| "HF_HUB_DISABLE_TELEMETRY": "1", |
| }) |
| .add_local_file("app.py", "/root/bharat_voice_app.py") |
| ) |
|
|
| with web_image.imports(): |
| from fastapi import FastAPI |
| from gradio.routes import mount_gradio_app |
|
|
|
|
| @app.function( |
| image=web_image, |
| gpu="A10G", |
| memory=16384, |
| max_containers=1, |
| scaledown_window=600, |
| timeout=1800, |
| ) |
| @modal.concurrent(max_inputs=50) |
| @modal.asgi_app() |
| def ui(): |
| import importlib.util |
| import threading |
|
|
| spec = importlib.util.spec_from_file_location( |
| "bharat_voice_app", "/root/bharat_voice_app.py" |
| ) |
| bharat = importlib.util.module_from_spec(spec) |
| spec.loader.exec_module(bharat) |
|
|
| |
| web_app = mount_gradio_app( |
| app=FastAPI(), |
| blocks=bharat.demo, |
| path="/", |
| css=bharat._TTS_CSS, |
| js=bharat._TTS_JS, |
| theme="soft", |
| show_error=True, |
| ) |
|
|
| def _warmup(): |
| print("[INFO] Loading MiniCPM-o on GPU (background warmup)...") |
| bharat.get_omni() |
| print("[INFO] MiniCPM-o ready.") |
| |
|
|
| threading.Thread(target=_warmup, daemon=True).start() |
| return web_app |
|
|