slipstream / app.py
ashaibani's picture
Upload folder using huggingface_hub
2d4823c verified
Raw
History Blame Contribute Delete
3.84 kB
"""Slipstream: interactive presentation of the project-controls forecasting benchmark.
A Gradio Server (FastAPI + Gradio's API engine) that serves a buildless Preact frontend and exposes
the benchmark data through typed `@app.api` endpoints the frontend calls via the @gradio/client JS
library. Runs locally (`python app.py`) and on Hugging Face Spaces (sdk: gradio, app_file: app.py).
"""
import json
import os
import urllib.request
from pathlib import Path
import gradio as gr
from fastapi import Request
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
ROOT = Path(__file__).parent
FRONTEND = ROOT / "frontend"
BENCH = json.loads((ROOT / "data" / "bench.json").read_text())
# Live-demo backend (deployed Modal app: pipeline/agent/demo_modal.py). The frontend calls the
# same-origin /demo/* routes below; we proxy to Modal server-side so the URL stays out of the client
# and the long-running, possibly-cold forecast (Modal 303-redirects + long-polls past ~150s) is
# resolved into a single clean response. Override the URL with SLIPSTREAM_DEMO_URL.
MODAL_DEMO = os.environ.get("SLIPSTREAM_DEMO_URL", "https://ashaibani--slipstream-demo-web.modal.run")
app = gr.Server(title="Slipstream")
# --------------------------------------------------------------------------- backend API
@app.api(name="summary")
def summary() -> dict:
"""High-level benchmark facts for the intro section, derived from the live results."""
methods = BENCH["methods"]
families = sorted({m["family"] for m in methods.values()})
return {
"n_projects": BENCH.get("n_eval"), # scored (>= 4 reporting periods)
"n_sourced": BENCH.get("n_test"), # real projects with recorded outcomes
"n_methods": len(methods),
"stages": BENCH.get("stages", []),
"primary": BENCH.get("primary"),
"families": families,
}
@app.api(name="benchmark")
def benchmark() -> dict:
"""The full benchmark results (every method's per-stage + per-strata metrics)."""
return BENCH
# --------------------------------------------------------------------------- live-demo proxy
def _modal_get(path: str, timeout: int = 60):
with urllib.request.urlopen(f"{MODAL_DEMO}{path}", timeout=timeout) as r:
return json.loads(r.read())
@app.get("/demo/projects")
def demo_projects():
try:
return JSONResponse(_modal_get("/api/projects"))
except Exception as e: # noqa: BLE001
return JSONResponse({"error": f"demo backend unreachable: {type(e).__name__}"}, status_code=502)
@app.post("/demo/forecast")
async def demo_forecast(request: Request):
body = await request.body()
rq = urllib.request.Request(f"{MODAL_DEMO}/api/forecast", data=body, method="POST",
headers={"Content-Type": "application/json"})
try:
with urllib.request.urlopen(rq, timeout=120) as r:
return JSONResponse(json.loads(r.read()))
except Exception as e: # noqa: BLE001
return JSONResponse({"error": f"demo backend error: {type(e).__name__}"}, status_code=502)
@app.get("/demo/result")
def demo_result(agent: str = "", tabpfn: str = ""):
from urllib.parse import urlencode
try:
return JSONResponse(_modal_get("/api/result?" + urlencode({"agent": agent, "tabpfn": tabpfn})))
except Exception as e: # noqa: BLE001
return JSONResponse({"error": f"demo backend error: {type(e).__name__}"}, status_code=502)
# --------------------------------------------------------------------------- serve frontend
@app.get("/")
def index():
return HTMLResponse((FRONTEND / "index.html").read_text())
app.mount("/static", StaticFiles(directory=str(FRONTEND)), name="static")
if __name__ == "__main__":
app.launch(server_name="0.0.0.0", server_port=7860)