Spaces:
Sleeping
Sleeping
| """XRayVision AI β FastAPI Application Entry Point. | |
| Initializes the FastAPI app with CORS, model preloading, and all routers. | |
| """ | |
| from __future__ import annotations | |
| import logging | |
| import threading | |
| from contextlib import asynccontextmanager | |
| from fastapi import FastAPI | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from app.config import get_settings | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format="%(asctime)s | %(levelname)-7s | %(name)s | %(message)s", | |
| ) | |
| logger = logging.getLogger("xrayvision") | |
| def _preload_models_background(): | |
| """Load AI models in a background thread so the server starts immediately.""" | |
| logger.info("π¦ Preloading AI models in background thread...") | |
| try: | |
| from app.services.chest_model import _get_model as load_chest | |
| load_chest() | |
| logger.info("β DenseNet121 (Chest Pathology) loaded") | |
| except Exception as e: | |
| logger.warning(f"β οΈ DenseNet121 failed to preload: {e}") | |
| try: | |
| from app.services.fracture_model import _get_model as load_fracture | |
| load_fracture() | |
| logger.info("β YOLOv8 (Fracture Detection) loaded") | |
| except Exception as e: | |
| logger.warning(f"β οΈ YOLOv8 failed to preload: {e}") | |
| try: | |
| if get_settings().fracture_classifier_enabled: | |
| from app.services.fracture_classifier import _get_model as load_fracture_classifier | |
| load_fracture_classifier() | |
| logger.info("HF Fracture Classifier loaded") | |
| except Exception as e: | |
| logger.warning(f"HF Fracture Classifier failed to preload: {e}") | |
| try: | |
| from app.services.wound_model import _get_model as load_wound | |
| load_wound() | |
| logger.info("β ViT (Wound Classification) loaded") | |
| except Exception as e: | |
| logger.warning(f"β οΈ ViT failed to preload: {e}") | |
| logger.info("π’ All AI models loaded and ready!") | |
| async def lifespan(app: FastAPI): | |
| """Start model loading in background β server is ready immediately.""" | |
| logger.info("π XRayVision AI backend starting...") | |
| settings = get_settings() | |
| if settings.disable_preload: | |
| # On free-tier hosts (<=512 MB RAM) skip preloading entirely. | |
| # Models will lazy-load on first use so auth/chat/diet work immediately. | |
| logger.info("βοΈ DISABLE_PRELOAD=true β models will load on first use") | |
| else: | |
| # Full preload on capable hosts (HuggingFace Spaces, Render Standard+) | |
| thread = threading.Thread(target=_preload_models_background, daemon=True) | |
| thread.start() | |
| logger.info("π’ XRayVision AI is accepting requests! (models loading in background)") | |
| yield | |
| logger.info("π΄ XRayVision AI shutting down...") | |
| def create_app() -> FastAPI: | |
| """Create and configure the FastAPI application.""" | |
| settings = get_settings() | |
| app = FastAPI( | |
| title="XRayVision AI", | |
| description=( | |
| "Advanced medical diagnostic API using a Hybrid Multi-Model Ensemble. " | |
| "DenseNet121 for chest pathology, YOLOv8 for fracture detection, " | |
| "ViT for wound classification, and OpenRouter GLM 4.5 Air for agentic synthesis." | |
| ), | |
| version="2.1.0", | |
| lifespan=lifespan, | |
| docs_url="/docs", | |
| redoc_url="/redoc", | |
| ) | |
| # CORS β allow common dev origins | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=[ | |
| settings.frontend_url, | |
| "http://localhost:5173", | |
| "http://localhost:5174", | |
| "http://localhost:3000", | |
| "http://localhost:3001", | |
| "http://localhost:8080", | |
| "http://localhost:8081", | |
| "http://127.0.0.1:5173", | |
| "http://127.0.0.1:3000", | |
| ], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # Register routers | |
| from app.routers import auth, analyze, scans, chat, diet, stats, clinics | |
| app.include_router(auth.router) | |
| app.include_router(analyze.router) | |
| app.include_router(scans.router) | |
| app.include_router(chat.router) | |
| app.include_router(diet.router) | |
| app.include_router(stats.router) | |
| app.include_router(clinics.router) | |
| async def health(): | |
| return { | |
| "status": "healthy", | |
| "service": "XRayVision AI", | |
| "version": "2.1.0", | |
| "models": ["DenseNet121", "YOLOv8", "ViT", "OpenRouter GLM 4.5 Air"], | |
| } | |
| async def health_check(): | |
| return {"status": "ok"} | |
| return app | |
| app = create_app() | |