""" Hugging Face Spaces entry point for seg_app. This file must be at repository root for HF Spaces deployment. IMPORTANT: - No heavy imports at module level (lazy loading only) - Model loading happens on first inference, not at startup - Gradio app is created on import but models are NOT loaded """ import os import logging import sys # Fix OpenMP duplicate library error on Windows # Must be set BEFORE importing numpy/torch os.environ["KMP_DUPLICATE_LIB_OK"] = "TRUE" # Configure logging before other imports logging.basicConfig( level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", ) logger = logging.getLogger(__name__) # Validate Python version if sys.version_info < (3, 8): logger.error("Python 3.8+ is required") sys.exit(1) # ============================================================================= # MONKEY-PATCH: Fix Gradio schema serialization bug # Bug: gradio_client/utils.py crashes when schema has additionalProperties: true # because it tries to do `if "const" in schema` on a boolean value. # This patch adds a guard to handle boolean schemas gracefully. # ============================================================================= def _patch_gradio_schema_bug(): """Patch the buggy _json_schema_to_python_type function in gradio_client.""" try: import gradio_client.utils as client_utils # Store original function original_func = client_utils._json_schema_to_python_type def patched_json_schema_to_python_type(schema, defs=None): """Patched version that handles boolean schemas.""" # Handle boolean schema (additionalProperties: true/false) if isinstance(schema, bool): return "Any" if schema else "None" # Handle None schema if schema is None: return "Any" # Call original for normal dict schemas return original_func(schema, defs) # Apply patch client_utils._json_schema_to_python_type = patched_json_schema_to_python_type logger.info("Applied Gradio schema bug patch") except Exception as e: logger.warning(f"Could not patch Gradio schema bug: {e}") # Apply patch before any Gradio imports _patch_gradio_schema_bug() def create_demo(): """Create and configure the Gradio demo. This function is called at import time but does NOT load any models. Models are loaded lazily on first inference via the model registry. Returns: Configured Gradio Blocks application """ try: # Import settings and configure from seg_app.config.settings import ( APP_SETTINGS, configure_logging, validate_environment, is_hf_spaces, ) # Configure logging based on environment configure_logging(verbose=not is_hf_spaces()) # Validate environment (warnings only, don't fail startup) validate_environment() # Import the Gradio app (models NOT loaded yet) from seg_app.ui.gradio_app import demo logger.info("Gradio app created successfully (models will load on first use)") return demo except ImportError as e: logger.error(f"Failed to import required modules: {e}") logger.error("Please ensure all dependencies are installed: pip install -r requirements.txt") raise except Exception as e: logger.error(f"Failed to create Gradio app: {e}") raise # Create the demo at module level (required for HF Spaces) # This does NOT load models - they are lazy-loaded on first inference demo = create_demo() # Launch the app # HF Spaces runs this file directly with `python app.py` if __name__ == "__main__": import os if os.environ.get("SPACE_ID"): # Running in HF Spaces logger.info("Starting seg_app on Hugging Face Spaces...") demo.launch( server_name="0.0.0.0", server_port=7860, share=False, show_api=False, ) else: # Local development logger.info("Starting seg_app in local mode...") demo.launch( server_name="127.0.0.1", server_port=7869, share=False, ) """ >> First Launch API server backend: Start the FastAPI backend with uvicorn # uvicorn seg_app.api.app:app --reload --host 127.0.0.1 --port 8000 uvicorn seg_app.backend.api:app --reload --host 127.0.0.1 --port 8000 >> Second, Start the FastAPI Frontend: cd seg_app/ui_slicer python serve_frontend.py >> Launch Gradio App for seg_app. python app.py # Terminal 1: FastAPI Backend uvicorn seg_app.backend.api:app --reload --host 127.0.0.1 --port 8000 # Terminal 2: Frontend Server cd seg_app/ui_slicer python serve_frontend.py Unified Mode (single server — recommended) One terminal, one port, serves both frontend + backend: ---------------------- cd /media/vsap/New\ Volume1/medical_webapp/seg_app conda activate facenet uvicorn seg_app.backend.api:app --host 127.0.0.1 --port 7860 Split Mode (two terminals — for development) If you ever need separate frontend/backend (e.g., for hot-reloading the frontend): Terminal 1 — Backend: ------------------------- cd /media/vsap/New\ Volume1/medical_webapp/seg_app conda activate facenet uvicorn seg_app.backend.api:app --reload --host 127.0.0.1 --port 8000 Terminal 2 — Frontend: ------------------------- cd /media/vsap/New\ Volume1/medical_webapp/seg_app/seg_app/ui_slicer conda activate facenet python serve_frontend.py ⚠️ In split mode, you'll need to temporarily revert api-client.js to use http://localhost:8000 instead of window.location.origin. You can test locally with Docker first if you want: -------------------------- docker build -t brain-seg-app . docker run -p 7860:7860 brain-seg-app # Open http://localhost:7860 For future pushes Whenever you make changes locally and want to update the Space: -------------------------------------------------------------- cd /media/vsap/New\ Volume1/medical_webapp/seg_app conda activate facenet git add -A git commit -m "your commit message" git push hf main """