""" Hugging Face Spaces entry point (Gradio). Run locally: python app.py --config config/default_config.yaml --host 0.0.0.0 --port 7860 """ from __future__ import annotations import argparse import logging import os from pathlib import Path from radiology_rag.gradio_compat import patch_gradio_predict_body_for_pydantic_v2 from radiology_rag.ui import RadiologyRAGApp # NOTE: ZeroGPU compatibility # If your Space hardware is set to "ZeroGPU", Hugging Face requires at least one # function decorated with `@spaces.GPU`, otherwise the Space will fail at startup # with: "No @spaces.GPU function detected during startup". # # This app is API-first and does not require a GPU, but we provide a tiny no-op # GPU-decorated function so the Space can still boot on ZeroGPU. try: import spaces # type: ignore @spaces.GPU # type: ignore[attr-defined] def _zerogpu_noop() -> None: return None except Exception: # Fallback for local runs or non-ZeroGPU environments. def _zerogpu_noop() -> None: # noqa: D401 return None def _configure_logging() -> None: level = os.getenv("LOG_LEVEL", "INFO").upper() logging.basicConfig( level=getattr(logging, level, logging.INFO), format="%(asctime)s - %(levelname)s - %(message)s", ) def _default_storage_dir() -> str: # Prefer /data on Spaces if persistent storage is enabled. if Path("/data").exists(): return "/data/radiology_rag" return "./storage" def main() -> int: _configure_logging() parser = argparse.ArgumentParser(description="Radiology RAG (Spaces-ready)") parser.add_argument("--config", type=str, default="config/default_config.yaml", help="Path to config YAML") parser.add_argument("--host", type=str, default="0.0.0.0", help="Server host") parser.add_argument("--port", type=int, default=int(os.getenv("PORT", "7860")), help="Server port") args = parser.parse_args() # Ensure storage dir env is set early so config interpolation uses it. if not os.getenv("RAG_STORAGE_DIR"): os.environ["RAG_STORAGE_DIR"] = _default_storage_dir() # Optional compatibility patch for Gradio 4.16 + Pydantic v2. if patch_gradio_predict_body_for_pydantic_v2(): logging.getLogger(__name__).info("Applied Gradio/Pydantic v2 compatibility patch") app = RadiologyRAGApp(config_path=args.config) demo = app.create_interface() demo.launch( server_name=args.host, server_port=args.port, share=False, show_error=True, ) return 0 if __name__ == "__main__": raise SystemExit(main())