Spaces:
Sleeping
Sleeping
| import os | |
| import subprocess | |
| import sys | |
| from pathlib import Path | |
| import modal | |
| APP_NAME = "corereader-backend" | |
| MODEL_VOLUME_NAME = os.getenv("MODEL_VOLUME_NAME", "corereader-models") | |
| # --- Image --- | |
| # Keep it simple: CPU-only. Kokoro ONNX + ORT CPU should run fine on Modal CPU. | |
| image = ( | |
| modal.Image.debian_slim(python_version="3.12") | |
| .apt_install("curl", "ca-certificates") | |
| .pip_install( | |
| "fastapi>=0.128.0", | |
| "uvicorn[standard]>=0.30.0", | |
| "aiohttp>=3.9.5", | |
| "beautifulsoup4>=4.12.3", | |
| "lxml>=5.2.2", | |
| "numpy>=1.26.0", | |
| "onnxruntime>=1.20.0", | |
| "kokoro-onnx>=0.2.6", | |
| "requests>=2.32.0", | |
| "soundfile>=0.12.0", | |
| ) | |
| .env( | |
| { | |
| # ORT threading: match the reserved CPU cores by default. | |
| "ORT_INTRA_OP_THREADS": os.getenv("ORT_INTRA_OP_THREADS", "3"), | |
| "ORT_INTER_OP_THREADS": os.getenv("ORT_INTER_OP_THREADS", "1"), | |
| "ORT_ALLOW_SPINNING": os.getenv("ORT_ALLOW_SPINNING", "1"), | |
| } | |
| ) | |
| # Copy backend source code into the container image (keep this last). | |
| .add_local_dir("backend", remote_path="/app/backend") | |
| ) | |
| app = modal.App(APP_NAME) | |
| models_volume = modal.Volume.from_name(MODEL_VOLUME_NAME, create_if_missing=True) | |
| def _ensure_models() -> None: | |
| backend_dir = Path("/app/backend") | |
| models_dir = backend_dir / "models" | |
| model_path = models_dir / "kokoro-v1.0.onnx" | |
| voices_path = models_dir / "voices-v1.0.bin" | |
| if model_path.exists() and voices_path.exists(): | |
| return | |
| models_dir.mkdir(parents=True, exist_ok=True) | |
| subprocess.run( | |
| [sys.executable, str(backend_dir / "download_models.py")], | |
| cwd=str(backend_dir), | |
| check=True, | |
| ) | |
| def fastapi_app(): | |
| # Match Docker behavior: run with backend directory as CWD so relative | |
| # paths and download scripts behave consistently. | |
| os.chdir("/app/backend") | |
| sys.path.insert(0, "/app/backend") | |
| # Download model/voices on cold start if missing (cached in Volume). | |
| _ensure_models() | |
| # Import the FastAPI app. | |
| from server import app as web_app # type: ignore | |
| return web_app | |