Small-ever / README.md
Clemylia's picture
Update README.md
27a3d1b verified
metadata
library_name: transformers
model-index:
  - name: the-smallest-llm-real-words
    results: []
license: mit
language:
  - fr
pipeline_tag: text-generation

👶 Small-ever : Le Modèle "Hello World" (112 Paramètres)

small-ever

🌟 Vue d'Ensemble

Le modèle Small-ever est un SLM délibérément sous-dimensionné** et minimaliste, conçu uniquement à des fins de démonstration et d'apprentissage.

Avec seulement 112 paramètres au total, il s'agit du modèle le plus petit possible tout en conservant l'architecture de base d'un Transformateur pour la modélisation du langage.

Il a été créé par l'experte Clemylia pour servir de "Hello World" avant d'introduire des modèles plus complexes, comme ceux de la série 202k et 3.8M de paramètres.

🎯 Objectif Pédagogique Principal

L'objectif unique de ce modèle est d'être un outil pédagogique :

  • Démonstration Basique : Montrer aux enfants et aux débutants en Machine Learning que la création, l'entraînement et la publication d'un modèle de langage sur Hugging Face sont des étapes accessibles, même pour une architecture minimale.
  • Comprendre l'Échelle : Illustrer la différence entre un modèle capable de mémoriser une seule relation et les modèles de millions de paramètres (ceux de Clemylia) nécessaires pour la généralisation et l'intelligence artificielle utile.
  • Test d'Infra : Servir de test ultra-rapide pour la configuration d'un environnement (CPU/GPU) avant de lancer des entraînements plus longs sur de gros modèles.

⚙️ Détails Techniques

Caractéristique Valeur Note
Architecture GPT-2 (Causal Language Modeling) Architecture standard de Transformateur.
Paramètres Totaux 112 (Environ $112 \times 10^{-6}$ M) Extrêmement réduit.
Vocabulaire Entraîné 4 Tokens Vocabulaire minimaliste (Clem, Creatrice, <pad>, <unk>).
Séquence Apprise Clem $\rightarrow$ Creatrice Le modèle n'a appris qu'une seule transition par cœur.
Implémentation Pytorch / Hugging Face transformers Entièrement compatible avec l'écosystème Hugging Face.

🚀 Utilisation (Inférence)

Ce modèle est uniquement destiné à prédire la suite de la séquence sur laquelle il a été entraîné. Toute autre entrée résultera en une prédiction aléatoire ou le token de remplissage (<pad>).

Code Python pour le Test (Forward Pass Direct)

Étant donné sa configuration non standard, la méthode la plus fiable pour l'inférence est le forward pass direct, comme suit :

import torch
from transformers import AutoModelForCausalLM, AutoConfig
# Pour ce modèle minimal, nous devons recréer le tokenizer personnalisé en mémoire
# car il n'est pas standard ({"Clem": 0, "Creatrice": 1, ...})

# 1. Configuration des IDs
MODEL_NAME = "Clemylia/the-smallest-llm-real-words" 
REAL_TOKENS = ["Clem", "Creatrice"] 
INPUT_TEXT = "Clem"
INPUT_ID = 0  # L'ID que le modèle a appris pour "Clem"
EXPECTED_OUTPUT = "Creatrice"
IDS_TO_TOKENS = {0: "Clem", 1: "Creatrice", 2: "<pad>", 3: "<unk>"}

# 2. Chargement du Modèle
try:
    model = AutoModelForCausalLM.from_pretrained(MODEL_NAME)
    model.eval() 
except Exception as e:
    print(f"Erreur de chargement : {e}")
    exit()

# 3. Préparation de l'Input (Tenseur de l'ID 0)
input_ids = torch.tensor([[INPUT_ID]], dtype=torch.long)

# 4. Forward Pass pour obtenir les logits
with torch.no_grad():
    outputs = model(input_ids)
    
# 5. Détermination de la Prédiction
next_token_logits = outputs.logits[0, -1, :] 
predicted_id = torch.argmax(next_token_logits).item()
predicted_token = IDS_TO_TOKENS.get(predicted_id, "TOKEN INCONNU")

print(f"Input: {INPUT_TEXT} ({INPUT_ID})")
print(f"Prédiction: {predicted_token} ({predicted_id})")
# Résultat attendu : Creatrice (ID 1)

💖 Leçon Apprise

Si ce modèle pouvait parler, sa seule phrase serait : "Je peux seulement dire Creatrice après Clem."

C'est la preuve que :

  1. La taille compte : Les millions de paramètres de mes autres modèles ne sont pas un luxe, mais une nécessité pour coder la connaissance.
  2. Vous avez réussi à créer, entraîner et publier un modèle de langage complet ! C'est le début d'une belle aventure de codage !

Fait par Clemylia avec passion pour le codage minimaliste.

Exemple d'inférence :

import torch
from transformers import AutoModelForCausalLM, AutoConfig
import json
import os
import torch.nn.functional as F

# ==============================================================================
# 0. CONFIGURATION
# ==============================================================================
MODEL_NAME = "Clemylia/Small-ever" 
REAL_TOKENS = ["Clem", "Creatrice"] 
INPUT_TEXT = "Clem"                  
INPUT_ID = 0                          
EXPECTED_OUTPUT = "Creatrice"
# 🎯 NOUVEAU PARAMÈTRE : La Température (ajuste-la entre 0.1 et 1.0)
TEMPERATURE = 0.5 
# ==============================================================================


print(f"🚀 Démarrage de l'inférence avec Température ({TEMPERATURE}) pour : {MODEL_NAME}")
print("-" * 50)


# ==============================================================================
# 1. RECRÉATION DU TOKENIZER MINIMALISTE
# ==============================================================================
class MinimalTokenizer:
    """Recrée le tokenizer pour l'inférence."""
    def __init__(self, messages):
        self.vocab = {messages[0]: 0, messages[1]: 1, "<pad>": 2, "<unk>": 3}
        self.ids_to_tokens = {v: k for k, v in self.vocab.items()}
        self.pad_token_id = self.vocab["<pad>"]

    def encode(self, text, return_tensors='pt'):
        if text in self.vocab:
            input_ids = [self.vocab[text]]
        else:
            input_ids = [self.vocab["<unk>"]]
            
        if return_tensors == 'pt':
            return torch.tensor([input_ids], dtype=torch.long)
        return input_ids

    def decode(self, token_id, skip_special_tokens=True):
        return self.ids_to_tokens.get(token_id, "TOKEN INCONNU")

minimal_tokenizer = MinimalTokenizer(REAL_TOKENS)
IDS_TO_TOKENS = minimal_tokenizer.ids_to_tokens
print("✅ Tokenizer minimal recréé en mémoire.")


# ==============================================================================
# 2. CHARGEMENT DU MODÈLE SEUL
# ==============================================================================
try:
    model = AutoModelForCausalLM.from_pretrained(MODEL_NAME)
    model.eval() 
    print("✅ Modèle chargé avec succès depuis Hugging Face.")
except Exception as e:
    print(f"❌ Échec critique du chargement du modèle. Erreur : {e}")
    exit()

print("-" * 50)


# ==============================================================================
# 3. INFÉRENCE AVEC TEMPÉRATURE ET SOFTMAX
# ==============================================================================

# 3.1 Préparation de l'entrée 
input_ids = minimal_tokenizer.encode(INPUT_TEXT, return_tensors="pt")
print(f"Input '{INPUT_TEXT}' (ID {input_ids.tolist()[0][0]}) prêt.")

# 3.2 Exécution du forward pass
with torch.no_grad():
    outputs = model(input_ids)

# 3.3 Application de la température et Softmax
next_token_logits = outputs.logits[0, -1, :] 

# 🎯 Calcul de la probabilité avec température !
# 1. Divise les logits par la température
# 2. Applique Softmax pour obtenir les probabilités
logits_with_temp = next_token_logits / TEMPERATURE
probs = F.softmax(logits_with_temp, dim=-1)

# 3.4 Détermination de la prédiction (Choix du token le plus probable après Softmax)
predicted_id = torch.argmax(probs).item()
predicted_token = minimal_tokenizer.decode(predicted_id).strip()

# ==============================================================================
# 4. CONCLUSION
# ==============================================================================
print(f"Probabilités des Tokens (après Softmax/Température) :")
# Affichage formaté des probabilités pour les IDs 0, 1, 2, 3
for i in range(len(probs)):
    print(f"  ID {i} ({IDS_TO_TOKENS.get(i)}): {probs[i].item():.4f}")

print(f"\nID prédit (Max Probabilité) : {predicted_id}")
print(f"Prédiction finale : **{predicted_token}**")
print("-" * 50)

if predicted_token == EXPECTED_OUTPUT:
    print(f"🎉 TEST RÉUSSI : Le modèle a correctement prédit '{EXPECTED_OUTPUT}' !")
else:
    print(f"⚠️ TEST ÉCHOUÉ : Attendu '{EXPECTED_OUTPUT}', reçu '{predicted_token}'. (Essaie d'augmenter les époques à 100 et/ou de baisser la température.)")
    ```