ddi / src /inference /app.py
github-actions[bot]
Deploy from GitHub Actions (fb28c05c54cf19184fc3f14f1bf3297ba5749ea2)
d29b763
from __future__ import annotations
import logging
import time
import sys
from pathlib import Path
# Ensure top-level `training`, `chemistry`, etc. packages are importable
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / 'src'))
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from .predictor import HybridDDIPredictor
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(name)s %(message)s')
logger = logging.getLogger('medcare_ddi.api')
predictor = HybridDDIPredictor.from_default_paths()
app = FastAPI(title='MEDCARE-DDI Hybrid Predictor', version='2.0.0')
app.add_middleware(
CORSMiddleware,
allow_origins=['*'],
allow_credentials=True,
allow_methods=['*'],
allow_headers=['*'],
)
class PredictionRequest(BaseModel):
# Accept both frontend keys (`drug_a`, `drug_b`) and legacy keys (`drug_a_id`, `drug_b_id`).
drug_a_id: str | None = None
drug_b_id: str | None = None
drug_a: str | None = None
drug_b: str | None = None
@app.get('/health')
def health() -> dict[str, object]:
return predictor.health()
@app.post('/predict')
def predict(request: PredictionRequest) -> dict[str, object]:
started_at = time.perf_counter()
# Prefer explicit `drug_a`/`drug_b` from frontend; fall back to legacy `drug_a_id` fields.
drug_a = (request.drug_a or request.drug_a_id or '')
drug_b = (request.drug_b or request.drug_b_id or '')
result = predictor.predict(drug_a, drug_b)
latency_ms = round((time.perf_counter() - started_at) * 1000, 2)
logger.info(
'prediction_completed source=%s severity=%s confidence=%.3f latency_ms=%.2f drug_a=%s drug_b=%s',
result['source'],
result['severity'],
result['confidence'],
latency_ms,
result['drug_a_name'],
result['drug_b_name'],
)
return {
**result,
'latency_ms': latency_ms,
}