toxipredict-api / routes /prediction.py
Arko006's picture
Upload routes/prediction.py with huggingface_hub
5960b6c verified
Raw
History Blame
2.58 kB
import uuid
import torch
from fastapi import APIRouter, Header, HTTPException
from pydantic import BaseModel
from firebase_auth import verify_token
from database import save_analysis
from models.molecule_graph import smiles_to_graph
from config import TASK_NAMES, TASK_CLASSES, NUM_TASKS
router = APIRouter(prefix="/api")
class PredictRequest(BaseModel):
smiles: str
class AssayPrediction(BaseModel):
assay: str
target_class: str
probability: float
predicted_class: str
class PredictResponse(BaseModel):
analysis_id: str
smiles: str
predictions: list[AssayPrediction]
uncertainty_weights: list[float]
molecule_num_atoms: int
def get_app_state():
from app import model_loader
return model_loader
@router.post("/predict")
async def predict(request: PredictRequest, authorization: str = Header(...)):
user = await verify_token(authorization)
uid = user["uid"]
model_loader = get_app_state()
model = model_loader.load_model()
try:
data = smiles_to_graph(request.smiles)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
model.eval()
device = next(model.parameters()).device
data = data.to(device)
with torch.no_grad():
logits = model(data.x, data.edge_index, data.edge_attr,
torch.zeros(data.x.shape[0], dtype=torch.long, device=device))
probs = torch.sigmoid(logits).cpu().numpy()[0]
predictions = []
for i in range(NUM_TASKS):
prob = float(probs[i])
predictions.append(AssayPrediction(
assay=TASK_NAMES[i],
target_class=TASK_CLASSES.get(TASK_NAMES[i], "Unknown"),
probability=round(prob, 4),
predicted_class="Toxic" if prob > 0.5 else "Non-Toxic",
))
analysis_id = str(uuid.uuid4())
uncertainty_weights = []
try:
from app import criterion
if criterion is not None:
uncertainty_weights = torch.exp(-criterion.s).detach().cpu().tolist()
except Exception:
uncertainty_weights = [1.0] * NUM_TASKS
save_analysis(analysis_id, uid, {
"smiles": request.smiles,
"predictions": [p.model_dump() for p in predictions],
"uncertainty_weights": uncertainty_weights,
"molecule_num_atoms": data.x.shape[0],
})
return PredictResponse(
analysis_id=analysis_id,
smiles=request.smiles,
predictions=predictions,
uncertainty_weights=uncertainty_weights,
molecule_num_atoms=data.x.shape[0],
)