maatt4face's picture
Update app.py
431c654 verified
Raw
History Blame Contribute Delete
4.08 kB
"""JamAI long-track rating app -- Hugging Face Space entrypoint.
Wraps s04_longtrack_rating_app.py (copied verbatim into the Space repo,
next to this file, with longtrack_pool/ beside it -- s04 resolves both
relative to its own location, so no path surgery is needed).
What this wrapper adds, and why:
1. RATINGS PERSISTENCE. Space containers have EPHEMERAL filesystems --
anything written locally is wiped on restart. A background
CommitScheduler pushes logs/ to a PRIVATE HF dataset repo every 2
minutes. Each server boot writes its own uniquely-named CSV
(longtrack_ratings_<bootid>.csv): CommitScheduler mirrors folder
state, so reusing one filename would let a fresh boot's empty file
OVERWRITE history in the dataset -- unique-per-boot files only ever
ADD. Analysis concatenates logs/*.csv from the dataset repo.
2. LOCKED WRITES. CSV appends take scheduler.lock so a commit never
snapshots a half-written row.
3. Plain launch() -- Spaces serves the app directly; no share tunnel,
no relay, stable URL.
Space setup (one-time, ~10 min -- see README.md for details):
- Create the Space (SDK: Gradio), upload this folder's files +
s04_longtrack_rating_app.py + longtrack_pool/.
- Space settings -> Secrets: HF_TOKEN = a WRITE-scoped token.
- Optionally set RATINGS_DATASET (else edit the default below).
Without HF_TOKEN the app still runs but ratings are NOT persisted --
it prints a loud warning (fine for a quick look, never for real raters).
"""
import os
import sys
import uuid
from pathlib import Path
try:
import spaces
@spaces.GPU
def _dummy_gpu():
pass
except ImportError:
pass
HERE = Path(__file__).resolve().parent
# On the Space, s04_longtrack_rating_app.py sits NEXT TO this file (repo
# root); for a local smoke test it is one level up (02_Conductor/).
for _p in (HERE, HERE.parent):
if str(_p) not in sys.path:
sys.path.insert(0, str(_p))
import s04_longtrack_rating_app as core
# ---- persistence: local logs/ -> private HF dataset repo ----------------
# Dataset namespace is derived from the TOKEN OWNER (whoami) unless
# RATINGS_DATASET overrides it -- a token can only create repos in its
# own namespace (a hardcoded guess 403s, as the first deploy showed).
BOOT_ID = uuid.uuid4().hex[:8]
core.RATINGS_CSV = core.LOG_DIR / f"longtrack_ratings_{BOOT_ID}.csv"
core.LOG_DIR.mkdir(parents=True, exist_ok=True)
# Persistence engages only when actually running on a Space (SPACE_ID is
# set by HF) AND a token secret exists; any failure degrades to
# no-persistence with a loud warning rather than killing the app.
scheduler = None
if os.environ.get("SPACE_ID") and os.environ.get("HF_TOKEN"):
try:
from huggingface_hub import CommitScheduler, HfApi
DATASET_ID = os.environ.get("RATINGS_DATASET") or (
HfApi(token=os.environ["HF_TOKEN"]).whoami()["name"]
+ "/jamai-longtrack-ratings")
scheduler = CommitScheduler(
repo_id=DATASET_ID, repo_type="dataset", private=True,
folder_path=str(core.LOG_DIR), path_in_repo="logs",
every=2, token=os.environ["HF_TOKEN"],
)
_orig_append = core.append_log
def _locked_append(row, csv_path=None):
with scheduler.lock:
_orig_append(row, csv_path)
core.append_log = _locked_append
print(f"ratings persist to dataset {DATASET_ID} "
f"(file logs/longtrack_ratings_{BOOT_ID}.csv, every 2 min)")
except Exception as e: # bad token / wrong namespace / network
scheduler = None
print(f"persistence setup FAILED ({e}) -- running WITHOUT it")
if scheduler is None:
print("=" * 70)
print("WARNING: ratings will NOT survive a restart (no persistence "
"active). On the Space, set the HF_TOKEN secret (write scope) "
"and check RATINGS_DATASET before real raters use this.")
print("=" * 70)
tracks = core.load_tracks()
print(f"loaded {len(tracks)} tracks")
demo = core.build_demo(tracks)
demo.launch(share=True, ssr_mode=False)