from fastapi import FastAPI, HTTPException from pydantic import BaseModel, Field from typing import Optional from app.handler import FastApiHandler app = FastAPI(title="Effici EPC Energy Prediction API") handler = None # ---------- EPC Request Schema ---------- class EPCPredictRequest(BaseModel): model_params: dict = Field( ..., json_schema_extra={ "example": { "PROPERTY_TYPE": "Flat", "BUILT_FORM": "Enclosed End-Terrace", "CONSTRUCTION_AGE_BAND": "England and Wales: 1996-2002", "TOTAL_FLOOR_AREA": 70.12, "FLOOR_HEIGHT": 2.32, "FLAT_TOP_STOREY": "N", "FLAT_STOREY_COUNT": 23.0, "WINDOWS_DESCRIPTION": "Fully triple glazed", "WALLS_DESCRIPTION": "System built, as built, insulated (assumed)", "ROOF_DESCRIPTION": "(another dwelling above)", "FLOOR_DESCRIPTION": "(other premises below)", "MAINHEAT_DESCRIPTION": "Air source heat pump, warm air, electric", "MAINHEAT_ENERGY_EFF": "Average", "SECONDHEAT_DESCRIPTION": "Room heaters, electric", "HOTWATER_DESCRIPTION": "Electric immersion, standard tariff, no cylinderstat", "HOT_WATER_ENERGY_EFF": "Very Poor", "LIGHTING_DESCRIPTION": "No low energy lighting", "MECHANICAL_VENTILATION": "natural", "PHOTO_SUPPLY": 0.0 } }, ) # ---------- Startup ---------- @app.on_event("startup") def load_model_once(): global handler handler = FastApiHandler() print("✅ EPC MLflow model loaded at startup") # ---------- Routes ---------- @app.get("/") def root(): return { "message": "🏠 Effici EPC Energy Prediction API is running", } @app.post("/predict") def predict(req: EPCPredictRequest): try: result = handler.handle(req.dict()) if "error" in result: raise HTTPException(status_code=400, detail=result["error"]) return result except Exception as e: raise HTTPException(status_code=400, detail=str(e)) @app.post("/explain") def explain(req: EPCPredictRequest): try: explanation = handler.explain_prediction(req.model_params) return explanation except Exception as e: raise HTTPException(status_code=400, detail=str(e))