mvlick/atisfaction-prediction-api
0
1from fastapi import FastAPI2from pydantic import BaseModel3import pandas as pd4import joblib5 6# ===============================7# ⚙️ Configuration8# ===============================9MODEL_PATH = "model_best.joblib" # ou model.pkl selon ton fichier10model = joblib.load(MODEL_PATH)11 12app = FastAPI(13 title="Satisfaction Prediction API",14 description="API de prédiction de satisfaction apprenants",15 version="1.0.0"16)17 18# ===============================19# 📦 Schémas d’entrée20# ===============================21class Diploma(BaseModel):22 level: str = ""23 title: str = ""24 25class Experience(BaseModel):26 title: str = ""27 description: str = ""28 29class PastCourse(BaseModel):30 title: str = ""31 description: str = ""32 numberOfStars: float | None = None33 34class Professor(BaseModel):35 fistname: str = ""36 lastname: str = ""37 city: str = ""38 description: str = ""39 diplomas: list[Diploma] = []40 experiences: list[Experience] = []41 pastCourses: list[PastCourse] = []42 43class Course(BaseModel):44 title: str = ""45 description: str = ""46 47class InputData(BaseModel):48 professor: Professor49 course: Course50 51# ===============================52# 🧩 Prétraitement53# ===============================54def adapt_input(body: dict) -> dict:55 prof = body.get("professor", {})56 course = body.get("course", {})57 58 diplomas = prof.get("diplomas", [])59 exps = prof.get("experiences", [])60 past_courses = prof.get("pastCourses", [])61 62 # Diplômes63 levels = [d.get("level", "").lower() for d in diplomas]64 has_master = int(any("master" in lvl for lvl in levels))65 has_licence = int(any("licence" in lvl or "bachelor" in lvl for lvl in levels))66 has_doctorat = int(any("doctor" in lvl or "phd" in lvl for lvl in levels))67 has_certif = int(any("certif" in lvl for lvl in levels))68 has_secondary = int(any("second" in lvl for lvl in levels))69 70 # Expériences71 all_exp_text = " ".join(72 f"{e.get('title', '')} {e.get('description', '')}".lower()73 for e in exps74 )75 has_teaching_exp = int(any(k in all_exp_text for k in ["prof", "enseign", "formateur"]))76 has_industry_exp = int(any(k in all_exp_text for k in ["dev", "engineer", "ingénieur", "consult", "industrie"]))77 has_management_exp = int(any(k in all_exp_text for k in ["chef", "lead", "manager", "responsable"]))78 has_academic_exp = int(any(k in all_exp_text for k in ["recherche", "thèse", "doctorat", "universit"]))79 80 # Moyenne et nombre de cours passés81 past_ratings = [c.get("numberOfStars") for c in past_courses if c.get("numberOfStars") is not None]82 teacher_mean_excl = float(sum(past_ratings) / len(past_ratings)) if past_ratings else 083 teacher_course_count = len(past_courses)84 85 # Infos générales86 desc_len_words = len(prof.get("description", "").split())87 n_diplomas = len(diplomas)88 n_experiences = len(exps)89 90 # Nouveau cours91 course_title = course.get("title", "").strip().lower()92 course_description = course.get("description", "").strip().lower()93 full_course_text = f"{course_title} {course_description}".strip()94 95 # ✅ Données prêtes pour le modèle96 return {97 "course_title": full_course_text,98 "desc_len_words": desc_len_words,99 "n_diplomas": n_diplomas,100 "n_experiences": n_experiences,101 "teacher_mean_excl": teacher_mean_excl,102 "teacher_course_count": teacher_course_count,103 "has_master": has_master,104 "has_licence": has_licence,105 "has_doctorat": has_doctorat,106 "has_certif": has_certif,107 "has_secondary": has_secondary,108 "has_teaching_exp": has_teaching_exp,109 "has_industry_exp": has_industry_exp,110 "has_management_exp": has_management_exp,111 "has_academic_exp": has_academic_exp112 }113 114# ===============================115# 🚀 Endpoint principal116# ===============================117@app.post("/api/predict")118def predict(data: InputData):119 body = data.dict()120 features = adapt_input(body)121 df = pd.DataFrame([features])122 123 prediction = model.predict(df)[0]124 prediction = round(float(prediction), 2)125 126 return {"gradeAverage": prediction}127 128# ===============================129# 🧪 Test rapide130# ===============================131@app.get("/")132def root():133 return {134 "message": "Bienvenue sur l’API de prédiction de satisfaction 🎯",135 "usage": "POST /api/predict avec le JSON d’un professeur et d’un cours"136 }