File size: 13,018 Bytes
3f2b9aa
 
 
fe5ed62
3f2b9aa
 
 
 
 
4b6f6a3
 
4daf054
3f2b9aa
 
 
 
 
 
 
 
 
 
 
 
 
370dfdb
3f2b9aa
 
 
 
 
 
 
370dfdb
 
 
 
 
 
 
 
 
3f2b9aa
 
 
 
 
 
 
 
 
 
 
 
 
370dfdb
3f2b9aa
 
370dfdb
3f2b9aa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
370dfdb
 
 
3f2b9aa
370dfdb
db60512
3f2b9aa
5035131
3f2b9aa
 
 
 
370dfdb
3f2b9aa
 
 
5035131
3f2b9aa
370dfdb
3f2b9aa
5035131
3f2b9aa
62795e2
e43362d
3f2b9aa
e43362d
3f2b9aa
5035131
3f2b9aa
 
 
 
5b1a214
3f2b9aa
 
 
 
 
 
5035131
3f2b9aa
 
 
 
 
 
 
 
 
 
 
 
 
a9e161a
3f2b9aa
 
 
a9e161a
3f2b9aa
 
7bf4c43
370dfdb
 
3f2b9aa
 
7bf4c43
3f2b9aa
 
7bf4c43
3f2b9aa
 
 
 
 
 
 
a9e161a
3f2b9aa
a9e161a
3f2b9aa
a9e161a
3f2b9aa
4daf054
3f2b9aa
4daf054
3f2b9aa
a9e161a
3f2b9aa
a9e161a
3f2b9aa
4daf054
3f2b9aa
4daf054
3f2b9aa
a9e161a
3f2b9aa
a9e161a
3f2b9aa
a9e161a
3f2b9aa
a9e161a
3f2b9aa
a9e161a
3f2b9aa
a9e161a
3f2b9aa
a9e161a
370dfdb
a9e161a
370dfdb
a9e161a
3f2b9aa
a9e161a
3f2b9aa
a9e161a
3f2b9aa
370dfdb
3f2b9aa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5035131
3f2b9aa
 
 
 
 
12749e6
 
 
3f2b9aa
 
 
 
 
12749e6
 
3f2b9aa
 
 
 
 
 
 
 
 
 
 
db60512
 
370dfdb
db60512
3f2b9aa
 
 
 
 
 
 
 
 
 
 
 
 
370dfdb
3f2b9aa
 
 
 
4b6f6a3
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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
import gradio as gr
import torch
import pandas as pd
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM, T5Tokenizer, T5ForConditionalGeneration
import numpy as np
import networkx as nx
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import sent_tokenize, word_tokenize
nltk.download('punkt')
nltk.download('stopwords')
nltk.download('punkt_tab')
import string

# Importations spécifiques à Sumy
from sumy.parsers.plaintext import PlaintextParser
from sumy.nlp.tokenizers import Tokenizer
from sumy.summarizers.lsa import LsaSummarizer
from sumy.summarizers.text_rank import TextRankSummarizer
from sumy.nlp.stemmers import Stemmer
from sumy.utils import get_stop_words

# --- Variables globales et chargement des modèles (mis en cache) ---
# Les modèles sont chargés une seule fois lorsque l'application démarre
def load_models():
    """Charge les tokenizers et les modèles T5 et MBart."""
    print("Initialisation de l'application et vérification des ressources...")
    
    # Définir le périphérique
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    print(f"Périphérique utilisé : {device}")

    # --- MT5 ---
    t5_model_name = 't5-large'
    print(f"Chargement du tokenizer T5 ({t5_model_name})...")
    t5_tokenizer = AutoTokenizer.from_pretrained(t5_model_name, use_fast=False)
    print("Tokenizer T5 chargé.")

    print(f"Chargement du modèle T5 ({t5_model_name})...")
    t5_model = T5ForConditionalGeneration.from_pretrained(t5_model_name, return_dict=True)
    t5_model.to(device)
    print("Modèle T5 chargé.")
    
    # --- MBart ---
    mbart_model_name = 'facebook/mbart-large-50'
    print(f"Chargement du tokenizer MBart ({mbart_model_name})...")
    mbart_tokenizer = AutoTokenizer.from_pretrained(mbart_model_name)
    print("Tokenizer MBart chargé.")

    print(f"Chargement du modèle MBart ({mbart_model_name})...")
    mbart_model = AutoModelForSeq2SeqLM.from_pretrained(mbart_model_name, return_dict=True)
    mbart_model.to(device)
    print("Modèle MBart chargé.")
    
    print("Tous les modèles et ressources sont chargés avec succès ! L'application est prête.")
    return t5_tokenizer, t5_model, mbart_tokenizer, mbart_model, device

# Charger les modèles une seule fois au démarrage de l'application
t5_tokenizer, t5_model, mbart_tokenizer, mbart_model, device = load_models()

# --- Fonctions de résumé ---

def summarize_lsa(text, num_sentences=3):
    """Génère un résumé extractif en utilisant LSA de Sumy."""
    if not text.strip():
        return "Article trop court ou vide pour LSA."

    parser = PlaintextParser.from_string(text, Tokenizer("french"))
    stemmer = Stemmer("french")
    
    summarizer = LsaSummarizer(stemmer)
    summarizer.stop_words = get_stop_words("french")

    summary_sentences = summarizer(parser.document, num_sentences)
    
    return " ".join([str(sentence) for sentence in summary_sentences])

def summarize_textrank(text, num_sentences=3):
    """Génère un résumé extractif en utilisant TextRank de Sumy."""
    if not text.strip():
        return "Article trop court ou vide pour TextRank."

    parser = PlaintextParser.from_string(text, Tokenizer("french"))
    stemmer = Stemmer("french")
    
    summarizer = TextRankSummarizer(stemmer)
    summarizer.stop_words = get_stop_words("french")

    summary_sentences = summarizer(parser.document, num_sentences)
    
    return " ".join([str(sentence) for sentence in summary_sentences])

def summarize_t5(text, min_length=200, max_length=350):
    """Génère un résumé abstractif en utilisant T5."""
    prefixed_text = f"resumer en francais: {text}"
    
    inputs = t5_tokenizer(
        prefixed_text,
        return_tensors='pt',
        max_length=max_length,
        truncation=True,
        padding=True
    ).to(device)

    output_sequences = t5_model.generate(
        input_ids=inputs['input_ids'],
        attention_mask=inputs['attention_mask'],
        min_length=min_length,
        max_length=max_length
    )
    return t5_tokenizer.decode(output_sequences[0], skip_special_tokens=True)

def summarize_mbart(text, min_length=200, max_length=350):
    """Génère un résumé abstractif en utilisant mBART."""

    #prefixed_text = f"résumer en français: {text}"
    inputs = mbart_tokenizer(
        text,
        return_tensors='pt',
        max_length=max_length,
        truncation=True,
        padding=True
    ).to(device)

    FRENCH_LANGUAGE_TOKEN_ID = mbart_tokenizer.lang_code_to_id["fr_XX"]

    output_sequences = mbart_model.generate(
        input_ids=inputs['input_ids'],
        attention_mask=inputs['attention_mask'],
        min_length=min_length,
        max_length=max_length,
        forced_bos_token_id=FRENCH_LANGUAGE_TOKEN_ID
    )
    return mbart_tokenizer.decode(output_sequences[0], skip_special_tokens=True)

# --- Fonction principale pour la page de résumé ---
def generate_all_summaries(article_input, num_sentences, min_summary_len, max_summary_len):
    """Génère les résumés pour tous les algorithmes et met à jour la progression."""
    if not article_input:
        return "Veuillez entrer un article pour générer les résumés.", "", "", ""

    # Utilisation de yield pour les mises à jour de progression dans Gradio
    # Gradio affichera automatiquement une barre de progression pour les fonctions qui yield
    
    # LSA
    yield "Génération du résumé LSA...", "", "", "",""
    lsa_summary = summarize_lsa(article_input, num_sentences)
    
    # TextRank
    yield "Génération du résumé TextRank...", lsa_summary, "", "",""
    textrank_summary = summarize_textrank(article_input, num_sentences)
    
    # T5
    yield "Génération du résumé T5...", lsa_summary, textrank_summary, "",""
    t5_summary = summarize_t5(article_input, min_summary_len, max_summary_len)
    
    # MBart
    yield "Génération du résumé MBart...", lsa_summary, textrank_summary, t5_summary,""
    mbart_summary = summarize_mbart(article_input, min_summary_len, max_summary_len)
    
    yield "Résumés terminés !", lsa_summary, textrank_summary, t5_summary, mbart_summary


# --- Contenu de la page d'explications (Markdown) ---
explanations_markdown = """
# Comprendre les Méthodes de Résumé de Texte
---
## Méthodes Extractives vs. Abstractives

Il existe deux grandes catégories de méthodes pour résumer du texte :

### 1. Méthodes Extractives

Ces méthodes fonctionnent en **sélectionnant des phrases ou des passages clés** directement à partir du texte original et en les assemblant pour former le résumé. Elles ne génèrent pas de nouvelles phrases ou de nouveaux mots.

**Avantages :** Les résumés sont garantis d'être grammaticalement corrects et fidèles au texte source.

**Inconvénients :** Ils peuvent manquer de fluidité ou de cohérence, car les phrases sont simplement juxtaposées, et ils peuvent inclure des informations redondantes.

### 2. Méthodes Abstractives

Ces méthodes **génèrent de nouvelles phrases** qui capturent le sens du texte original, de manière similaire à la façon dont un humain écrirait un résumé. Elles peuvent paraphraser, condenser et même introduire des mots qui n'étaient pas présents dans le texte source.

**Avantages :** Les résumés sont plus fluides, plus concis et plus cohérents.

**Inconvénients :** Elles sont plus complexes à développer et peuvent parfois générer des informations incorrectes ou des 'hallucinations' (informations non présentes dans le texte original).

---

## Principes des Algorithmes Spécifiques

### LSA (Latent Semantic Analysis) - Extractif

LSA est une technique qui utilise l'algèbre linéaire pour identifier les relations entre les termes et les documents. Pour le résumé, LSA crée une représentation numérique du texte où les phrases sont des points dans un espace multidimensionnel. Il utilise la **Décomposition en Valeurs Singulières (SVD)** pour réduire la dimensionnalité et identifier les concepts latents (thèmes) dans le texte. Les phrases qui sont les plus représentatives de ces concepts latents sont sélectionnées pour former le résumé.

### TextRank - Extractif

TextRank est un algorithme basé sur le célèbre algorithme PageRank de Google, utilisé pour classer l'importance des pages web. Pour le résumé, TextRank construit un **graphe** où chaque **phrase** du texte est un **nœud**. Les **liens (arêtes)** entre les phrases sont basés sur leur **similarité sémantique** (par exemple, le nombre de mots partagés ou la similarité cosinus des vecteurs de mots). L'algorithme parcourt ensuite ce graphe pour attribuer un score d'importance à chaque phrase. Les phrases avec les scores les plus élevés sont choisies pour le résumé.

### T5 (Text-to-Text Transfer Transformer) - Abstractif

T5 est un modèle de langage développé par Google, dont le principe est de traiter toutes les tâches de traitement du langage naturel (NLP) comme des problèmes de "texte-à-texte". Cela signifie que pour n'importe quelle tâche (résumé, traduction, question-réponse), l'entrée et la sortie du modèle sont toujours du texte. Pour réaliser un résumé, on fournit à T5 le texte original avec un préfixe spécifique, comme 'summarize: '. Le modèle va ensuite générer un nouveau texte qui représente le résumé. Ce résumé n'est pas une simple extraction de phrases existantes, mais une nouvelle formulation des informations clés, ce qui en fait une méthode abstractive.

### MBart (Multilingual BART) - Abstractif

MBart est un modèle de séquence-à-séquence (encoder-decoder) pré-entraîné sur un grand corpus multilingue. Il est particulièrement adapté aux tâches de **traduction** et de **génération de texte multilingues**. Pour le résumé, MBart apprend à reconstruire le texte original tout en le compressant. Pour forcer la génération dans une langue spécifique (comme le français), on utilise un **token de début de séquence (BOS)** spécifique à la langue cible lors de la génération. Cela lui indique de commencer à générer le résumé en français, quelle que soit la langue de l'article d'entrée.

---
*Les modèles abstractifs (T5, MBart) nécessitent généralement plus de ressources de calcul (GPU) que les méthodes extractives (LSA, TextRank).*
"""

# --- Interface Gradio ---
with gr.Blocks(title="Application de Résumé d'Articles") as demo:
    gr.Markdown("# Application de Résumé de Texte")

    with gr.Tabs() as tabs:
        with gr.TabItem("Explications", id="explanations_tab"):
            gr.Markdown(explanations_markdown)

        with gr.TabItem("Outil de Résumé", id="summarization_tool_tab"):
            gr.Markdown("## Outil de Résumé de Texte")
            gr.Markdown("---")

            article_input = gr.Textbox(
                label="Article à résumer",
                lines=10,
                placeholder="Collez votre article ici. Les modèles abstractifs peuvent résumer des articles multilingues en français."
            )

            num_sentences_slider = gr.Slider(
                minimum=1,
                maximum=10,
                value=5,
                step=1,
                label="Nombre de phrases pour les résumés extractifs (LSA, TextRank)"
            )
            
            min_summary_len_slider = gr.Slider(
                minimum=100,
                maximum=300,
                value=200,
                step=1,
                label="Longueur minimale du résumé (tokens) pour les modèles abstractifs"
            )
            max_summary_len_slider = gr.Slider(
                minimum=50,
                maximum=600,
                value=350,
                step=1,
                label="Longueur maximale du résumé (tokens) pour les modèles abstractifs"
            )

            generate_button = gr.Button("Générer les résumés")

            status_output = gr.Textbox(label="Statut", interactive=False)
            
            gr.Markdown("---")
            gr.Markdown("### Résultats des Résumés")

            lsa_output = gr.Textbox(label="Résumé LSA", interactive=False, lines=10)
            textrank_output = gr.Textbox(label="Résumé TextRank", interactive=False, lines=10)
            t5_output = gr.Textbox(label="Résumé T5", interactive=False, lines=10)
            mbart_output = gr.Textbox(label="Résumé MBart", interactive=False, lines=10)

            generate_button.click(
                fn=generate_all_summaries,
                inputs=[
                    article_input,
                    num_sentences_slider,
                    min_summary_len_slider,
                    max_summary_len_slider
                ],
                outputs=[
                    status_output,
                    lsa_output,
                    textrank_output,
                    t5_output,
                    mbart_output
                ]
            )

demo.launch()