| --- |
| license: mit |
| language: |
| - fr |
| pipeline_tag: text-generation |
| tags: |
| - child |
| - Alphabet |
| - récitation |
| - Simulation enfantine |
| - ABX |
| - simulation de ABX |
| - jeunes enfants |
| - 2 a 7 ans |
| --- |
| # 🦋 ABX |
|
|
|  |
|
|
| Bienvenue sur la page de notre modèle `ABX`. |
| Ce modèle de machine learning est une idée que Nous avions prototyper avec des règles. |
| Mais nous avons considéré l'idée assez créative et intéressante pour faire l'objet de la création d'une IA de ML (machine learning), |
| Et d'une version finale fonctionnelle concrète pour l'utilisation. |
|
|
| ## 🌷 Ce que fait ABX |
|
|
| ABX est une IA qui simule la récitation de l'alphabet par un jeune enfant âgé de 2 a 7 ans. |
| L'enfant (ABX) essaye de réciter l'alphabet, |
| Mais plus son âge est faible et plus sa température est élevé, plus il oublie les lettres et se trompe. |
| Il aura tendance à s'excuser, à pleurer ou à sauter des lettres quand il est en bas âge (2 ou 3 ans), et se tromper de façon perpétuelle. |
| Mais ABX, sera extrêmement précis et fera un sans faute quand il est beaucoup plus grand (7 ans). |
| Plus sa température est élevée, et plus il est jeune, plus il va faire des boulettes (a l'image d'un vrai enfant). |
| Un bébé de 2 ans ne sais pas réciter l'alphabet, mais un enfant de 7 ans sais le faire (enfin normalement 😉). |
| ABX simule donc cela. |
|
|
| # 🌸 Comment ABX a été entraîné |
|
|
| ABX a été entraîné de façon rapide, |
| Mais a quand même nécessiter l'activation du GPU pour un entraînement efficace et continue sans plantage de session. |
| Pour qu'il apprenne à simuler la récitation de des jeunes enfants, |
| nous lui avons montrer l'alphabet correcte en entier, |
| puis lui avons aussi donner des données d'entraînement pour les probabilités pour chaque âge. |
| Nous avons aussi ajouté des petits messages aléatoires d'excuses, de pleurs et autre...que ABX utilise de temps et autres pour s'excuser et mettre de l'action a sa récitation foireuse de ses bas âge. |
|
|
| # 🔥 Que faire avec ABX |
|
|
| ABX peut vous être utile pour beaucoup de tâches créatives impliquant de la simulation enfantine. |
| (Par exemple : jeux de récitation l'alphabet ou les enfants qui doivent réciter l'alphabet sont des bots gérer par le modèle). |
| Trouvez votre propre cas d'usage et amusez vous ! |
|
|
| # 🩵 Utilisation |
|
|
| Voici un exemple de code d'utilisation de ABX : |
|
|
| ``` |
| import torch |
| import torch.nn as nn |
| import torch.nn.functional as F |
| import json |
| import os |
| from huggingface_hub import hf_hub_download |
| |
| # ================================================================= |
| # 0. CONFIGURATION ET DÉFINITION DES CLASSES DU MODÈLE |
| # ================================================================= |
| |
| # --- Configuration du dépôt Hugging Face --- |
| HF_REPO_ID = "Clemylia/ABX" |
| MODEL_FILENAME = "abx_model_state.pt" |
| CONFIG_FILENAME = "config.json" |
| VOCAB_FILENAME = "vocab.json" |
| DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
| |
| print(f"Périphérique utilisé : {DEVICE}") |
| |
| # --- Définition des classes du modèle (Doit être identique à l'entraînement !) --- |
| |
| # 1. Attention (Self-Attention Masquée Causale) |
| class Attention(nn.Module): |
| def __init__(self, embed_dim, num_heads, dropout): |
| super().__init__() |
| self.norm = nn.LayerNorm(embed_dim) |
| self.attn = nn.MultiheadAttention(embed_dim, num_heads, dropout=dropout, batch_first=True) |
| self.dropout_rate = dropout |
| |
| def forward(self, x, mask): |
| res = x |
| x = self.norm(x) |
| attn_output, _ = self.attn(x, x, x, attn_mask=mask, need_weights=False) |
| return res + attn_output |
| |
| # 2. Feed Forward (MLP) |
| class FeedForward(nn.Module): |
| def __init__(self, embed_dim, d_ff, dropout): |
| super().__init__() |
| self.norm = nn.LayerNorm(embed_dim) |
| self.ffn = nn.Sequential( |
| nn.Linear(embed_dim, d_ff), |
| nn.GELU(), |
| nn.Dropout(dropout), |
| nn.Linear(d_ff, embed_dim), |
| nn.Dropout(dropout) |
| ) |
| |
| def forward(self, x): |
| res = x |
| x = self.norm(x) |
| return res + self.ffn(x) |
| |
| # 3. Bloc Décodeur |
| class DecoderBlock(nn.Module): |
| def __init__(self, embed_dim, num_heads, d_ff, dropout): |
| super().__init__() |
| self.attention = Attention(embed_dim, num_heads, dropout) |
| self.feed_forward = FeedForward(embed_dim, d_ff, dropout) |
| |
| def forward(self, x, mask): |
| x = self.attention(x, mask) |
| x = self.feed_forward(x, ) |
| return x |
| |
| # 4. Le Modèle ABX Principal |
| class ABXModel(nn.Module): |
| def __init__(self, vocab_size, embed_dim, num_heads, num_layers, max_seq_len, d_ff, pad_token_id, dropout=0.1): |
| super().__init__() |
| self.pad_token_id = pad_token_id |
| self.token_embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=pad_token_id) |
| self.position_embedding = nn.Embedding(max_seq_len, embed_dim) |
| self.dropout = nn.Dropout(dropout) |
| |
| self.layers = nn.ModuleList([ |
| DecoderBlock(embed_dim, num_heads, d_ff, dropout) for _ in range(num_layers) |
| ]) |
| |
| self.norm = nn.LayerNorm(embed_dim) |
| self.output_linear = nn.Linear(embed_dim, vocab_size) |
| |
| def creer_masque(self, taille): |
| masque = torch.triu(torch.ones(taille, taille), diagonal=1).bool().to(DEVICE) |
| return masque |
| |
| def forward(self, input_ids): |
| T = input_ids.size(1) |
| |
| token_embed = self.token_embedding(input_ids) |
| positions = torch.arange(T, device=DEVICE).unsqueeze(0) |
| pos_embed = self.position_embedding(positions) |
| |
| x = self.dropout(token_embed + pos_embed) |
| |
| masque_causal = self.creer_masque(T) |
| |
| for layer in self.layers: |
| x = layer(x, masque_causal) |
| |
| x = self.norm(x) |
| logits = self.output_linear(x) |
| |
| return logits |
| |
| |
| # ================================================================= |
| # 1. TÉLÉCHARGEMENT DES FICHIERS DE CONFIGURATION ET DES POIDS |
| # ================================================================= |
| |
| print("Téléchargement des fichiers du dépôt Hugging Face...") |
| |
| # Télécharger les fichiers |
| config_path = hf_hub_download(repo_id=HF_REPO_ID, filename=CONFIG_FILENAME) |
| vocab_path = hf_hub_download(repo_id=HF_REPO_ID, filename=VOCAB_FILENAME) |
| model_weights_path = hf_hub_download(repo_id=HF_REPO_ID, filename=MODEL_FILENAME) |
| |
| # --- Chargement de la Configuration --- |
| with open(config_path, 'r') as f: |
| config = json.load(f) |
| |
| # --- Chargement du Vocabulaire --- |
| with open(vocab_path, 'r') as f: |
| # Le vocabulaire a été sauvegardé comme un mapping ID -> Token (string) |
| id_to_token_str_keys = json.load(f) |
| |
| # Reconstruire le mapping Token -> ID pour l'inférence |
| # Convertir les clés en int |
| id_to_token = {int(k): v for k, v in id_to_token_str_keys.items()} |
| token_to_id = {v: k for k, v in id_to_token.items()} |
| |
| |
| # --- Extraction des paramètres --- |
| VOCAB_SIZE = config['vocab_size'] |
| EMBED_DIM = config['embed_dim'] |
| NUM_HEADS = config['num_heads'] |
| NUM_LAYERS = config['num_layers'] |
| MAX_SEQ_LEN = config['max_seq_len'] |
| D_FF = config['d_ff'] |
| PAD_TOKEN_ID = config['pad_token_id'] |
| |
| # Extraction des tokens spéciaux |
| START_TOKEN = config['special_tokens']['start'] |
| END_TOKEN = config['special_tokens']['end'] |
| SEP_TOKEN = config['special_tokens']['sep'] |
| PAD_TOKEN = config['special_tokens']['pad'] |
| |
| |
| # ================================================================= |
| # 2. INSTANCIATION ET CHARGEMENT DU MODÈLE |
| # ================================================================= |
| |
| # Instanciation du modèle ABX |
| model = ABXModel( |
| vocab_size=VOCAB_SIZE, |
| embed_dim=EMBED_DIM, |
| num_heads=NUM_HEADS, |
| num_layers=NUM_LAYERS, |
| max_seq_len=MAX_SEQ_LEN, |
| d_ff=D_FF, |
| pad_token_id=PAD_TOKEN_ID |
| ).to(DEVICE) |
| |
| # Chargement des poids entraînés |
| model.load_state_dict(torch.load(model_weights_path, map_location=DEVICE)) |
| model.eval() # Toujours passer en mode évaluation pour l'inférence |
| |
| print("\nModèle et configuration chargés avec succès !") |
| |
| # ================================================================= |
| # 3. FONCTION DE GÉNÉRATION (Inférence) |
| # ================================================================= |
| |
| @torch.no_grad() |
| def generer_recitation(model, age: int, temperature: float): |
| """ |
| Génère une récitation de l'alphabet à partir de l'âge et de la température. |
| """ |
| model.eval() |
| |
| # Création du prompt initial |
| prompt_text = f"{START_TOKEN} [AGE:{age}] {SEP_TOKEN}" |
| prompt_tokens = prompt_text.split() |
| |
| # Conversion en IDs |
| input_ids = [token_to_id.get(token, PAD_TOKEN_ID) for token in prompt_tokens] |
| input_tensor = torch.tensor([input_ids], dtype=torch.long, device=DEVICE) |
| output_ids = input_ids[:] |
| |
| # Boucle de génération |
| for _ in range(len(prompt_tokens), MAX_SEQ_LEN): |
| |
| logits = model(input_tensor) |
| next_token_logits = logits[0, -1, :] |
| |
| # Application de la Température (échantillonnage) |
| if temperature <= 0.01: |
| next_token_id = torch.argmax(next_token_logits).item() |
| else: |
| probabilities = F.softmax(next_token_logits / temperature, dim=-1) |
| |
| if torch.isnan(probabilities).any() or probabilities.sum() == 0: |
| next_token_id = torch.argmax(next_token_logits).item() |
| else: |
| next_token_id = torch.multinomial(probabilities, num_samples=1).item() |
| |
| # Condition d'arrêt |
| if id_to_token.get(next_token_id) == END_TOKEN: |
| break |
| |
| output_ids.append(next_token_id) |
| |
| # Mise à jour de la séquence d'entrée |
| next_token_tensor = torch.tensor([[next_token_id]], dtype=torch.long, device=DEVICE) |
| input_tensor = torch.cat([input_tensor, next_token_tensor], dim=1) |
| |
| # Conversion en texte et nettoyage |
| output_text = " ".join([id_to_token.get(id) for id in output_ids]) |
| output_text = output_text.replace(f"{START_TOKEN} [AGE:{age}] {SEP_TOKEN}", "").replace(END_TOKEN, "").replace(PAD_TOKEN, "").strip() |
| |
| return output_text |
| |
| |
| # ================================================================= |
| # 4. EXEMPLES D'UTILISATION POUR L'UTILISATEUR |
| # ================================================================= |
| |
| print("\n" + "="*50) |
| print(" TESTS UTILISATEUR ABX") |
| print("="*50) |
| |
| # Scénario 1: L'enfant ne se concentre pas (Age bas, Température haute) |
| age_test_1 = 2 |
| temp_test_1 = 1.3 |
| result_1 = generer_recitation(model, age_test_1, temp_test_1) |
| print(f"-> Âge: {age_test_1} ans, Température: {temp_test_1} (Distrait)") |
| print(f"Récitation: {result_1}\n") |
| |
| # Scénario 2: L'enfant fait un effort (Age moyen, Température modérée) |
| age_test_2 = 5 |
| temp_test_2 = 0.7 |
| result_2 = generer_recitation(model, age_test_2, temp_test_2) |
| print(f"-> Âge: {age_test_2} ans, Température: {temp_test_2} (Normal)") |
| print(f"Récitation: {result_2}\n") |
| |
| # Scénario 3: L'enfant est très attentif (Age haut, Température basse) |
| age_test_3 = 7 |
| temp_test_3 = 0.1 |
| result_3 = generer_recitation(model, age_test_3, temp_test_3) |
| print(f"-> Âge: {age_test_3} ans, Température: {temp_test_3} (Précis)") |
| print(f"Récitation: {result_3}") |
| ``` |
|
|