| --- |
| tags: |
| - pytorch |
| - seq2seq |
| - custom-language |
| - nac-1 |
| license: other |
| language: |
| - fr |
| pipeline_tag: translation |
| --- |
| |
| ----- |
|
|
| ## 🩷 Modèle Nac-1 (Langue Créative) 🩷 |
|
|
|  |
|
|
|
|
| Ce modèle est **Nac-1**, un modèle de type **Encoder-Decoder Seq2Seq** basé sur des **LSTM** (Long Short-Term Memory). Il a été entraîné pour traduire le Français vers la langue créative **Nacacia**. |
|
|
| Ce dépôt sert de **modèle de base et de point de départ** pour la création de tout projet de traduction ou de transformation linguistique personnalisé. |
|
|
| ----- |
|
|
| ## 🚀 1. Utilisation du Modèle Nac-1 Publié |
|
|
| Pour utiliser le modèle **Nac-1** pour l'inférence (traduction Français → Nacacia), vous devez charger les fichiers d'architecture, de poids et de vocabulaire directement depuis ce dépôt Hugging Face. |
|
|
| ### 1.1. Pré-requis |
|
|
| ```bash |
| # Nécessaire pour télécharger les fichiers depuis Hugging Face |
| !pip install torch huggingface_hub |
| ``` |
|
|
| ### 1.2. Chargement et Inférence |
|
|
| Le code ci-dessous télécharge le modèle, reconstitue l'architecture, et exécute la transformation. |
|
|
| **(Note : Les classes `EncoderRNN`, `DecoderRNN`, `Language`, `tensor_from_sentence`, et la fonction `evaluate` complètes doivent être incluses dans le script de l'utilisateur pour que le code d'inférence fonctionne.)** |
|
|
| ```python |
| import torch |
| import json |
| from huggingface_hub import hf_hub_download |
| |
| REPO_ID = "Clemylia/Nac-1" |
| FINAL_FILENAME = 'nac1_final_weights.pth' |
| VOCAB_FILENAME = "nac1_vocab.json" |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
| # ... [Inclure ici les définitions complètes des classes EncoderRNN, DecoderRNN, Language] ... |
| |
| def load_and_evaluate(sentence: str): |
| """Charge le modèle et exécute la traduction d'une phrase.""" |
| # (Logique de hf_hub_download et de load_vocab_and_models ici) |
| # ... [Voir le code de chargement complet pour l'implémentation] ... |
| |
| # Exemple d'exécution |
| # encoder, decoder, input_lang, output_lang = load_vocab_and_models(REPO_ID, ...) |
| # return evaluate(encoder, decoder, sentence, input_lang, output_lang) |
| |
| # Simuler le chargement réussi et le résultat pour cette documentation |
| return "krosh chata supe domanacafe" |
| |
| phrase = "le chat dort sur le canapé" |
| resultat = load_and_evaluate(phrase) |
| print(f'Source: "{phrase}" -> Nacacia: "{resultat}"') |
| ``` |
|
|
| ----- |
|
|
| ## 🛠️ 2. Créer votre Propre Nac Personnalisé (À Partir de Nac-1) |
|
|
| L'architecture de **Nac-1** est entièrement réutilisable pour créer vos propres modèles de transformation de séquence, que ce soit pour une autre langue inventée (Nac-2) ou une tâche différente (résumé, changement de style). |
|
|
| ### Étapes Clés de Réutilisation : |
|
|
| #### 2.1. Mise en Place des Données |
|
|
| Créez votre propre jeu de données de paires de séquences (`(input_sequence, target_sequence)`). |
|
|
| ```python |
| # Modifiez ces données pour votre nouveau projet ! |
| mon_nouveau_projet_data = [ |
| ("anglais : the car is red", "langue_inventee : voxta esta reeda"), |
| ("anglais : i love coding", "langue_inventee : amou codio") |
| ] |
| ``` |
|
|
| #### 2.2. Réutilisation du Code d'Architecture |
|
|
| Vous devez simplement copier les classes PyTorch : |
|
|
| * **`class EncoderRNN(...)`** |
| * **`class DecoderRNN(...)`** |
| * **`class Language(...)`** |
| * Les fonctions utilitaires (`prepare_data`, `tensor_from_sentence`) |
|
|
| #### 2.3. Initialisation |
|
|
| La seule chose qui change est la taille des vocabulaires, qui s'ajustera automatiquement : |
|
|
| 1. **Exécutez `prepare_data`** sur vos nouvelles données pour obtenir `input_lang` et `output_lang`. |
| 2. **Initialisez vos modèles** avec vos nouveaux vocabulaires : |
| |
| <!-- end list --> |
| |
| ```python |
| # Les tailles sont basées sur VOS données, pas celles de Nac-1. |
| nouveau_encodeur = EncoderRNN(input_lang.n_words, HIDDEN_SIZE) |
| nouveau_decodeur = DecoderRNN(HIDDEN_SIZE, output_lang.n_words) |
| ``` |
| |
| #### 2.4. Entraînement |
| |
| Utilisez la fonction d'entraînement (`train()`) de Nac-1 avec vos nouveaux modèles et vos nouvelles paires de tenseurs pour entraîner votre propre modèle personnalisé \! |
| |
| ----- |
| |
| ## ⚙️ Configuration Détaillée de Nac-1 |
| |
| | Métrique | Encodeur | Décodeur | Total | Note | |
| | :--- | :--- | :--- | :--- | :--- | |
| | **Taille Cachée** (`HIDDEN_SIZE`) | 256 | 256 | N/A | Définit la capacité de la mémoire LSTM. | |
| | **Taille Vocabulaire** | 117 mots | 123 mots | N/A | Inclut les tokens `SOS` et `EOS`. | |
| | **Paramètres Entraînables** | 556,288 | 589,435 | **1,145,723** | Taille totale du modèle (environ 1.15 Million). | |
|
|
| ### Fichiers du Dépôt |
|
|
| * `nac1_final_weights.pth`: Fichier binaire PyTorch contenant les poids optimisés. |
| * `nac1_vocab.json`: Contient le mapping mot ↔ index (`word2index`) et les tailles exactes de vocabulaire nécessaires pour charger le modèle correctement. |
| * `README.md`: Ce fichier. |
| |
| **Exemple de code d'utilisation (Fonctionnel)** : |
| |
| ``` |
| # Installation des bibliothèques nécessaires |
| !pip install huggingface_hub |
| |
| import torch |
| import torch.nn as nn |
| import json |
| import os |
| from huggingface_hub import hf_hub_download |
| |
| # ============================================================================== |
| # 0. CONFIGURATION GLOBALE |
| # ============================================================================== |
| |
| # Identifiant du dépôt (à remplacer par le vôtre si différent) |
| REPO_ID = "Clemylia/Nac-1" |
| FINAL_FILENAME = 'nac1_final_weights.pth' |
| VOCAB_FILENAME = "nac1_vocab.json" |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
| HIDDEN_SIZE = 256 # Doit correspondre à la taille utilisée lors de l'entraînement |
| |
| # Tokens Spéciaux (doivent être les mêmes que ceux utilisés dans le vocabulaire) |
| SOS_token = 0 |
| EOS_token = 1 |
| |
| # ============================================================================== |
| # 1. CLASSES D'ARCHITECTURE DU MODÈLE (L'utilisateur en a besoin) |
| # ============================================================================== |
| |
| # Note : Les utilisateurs doivent copier ces définitions exactes pour charger les poids. |
| |
| class Language: |
| """Simule la classe Language en utilisant le vocabulaire chargé.""" |
| def __init__(self, name, word2index, index2word): |
| self.name = name |
| self.word2index = word2index |
| self.index2word = index2word |
| self.n_words = len(word2index) |
| |
| class EncoderRNN(nn.Module): |
| def __init__(self, input_size, hidden_size): |
| super().__init__() |
| self.hidden_size = hidden_size |
| self.embedding = nn.Embedding(input_size, hidden_size) |
| self.lstm = nn.LSTM(hidden_size, hidden_size) |
| def forward(self, input_tensor, hidden_state, cell_state): |
| embedded = self.embedding(input_tensor).view(1, 1, -1) |
| output, (hidden_state, cell_state) = self.lstm(embedded, (hidden_state, cell_state)) |
| return output, hidden_state, cell_state |
| def init_hidden(self, device): |
| return (torch.zeros(1, 1, self.hidden_size, device=device), |
| torch.zeros(1, 1, self.hidden_size, device=device)) |
| |
| class DecoderRNN(nn.Module): |
| def __init__(self, hidden_size, output_size): |
| super().__init__() |
| self.hidden_size = hidden_size |
| self.embedding = nn.Embedding(output_size, hidden_size) |
| self.lstm = nn.LSTM(hidden_size, hidden_size) |
| self.out = nn.Linear(hidden_size, output_size) |
| self.softmax = nn.LogSoftmax(dim=1) |
| def forward(self, input_tensor, hidden_state, cell_state): |
| embedded = self.embedding(input_tensor).view(1, 1, -1) |
| output, (hidden_state, cell_state) = self.lstm(embedded, (hidden_state, cell_state)) |
| output = self.softmax(self.out(output[0])) |
| return output, hidden_state, cell_state |
| def init_hidden(self, device): |
| return (torch.zeros(1, 1, self.hidden_size, device=device), |
| torch.zeros(1, 1, self.hidden_size, device=device)) |
| |
| |
| # ============================================================================== |
| # 2. FONCTIONS DE TÉLÉCHARGEMENT ET UTILITAIRES |
| # ============================================================================== |
| |
| def load_vocab_and_models(repo_id, vocab_filename, weights_filename, hidden_size, device): |
| """Télécharge les fichiers et initialise les modèles.""" |
| print(f"Téléchargement des fichiers depuis {repo_id}...") |
| |
| # 1. Téléchargement du vocabulaire |
| vocab_path = hf_hub_download(repo_id=repo_id, filename=vocab_filename) |
| with open(vocab_path, 'r') as f: |
| vocab_data = json.load(f) |
| |
| # Reconstruire les objets Language |
| input_w2i = vocab_data['source_vocab'] |
| output_w2i = vocab_data['nacacia_vocab'] |
| |
| # L'index-to-word (i2w) est essentiel pour la prédiction |
| input_i2w = {int(v): k for k, v in input_w2i.items()} |
| output_i2w = {int(v): k for k, v in output_w2i.items()} |
| |
| input_lang = Language("Source", input_w2i, input_i2w) |
| output_lang = Language("Nacacia", output_w2i, output_i2w) |
| |
| # 2. Initialisation des modèles |
| encoder = EncoderRNN(input_lang.n_words, hidden_size).to(device) |
| decoder = DecoderRNN(hidden_size, output_lang.n_words).to(device) |
| |
| # 3. Téléchargement et chargement des poids |
| weights_path = hf_hub_download(repo_id=repo_id, filename=weights_filename) |
| checkpoint = torch.load(weights_path, map_location=device) |
| |
| encoder.load_state_dict(checkpoint['encoder_state_dict']) |
| decoder.load_state_dict(checkpoint['decoder_state_dict']) |
| |
| encoder.eval() # Mode évaluation |
| decoder.eval() |
| |
| print("✅ Modèle Nac-1 chargé et prêt pour l'inférence.") |
| return encoder, decoder, input_lang, output_lang |
| |
| def tensor_from_sentence(lang, sentence): |
| """Convertit une phrase en un tenseur d'indices de mots.""" |
| # S'assurer que tous les mots sont connus |
| try: |
| indexes = [lang.word2index[word] for word in sentence.split(' ')] |
| except KeyError as e: |
| raise ValueError(f"Le mot '{e.args[0]}' n'est pas dans le vocabulaire connu du modèle. Échec.") |
| |
| indexes.append(EOS_token) |
| return torch.tensor(indexes, dtype=torch.long, device=device).view(-1, 1) |
| |
| def evaluate(encoder, decoder, sentence, input_lang, output_lang, max_length=15): |
| """Génère la phrase Nacacia à partir d'une phrase source.""" |
| with torch.no_grad(): |
| try: |
| input_tensor = tensor_from_sentence(input_lang, sentence.lower().strip()) |
| except ValueError as e: |
| return str(e) # Retourne l'erreur de vocabulaire |
| |
| input_length = input_tensor.size(0) |
| encoder_hidden, encoder_cell = encoder.init_hidden(device) |
| |
| # ENCODEUR |
| for ei in range(input_length): |
| _, encoder_hidden, encoder_cell = encoder(input_tensor[ei], encoder_hidden, encoder_cell) |
| |
| # DÉCODEUR |
| decoder_input = torch.tensor([[SOS_token]], device=device) |
| decoder_hidden, decoder_cell = encoder_hidden, encoder_cell |
| decoded_words = [] |
| |
| for _ in range(max_length): |
| decoder_output, decoder_hidden, decoder_cell = decoder(decoder_input, decoder_hidden, decoder_cell) |
| topv, topi = decoder_output.data.topk(1) |
| predicted_index = topi.item() |
| |
| if predicted_index == EOS_token: break |
| |
| decoded_words.append(output_lang.index2word[predicted_index]) |
| decoder_input = torch.tensor([[predicted_index]], device=device) |
| |
| return ' '.join(decoded_words) |
| |
| # ============================================================================== |
| # 3. EXÉCUTION POUR L'UTILISATEUR |
| # ============================================================================== |
| |
| if __name__ == "__main__": |
| |
| # 1. Chargement du modèle depuis Hugging Face |
| encoder, decoder, input_lang, output_lang = load_vocab_and_models( |
| REPO_ID, VOCAB_FILENAME, FINAL_FILENAME, HIDDEN_SIZE, device |
| ) |
| |
| print("\n--- Inférence sur de Nouvelles Phrases ---") |
| |
| # Phrases de test utilisant le vocabulaire connu : |
| test_sentences = [ |
| "il fait beau aujourd'hui", |
| "la lune est claire", |
| "j'ai besoin d'aide", |
| "le chat dort sur le canapé" |
| ] |
| |
| # Phrase avec un mot inconnu pour tester la robustesse : |
| test_sentences.append("le soleil orange brille") |
| |
| for sentence in test_sentences: |
| output_sentence = evaluate(encoder, decoder, sentence, input_lang, output_lang) |
| print(f'Source: "{sentence}" -> Nacacia: "{output_sentence}"') |
| ``` |