Spaces:
Sleeping
Sleeping
File size: 1,897 Bytes
570a76f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #!/usr/bin/env python3
"""
app.py (HuggingFace Spaces entry point)
=========================================
Boots the FastAPI backend in a background thread, then hands control
to the Streamlit UI β both run inside a single Spaces process.
HuggingFace Spaces runs one process and exposes port 7860.
Streamlit listens on 7860; FastAPI listens on 8000 (internal only).
The Streamlit UI talks to FastAPI at http://localhost:8000.
Usage (locally)
---------------
streamlit run app.py --server.port 7860
Usage (Spaces) β Spaces calls `streamlit run app.py` automatically
when SDK: streamlit is set in README.md.
"""
from __future__ import annotations
import os
import sys
import threading
import time
# ββ Point the UI at the in-process FastAPI ββ
os.environ.setdefault("API_URL", "http://localhost:8000")
# ββ Download model checkpoint if not present ββ
_CHECKPOINT = os.path.join(os.path.dirname(__file__), "checkpoints", "model.pt")
if not os.path.isfile(_CHECKPOINT):
print("[startup] Checkpoint not found β downloading from HuggingFace Hub β¦")
import subprocess
subprocess.run(
[sys.executable, "scripts/download_model.py"],
check=False,
)
def _run_fastapi() -> None:
"""Start uvicorn in a daemon thread."""
import uvicorn
uvicorn.run(
"api.main:app",
host="0.0.0.0",
port=8000,
log_level="warning",
)
# Start FastAPI in the background
_api_thread = threading.Thread(target=_run_fastapi, daemon=True)
_api_thread.start()
# Give FastAPI a moment to bind before Streamlit starts hitting /health
time.sleep(3)
# ββ Hand off to the Streamlit UI ββ
# Streamlit's entry point is ui/app.py β we import and call main() directly
# so Spaces only needs to run `streamlit run app.py`.
sys.path.insert(0, os.path.dirname(__file__))
from ui.app import main # noqa: E402
main() |