File size: 6,844 Bytes
766250f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
"""
Module pour les IA génératives légères
"""
import numpy as np
from typing import List, Optional
import random
class GenerativeAI:
"""
IA générative légère pour créer des noms et autres contenus
Args:
mode: Mode de génération ('name_generator', 'text_generator')
**kwargs: Paramètres additionnels
Example:
>>> from sitiai import create
>>> ai = create.ai('generative', mode='name_generator')
>>> ai.load_data(['Alice', 'Bob', 'Charlie', 'David'])
>>> ai.train(epochs=100)
>>> new_name = ai.generate()
"""
def __init__(self, mode: str = 'name_generator', **kwargs):
self.mode = mode
self.data = []
self.char_to_idx = {}
self.idx_to_char = {}
self.transition_matrix = None
self.is_trained = False
def load_data(self, data: List[str]):
"""
Charge les données d'entraînement
Args:
data: Liste de chaînes de caractères pour l'entraînement
"""
self.data = [d.lower() for d in data]
# Créer le vocabulaire avec tokens spéciaux
all_chars = set(''.join(self.data))
all_chars.add('^') # Token START
all_chars.add('$') # Token END
self.char_to_idx = {char: idx for idx, char in enumerate(sorted(all_chars))}
self.idx_to_char = {idx: char for char, idx in self.char_to_idx.items()}
def train(self, epochs: int = 100, ngram_size: int = 2):
"""
Entraîne le modèle génératif
Args:
epochs: Nombre d'époques (non utilisé pour les n-grammes, mais conservé pour l'API)
ngram_size: Taille des n-grammes (par défaut 2 = bigrammes)
"""
if not self.data:
raise ValueError("Aucune donnée chargée. Utilisez load_data() d'abord.")
vocab_size = len(self.char_to_idx)
self.transition_matrix = np.zeros((vocab_size, vocab_size))
# Compter les transitions
for word in self.data:
# Ajouter tokens START (^) et END ($)
extended_word = '^' + word + '$'
for i in range(len(extended_word) - 1):
curr_char = extended_word[i]
next_char = extended_word[i + 1]
curr_idx = self.char_to_idx[curr_char]
next_idx = self.char_to_idx[next_char]
self.transition_matrix[curr_idx, next_idx] += 1
# Normaliser pour obtenir des probabilités
row_sums = self.transition_matrix.sum(axis=1, keepdims=True)
row_sums[row_sums == 0] = 1 # Éviter division par zéro
self.transition_matrix = self.transition_matrix / row_sums
self.is_trained = True
def generate(self, max_length: int = 20, temperature: float = 1.0) -> str:
"""
Génère un nouveau nom ou texte
Args:
max_length: Longueur maximale de la génération
temperature: Contrôle la créativité (plus élevé = plus créatif)
Returns:
Texte généré
"""
if not self.is_trained:
raise ValueError("Le modèle n'est pas entraîné. Utilisez train() d'abord.")
# Commencer par START (^)
current_idx = self.char_to_idx['^']
result = []
for _ in range(max_length):
# Obtenir les probabilités pour le prochain caractère
probs = self.transition_matrix[current_idx].copy()
# Appliquer la température
if temperature != 1.0:
probs = np.power(probs, 1.0 / temperature)
probs = probs / probs.sum()
# Échantillonner le prochain caractère
if probs.sum() == 0:
break
next_idx = np.random.choice(len(probs), p=probs)
next_char = self.idx_to_char[next_idx]
# Si on atteint END ($), on s'arrête
if next_char == '$':
break
result.append(next_char)
current_idx = next_idx
return ''.join(result).capitalize()
def generate_batch(self, n: int = 5, max_length: int = 20, temperature: float = 1.0) -> List[str]:
"""
Génère plusieurs résultats
Args:
n: Nombre de générations
max_length: Longueur maximale de chaque génération
temperature: Contrôle la créativité
Returns:
Liste de textes générés
"""
return [self.generate(max_length, temperature) for _ in range(n)]
def save_weights(self, filepath: str):
"""
Sauvegarde le modèle génératif dans un fichier
Args:
filepath: Chemin du fichier de sauvegarde (.npz)
Example:
>>> ai.save_weights('name_generator.npz')
"""
if not filepath.endswith('.npz'):
filepath += '.npz'
if not self.is_trained:
print("⚠️ Attention: Le modèle n'est pas entraîné")
save_data = {
'transition_matrix': self.transition_matrix,
'char_to_idx': np.array(list(self.char_to_idx.items()), dtype=object),
'idx_to_char': np.array(list(self.idx_to_char.items()), dtype=object),
'mode': np.array([self.mode]),
'is_trained': np.array([self.is_trained])
}
np.savez(filepath, **save_data)
print(f"✓ Modèle génératif sauvegardé dans '{filepath}'")
def load_weights(self, filepath: str):
"""
Charge un modèle génératif depuis un fichier
Args:
filepath: Chemin du fichier de sauvegarde (.npz)
Example:
>>> ai = sitiai.create.ai('generative')
>>> ai.load_weights('name_generator.npz')
"""
if not filepath.endswith('.npz'):
filepath += '.npz'
data = np.load(filepath, allow_pickle=True)
self.transition_matrix = data['transition_matrix']
self.char_to_idx = dict(data['char_to_idx'])
self.idx_to_char = {int(k): v for k, v in data['idx_to_char']}
self.mode = str(data['mode'][0])
self.is_trained = bool(data['is_trained'][0])
print(f"✓ Modèle génératif chargé depuis '{filepath}'")
def __repr__(self):
status = "entraîné" if self.is_trained else "non entraîné"
return f"GenerativeAI(mode='{self.mode}', status='{status}')"
|