Spaces:
Sleeping
Sleeping
| # PhysiX-Live demo Space — CPU-only env + UI. | |
| # | |
| # What this Space hosts: | |
| # | |
| # :7860 uvicorn _space_app:app | |
| # ├─ /reset, /step (OpenEnv stateless API) | |
| # ├─ /interactive/* (browser session API) | |
| # ├─ /web/ (built React SPA) | |
| # └─ /interactive/.../llm-step (LLM-driven episode) | |
| # | |
| # What this Space does NOT host: | |
| # * Inference. The demo is CPU-only — no torch, no vLLM, no GPU. When | |
| # the UI calls `/interactive/.../llm-step` the server forwards to | |
| # whatever OpenAI-compatible base URL the browser handed us | |
| # (HF Router, OpenAI, Ollama, or our sister L4 Space at | |
| # `Pratyush-01/physix-infer` for the trained 3B + Qwen baseline). | |
| # | |
| # Why a separate inference Space: | |
| # Keeps this CPU image tiny (sub-second cold-start) so the demo URL | |
| # never feels like it's stalled. The L4 Space pays GPU rates only | |
| # while it's actually serving requests — its `sleep_time=300s` shuts | |
| # it down between sessions. Two Spaces, two failure surfaces; if | |
| # inference is broken the verifier-only demo (Custom URL → Ollama | |
| # etc.) still works. | |
| ############################ | |
| # Stage 1: build the SPA | |
| ############################ | |
| # WORKDIR renamed (was /build) to break HF BuildKit's poisoned cache. | |
| # The previous /build mount kept a stale pnpm symlink at | |
| # /build/node_modules/@types/katex | |
| # from an earlier failed deploy, and every subsequent `COPY frontend/ ./` | |
| # blew up with `cannot copy to non-directory`. Switching paths gets us | |
| # a fresh cache bucket; nothing in the project depends on /build itself. | |
| FROM node:20-alpine AS frontend | |
| WORKDIR /spa | |
| RUN corepack enable | |
| # Copy ALL of frontend/ first — including package.json/pnpm-lock.yaml — | |
| # THEN install. Order matters: install runs ON TOP OF the source tree | |
| # instead of the source tree being overlaid on top of a pre-installed | |
| # node_modules, eliminating the directory-vs-symlink collision class | |
| # of failure entirely. | |
| COPY frontend/ ./ | |
| # Same-origin API fetches (relative paths). The Space serves both API and UI. | |
| ENV VITE_PHYSIX_API_URL="" | |
| # Cache-bust marker. Bump when an SPA change isn't taking on the Space. | |
| # physix-spa-rebuild: 9 | |
| RUN pnpm install --frozen-lockfile \ | |
| && pnpm exec tsc -b \ | |
| && pnpm exec vite build --base=/web/ | |
| ############################ | |
| # Stage 2: runtime (FastAPI + SPA) | |
| ############################ | |
| FROM python:3.11-slim AS runtime | |
| ENV PYTHONUNBUFFERED=1 \ | |
| PIP_NO_CACHE_DIR=1 \ | |
| PIP_DISABLE_PIP_VERSION_CHECK=1 \ | |
| HOME=/tmp/home \ | |
| HF_HOME=/tmp/hf_cache \ | |
| XDG_CACHE_HOME=/tmp/xdg-cache \ | |
| PORT=7860 \ | |
| PHYSIX_HOST=0.0.0.0 \ | |
| PHYSIX_CORS_ORIGINS=* | |
| # curl for healthchecks; the slim image has neither curl nor build tools | |
| # by default. Everything else (numpy, scipy, sympy) is a wheel install. | |
| RUN apt-get update \ | |
| && apt-get install -y --no-install-recommends curl \ | |
| && rm -rf /var/lib/apt/lists/* | |
| WORKDIR /app | |
| # Pin the server-side runtime stack. NO torch / unsloth / trl here — | |
| # this Space never trains and never runs a model locally. | |
| RUN pip install \ | |
| "openenv-core[core]>=0.2.2" \ | |
| "numpy>=1.24" \ | |
| "scipy>=1.10" \ | |
| "sympy>=1.12" \ | |
| "fastapi>=0.110" \ | |
| "uvicorn[standard]>=0.29" \ | |
| "pydantic>=2.5" \ | |
| "openai>=1.40" \ | |
| "requests>=2.31" | |
| COPY pyproject.toml ./ | |
| COPY physix ./physix | |
| COPY README.md ./ | |
| RUN pip install --no-deps -e . | |
| # Built SPA from stage 1. | |
| COPY --from=frontend /spa/dist /app/static | |
| # Space wrapper — mounts the React SPA at /web/, registers / -> /web/ | |
| # redirect (OpenEnv's create_fastapi_app doesn't add one for us). | |
| COPY scripts/space_app.py /app/_space_app.py | |
| # Pre-create writable dirs. HF Spaces runs containers as a non-root UID | |
| # with no /etc/passwd entry, so any cache path under $HOME must exist | |
| # and be world-writable BEFORE the runtime user shows up. | |
| RUN mkdir -p "$HOME" "$HF_HOME" "$XDG_CACHE_HOME" \ | |
| && chmod -R 0777 /tmp /app | |
| EXPOSE 7860 | |
| # /health is OpenEnv's stock endpoint and turns 200 once uvicorn binds. | |
| HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ | |
| CMD curl -fsS "http://127.0.0.1:${PORT}/health" || exit 1 | |
| ENV ENABLE_WEB_INTERFACE=true | |
| CMD ["python3", "-m", "uvicorn", "_space_app:app", "--host", "0.0.0.0", "--port", "7860"] | |