# app.py from __future__ import annotations import os from typing import Optional from app.gradio_app import build_demo from models.tts_router import cleanup_old_audio from utils.config import get_settings import huggingface_hub def ensure_model() -> str: """ Ensure a local GGUF exists: - Reads settings from .env via pydantic (get_settings()). - If the file at LLAMACPP_MODEL_PATH doesn't exist, download from HF_MODEL_REPO/HF_MODEL_FILE. - HF_MODEL_FILE is optional; if missing, we use basename(LLAMACPP_MODEL_PATH). - The file is saved exactly at LLAMACPP_MODEL_PATH (e.g., models/.gguf). """ s = get_settings() # <- loads .env model_path: Optional[str] = getattr(s, "LLAMACPP_MODEL_PATH", None) or os.getenv("LLAMACPP_MODEL_PATH") repo_id: Optional[str] = getattr(s, "HF_MODEL_REPO", None) or os.getenv("HF_MODEL_REPO") file_name: Optional[str] = getattr(s, "HF_MODEL_FILE", None) or os.getenv("HF_MODEL_FILE") if not model_path or not repo_id: raise RuntimeError( "Missing config: set LLAMACPP_MODEL_PATH and HF_MODEL_REPO in .env " "(optionally HF_MODEL_FILE)." ) # Where/what to download if not file_name: file_name = os.path.basename(model_path) # Already present? if os.path.exists(model_path): print(f"[MODEL] Found existing model at {model_path}") return model_path # Make sure models/ exists os.makedirs(os.path.dirname(model_path), exist_ok=True) print(f"[MODEL] Downloading {file_name} from {repo_id} → {model_path}") # Download into a temp cache, then copy/symlink into our desired path local_cached = huggingface_hub.hf_hub_download( repo_id=repo_id, filename=file_name, local_dir=os.path.dirname(model_path), # ensure it lands under models/ local_dir_use_symlinks=False ) # hf_hub_download already placed it in local_dir; ensure final path matches model_path if os.path.abspath(local_cached) != os.path.abspath(model_path): # If HF wrote it to a different name/path, copy/rename import shutil shutil.move(local_cached, model_path) print(f"[MODEL] Ready at {model_path}") return model_path def main(): # Clean old TTS files cleanup_old_audio(keep_latest=None) # Ensure the local model is present (downloads if missing) ensure_model() demo = build_demo() # On HF Spaces, share=True is fine; server host/port are managed by Spaces demo.launch(share=True) if __name__ == "__main__": main()