CoolFace
Apppublic

tchamfi/pollution-api

sourceHugging Facemitupdated 2y agoView on Hugging Face
0likes
app.py124 linesDownload Raw Back to root
1import openai2import os3import pandas as pd4from fastapi import FastAPI, Query, HTTPException5import joblib6 7# Charger le modèle et les données8 9# Utiliser le bon chemin relatif pour les fichiers10BASE_DIR = os.path.dirname(os.path.abspath(__file__))11MODEL_PATH = os.path.join(BASE_DIR, "pollution_model.pkl")12CSV_PATH = os.path.join(BASE_DIR, "pollution_cleaned.csv")13df = pd.read_csv(CSV_PATH)14model = joblib.load(MODEL_PATH)15 16# Définir les features utilisées pour la prédiction (sans 'Date' et 'City')17features = ['temperature_median', 'humidity_median', 'pressure_median', 18            'dew_median', 'wind-gust_median', 'wind-speed_median', 'pp_feat']19 20app = FastAPI()21 22@app.get("/chatbot")23def chatbot_response(city: str = Query(..., description="Ville à analyser"), 24                     date: str = Query(..., description="Date de prédiction au format YYYY-MM-DD"),25                     question: str = Query(..., description="Question sur la pollution")):26    """27    Chatbot IA qui répond aux questions sur la pollution avec un modèle prédictif.28    """29 30    # Vérifier si la ville existe dans les données31    city_data = df[df["City"].str.lower() == city.lower()]32 33    if city_data.empty:34        raise HTTPException(status_code=404, detail=f"Désolé, je n'ai pas de données pour {city}.")35 36    # Vérifier que les features sont bien des colonnes numériques37    numeric_features = city_data[features].select_dtypes(include=['number'])38 39    if numeric_features.empty:40        raise HTTPException(status_code=400, detail="Aucune donnée numérique disponible pour faire la prédiction.")41 42    # Vérifier si le modèle contient bien les noms des features43    expected_features = model.get_booster().feature_names44    if expected_features is None:45        expected_features = [f"f{i}" for i in range(model.get_booster().num_features())]  # Génère des noms par défaut46        print("⚠️ Attention : Le modèle ne contient pas de noms de features. Utilisation de noms générés.")47 48    input_features = list(numeric_features.columns)49 50    # Vérifier les différences entre features attendues et réelles51    missing_features = set(expected_features) - set(input_features)52    extra_features = set(input_features) - set(expected_features)53 54    print("🚨 Features attendues mais manquantes :", missing_features)55    print("🔹 Features en trop :", extra_features)56 57    # Réordonner et compléter les features manquantes avec 058    numeric_features = numeric_features.reindex(columns=expected_features, fill_value=0)59 60    # ✅ Assurer qu'on a bien une seule ligne (évite l'erreur de shape mismatch)61    input_data = numeric_features.mean().values.reshape(1, -1)62 63    # Vérifier la forme finale64    print("📊 Shape de input_data après correction :", input_data.shape)  # Devrait être (1, 53)65 66    # Prédiction67    predicted_pm25 = float(model.predict(input_data)[0])68 69    # ✅ prompt GPT-4 engageant et structuré70    context = (71        "🌍 **Bienvenue !** Tu es un expert en qualité de l’air et en recommandations sanitaires. "72        "Ton objectif est d’aider l’utilisateur à comprendre les niveaux de pollution et à adapter ses activités en conséquence. "73        "Utilise un ton **clair, pédagogique et engageant**.\n\n"74 75        "💨 **Comprendre le PM2.5** : Ces particules fines peuvent affecter la santé, surtout chez les personnes vulnérables. "76        "Voici l’échelle officielle de la qualité de l’air :\n\n"77        78        "🌿 **PM2.5 < 50** : 🟢 **Excellente qualité de l'air !** Profitez de votre journée sans restriction. 😃\n"79        "🌤 **50 ≤ PM2.5 < 100** : 🟡 **Qualité de l'air correcte.** Aucune gêne pour la plupart des gens, mais les personnes sensibles doivent éviter les efforts prolongés.\n"80        "😷 **100 ≤ PM2.5 < 150** : 🟠 **Attention aux personnes sensibles !** Réduisez l’activité en extérieur si vous êtes asthmatique ou allergique.\n"81        "🚨 **150 ≤ PM2.5 < 200** : 🔴 **Pollution élevée !** Limitez les sorties et évitez le sport en extérieur.\n"82        "⚠️ **PM2.5 ≥ 200** : 🟣 **Alerte pollution !** Il est recommandé de rester à l’intérieur et de porter un masque FFP2 en cas de sortie.\n\n"83 84        "🔹 **Ton rôle** : Fournis une réponse détaillée et adaptée en fonction du niveau de pollution. "85        "Si la pollution est faible, encourage l’utilisateur à profiter de l’extérieur. "86        "Si elle est élevée, conseille des alternatives (masques, air purifié, etc.).\n\n"87 88        "📌 **Situation actuelle :**"89    )90 91    # ✅ Amélioration de l'appel GPT-4 pour des réponses plus développées92    api = openai.OpenAI(api_key="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")93 94    response = api.chat.completions.create(95        model="gpt-4",96        messages=[97            {"role": "system", "content": context},98            {"role": "user", "content": f"🌍 Ville : {city}\n📅 Date : {date}\n💨 Niveau de pollution PM2.5 prévu : {predicted_pm25:.2f}\n\n{question}"}99        ],100        temperature=0.7,  # 🔹 Réponses plus variées et naturelles101        max_tokens=200,  # 🔹 Réponses plus détaillées102        top_p=0.9  # 🔹 Plus de diversité dans la réponse103    )104 105    # ✅ Ajout d'une mise en forme plus agréable à lire106    gpt_response = response.choices[0].message.content107 108    formatted_response = f"""109🌍 Ville : {city}  110📅 Date :  {date}  111💨 Niveau de pollution PM2.5 prévu : {predicted_pm25:.2f}  112 113🗣 Réponse de l'expert pollution : 114 115{gpt_response}  116"""117 118    return {119        "city": city,120        "date": date,121        "predicted_pm25": predicted_pm25,122        "response": formatted_response123    }124