# --- imports --- from fastapi import FastAPI, HTTPException from fastapi.responses import HTMLResponse from pydantic import BaseModel from typing import List import pandas as pd import joblib # --- Load model bundle --- BUNDLE_FILE = "RF_model.joblib" bundle = joblib.load(BUNDLE_FILE) model = bundle["model"] feature_names = ['model_key', 'mileage', 'engine_power', 'fuel', 'paint_color', 'car_type', 'private_parking_available', 'has_gps', 'has_air_conditioning', 'automatic_car', 'has_getaround_connect', 'has_speed_regulator', 'winter_tires'] N = len(feature_names) # --- Move Swagger UI to /api-docs --- app = FastAPI( title="Pricing Optimization API", description="See /api-docs for interactive Swagger UI.", version="1.0.0", docs_url="/api-docs", redoc_url=None, ) # ===== Schemas ===== class CarFeatures(BaseModel): model_key: str mileage: int engine_power: int fuel: str paint_color: str car_type: str private_parking_available: bool has_gps: bool has_air_conditioning: bool automatic_car: bool has_getaround_connect: bool has_speed_regulator: bool winter_tires: bool class PredictRequest(BaseModel): input: List[CarFeatures] class PredictResponse(BaseModel): prediction: List[float] # ===== Endpoints ===== @app.get("/", tags=["health"]) def root(): return {"status": "ok", "message": "See /docs for API documentation."} @app.post("/predict", response_model=PredictResponse, tags=["inference"]) def predict(payload: PredictRequest): try: # Convert list of CarFeatures -> DataFrame in correct order rows = [[ car.model_key, car.mileage, car.engine_power, car.fuel, car.paint_color, car.car_type, car.private_parking_available, car.has_gps, car.has_air_conditioning, car.automatic_car, car.has_getaround_connect, car.has_speed_regulator, car.winter_tires ] for car in payload.input] X_df = pd.DataFrame(rows, columns=feature_names) y_pred = model.predict(X_df).tolist() return {"prediction": y_pred} except Exception as e: raise HTTPException(status_code=400, detail=str(e)) # ===== Custom HTML docs at /docs ===== @app.get("/docs", response_class=HTMLResponse, tags=["documentation"]) def custom_docs(): feature_rows = "\n".join( f"{i+1}{name}" for i, name in enumerate(feature_names) ) example_request = """{ "input": [ { "model_key": "Peugeot", "mileage": 174631, "engine_power": 120, "fuel": "diesel", "paint_color": "black", "car_type": "convertible", "private_parking_available": true, "has_gps": true, "has_air_conditioning": false, "automatic_car": false, "has_getaround_connect": false, "has_speed_regulator": false, "winter_tires": true } ] }""" example_response = '{ "prediction": [42.0] }' html = f""" Pricing Optimization API — Docs

Pricing Optimization API

Predict optimal daily price for a car given its attributes.

Endpoints

POST /predict — Send a list of car feature objects

GET / — Health check

Expected Feature Order (N = {N})

{feature_rows}
#Feature

Example Request

{example_request}

Example Response

{example_response}

Interactive API docs: Swagger UI

""" return HTMLResponse(content=html, status_code=200)