Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import pickle | |
| import numpy as np | |
| import pandas as pd | |
| import os | |
| # --- VÉRIFICATION ET CHARGEMENT --- | |
| MODEL_FILE = "smartrack_health_alert_vet_model.pkl" | |
| ENCODER_FILE = "species_encoder_vet.pkl" | |
| # Fichiers audio par langue (simulés) | |
| # IMPORTANT: Pour une implémentation réelle, ces fichiers MP3 devraient | |
| # contenir l'alerte enregistrée dans la langue spécifiée. | |
| AUDIO_PATHS = { | |
| 'Français': { | |
| 'alert': "alert_high.mp3", # Français (Alerte Grave) | |
| 'ok': "alert_ok.mp3" # Français (Statut OK) | |
| }, | |
| 'Pular (Peul)': { | |
| 'alert': "alert_high_pular.mp3", # Fichier audio Pular (à fournir) | |
| 'ok': "alert_ok_pular.mp3" # Fichier audio Pular (à fournir) | |
| }, | |
| 'Mandinka (Malinké)': { | |
| 'alert': "alert_high_mandinka.mp3", # Fichier audio Mandinka (à fournir) | |
| 'ok': "alert_ok_mandinka.mp3" # Fichier audio Mandinka (à fournir) | |
| }, | |
| 'Soussou': { | |
| 'alert': "alert_high_soussou.mp3", # Fichier audio Soussou (à fournir) | |
| 'ok': "alert_ok_soussou.mp3" # Fichier audio Soussou (à fournir) | |
| } | |
| } | |
| # Messages d'alerte dans différentes langues vernaculaires (texte) | |
| MESSAGES = { | |
| 'Français': { | |
| 'alert': "🚨 ALERTE: Problème de Santé Détecté. Vérification immédiate recommandée.", | |
| 'ok': "✅ Statut de Santé: OK. Les signes vitaux sont dans la plage normale.", | |
| 'action': "Veuillez vérifier immédiatement l'animal ou consulter un vétérinaire." | |
| }, | |
| 'Pular (Peul)': { | |
| 'alert': "🚨 **Habbere Sellal Habi !** (Problème de santé grave !)", | |
| 'ok': "✅ **Cellal Habi: No Ngol'li.** (Santé OK : Tout est bien.)", | |
| 'action': "Jooni jooni ngeesa ndabba oo malla yaara ngesa." # Vérifiez immédiatement... | |
| }, | |
| 'Mandinka (Malinké)': { | |
| 'alert': "🚨 **Nteeri-nkoo Kori!** (Problème de collier !) (Simulation - Le message sera le même)", | |
| 'ok': "✅ **Jato Kamma: Ikoo.** (Statut OK : Il n'y a rien.) (Simulation - Le message sera le même)", | |
| 'action': "I ye dabba lafii siininiwalla yaara dakteri." # Vous devez vérifier l'animal ou aller chez le docteur. | |
| }, | |
| 'Soussou': { | |
| 'alert': "🚨 **Lanfana Xadi !** (Problème de santé grave !) (Simulation)", | |
| 'ok': "✅ **Lanfana: Mu Wali.** (Santé : Tout va bien.) (Simulation)", | |
| 'action': "Yandi lanfana xadi, ye dabba la fisa walla ye dakteri xadi." # Vérifiez rapidement l'animal ou allez voir le docteur. | |
| } | |
| } | |
| # Vérification préalable pour s'assurer que les artefacts existent | |
| if not os.path.exists(MODEL_FILE) or not os.path.exists(ENCODER_FILE): | |
| print(f"❌ ERREUR FATALE: Les fichiers du modèle ({MODEL_FILE} ou {ENCODER_FILE}) sont introuvables.") | |
| print("Veuillez vous assurer d'avoir exécuté les étapes de Simulation et d'Entraînement.") | |
| # On laisse le FileNotFoundError, mais on continue avec model=None pour le déploiement local | |
| try: | |
| model = pickle.load(open(MODEL_FILE, "rb")) | |
| encoder = pickle.load(open(ENCODER_FILE, "rb")) | |
| except Exception as e: | |
| print(f"❌ ERREUR: Problème lors du chargement des fichiers pickle : {e}") | |
| model = None | |
| # --- DÉFINITION GLOBALE --- | |
| classes = ['OK (Santé Normale)', 'ALERTE (Intervention Recommandée)'] | |
| SPECIES_LIST = list(encoder.categories_[0]) | |
| # 2. Fonction de Prédiction avec Output Audio (mis à jour avec Langue) | |
| def predict_health_alert_vocal(langue_choisie, species, hr, spo2, temp, acc_mean, gyro_mean): | |
| """ Prend les données, la langue choisie, et renvoie le texte d'alerte et l'audio correspondant. """ | |
| if model is None: | |
| return "Erreur: Modèle non chargé. Veuillez corriger l'erreur ci-dessus.", None | |
| # 1. Préparation des données d'entrée | |
| input_data = pd.DataFrame({ | |
| 'hr': [hr], 'spo2': [spo2], 'temp': [temp], | |
| 'acc_mean': [acc_mean], 'gyro_mean': [gyro_mean], | |
| 'species': [species] | |
| }) | |
| # 2. Prétraitement | |
| numerical_features = input_data.drop('species', axis=1) | |
| species_encoded = encoder.transform(input_data[['species']]) | |
| species_df = pd.DataFrame(species_encoded, columns=encoder.get_feature_names_out(['species'])) | |
| X_final = pd.concat([numerical_features, species_df], axis=1) | |
| # 3. Prédiction | |
| prediction = model.predict(X_final)[0] | |
| probas = model.predict_proba(X_final)[0] | |
| predicted_class = classes[prediction] | |
| # Récupération des messages et chemins audio dans la langue choisie | |
| messages = MESSAGES.get(langue_choisie, MESSAGES['Français']) | |
| audio_files = AUDIO_PATHS.get(langue_choisie, AUDIO_PATHS['Français']) | |
| # 4. Formatage des Sorties | |
| if prediction == 1: | |
| # Sélectionne le bon chemin audio pour l'alerte | |
| audio_filename = audio_files['alert'] | |
| audio_path = audio_filename if os.path.exists(audio_filename) else None | |
| alert_style = messages['alert'] | |
| action_message = messages['action'] | |
| else: | |
| # Sélectionne le bon chemin audio pour l'OK | |
| audio_filename = audio_files['ok'] | |
| audio_path = audio_filename if os.path.exists(audio_filename) else None | |
| alert_style = messages['ok'] | |
| action_message = "" # Pas d'action si OK | |
| # Si le fichier audio n'existe pas, nous utilisons le français par défaut si disponible | |
| if audio_path is None: | |
| if prediction == 1 and os.path.exists(AUDIO_PATHS['Français']['alert']): | |
| audio_path = AUDIO_PATHS['Français']['alert'] | |
| elif prediction == 0 and os.path.exists(AUDIO_PATHS['Français']['ok']): | |
| audio_path = AUDIO_PATHS['Français']['ok'] | |
| # Construction du rapport textuel final | |
| output_text = f"## {alert_style} \n\n" | |
| output_text += f"**Espèce :** {species.capitalize()}\n" | |
| output_text += f"**Statut Analysé :** **{predicted_class}**\n\n" | |
| output_text += f"--- \n\n" | |
| output_text += f"**Action Recommandée :** {action_message}\n\n" | |
| output_text += f"*(Probabilité d'Alerte : {probas[1]*100:.2f}%)*" | |
| return output_text, audio_path | |
| # 3. Création de l'Interface Gradio (avec le composant Langue en premier) | |
| iface = gr.Interface( | |
| fn=predict_health_alert_vocal, | |
| inputs=[ | |
| gr.Dropdown(choices=list(MESSAGES.keys()), label="0. Langue de l'Alerte", value="Français"), | |
| gr.Dropdown(choices=SPECIES_LIST, label="1. Espèce Animale", value="boeuf"), | |
| gr.Slider(minimum=30, maximum=200, value=75, label="2. Rythme Cardiaque (BPM)"), | |
| gr.Slider(minimum=80, maximum=100, value=96, label="3. Saturation O₂ (SpO2 %)"), | |
| gr.Slider(minimum=35.0, maximum=42.0, value=38.0, label="4. Température Corporelle (°C)"), | |
| gr.Slider(minimum=0.0, maximum=5.0, value=0.5, label="5. Mouvement (Accél. Moy.)"), | |
| gr.Slider(minimum=0.0, maximum=5.0, value=1.5, label="6. Mouvement (Gyro. Moy.)"), | |
| ], | |
| outputs=[ | |
| gr.Markdown(label="Rapport Textuel d'Alerte"), | |
| gr.Audio(label="Alerte Vocale (Si disponible dans la langue choisie)"), | |
| ], | |
| title="Système d'Alerte de Santé Vétérinaire SmarTrack (Vocal Multi-Langue)", | |
| description="Validation locale : Le modèle prédit l'état de santé et affiche les alertes dans la langue choisie (le fichier audio est sélectionné en conséquence).", | |
| examples=[ | |
| ['Français', 'boeuf', 55, 96, 38.5, 0.1, 0.1], # Normal | |
| ['Pular (Peul)', 'chat', 170, 95, 38.5, 3.0, 3.0], # Normal | |
| ['Soussou', 'boeuf', 150, 85, 41.0, 0.0, 0.0], # Alerte en Soussou | |
| ] | |
| ) | |
| # --- LANCEMENT LOCAL --- | |
| # C'est cette ligne qui fait la différence pour le test local ! | |
| iface.launch(share=True) | |