File size: 7,691 Bytes
22ca435
 
 
 
 
 
ec25577
22ca435
 
 
ec25577
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a39088f
 
ec25577
 
22ca435
ec25577
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22ca435
 
 
 
ec25577
22ca435
 
ec25577
22ca435
 
 
 
ec25577
 
 
22ca435
 
ec25577
22ca435
ec25577
22ca435
 
 
 
 
 
ec25577
22ca435
 
 
 
 
 
ec25577
22ca435
 
 
 
ec25577
 
 
 
 
22ca435
ec25577
 
 
 
 
 
22ca435
ec25577
 
 
 
 
 
22ca435
ec25577
 
 
 
 
 
 
 
22ca435
 
 
 
 
 
 
ec25577
22ca435
 
ec25577
22ca435
ec25577
22ca435
ec25577
22ca435
 
 
 
 
 
 
 
ec25577
 
22ca435
ec25577
 
 
 
 
 
 
22ca435
 
ec25577
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
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)