Team Ai
Apppublic

meedv/NextStepAI

sourceHugging Facemitupdated 4mo agoView on Hugging Face
0likes
app.py152 linesDownload Raw Back to root
1from flask import Flask, render_template, request, jsonify2import joblib, json, numpy as np3from pymongo import MongoClient4import os5 6# --- Connexion sécurisée à MongoDB ---7MONGO_URI = os.environ.get("MONGO_URI")8if MONGO_URI:9    client = MongoClient(MONGO_URI)10    db = client['orientation_db']11    collection = db['student_responses']12 13app = Flask(__name__)14 15# --- Chargement du modèle + encoders ---16model     = joblib.load('model_xgb.pkl')17le_target = joblib.load('le_target.pkl')18encoders  = joblib.load('encoders.pkl')19with open('model_meta.json', encoding='utf-8') as f:20    meta = json.load(f)21 22FEATURES = meta['features']23CAT_COLS = meta['cat_cols']24NUM_COLS = meta['num_cols']25 26FILIERES_INFO = {27    "3G":   {"nom":"Géosciences, Géodynamique et Géomatique","couleur":"#92400e","icone":"🌍","debouches":["Géologue","Ingénieur mines","Cartographe","Environnement"],"modules":["Géophysique","Cartographie","Géologie","Géostatistiques"]},28    "BPV":  {"nom":"Biotechnologie et Production Végétale","couleur":"#15803d","icone":"🌿","debouches":["Ingénieur agronome","Biotechnologiste","Agriculture","Industrie pharma"],"modules":["Biotechnologie végétale","Physiologie végétale","Génétique","Agroalimentaire"]},29    "COA":  {"nom":"Chimie Organique Appliquée","couleur":"#dc2626","icone":"🧪","debouches":["Chimiste","Agroalimentaire","Pharmacie","Cosmétique"],"modules":["Chimie organique","Polymères","Réactions organiques","Agroalimentaire"]},30    "CPA":  {"nom":"Chimie Physique et Applications","couleur":"#ea580c","icone":"🔬","debouches":["Ingénieur procédés","Chimiste analytique","Environnement"],"modules":["Electrochimie","Cinétique","Catalyse","Environnement"]},31    "GEER": {"nom":"Génie Electrique et Energies Renouvelables","couleur":"#ca8a04","icone":"⚡","debouches":["Ingénieur électrique","Energies renouvelables","Industrie électrique"],"modules":["Electronique","Energies renouvelables","Automatique","Réseaux électriques"]},32    "IMEI": {"nom":"Ingénierie Mécanique et Energétiques Industrielles","couleur":"#0369a1","icone":"⚙️","debouches":["Ingénieur mécanique","Industrie","Bureau d'études"],"modules":["Mécanique","Thermodynamique","Matériaux","CAO"]},33    "MA":   {"nom":"Mathématiques et Applications","couleur":"#059669","icone":"📐","debouches":["Chercheur","Enseignant","Actuaire","Grandes écoles"],"modules":["Analyse","Algèbre","Topologie","Calcul différentiel"]},34    "MI":   {"nom":"Développement et Bases de données","couleur":"#2563eb","icone":"💻","debouches":["Développeur web","Admin BDD","Ingénieur logiciel"],"modules":["Programmation web","Bases de données","Réseaux","POO Java"]},35    "MIA":  {"nom":"Matériaux Inorganiques et Applications","couleur":"#d97706","icone":"⚗️","debouches":["Ingénieur matériaux","Chercheur chimiste","Industrie"],"modules":["Chimie des matériaux","Cristallographie","Electrochimie","Spectroscopie"]},36    "PM":   {"nom":"Physique Moderne","couleur":"#7c3aed","icone":"🔭","debouches":["Chercheur physicien","Enseignant","Ingénieur R&D"],"modules":["Physique quantique","Optique","Mécanique","Physique des matériaux"]},37    "SD":   {"nom":"Sciences des données","couleur":"#6d28d9","icone":"📊","debouches":["Data Scientist","Analyste données","Ingénieur ML"],"modules":["Machine learning","Big data","Python","Statistiques"]},38    "SESBM":{"nom":"Santé, Environnement et Sciences Bio Médicales","couleur":"#0891b2","icone":"🧬","debouches":["Biologiste","Chercheur santé","Pharmacie","Médecine"],"modules":["Biochimie","Microbiologie","Génétique","Immunologie"]},39    "TR":   {"nom":"Télécommunications et Réseaux","couleur":"#0f766e","icone":"📡","debouches":["Ingénieur télécom","Réseaux","Opérateur télécoms"],"modules":["Réseaux","Télécoms","Protocoles","Systèmes embarqués"]},40}41 42RENFORCER = {43    "MI":   [("note_math",13,"Mathématiques"),("note_biologie",0,"—")],44    "SD":   [("note_math",13,"Mathématiques & Statistiques"),("note_biologie",0,"—")],45    "MA":   [("note_math",16,"Mathématiques (niveau élevé requis)")],46    "MIA":  [("note_chimie",13,"Chimie"),("note_physique",13,"Physique")],47    "COA":  [("note_chimie",13,"Chimie organique")],48    "CPA":  [("note_chimie",13,"Chimie physique"),("note_physique",13,"Physique")],49    "PM":   [("note_physique",14,"Physique")],50    "GEER": [("note_physique",13,"Physique"),("note_math",12,"Mathématiques")],51    "IMEI": [("note_physique",13,"Physique"),("note_math",12,"Mathématiques")],52    "TR":   [("note_physique",12,"Physique"),("note_math",12,"Mathématiques")],53    "SESBM":[("note_biologie",13,"Biologie / SVT")],54    "BPV":  [("note_biologie",13,"Biologie végétale")],55    "3G":   [("note_biologie",11,"SVT & Géologie")],56}57 58def safe_encode(col, val):59    le = encoders.get(col)60    if le is None: return 061    try:    return int(le.transform([str(val)])[0])62    except: return 063 64def build_X(d):65    row = {66        "moyenne_generale_bac": float(d.get("moyenne_generale_bac",12)),67        "note_math":      float(d.get("note_math",12)),68        "note_physique":  float(d.get("note_physique",12)),69        "note_chimie":    float(d.get("note_chimie",12)),70        "note_biologie":  float(d.get("note_biologie",12)),71        "q6_interet_biologie":              float(d.get("q6",3)),72        "q7_interet_chimie":                float(d.get("q7",3)),73        "q8_interet_math":                  float(d.get("q8",3)),74        "q9_interet_physique":              float(d.get("q9",3)),75        "q10_interet_informatique":        float(d.get("q10",3)),76        "q11_interet_terrain":              float(d.get("q11",3)),77        "q12_interet_sante":                float(d.get("q12",3)),78        "q13_interet_environnement":       float(d.get("q13",3)),79        "q14_interet_industrie":           float(d.get("q14",3)),80        "q15_interet_developpement_logiciel": float(d.get("q15",3)),81        "q16_interet_data_ia":             float(d.get("q16",3)),82        "q17_niveau_memorisation":         float(d.get("q17",3)),83        "q18_niveau_analyse":              float(d.get("q18",3)),84        "q19_niveau_abstraction":          float(d.get("q19",3)),85        "q20_niveau_programmation":        float(d.get("q20",3)),86        "q21_aisance_laboratoire_bio":     float(d.get("q21",3)),87        "q22_aisance_laboratoire_phys_chim": float(d.get("q22",3)),88        "q23_aisance_projets_numeriques":  float(d.get("q23",3)),89        "q24_aisance_sorties_terrain":     float(d.get("q24",3)),90        "sexe_enc":           safe_encode("sexe", d.get("sexe","M")),91        "bac_type_enc":       safe_encode("bac_type", d.get("bac_type","SM")),92        "bac_mention_enc":    safe_encode("bac_mention", d.get("bac_mention","Bien")),93        "q1_matiere_preferee_enc":        safe_encode("q1_matiere_preferee", d.get("q1","")),94        "q2_activite_preferee_enc":       safe_encode("q2_activite_preferee", d.get("q2","")),95        "q3_type_problemes_prefere_enc":  safe_encode("q3_type_problemes_prefere", d.get("q3","")),96        "q4_preference_travail_enc":      safe_encode("q4_preference_travail", d.get("q4","Individuel")),97        "q5_preference_environnement_enc":safe_encode("q5_preference_environnement", d.get("q5","Mixte")),98        "q25_objectif_carriere_enc":      safe_encode("q25_objectif_carriere", d.get("q25","")),99    }100    return np.array([[row[f] for f in FEATURES]])101 102@app.route("/")103def index():104    return render_template("index.html")105 106@app.route("/recommander", methods=["POST"])107def recommander():108    data  = request.json109    X     = build_X(data)110    proba = model.predict_proba(X)[0]111    top3  = np.argsort(proba)[::-1][:3]112 113    results = []114    for rank, idx in enumerate(top3):115        code  = le_target.classes_[idx]116        score = float(proba[idx])117        info  = FILIERES_INFO.get(code, {"nom":code,"couleur":"#64748b","icone":"🎓","debouches":[],"modules":[]})118 119        renforcer = []120        for nkey, seuil, label in RENFORCER.get(code, []):121            if seuil > 0 and float(data.get(nkey, 12)) < seuil:122                renforcer.append(label)123        if not renforcer:124            renforcer = ["✅ Bon profil — continuez!"]125 126        results.append({127            "rang": rank+1, "code": code,128            "nom": info["nom"], "couleur": info["couleur"], "icone": info["icone"],129            "taux": round(score*100, 1),130            "modules": info["modules"], "debouches": info["debouches"],131            "renforcer": renforcer132        })133 134    # --- ENREGISTREMENT AUTOMATIQUE DANS MONGODB ---135    if MONGO_URI:136        try:137            # On fait une copie propre des données reçues pour ne pas altérer le flux138            donnees_a_sauvegarder = dict(data)139            # On enregistre le Top 1 recommandé (le choix principal du modèle)140            donnees_a_sauvegarder['prediction_proposee'] = results[0]['nom']141            donnees_a_sauvegarder['code_filiere'] = results[0]['code']142            143            # Insertion dans la base Cloud144            collection.insert_one(donnees_a_sauvegarder)145            print("Données enregistrées avec succès dans MongoDB Atlas !")146        except Exception as e:147            print(f"Erreur MongoDB lors de la sauvegarde : {e}")148 149    return jsonify(results)150 151if __name__ == "__main__":152    app.run(host="0.0.0.0", port=7860)