Spaces:
Sleeping
Sleeping
| import os | |
| from fastapi import FastAPI, UploadFile, File, Form, Depends, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.staticfiles import StaticFiles | |
| from fastapi.responses import FileResponse | |
| from sqlalchemy.orm import Session | |
| from database import init_db, get_db, PredictionRecord | |
| from model_loader import preload_all_models | |
| from predict import predict_image | |
| app = FastAPI(title="AI-Assisted Diagnostic Support API", version="1.0.0") | |
| # Enable CORS for frontend integration | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], # For local development simplicity | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # Startup event: Initialize database and preload models | |
| def startup_event(): | |
| print("Starting up diagnostic API...") | |
| print("Initializing SQLite Database...") | |
| init_db() | |
| # Preload models to avoid lag on first request | |
| try: | |
| preload_all_models() | |
| print("All models preloaded successfully and ready.") | |
| except Exception as e: | |
| print(f"Warning: Failed to preload models during startup: {str(e)}") | |
| def health_check(): | |
| return { | |
| "status": "healthy", | |
| "models_loaded": True, | |
| "supported_modules": ["blood_cell", "skin_lesion"] | |
| } | |
| async def run_predict( | |
| file: UploadFile = File(...), | |
| module_type: str = Form(...), # 'blood_cell' or 'skin_lesion' | |
| db: Session = Depends(get_db) | |
| ): | |
| if module_type not in ["blood_cell", "skin_lesion"]: | |
| raise HTTPException(status_code=400, detail="Invalid module type. Choose 'blood_cell' or 'skin_lesion'.") | |
| try: | |
| # Read uploaded image bytes | |
| image_bytes = await file.read() | |
| # Run inference pipeline | |
| label, confidence, class_probs, heatmap_b64, inf_time = predict_image( | |
| image_bytes=image_bytes, | |
| filename=file.filename, | |
| module_type=module_type | |
| ) | |
| # Save record in the SQLite database | |
| record = PredictionRecord( | |
| module=module_type, | |
| filename=file.filename, | |
| predicted_class=label, | |
| confidence=confidence, | |
| notes=f"Inference took {inf_time:.4f} seconds." | |
| ) | |
| db.add(record) | |
| db.commit() | |
| db.refresh(record) | |
| return { | |
| "id": record.id, | |
| "timestamp": record.timestamp, | |
| "filename": record.filename, | |
| "prediction": label, | |
| "confidence": confidence, | |
| "class_probabilities": class_probs, | |
| "heatmap_base64": heatmap_b64, | |
| "inference_time_sec": inf_time | |
| } | |
| except Exception as e: | |
| import traceback | |
| traceback.print_exc() | |
| raise HTTPException(status_code=500, detail=f"Inference execution failed: {str(e)}") | |
| def get_prediction_history(db: Session = Depends(get_db)): | |
| records = db.query(PredictionRecord).order_by(PredictionRecord.timestamp.desc()).all() | |
| # Format database records into JSON-friendly structures | |
| history_list = [] | |
| for r in records: | |
| history_list.append({ | |
| "id": r.id, | |
| "timestamp": r.timestamp.isoformat() + "Z" if r.timestamp else None, | |
| "module": "Blood Cell" if r.module == "blood_cell" else "Skin Lesion", | |
| "filename": r.filename, | |
| "prediction": r.predicted_class, | |
| "confidence": r.confidence, | |
| "notes": r.notes | |
| }) | |
| return history_list | |
| # Serve static files and index.html | |
| static_dir = os.path.join(os.path.dirname(__file__), "static") | |
| if os.path.exists(static_dir): | |
| app.mount("/static", StaticFiles(directory=static_dir), name="static") | |
| def read_index(): | |
| return FileResponse(os.path.join(static_dir, "index.html")) | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run("backend.app:app", host="0.0.0.0", port=8000, reload=True) | |