Spaces:
Sleeping
Sleeping
| from fastapi import FastAPI, HTTPException | |
| from pydantic import BaseModel | |
| import os | |
| import joblib | |
| import pandas as pd | |
| import threading | |
| import time | |
| import requests | |
| from huggingface_hub import hf_hub_download | |
| # --- 0. Initialize FastAPI app --- | |
| app = FastAPI() | |
| def read_root(): | |
| return { | |
| "message": "Welcome to the Taxi Fare Prediction API. Use POST /predict to get predictions." | |
| } | |
| def health(): | |
| return {"status": "ok"} | |
| # --- 1. Define Input and Output Data Models --- | |
| class InferenceInput(BaseModel): | |
| vendor_id: str | |
| dist_meters: float | |
| wait_sec: float | |
| geodetic_dist: float | |
| mean_velocity: float | |
| is_rush_hour: bool | |
| model_name: str # "bog", "mex", or "uio" | |
| class InferenceOutput(BaseModel): | |
| trip_duration: float | |
| model_used: str | |
| message: str | |
| # --- 2. Lazy-loading ML Model Manager --- | |
| class MLModels: | |
| def __init__(self): | |
| self.models = {} | |
| self.repo_id = "MatteoAld/my-ml-models" # ⚠️ Change to your actual repo | |
| self.valid_models = {"bog", "mex", "uio"} | |
| self.file_template = "{}_ridge_pipeline.pkl" | |
| def get_model(self, model_name: str): | |
| model_name = model_name.lower() | |
| if model_name not in self.valid_models: | |
| raise ValueError( | |
| f"Invalid model name '{model_name}'. Choose from 'bog', 'mex', or 'uio'." | |
| ) | |
| if model_name in self.models: | |
| return self.models[model_name] | |
| filename = self.file_template.format(model_name) | |
| try: | |
| # Download from Hugging Face Hub (cached automatically) | |
| model_path = hf_hub_download( | |
| repo_id=self.repo_id, | |
| filename=filename, | |
| cache_dir="/tmp/hf_models" # Use /tmp for write permissions | |
| ) | |
| model = joblib.load(model_path) | |
| self.models[model_name] = model | |
| print(f"✅ Downloaded and loaded model '{model_name}' from Hugging Face Hub") | |
| return model | |
| except Exception as e: | |
| raise RuntimeError(f"Error loading model '{model_name}': {e}") | |
| def predict_one(self, features: dict, model_name: str): | |
| model = self.get_model(model_name) | |
| X_df = pd.DataFrame([features]) | |
| pred = model.predict(X_df)[0] | |
| return float(pred) | |
| # --- 3. Instantiate ML Model Manager --- | |
| ml_models = MLModels() | |
| # --- 4. Inference Endpoint --- | |
| async def predict_inference(data: InferenceInput): | |
| try: | |
| features = data.dict() | |
| model_name = features.pop("model_name") | |
| trip_duration = ml_models.predict_one(features, model_name) | |
| return InferenceOutput( | |
| trip_duration=trip_duration, | |
| model_used=model_name, | |
| message=f"Inference successful using {model_name.upper()} model.", | |
| ) | |
| except FileNotFoundError as fnf: | |
| raise HTTPException(status_code=404, detail=str(fnf)) | |
| except ValueError as ve: | |
| raise HTTPException(status_code=400, detail=str(ve)) | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=f"Inference failed: {str(e)}") | |
| # --- 5. Run the app --- | |