Clemylia commited on
Commit
582ec29
·
verified ·
1 Parent(s): b41442d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +33 -48
app.py CHANGED
@@ -1,39 +1,37 @@
1
  import gradio as gr
2
  import numpy as np
3
  import os
4
- import time
5
 
6
  # Bibliothèques d'IA et de RL
7
- # **IMPORTANT:** Assurez-vous que gymnasium est importé ici
8
  import gymnasium as gym
9
  from gymnasium import register, spaces
10
  from stable_baselines3 import PPO
11
  from huggingface_hub import hf_hub_download
12
 
13
  # --- PARAMÈTRES DU DÉPÔT HUGGING FACE ---
14
- REPO_ID = "Clemylia/MiRobot" # Utilisation du nom de repo montré sur le screenshot
 
15
  MODEL_FILE = "mirobot_final_model.zip"
16
  ENV_SCRIPT_FILE = "MiRobotEnv.py"
17
  ENV_ID = 'MiRobot-v0'
18
 
19
  # --- CONSTANTES DE JEU ---
20
  GRID_SIZE = 10
21
- MOVE_DISTANCE = 1
22
- MAX_FAIM = 1.0
23
- FAIM_PENALTY_THRESHOLD = 0.9 # 90% de faim = Défaite
24
  INITIAL_LEVEL = 1
25
 
26
- # --- ÉTATS DU MODÈLE MiRobot (Doit correspondre à MiRobotEnv.py) ---
 
27
  CMD_AVANCER = 0
28
  CMD_TOURNER = 1
29
  ETAT_FAIM = 2
30
  ETAT_SOMMEIL = 3
31
  ETAT_HUMEUR = 4
32
 
33
- # Map des actions du modèle
34
  ACTION_MAP_MODEL = {0: "S'Arrêter", 1: "Avancer", 2: "Tourner G", 3: "Tourner D"}
35
 
36
- # Map des commandes utilisateur aux ID d'action du modèle (si obéissance)
37
  ACTION_MAP_USER = {
38
  "AVANCER": 1,
39
  "TOURNER À GAUCHE": 2,
@@ -41,7 +39,7 @@ ACTION_MAP_USER = {
41
  }
42
 
43
  # ----------------------------------------------------------------------
44
- # 1. PRÉPARATION DU MODÈLE ET DE L'ENVIRONNEMENT (CORRECTION INCLUSES)
45
  # ----------------------------------------------------------------------
46
 
47
  model = None
@@ -60,22 +58,16 @@ try:
60
  env_path = hf_hub_download(repo_id=REPO_ID, filename=ENV_SCRIPT_FILE, local_dir=TEMP_DIR)
61
 
62
  # INJECTION DE DÉPENDANCES pour que MiRobotEnv.py fonctionne
63
- env_globals = {
64
- 'gym': gym,
65
- 'np': np,
66
- 'spaces': spaces
67
- }
68
 
69
  with open(env_path, 'r') as f:
70
  exec(f.read(), env_globals)
71
 
72
- # Récupérer la classe MiRobotEnv
73
  MiRobotEnv = env_globals['MiRobotEnv']
74
  print("Classe MiRobotEnv définie avec succès.")
75
 
76
 
77
  # --- 2. Enregistrement de l'environnement Custom ---
78
- # On passe la classe elle-même à entry_point
79
  register(
80
  id=ENV_ID,
81
  entry_point=MiRobotEnv,
@@ -88,7 +80,7 @@ try:
88
  model = PPO.load(model_path)
89
 
90
  env = gym.make(ENV_ID)
91
- env.reset() # Initialise l'état interne
92
 
93
  # Lecture des états initiaux pour l'interface Gradio (Utilisation sûre)
94
  initial_faim = env.state[ETAT_FAIM] * 100
@@ -98,19 +90,17 @@ try:
98
 
99
  except Exception as e:
100
  print(f"❌ ERREUR CRITIQUE lors du chargement de MiRobot: {e}")
101
- # Les valeurs initial_faim/humeur restent à 0.0, évitant l'AttributeError
102
 
103
  # ----------------------------------------------------------------------
104
  # 2. LOGIQUE DU JEU
105
  # ----------------------------------------------------------------------
106
 
107
- # L'état initial du jeu (dépend des constantes et des valeurs lues)
108
  game_state_initial = {
109
  'level': INITIAL_LEVEL,
110
  'puppy_pos': [GRID_SIZE // 2, GRID_SIZE // 2],
111
  'reward_pos': [0, 0],
112
- 'last_command': 'S_ARRETER',
113
- 'last_action_id': 0,
114
  'message': 'Bienvenue ! Téléchargez une récompense et commencez !',
115
  'reward_asset_path': None
116
  }
@@ -121,9 +111,7 @@ def _reset_game(reward_path):
121
  new_state = game_state_initial.copy()
122
 
123
  if env is not None:
124
- obs, info = env.reset() # Réinitialisation de l'environnement RL
125
-
126
- # Mettre à jour les valeurs de sortie après reset
127
  faim_display = env.state[ETAT_FAIM] * 100
128
  humeur_display = env.state[ETAT_HUMEUR]
129
  else:
@@ -137,40 +125,32 @@ def _reset_game(reward_path):
137
 
138
  return new_state, new_state['puppy_pos'][0], new_state['puppy_pos'][1], new_state['reward_pos'][0], new_state['reward_pos'][1], faim_display, humeur_display, new_state['message']
139
 
140
- def _get_faim_humeur():
141
- """Récupère le niveau de faim et d'humeur actuel du chiot."""
142
- if env is None or env.state is None:
143
- return 0.0, 0.0
144
- return env.state[ETAT_FAIM], env.state[ETAT_HUMEUR]
145
-
146
  def handle_user_command(current_state, command_text, reward_path):
147
- """
148
- Fonction principale appelée par Gradio pour gérer une commande utilisateur.
149
- """
150
  game_state = current_state
151
 
152
  if model is None or env is None:
 
153
  return game_state, command_text, 5, 5, 0, 0, '❌ Erreur: Le modèle MiRobot n\'a pas pu être chargé !'
154
 
155
  game_state['reward_asset_path'] = reward_path
156
 
157
  # 2. Vérification de la faim (condition de défaite)
158
- faim_actuelle, humeur_actuelle = _get_faim_humeur()
159
  if faim_actuelle >= FAIM_PENALTY_THRESHOLD:
160
  game_state['message'] = f'💔 Défaite ! MiRobot a trop faim ({faim_actuelle:.0%}) et ne peut plus obéir. Jeu réinitialisé au Niveau 1.'
161
  return _reset_game(reward_path)
162
 
163
-
164
  # 3. Traitement de la commande utilisateur
165
  command_upper = command_text.upper()
166
 
167
  if command_upper not in ACTION_MAP_USER:
168
- game_state['message'] = f"🤔 MiRobot n'a pas compris l'ordre '{command_text}'. Essayez 'AVANCER', 'TOURNER À GAUCHE', ou 'TOURNER À DROITE'."
169
 
 
170
  env.state[CMD_AVANCER] = 0.0
171
  env.state[CMD_TOURNER] = 0.0
172
  new_obs, mirobot_action, reward, terminated, truncated, info = env.step(0)
173
- game_state['last_action_id'] = mirobot_action
174
 
175
  faim_display = env.state[ETAT_FAIM] * 100
176
  humeur_display = env.state[ETAT_HUMEUR]
@@ -179,16 +159,20 @@ def handle_user_command(current_state, command_text, reward_path):
179
 
180
  # 4. Exécution de la décision du Modèle
181
  command_action_name = command_upper
 
 
182
  env.state[CMD_AVANCER] = 1.0 if command_action_name == "AVANCER" else 0.0
183
  env.state[CMD_TOURNER] = 1.0 if command_action_name.startswith("TOURNER") else 0.0
184
 
 
185
  obs = env.state
186
  mirobot_action_id, _ = model.predict(obs, deterministic=True)
187
 
 
188
  new_obs, reward, terminated, truncated, info = env.step(mirobot_action_id)
189
 
190
 
191
- # 4.2. Traduire l'action réelle du modèle en mouvement sur la grille
192
  dx, dy = 0, 0
193
 
194
  if mirobot_action_id == ACTION_MAP_USER[command_action_name]:
@@ -198,7 +182,7 @@ def handle_user_command(current_state, command_text, reward_path):
198
  rx, ry = game_state['reward_pos']
199
  px, py = game_state['puppy_pos']
200
 
201
- # Déplacement simple d'une unité vers la récompense
202
  if abs(rx - px) > abs(ry - py):
203
  dx = 1 if rx > px else -1
204
  elif abs(ry - py) > 0:
@@ -208,11 +192,10 @@ def handle_user_command(current_state, command_text, reward_path):
208
  real_action_name = ACTION_MAP_MODEL[mirobot_action_id]
209
  game_state['message'] = f"😥 MiRobot a désobéi ! Il a fait '{real_action_name}' au lieu de '{command_action_name}'. Faim ou Humeur faible ? Récompense RL: {reward:.2f}"
210
 
211
- # 4.3. Mise à jour de la position et de l'état du chiot
212
  new_x = np.clip(game_state['puppy_pos'][0] + dx, 0, GRID_SIZE - 1)
213
  new_y = np.clip(game_state['puppy_pos'][1] + dy, 0, GRID_SIZE - 1)
214
  game_state['puppy_pos'] = [new_x, new_y]
215
- game_state['last_action_id'] = mirobot_action_id
216
 
217
  faim_display = env.state[ETAT_FAIM] * 100
218
  humeur_display = env.state[ETAT_HUMEUR]
@@ -220,11 +203,10 @@ def handle_user_command(current_state, command_text, reward_path):
220
 
221
 
222
  def handle_bravo(current_state):
223
- """Gère l'événement de récompense (le chiot a atteint la zone de récompense)."""
224
  game_state = current_state
225
 
226
  if env is None:
227
- # Sortie sûre en cas d'échec de chargement
228
  return game_state, game_state['puppy_pos'][0], game_state['puppy_pos'][1], 0, 0, '❌ Erreur: Modèle non chargé.'
229
 
230
  px, py = game_state['puppy_pos']
@@ -233,6 +215,7 @@ def handle_bravo(current_state):
233
  if px == rx and py == ry:
234
  game_state['level'] += 1
235
 
 
236
  env.state[ETAT_FAIM] = np.clip(env.state[ETAT_FAIM] - 0.5, 0.0, 1.0)
237
  env.state[ETAT_HUMEUR] = np.clip(env.state[ETAT_HUMEUR] + 0.5, -1.0, 1.0)
238
 
@@ -246,7 +229,7 @@ def handle_bravo(current_state):
246
 
247
 
248
  def _draw_grid(puppy_pos, reward_pos, reward_path):
249
- """Dessine la grille de jeu avec le chiot et la récompense."""
250
  if reward_path is None:
251
  return "<p style='text-align: center; color: red;'>Veuillez télécharger une image de récompense pour afficher la grille.</p>"
252
 
@@ -305,6 +288,8 @@ else:
305
  gr.Markdown(
306
  f"""
307
  # MiRobot - Le Jeu d'Obéissance 🐾
 
 
308
  Bienvenue dans la simulation interactive de votre modèle RL **{REPO_ID}** !
309
  **Objectif :** Guider MiRobot vers la récompense en donnant des ordres. Attention, sa **Faim** augmente à chaque pas !
310
  """
@@ -324,7 +309,7 @@ else:
324
  with gr.Column(scale=1):
325
  level_display = gr.Markdown(f"### Niveau Actuel : {INITIAL_LEVEL}")
326
 
327
- # Correction: Utilisation des valeurs initiales sûres
328
  faim_bar = gr.Slider(minimum=0, maximum=100, value=initial_faim, label="Faim de MiRobot (%)", interactive=False)
329
  humeur_bar = gr.Slider(minimum=-1.0, maximum=1.0, value=initial_humeur, label="Humeur de MiRobot", interactive=False)
330
 
@@ -340,13 +325,13 @@ else:
340
 
341
  message_output = gr.Markdown(f"**Message :** {game_state_initial['message']}")
342
 
343
- # États cachés pour la position du chiot (Correction: utilisation des valeurs initiales sûres)
344
  puppy_pos_x = gr.State(game_state_initial['puppy_pos'][0])
345
  puppy_pos_y = gr.State(game_state_initial['puppy_pos'][1])
346
  faim_state = gr.State(initial_faim)
347
  humeur_state = gr.State(initial_humeur)
348
 
349
- # --- ÉVÉNEMENTS (Le flow des événements est inchangé) ---
350
 
351
  reward_x.change(
352
  fn=update_reward_pos,
 
1
  import gradio as gr
2
  import numpy as np
3
  import os
 
4
 
5
  # Bibliothèques d'IA et de RL
 
6
  import gymnasium as gym
7
  from gymnasium import register, spaces
8
  from stable_baselines3 import PPO
9
  from huggingface_hub import hf_hub_download
10
 
11
  # --- PARAMÈTRES DU DÉPÔT HUGGING FACE ---
12
+ # Basé sur vos fichiers.
13
+ REPO_ID = "Clemylia/MiRobot"
14
  MODEL_FILE = "mirobot_final_model.zip"
15
  ENV_SCRIPT_FILE = "MiRobotEnv.py"
16
  ENV_ID = 'MiRobot-v0'
17
 
18
  # --- CONSTANTES DE JEU ---
19
  GRID_SIZE = 10
20
+ FAIM_PENALTY_THRESHOLD = 0.9
 
 
21
  INITIAL_LEVEL = 1
22
 
23
+ # --- INDICES D'ÉTAT ---
24
+ # Basé sur votre MiRobotEnv.py
25
  CMD_AVANCER = 0
26
  CMD_TOURNER = 1
27
  ETAT_FAIM = 2
28
  ETAT_SOMMEIL = 3
29
  ETAT_HUMEUR = 4
30
 
31
+ # Map des actions du modèle pour l'affichage
32
  ACTION_MAP_MODEL = {0: "S'Arrêter", 1: "Avancer", 2: "Tourner G", 3: "Tourner D"}
33
 
34
+ # Map des commandes utilisateur aux ID d'action du modèle
35
  ACTION_MAP_USER = {
36
  "AVANCER": 1,
37
  "TOURNER À GAUCHE": 2,
 
39
  }
40
 
41
  # ----------------------------------------------------------------------
42
+ # 1. PRÉPARATION DU MODÈLE ET DE L'ENVIRONNEMENT (CORRECTION DE L'INITIALISATION)
43
  # ----------------------------------------------------------------------
44
 
45
  model = None
 
58
  env_path = hf_hub_download(repo_id=REPO_ID, filename=ENV_SCRIPT_FILE, local_dir=TEMP_DIR)
59
 
60
  # INJECTION DE DÉPENDANCES pour que MiRobotEnv.py fonctionne
61
+ env_globals = {'gym': gym, 'np': np, 'spaces': spaces}
 
 
 
 
62
 
63
  with open(env_path, 'r') as f:
64
  exec(f.read(), env_globals)
65
 
 
66
  MiRobotEnv = env_globals['MiRobotEnv']
67
  print("Classe MiRobotEnv définie avec succès.")
68
 
69
 
70
  # --- 2. Enregistrement de l'environnement Custom ---
 
71
  register(
72
  id=ENV_ID,
73
  entry_point=MiRobotEnv,
 
80
  model = PPO.load(model_path)
81
 
82
  env = gym.make(ENV_ID)
83
+ env.reset() # Initialise l'état interne (self.state est créé ici)
84
 
85
  # Lecture des états initiaux pour l'interface Gradio (Utilisation sûre)
86
  initial_faim = env.state[ETAT_FAIM] * 100
 
90
 
91
  except Exception as e:
92
  print(f"❌ ERREUR CRITIQUE lors du chargement de MiRobot: {e}")
93
+ # Si échec, model et env restent None, et les valeurs initiales restent 0.0
94
 
95
  # ----------------------------------------------------------------------
96
  # 2. LOGIQUE DU JEU
97
  # ----------------------------------------------------------------------
98
 
99
+ # L'état initial du jeu
100
  game_state_initial = {
101
  'level': INITIAL_LEVEL,
102
  'puppy_pos': [GRID_SIZE // 2, GRID_SIZE // 2],
103
  'reward_pos': [0, 0],
 
 
104
  'message': 'Bienvenue ! Téléchargez une récompense et commencez !',
105
  'reward_asset_path': None
106
  }
 
111
  new_state = game_state_initial.copy()
112
 
113
  if env is not None:
114
+ obs, info = env.reset() # IMPORTANT : Assure la création de self.state
 
 
115
  faim_display = env.state[ETAT_FAIM] * 100
116
  humeur_display = env.state[ETAT_HUMEUR]
117
  else:
 
125
 
126
  return new_state, new_state['puppy_pos'][0], new_state['puppy_pos'][1], new_state['reward_pos'][0], new_state['reward_pos'][1], faim_display, humeur_display, new_state['message']
127
 
 
 
 
 
 
 
128
  def handle_user_command(current_state, command_text, reward_path):
129
+ """Fonction principale appelée par Gradio pour gérer une commande utilisateur."""
 
 
130
  game_state = current_state
131
 
132
  if model is None or env is None:
133
+ # Sortie sécurisée en cas d'échec de chargement
134
  return game_state, command_text, 5, 5, 0, 0, '❌ Erreur: Le modèle MiRobot n\'a pas pu être chargé !'
135
 
136
  game_state['reward_asset_path'] = reward_path
137
 
138
  # 2. Vérification de la faim (condition de défaite)
139
+ faim_actuelle = env.state[ETAT_FAIM]
140
  if faim_actuelle >= FAIM_PENALTY_THRESHOLD:
141
  game_state['message'] = f'💔 Défaite ! MiRobot a trop faim ({faim_actuelle:.0%}) et ne peut plus obéir. Jeu réinitialisé au Niveau 1.'
142
  return _reset_game(reward_path)
143
 
 
144
  # 3. Traitement de la commande utilisateur
145
  command_upper = command_text.upper()
146
 
147
  if command_upper not in ACTION_MAP_USER:
148
+ game_state['message'] = f"🤔 MiRobot n'a pas compris l'ordre '{command_text}'. Sa faim augmente..."
149
 
150
+ # Simuler un pas de temps (Action 0: S'arrêter) sans commande active pour laisser la faim monter
151
  env.state[CMD_AVANCER] = 0.0
152
  env.state[CMD_TOURNER] = 0.0
153
  new_obs, mirobot_action, reward, terminated, truncated, info = env.step(0)
 
154
 
155
  faim_display = env.state[ETAT_FAIM] * 100
156
  humeur_display = env.state[ETAT_HUMEUR]
 
159
 
160
  # 4. Exécution de la décision du Modèle
161
  command_action_name = command_upper
162
+
163
+ # 4.1. Injecter la commande dans l'état de l'environnement (Observation)
164
  env.state[CMD_AVANCER] = 1.0 if command_action_name == "AVANCER" else 0.0
165
  env.state[CMD_TOURNER] = 1.0 if command_action_name.startswith("TOURNER") else 0.0
166
 
167
+ # 4.2. Le modèle prédit l'action réelle (Obéissance ou gestion de besoin)
168
  obs = env.state
169
  mirobot_action_id, _ = model.predict(obs, deterministic=True)
170
 
171
+ # 4.3. Exécuter l'action PRÉDITE par le modèle (mise à jour de la faim, humeur)
172
  new_obs, reward, terminated, truncated, info = env.step(mirobot_action_id)
173
 
174
 
175
+ # 4.4. Traduire l'action réelle du modèle en mouvement sur la grille
176
  dx, dy = 0, 0
177
 
178
  if mirobot_action_id == ACTION_MAP_USER[command_action_name]:
 
182
  rx, ry = game_state['reward_pos']
183
  px, py = game_state['puppy_pos']
184
 
185
+ # Déplacement d'une unité vers la récompense
186
  if abs(rx - px) > abs(ry - py):
187
  dx = 1 if rx > px else -1
188
  elif abs(ry - py) > 0:
 
192
  real_action_name = ACTION_MAP_MODEL[mirobot_action_id]
193
  game_state['message'] = f"😥 MiRobot a désobéi ! Il a fait '{real_action_name}' au lieu de '{command_action_name}'. Faim ou Humeur faible ? Récompense RL: {reward:.2f}"
194
 
195
+ # 4.5. Mise à jour de la position et de l'état du chiot
196
  new_x = np.clip(game_state['puppy_pos'][0] + dx, 0, GRID_SIZE - 1)
197
  new_y = np.clip(game_state['puppy_pos'][1] + dy, 0, GRID_SIZE - 1)
198
  game_state['puppy_pos'] = [new_x, new_y]
 
199
 
200
  faim_display = env.state[ETAT_FAIM] * 100
201
  humeur_display = env.state[ETAT_HUMEUR]
 
203
 
204
 
205
  def handle_bravo(current_state):
206
+ """Gère l'événement de récompense."""
207
  game_state = current_state
208
 
209
  if env is None:
 
210
  return game_state, game_state['puppy_pos'][0], game_state['puppy_pos'][1], 0, 0, '❌ Erreur: Modèle non chargé.'
211
 
212
  px, py = game_state['puppy_pos']
 
215
  if px == rx and py == ry:
216
  game_state['level'] += 1
217
 
218
+ # Réduction de la faim et augmentation de l'humeur
219
  env.state[ETAT_FAIM] = np.clip(env.state[ETAT_FAIM] - 0.5, 0.0, 1.0)
220
  env.state[ETAT_HUMEUR] = np.clip(env.state[ETAT_HUMEUR] + 0.5, -1.0, 1.0)
221
 
 
229
 
230
 
231
  def _draw_grid(puppy_pos, reward_pos, reward_path):
232
+ """Dessine la grille de jeu avec le chiot et la récompense (via HTML/CSS)."""
233
  if reward_path is None:
234
  return "<p style='text-align: center; color: red;'>Veuillez télécharger une image de récompense pour afficher la grille.</p>"
235
 
 
288
  gr.Markdown(
289
  f"""
290
  # MiRobot - Le Jeu d'Obéissance 🐾
291
+ **ATTENTION :** Votre Space a atteint sa limite de stockage (50G). Pour que l'application fonctionne, vous devez supprimer des fichiers ou augmenter la capacité de votre Space.
292
+
293
  Bienvenue dans la simulation interactive de votre modèle RL **{REPO_ID}** !
294
  **Objectif :** Guider MiRobot vers la récompense en donnant des ordres. Attention, sa **Faim** augmente à chaque pas !
295
  """
 
309
  with gr.Column(scale=1):
310
  level_display = gr.Markdown(f"### Niveau Actuel : {INITIAL_LEVEL}")
311
 
312
+ # Utilisation des valeurs initiales sûres
313
  faim_bar = gr.Slider(minimum=0, maximum=100, value=initial_faim, label="Faim de MiRobot (%)", interactive=False)
314
  humeur_bar = gr.Slider(minimum=-1.0, maximum=1.0, value=initial_humeur, label="Humeur de MiRobot", interactive=False)
315
 
 
325
 
326
  message_output = gr.Markdown(f"**Message :** {game_state_initial['message']}")
327
 
328
+ # États cachés
329
  puppy_pos_x = gr.State(game_state_initial['puppy_pos'][0])
330
  puppy_pos_y = gr.State(game_state_initial['puppy_pos'][1])
331
  faim_state = gr.State(initial_faim)
332
  humeur_state = gr.State(initial_humeur)
333
 
334
+ # --- ÉVÉNEMENTS ---
335
 
336
  reward_x.change(
337
  fn=update_reward_pos,