voicerag / deploy /boot.py
menoone's picture
Add voice RAG over MSMARCO-XI, deployable without the GPU pod
11ecc5b
Raw
History Blame Contribute Delete
3.6 kB
#!/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())