Spaces:
Running
Running
| """FastAPI entrypoint for the Medbillcodes OHIP billing copilot backend.""" | |
| from __future__ import annotations | |
| import logging | |
| from fastapi import FastAPI | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from .config import settings | |
| from .routes import analyze, approve, intake, specialties, provinces, workspace | |
| from .weave_trace import init_weave | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| app = FastAPI( | |
| title="Medbillcodes Billing Copilot", | |
| version="0.3.0", | |
| description=( | |
| "Provincial fee suggestions grounded in the current physician schedule. " | |
| f"Default jurisdiction: {settings.default_province_code}; " | |
| f"default specialty: {settings.default_specialty_code}; " | |
| f"retrieval: {settings.retrieval_backend}." | |
| ), | |
| ) | |
| # LAN-only frontend; tighten origins for the actual clinic deployment. | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| app.include_router(intake.router) | |
| app.include_router(analyze.router) | |
| app.include_router(approve.router) | |
| app.include_router(specialties.router) | |
| app.include_router(provinces.router) | |
| app.include_router(workspace.router) | |
| def _use_sqlite() -> bool: | |
| return settings.retrieval_backend == "sqlite" | |
| async def _startup() -> None: | |
| init_weave() | |
| if _use_sqlite(): | |
| from . import sqlite_store # noqa: PLC0415 | |
| from .build_sqlite import build_sqlite_index # noqa: PLC0415 | |
| sqlite_store.ensure_schema() | |
| if sqlite_store.count_codes() == 0: | |
| logger.info("SQLite fee index empty — building from public OHIP sources…") | |
| try: | |
| summary = build_sqlite_index(force=True) | |
| logger.info("SQLite index ready: %s", summary) | |
| except Exception as exc: # noqa: BLE001 | |
| logger.error( | |
| "Failed to build SQLite index at startup (%s). " | |
| "Call POST /admin/ingest after fixing data paths.", | |
| exc, | |
| ) | |
| else: | |
| logger.info( | |
| "SQLite fee index ready (%d codes)", sqlite_store.count_codes() | |
| ) | |
| return | |
| # Full path: OpenSearch + feedback learning (+ optional remote embeddings). | |
| try: | |
| from .clinic_workspace import ensure_workspace_index # noqa: PLC0415 | |
| from .feedback import ensure_feedback_index # noqa: PLC0415 | |
| from .opensearch_client import ensure_index, get_client # noqa: PLC0415 | |
| from .reconciliation import ensure_remittance_index # noqa: PLC0415 | |
| client = get_client() | |
| ensure_index(client) | |
| ensure_feedback_index(client) | |
| ensure_remittance_index(client) | |
| ensure_workspace_index(client) | |
| logger.info( | |
| "OpenSearch ready (index=%s, embeddings=%s)", | |
| settings.opensearch_index, | |
| "remote" if settings.embedding_url else "local", | |
| ) | |
| except Exception as exc: # noqa: BLE001 | |
| logger.warning( | |
| "OpenSearch not ready at startup (%s). Retry via /admin/ingest.", exc | |
| ) | |
| if settings.refresh_enabled: | |
| from .scheduler import start_scheduler # noqa: PLC0415 | |
| start_scheduler() | |
| async def _shutdown() -> None: | |
| if _use_sqlite(): | |
| return | |
| try: | |
| from .scheduler import shutdown_scheduler # noqa: PLC0415 | |
| shutdown_scheduler() | |
| except Exception: # noqa: BLE001 | |
| pass | |
| def health() -> dict: | |
| payload: dict = { | |
| "status": "ok", | |
| "retrieval_backend": settings.retrieval_backend, | |
| "pilot_mode": settings.pilot_mode, | |
| "model": settings.llm_model, | |
| "vllm_url": settings.vllm_url, | |
| "embeddings": "remote" if settings.embedding_url else "local", | |
| "embedding_model": settings.embedding_model, | |
| "embedding_dim": settings.embedding_dim, | |
| "fusion_technique": settings.fusion_technique, | |
| "rrf_rank_constant": settings.rrf_rank_constant, | |
| "feedback_learning": not _use_sqlite(), | |
| "llm_justify_sync": settings.llm_justify, | |
| "llm_enrich_justifications": settings.llm_enrich_justifications, | |
| "weave_enabled": settings.weave_enabled, | |
| "weave_project": settings.weave_project if settings.weave_enabled else None, | |
| "weave_llm_judge": settings.weave_llm_judge, | |
| "weave_gate_top3": settings.weave_gate_top3, | |
| "weave_gate_mrr": settings.weave_gate_mrr, | |
| } | |
| if _use_sqlite(): | |
| from . import sqlite_store # noqa: PLC0415 | |
| payload["codes"] = sqlite_store.count_codes() | |
| payload["sqlite_path"] = str(sqlite_store.db_path()) | |
| else: | |
| payload["index"] = settings.opensearch_index | |
| return payload | |