TestGrutext / app.py
E-Adam's picture
Update app.py
546e881 verified
import subprocess
import sys
import gradio as gr
import numpy as np
# Installation PyTorch (plus fiable que TensorFlow)
try:
import torch
import torch.nn as nn
import torch.optim as optim
from collections import Counter
print(f"PyTorch {torch.__version__} déjà disponible")
except ImportError:
print("Installation de PyTorch...")
subprocess.check_call([
sys.executable, "-m", "pip", "install",
"torch", "--index-url", "https://download.pytorch.org/whl/cpu"
])
import torch
import torch.nn as nn
import torch.optim as optim
from collections import Counter
print(f"✓ PyTorch {torch.__version__} prêt")
# Tokenizer simple pour remplacer Keras
class SimpleTokenizer:
def __init__(self):
self.word_index = {}
self.index_word = {}
def fit_on_texts(self, texts):
# Compter tous les mots
word_counts = Counter()
for text in texts:
words = text.lower().split()
word_counts.update(words)
# Créer les dictionnaires word <-> index
self.word_index = {word: i+1 for i, (word, _) in enumerate(word_counts.most_common())}
self.index_word = {i+1: word for word, i in self.word_index.items()}
def texts_to_sequences(self, texts):
sequences = []
for text in texts:
words = text.lower().split()
sequence = [self.word_index.get(word, 0) for word in words]
sequences.append(sequence)
return sequences
# Fonction de padding
def pad_sequences(sequences, maxlen, padding='pre'):
padded = []
for seq in sequences:
if len(seq) > maxlen:
if padding == 'pre':
seq = seq[-maxlen:]
else:
seq = seq[:maxlen]
else:
if padding == 'pre':
seq = [0] * (maxlen - len(seq)) + seq
else:
seq = seq + [0] * (maxlen - len(seq))
padded.append(seq)
return np.array(padded)
# Modèle PyTorch équivalent au modèle Keras
class GRUWordPredictor(nn.Module):
def __init__(self, vocab_size, embedding_dim=50, hidden_dim=120, max_seq_len=10):
super(GRUWordPredictor, self).__init__()
self.embedding = nn.Embedding(vocab_size, embedding_dim, padding_idx=0)
self.gru = nn.GRU(embedding_dim, hidden_dim, batch_first=True)
self.fc = nn.Linear(hidden_dim, vocab_size)
self.softmax = nn.Softmax(dim=1)
def forward(self, x):
embedded = self.embedding(x)
gru_out, _ = self.gru(embedded)
# Prendre la dernière sortie de la séquence
output = self.fc(gru_out[:, -1, :])
return self.softmax(output)
# Variables globales
model = None
tokenizer = SimpleTokenizer()
max_sequence_len = 0
textes = [
"la goutte d'eau qui fait déborder le vase",
"Il n'y a pas de fumée sans feu",
"Il faut battre le fer tant qu'il est chaud",
"Il ne faut pas mettre tous ses oeufs dans le même panier",
"Il faut tourner sept fois sa langue dans sa bouche avant de parler",
"L'habit ne fait pas le moine",
"Il ne faut pas réveiller le chat qui dort",
"Il faut se méfier de l'eau qui dort",
"C'est l'hôpital qui se moque de la charité",
"Qui vole un oeuf vole un boeuf",
"Chercher midi à quatorze heures",
"Avoir un poil dans la main",
"Être dans de beaux draps",
"Avoir la tête dans les nuages",
"Mettre les pieds dans le plat"
]
def afficher_liste(liste):
return "\n".join(liste)
def ajouter_a_liste(liste_actuelle, nouveau_texte):
if nouveau_texte:
liste_actuelle.append(nouveau_texte)
return liste_actuelle, ""
def supprimer_de_liste(liste_actuelle, index_a_supprimer):
if index_a_supprimer is not None and 0 <= index_a_supprimer < len(liste_actuelle):
ligne_supprimee = liste_actuelle.pop(index_a_supprimer)
message = f"Ligne supprimée : '{ligne_supprimee}'"
else:
message = "Aucune ligne sélectionnée pour suppression"
return liste_actuelle, liste_actuelle, message
def apprendre(liste_actuelle):
global max_sequence_len, model, tokenizer
print("Liste soumise:", liste_actuelle)
# Analyse du texte
tokenizer.fit_on_texts(liste_actuelle)
total_words = len(tokenizer.word_index) + 1
print("nb de mots différents rencontrés :", total_words)
# Afficher les premiers mots
liste_mots = list(tokenizer.word_index.keys())
print("voici les premiers mots trouvés : ")
for i in range(min(10, len(liste_mots))):
print(f"({i+1}:'{liste_mots[i]}')", end=", ")
print()
# Transformation des textes en séquences
input_sequences = []
for sentence in liste_actuelle:
token_list = tokenizer.texts_to_sequences([sentence])[0]
for i in range(1, len(token_list)):
n_gram_sequence = token_list[:i+1]
input_sequences.append(n_gram_sequence)
# Calibrage des séquences
max_sequence_len = max([len(x) for x in input_sequences])
input_sequences = pad_sequences(input_sequences, maxlen=max_sequence_len, padding='pre')
# Afficher exemple de transformation
if liste_actuelle:
print("la phrase '", liste_actuelle[0], "' est traduite en plusieurs vecteurs :")
split = liste_actuelle[0].lower().split()
for i in range(min(6, len(input_sequences))):
print(input_sequences[i], end=" -> '")
for j in range(min(i+2, len(split))):
print(split[j], end=" ")
print("'")
# Créer X et y
X = input_sequences[:, :-1]
y = input_sequences[:, -1]
# Convertir en tenseurs PyTorch
X_tensor = torch.LongTensor(X)
y_tensor = torch.LongTensor(y)
# Créer le modèle
model = GRUWordPredictor(
vocab_size=total_words,
embedding_dim=50,
hidden_dim=120,
max_seq_len=max_sequence_len-1
)
# Définir la fonction de perte et l'optimiseur
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters())
# Entraînement
print("patienter 30s pendant l'entrainement...")
model.train()
for epoch in range(3000):
optimizer.zero_grad()
outputs = model(X_tensor)
loss = criterion(outputs, y_tensor)
loss.backward()
optimizer.step()
if epoch % 50 == 0:
print(f"Epoch {epoch}, Loss: {loss.item():.4f}")
model.eval() # Mode évaluation
return f"Entrainement effectué, saisissez un début de phrase pour demander la suite"
def predict_next_word(start_text, nb_words):
global model, tokenizer, max_sequence_len
if model is None:
return "Veuillez d'abord entraîner le modèle"
print("===> start_text=", start_text)
print(f"prédictions de {nb_words} mots.")
current_text = start_text.lower()
for _ in range(nb_words):
token_list = tokenizer.texts_to_sequences([current_text])[0]
token_list = pad_sequences([token_list], maxlen=max_sequence_len-1, padding='pre')
print("===> token_list=", token_list)
# Prédiction avec PyTorch
with torch.no_grad():
input_tensor = torch.LongTensor(token_list)
outputs = model(input_tensor)
predicted = torch.argmax(outputs, dim=-1).item()
print("===> predicted=", predicted)
# Trouver le mot correspondant
if predicted in tokenizer.index_word:
word = tokenizer.index_word[predicted]
current_text += " " + word
else:
break # Si pas de mot trouvé, arrêter
print(f"Prediction: {current_text}")
print("-" * 50)
return current_text
# Interface Gradio
with gr.Blocks() as demo:
# ENTETE
gr.Markdown("# Exemple de prévision de mots (PyTorch)")
gr.Markdown("Exemple simple, utilisant un réseau de neurone de type **GRU** avec PyTorch")
gr.Markdown("- Le réseau 'apprend' les phrases de la liste (vous pouvez en ajouter)")
gr.Markdown("- Cliquez sur apprendre si l'apprentissage n'a pas eu lieu")
gr.Markdown("- Donnez plus bas un début de phrase et laissez le réseau en déduire la suite")
# Liste de phrases
with gr.Row():
sortie = gr.Textbox(label="Phrases actuelles", lines=5)
liste = gr.State(textes)
# Ajouter et supprimer des lignes
with gr.Column():
texte = gr.Textbox(label="Nouvelle phrase courte")
btn_add = gr.Button("Ajouter")
# Liste déroulante pour sélectionner une ligne à supprimer
choix_ligne = gr.Dropdown(
choices=textes,
label="Sélectionner une ligne à supprimer",
type="index"
)
btn_supprimer = gr.Button("Supprimer de la liste")
feedback = gr.Textbox(label="Message", lines=1)
# Ajouter une ligne
btn_add.click(
fn=ajouter_a_liste,
inputs=[liste, texte],
outputs=[liste, texte]
).then(
fn=lambda x: "\n".join(x),
inputs=[liste],
outputs=[sortie]
)
# Supprimer une ligne
btn_supprimer.click(
fn=supprimer_de_liste,
inputs=[liste, choix_ligne],
outputs=[liste, choix_ligne, feedback]
).then(
fn=afficher_liste,
inputs=[liste],
outputs=[sortie]
)
# Apprentissage
with gr.Row():
message_apprentissage = gr.Textbox(
label="Résultat de l'apprentissage",
value="Apprentissage non réalisé. Cliquez et attendez > 30s"
)
apprendre_btn = gr.Button("Apprendre")
apprendre_btn.click(
fn=apprendre,
inputs=[liste],
outputs=[message_apprentissage]
)
# Prédiction
with gr.Row():
bout_texte = gr.Textbox(label="Début de phrase ")
with gr.Column():
nb_mots_pred = gr.Slider(
minimum=1,
maximum=6,
value=3,
step=1,
label="Nombre de mots à prédire",
interactive=True
)
btn_suite = gr.Button("Poursuivre")
btn_suite.click(
fn=predict_next_word,
inputs=[bout_texte, nb_mots_pred],
outputs=[bout_texte]
)
if __name__ == "__main__":
demo.launch()