Clemylia commited on
Commit
ae17d5e
·
verified ·
1 Parent(s): fa986ba

Update README.md

Browse files
Files changed (1) hide show
  1. README.md +187 -1
README.md CHANGED
@@ -130,4 +130,190 @@ Utilisez la fonction d'entraînement (`train()`) de Nac-1 avec vos nouveaux mod
130
 
131
  * `nac1_final_weights.pth`: Fichier binaire PyTorch contenant les poids optimisés.
132
  * `nac1_vocab.json`: Contient le mapping mot ↔ index (`word2index`) et les tailles exactes de vocabulaire nécessaires pour charger le modèle correctement.
133
- * `README.md`: Ce fichier.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
  * `nac1_final_weights.pth`: Fichier binaire PyTorch contenant les poids optimisés.
132
  * `nac1_vocab.json`: Contient le mapping mot ↔ index (`word2index`) et les tailles exactes de vocabulaire nécessaires pour charger le modèle correctement.
133
+ * `README.md`: Ce fichier.
134
+
135
+ **Exemple de code d'utilisation (Fonctionnel)** :
136
+
137
+ ```
138
+ # Installation des bibliothèques nécessaires
139
+ !pip install huggingface_hub
140
+
141
+ import torch
142
+ import torch.nn as nn
143
+ import json
144
+ import os
145
+ from huggingface_hub import hf_hub_download
146
+
147
+ # ==============================================================================
148
+ # 0. CONFIGURATION GLOBALE
149
+ # ==============================================================================
150
+
151
+ # Identifiant du dépôt (à remplacer par le vôtre si différent)
152
+ REPO_ID = "Clemylia/Nac-1"
153
+ FINAL_FILENAME = 'nac1_final_weights.pth'
154
+ VOCAB_FILENAME = "nac1_vocab.json"
155
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
156
+ HIDDEN_SIZE = 256 # Doit correspondre à la taille utilisée lors de l'entraînement
157
+
158
+ # Tokens Spéciaux (doivent être les mêmes que ceux utilisés dans le vocabulaire)
159
+ SOS_token = 0
160
+ EOS_token = 1
161
+
162
+ # ==============================================================================
163
+ # 1. CLASSES D'ARCHITECTURE DU MODÈLE (L'utilisateur en a besoin)
164
+ # ==============================================================================
165
+
166
+ # Note : Les utilisateurs doivent copier ces définitions exactes pour charger les poids.
167
+
168
+ class Language:
169
+ """Simule la classe Language en utilisant le vocabulaire chargé."""
170
+ def __init__(self, name, word2index, index2word):
171
+ self.name = name
172
+ self.word2index = word2index
173
+ self.index2word = index2word
174
+ self.n_words = len(word2index)
175
+
176
+ class EncoderRNN(nn.Module):
177
+ def __init__(self, input_size, hidden_size):
178
+ super().__init__()
179
+ self.hidden_size = hidden_size
180
+ self.embedding = nn.Embedding(input_size, hidden_size)
181
+ self.lstm = nn.LSTM(hidden_size, hidden_size)
182
+ def forward(self, input_tensor, hidden_state, cell_state):
183
+ embedded = self.embedding(input_tensor).view(1, 1, -1)
184
+ output, (hidden_state, cell_state) = self.lstm(embedded, (hidden_state, cell_state))
185
+ return output, hidden_state, cell_state
186
+ def init_hidden(self, device):
187
+ return (torch.zeros(1, 1, self.hidden_size, device=device),
188
+ torch.zeros(1, 1, self.hidden_size, device=device))
189
+
190
+ class DecoderRNN(nn.Module):
191
+ def __init__(self, hidden_size, output_size):
192
+ super().__init__()
193
+ self.hidden_size = hidden_size
194
+ self.embedding = nn.Embedding(output_size, hidden_size)
195
+ self.lstm = nn.LSTM(hidden_size, hidden_size)
196
+ self.out = nn.Linear(hidden_size, output_size)
197
+ self.softmax = nn.LogSoftmax(dim=1)
198
+ def forward(self, input_tensor, hidden_state, cell_state):
199
+ embedded = self.embedding(input_tensor).view(1, 1, -1)
200
+ output, (hidden_state, cell_state) = self.lstm(embedded, (hidden_state, cell_state))
201
+ output = self.softmax(self.out(output[0]))
202
+ return output, hidden_state, cell_state
203
+ def init_hidden(self, device):
204
+ return (torch.zeros(1, 1, self.hidden_size, device=device),
205
+ torch.zeros(1, 1, self.hidden_size, device=device))
206
+
207
+
208
+ # ==============================================================================
209
+ # 2. FONCTIONS DE TÉLÉCHARGEMENT ET UTILITAIRES
210
+ # ==============================================================================
211
+
212
+ def load_vocab_and_models(repo_id, vocab_filename, weights_filename, hidden_size, device):
213
+ """Télécharge les fichiers et initialise les modèles."""
214
+ print(f"Téléchargement des fichiers depuis {repo_id}...")
215
+
216
+ # 1. Téléchargement du vocabulaire
217
+ vocab_path = hf_hub_download(repo_id=repo_id, filename=vocab_filename)
218
+ with open(vocab_path, 'r') as f:
219
+ vocab_data = json.load(f)
220
+
221
+ # Reconstruire les objets Language
222
+ input_w2i = vocab_data['source_vocab']
223
+ output_w2i = vocab_data['nacacia_vocab']
224
+
225
+ # L'index-to-word (i2w) est essentiel pour la prédiction
226
+ input_i2w = {int(v): k for k, v in input_w2i.items()}
227
+ output_i2w = {int(v): k for k, v in output_w2i.items()}
228
+
229
+ input_lang = Language("Source", input_w2i, input_i2w)
230
+ output_lang = Language("Nacacia", output_w2i, output_i2w)
231
+
232
+ # 2. Initialisation des modèles
233
+ encoder = EncoderRNN(input_lang.n_words, hidden_size).to(device)
234
+ decoder = DecoderRNN(hidden_size, output_lang.n_words).to(device)
235
+
236
+ # 3. Téléchargement et chargement des poids
237
+ weights_path = hf_hub_download(repo_id=repo_id, filename=weights_filename)
238
+ checkpoint = torch.load(weights_path, map_location=device)
239
+
240
+ encoder.load_state_dict(checkpoint['encoder_state_dict'])
241
+ decoder.load_state_dict(checkpoint['decoder_state_dict'])
242
+
243
+ encoder.eval() # Mode évaluation
244
+ decoder.eval()
245
+
246
+ print("✅ Modèle Nac-1 chargé et prêt pour l'inférence.")
247
+ return encoder, decoder, input_lang, output_lang
248
+
249
+ def tensor_from_sentence(lang, sentence):
250
+ """Convertit une phrase en un tenseur d'indices de mots."""
251
+ # S'assurer que tous les mots sont connus
252
+ try:
253
+ indexes = [lang.word2index[word] for word in sentence.split(' ')]
254
+ except KeyError as e:
255
+ raise ValueError(f"Le mot '{e.args[0]}' n'est pas dans le vocabulaire connu du modèle. Échec.")
256
+
257
+ indexes.append(EOS_token)
258
+ return torch.tensor(indexes, dtype=torch.long, device=device).view(-1, 1)
259
+
260
+ def evaluate(encoder, decoder, sentence, input_lang, output_lang, max_length=15):
261
+ """Génère la phrase Nacacia à partir d'une phrase source."""
262
+ with torch.no_grad():
263
+ try:
264
+ input_tensor = tensor_from_sentence(input_lang, sentence.lower().strip())
265
+ except ValueError as e:
266
+ return str(e) # Retourne l'erreur de vocabulaire
267
+
268
+ input_length = input_tensor.size(0)
269
+ encoder_hidden, encoder_cell = encoder.init_hidden(device)
270
+
271
+ # ENCODEUR
272
+ for ei in range(input_length):
273
+ _, encoder_hidden, encoder_cell = encoder(input_tensor[ei], encoder_hidden, encoder_cell)
274
+
275
+ # DÉCODEUR
276
+ decoder_input = torch.tensor([[SOS_token]], device=device)
277
+ decoder_hidden, decoder_cell = encoder_hidden, encoder_cell
278
+ decoded_words = []
279
+
280
+ for _ in range(max_length):
281
+ decoder_output, decoder_hidden, decoder_cell = decoder(decoder_input, decoder_hidden, decoder_cell)
282
+ topv, topi = decoder_output.data.topk(1)
283
+ predicted_index = topi.item()
284
+
285
+ if predicted_index == EOS_token: break
286
+
287
+ decoded_words.append(output_lang.index2word[predicted_index])
288
+ decoder_input = torch.tensor([[predicted_index]], device=device)
289
+
290
+ return ' '.join(decoded_words)
291
+
292
+ # ==============================================================================
293
+ # 3. EXÉCUTION POUR L'UTILISATEUR
294
+ # ==============================================================================
295
+
296
+ if __name__ == "__main__":
297
+
298
+ # 1. Chargement du modèle depuis Hugging Face
299
+ encoder, decoder, input_lang, output_lang = load_vocab_and_models(
300
+ REPO_ID, VOCAB_FILENAME, FINAL_FILENAME, HIDDEN_SIZE, device
301
+ )
302
+
303
+ print("\n--- Inférence sur de Nouvelles Phrases ---")
304
+
305
+ # Phrases de test utilisant le vocabulaire connu :
306
+ test_sentences = [
307
+ "il fait beau aujourd'hui",
308
+ "la lune est claire",
309
+ "j'ai besoin d'aide",
310
+ "le chat dort sur le canapé"
311
+ ]
312
+
313
+ # Phrase avec un mot inconnu pour tester la robustesse :
314
+ test_sentences.append("le soleil orange brille")
315
+
316
+ for sentence in test_sentences:
317
+ output_sentence = evaluate(encoder, decoder, sentence, input_lang, output_lang)
318
+ print(f'Source: "{sentence}" -> Nacacia: "{output_sentence}"')
319
+ ```