#!/usr/bin/env python3 """Space entrypoint: fetch the index, then hand off to src/serve.py. WHY THE INDEX IS NOT IN THIS REPO --------------------------------- It lives in a separate HF Dataset. Pushing a rebuilt index into the Space repo would trigger a full Docker rebuild (~10 min, and it re-bakes 2.3 GB of models) where a restart (~40 s) is all that is actually needed. The split also keeps the Space's build context small enough to push over a hotel wifi. Configuration is entirely environment variables, because that is what the Space settings UI gives you: VOICERAG_INDEX_REPO required HF dataset holding index/ -- "you/voicerag-index" ELEVENLABS_API_KEY required requirement 1; set it as a SECRET, not a variable VOICERAG_CORS optional origin of the Vercel page VOICERAG_LANGS optional subset to serve; default = everything in the manifest VOICERAG_PREWARM optional langs to warm TTS for, or "all" HF_TOKEN optional only if the dataset is private """ from __future__ import annotations import os import pathlib import subprocess import sys import time ROOT = pathlib.Path(os.environ.get("VOICERAG_ROOT", "/home/user/app/data")) INDEX_REPO = os.environ.get("VOICERAG_INDEX_REPO", "").strip() def fetch_index() -> None: manifest = ROOT / "index" / "manifest.json" if manifest.exists(): print(f"==> index already at {ROOT}, skipping download") return if not INDEX_REPO: sys.exit( "!! VOICERAG_INDEX_REPO is not set.\n" " Build the index with notebooks/build_index.ipynb, push it to an\n" " HF dataset, then set VOICERAG_INDEX_REPO in the Space settings." ) from huggingface_hub import snapshot_download t0 = time.time() print(f"==> pulling index from {INDEX_REPO}") ROOT.mkdir(parents=True, exist_ok=True) snapshot_download(repo_id=INDEX_REPO, repo_type="dataset", local_dir=str(ROOT), token=os.environ.get("HF_TOKEN") or None) if not manifest.exists(): sys.exit(f"!! {INDEX_REPO} has no index/manifest.json -- wrong repo?") mb = sum(f.stat().st_size for f in (ROOT / "index").rglob("*")) / 2**20 print(f"==> {mb:.0f} MB in {time.time() - t0:.1f}s") def build_cmd(env: dict, python: str = sys.executable) -> list[str]: """serve.py's argv, assembled from Space environment variables. An unset variable must not become an empty flag: `--cors ""` reaches argparse as a real value and CORSMiddleware would be installed with an empty origin list, which blocks the Vercel page as surely as no middleware at all -- but silently, and only in the browser. """ cmd = [python, "src/serve.py", "--host", "0.0.0.0", "--port", env.get("PORT", "7860")] for name, flag in (("VOICERAG_LANGS", "--langs"), ("VOICERAG_CORS", "--cors"), ("VOICERAG_PREWARM", "--prewarm-tts")): if env.get(name, "").strip(): cmd += [flag, env[name].strip()] return cmd def main() -> int: fetch_index() if not os.environ.get("ELEVENLABS_API_KEY"): # Not fatal: the text path is the whole of requirements 2-6 and stays # up. /health reports asr:false so the failure is visible, not silent. print("!! ELEVENLABS_API_KEY unset -- voice input will return an error") cmd = build_cmd(dict(os.environ)) print("==>", " ".join(cmd), flush=True) return subprocess.call(cmd) if __name__ == "__main__": raise SystemExit(main())