Spaces:
Sleeping
Sleeping
| try: | |
| import spaces | |
| has_spaces = True | |
| except ImportError: | |
| has_spaces = False | |
| import asyncio | |
| import gradio as gr | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from backend.app.api.v1.router import api_router | |
| from backend.app.ml.manager import model_manager | |
| from backend.app.core.database import init_db | |
| # 1. ZeroGPU worker function | |
| def _run_ner(text: str): | |
| if not text or not text.strip(): | |
| return "Please provide clinical text." | |
| try: | |
| service = model_manager.get_ner_service() | |
| results = service.model.predict(text) | |
| if not results: | |
| return "No biomedical entities detected." | |
| return "\n".join( | |
| f"β’ [{e.label}] {e.text} (Confidence: {round((e.confidence or 1.0)*100, 1)}%)" | |
| for e in results | |
| ) | |
| except Exception as e: | |
| return f"Inference notice: {e}" | |
| if has_spaces: | |
| def predict_ner(text: str): | |
| return _run_ner(text) | |
| else: | |
| def predict_ner(text: str): | |
| return _run_ner(text) | |
| # 2. Gradio Interface β this IS the app ZeroGPU launches, so it must be the | |
| # thing that actually calls .launch() below. | |
| with gr.Blocks(title="SanjeevaniAI Healthcare Intelligence") as demo: | |
| gr.Markdown("# π₯ SanjeevaniAI β Healthcare Intelligence Engine") | |
| gr.Markdown( | |
| "Backend REST API Engine powered by **FastAPI** on Hugging Face **ZeroGPU**.\n\n" | |
| "- **Health Status**: `/api/v1/health`\n" | |
| "- **NER Analysis**: `/api/v1/ner/analyze`" | |
| ) | |
| with gr.Row(): | |
| inp = gr.Textbox( | |
| label="Test Clinical Text", | |
| value="Metformin 500mg prescribed for type 2 diabetes mellitus and hypertension.", | |
| ) | |
| out = gr.Textbox(label="ZeroGPU Extracted Biomedical Entities") | |
| btn = gr.Button("β‘ Run ZeroGPU Clinical NER", variant="primary") | |
| btn.click(fn=predict_ner, inputs=inp, outputs=out) | |
| async def _startup(): | |
| await init_db() | |
| try: | |
| model_manager.initialize() | |
| except Exception as e: | |
| print(f"ML Model initialization: {e}") | |
| def main(): | |
| # prevent_thread_lock=True makes launch() return instead of blocking, | |
| # so we can attach to the REAL, live app object it just built. | |
| # Anything attached to demo.app BEFORE this call gets discarded β | |
| # launch() rebuilds the app internally to apply ssr_mode etc. | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| ssr_mode=False, | |
| prevent_thread_lock=True, | |
| ) | |
| # --- Everything below runs against the app that's actually serving traffic --- | |
| demo.app.include_router(api_router, prefix="/api/v1") | |
| # Defensive reset: guarantees add_middleware never raises | |
| # "Cannot add middleware after an application has started", | |
| # even if a request theoretically slipped in during the gap above. | |
| demo.app.middleware_stack = None | |
| demo.app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| asyncio.run(_startup()) | |
| # Keep the process alive β launch() no longer blocks on its own, | |
| # so without this the script exits and the server dies immediately. | |
| demo.block_thread() | |
| if __name__ == "__main__": | |
| main() |