Spaces:
Build error
Build error
| """ | |
| Single-port entrypoint for the Multi-Agent Medical Assistant on HF Spaces. | |
| Everything is served from one FastAPI app on port 7860: | |
| - /api/* your agent + RAG + imaging routes | |
| - /health liveness probe | |
| - /* the React single-page app (static build) | |
| Design constraints baked in: | |
| - Hosted LLM API (keys read from Space Secrets via env vars) | |
| - Embedded Qdrant + SQLite (no external DB servers) | |
| - Imaging models loaded lazily on first request (no GPU work at import time) | |
| """ | |
| import os | |
| from pathlib import Path | |
| from fastapi import FastAPI | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.staticfiles import StaticFiles | |
| from fastapi.responses import FileResponse | |
| # ---- Secrets / config (set these in Space Settings -> Variables & secrets) ---- | |
| # e.g. OPENAI_API_KEY, ANTHROPIC_API_KEY, ELEVENLABS_API_KEY | |
| LLM_API_KEY = os.environ.get("LLM_API_KEY") # rename to match your provider | |
| ELEVENLABS_API_KEY = os.environ.get("ELEVENLABS_API_KEY") | |
| STATIC_DIR = Path(__file__).resolve().parent.parent / "static" | |
| app = FastAPI(title="Multi-Agent Medical Assistant") | |
| # Frontend is served from the same origin, so CORS is mostly a no-op here, | |
| # but keep it permissive if you ever call the API from elsewhere. | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| def health(): | |
| return {"status": "ok"} | |
| # --------------------------------------------------------------------------- | |
| # API ROUTES | |
| # Import your existing routers here. Keep heavy imports (torch, imaging models) | |
| # INSIDE the route handlers or a lazy loader — never at module top level, so the | |
| # container starts fast and the build never touches the GPU. | |
| # --------------------------------------------------------------------------- | |
| # from backend.agents.router import router as agents_router | |
| # app.include_router(agents_router, prefix="/api") | |
| # ---- Lazy imaging-model loader example (T4 GPU) ---------------------------- | |
| _models = {} | |
| def get_imaging_model(name: str): | |
| """Load a model once, on first use, onto the GPU.""" | |
| if name not in _models: | |
| import torch # imported lazily so build stage never needs CUDA | |
| # _models[name] = load_your_model(name).to( | |
| # "cuda" if torch.cuda.is_available() else "cpu" | |
| # ) | |
| raise NotImplementedError("Wire up your imaging model loader here.") | |
| return _models[name] | |
| # --------------------------------------------------------------------------- | |
| # STATIC FRONTEND (mounted LAST so it doesn't shadow /api and /health) | |
| # --------------------------------------------------------------------------- | |
| if STATIC_DIR.exists(): | |
| app.mount("/assets", StaticFiles(directory=STATIC_DIR / "assets"), name="assets") | |
| def serve_spa(full_path: str): | |
| # Serve real files if they exist, else fall back to index.html (SPA routing) | |
| candidate = STATIC_DIR / full_path | |
| if full_path and candidate.is_file(): | |
| return FileResponse(candidate) | |
| return FileResponse(STATIC_DIR / "index.html") | |