MisterAI commited on
Commit
001be45
·
verified ·
1 Parent(s): 23c1a94

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +326 -0
app.py ADDED
@@ -0,0 +1,326 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #https://huggingface.co/spaces/MisterAI/GenDoc_05
2
+ #143
3
+
4
+ import os
5
+ import gradio as gr
6
+ from huggingface_hub import hf_hub_download, login
7
+ from transformers import AutoModelForCausalLM, AutoTokenizer
8
+ from pptx import Presentation
9
+ from pptx.util import Inches, Pt
10
+ from pptx.enum.text import PP_ALIGN
11
+ import torch
12
+ from llama_cpp import Llama
13
+ import time
14
+
15
+ # [Configuration des modèles et PREPROMPT restent identiques à C141]
16
+ TEXT_MODELS = {
17
+ "Mistral Nemo 2407 (GGUF)": "MisterAI/Bartowski_MistralAI_Mistral-Nemo-Instruct-2407-IQ4_XS.gguf",
18
+ "Mixtral 8x7B": "mistralai/Mixtral-8x7B-v0.1",
19
+ "Lucie 7B": "OpenLLM-France/Lucie-7B"
20
+ }
21
+
22
+ PREPROMPT = """Vous êtes un assistant IA expert en création de présentations PowerPoint professionnelles.
23
+ Générez une présentation structurée et détaillée en suivant ce format EXACT:
24
+
25
+ TITRE: [Titre principal de la présentation]
26
+
27
+ DIAPO 1:
28
+ Titre: [Titre de la diapo]
29
+ Points:
30
+ - Point 1
31
+ - Point 2
32
+ - Point 3
33
+
34
+ DIAPO 2:
35
+ Titre: [Titre de la diapo]
36
+ Points:
37
+ - Point 1
38
+ - Point 2
39
+ - Point 3
40
+
41
+ [Continuez avec ce format pour chaque diapositive]
42
+
43
+ Analysez le texte suivant et créez une présentation professionnelle :"""
44
+
45
+ class PresentationGenerator:
46
+ def __init__(self):
47
+ self.token = os.getenv('Authentification_HF')
48
+ if not self.token:
49
+ raise ValueError("Token d'authentification HuggingFace non trouvé")
50
+ login(self.token)
51
+ self.text_model = None
52
+ self.text_tokenizer = None
53
+
54
+ def load_text_model(self, model_name):
55
+ """Charge le modèle de génération de texte"""
56
+ model_id = TEXT_MODELS[model_name]
57
+ if model_id.endswith('.gguf'):
58
+ model_path = hf_hub_download(
59
+ repo_id=model_id.split('/')[0] + '/' + model_id.split('/')[1],
60
+ filename=model_id.split('/')[-1],
61
+ token=self.token
62
+ )
63
+ self.text_model = Llama(
64
+ model_path=model_path,
65
+ n_ctx=4096,
66
+ n_batch=512,
67
+ verbose=False
68
+ )
69
+ print(f"Modèle GGUF {model_id} chargé avec succès!")
70
+ else:
71
+ self.text_tokenizer = AutoTokenizer.from_pretrained(model_id, token=self.token)
72
+ self.text_model = AutoModelForCausalLM.from_pretrained(
73
+ model_id,
74
+ torch_dtype=torch.bfloat16,
75
+ device_map="auto",
76
+ token=self.token
77
+ )
78
+ print(f"Modèle Transformers {model_id} chargé avec succès!")
79
+
80
+ def generate_text(self, prompt, temperature=0.7, max_tokens=4096):
81
+ """Génère le texte de la présentation"""
82
+ if isinstance(self.text_model, Llama):
83
+ response = self.text_model(
84
+ prompt,
85
+ max_tokens=max_tokens,
86
+ temperature=temperature,
87
+ echo=False
88
+ )
89
+ print("Texte généré par Llama :", response['choices'][0]['text'])
90
+ return response['choices'][0]['text']
91
+ else:
92
+ inputs = self.text_tokenizer.apply_chat_template(
93
+ [{"role": "user", "content": prompt}],
94
+ return_tensors="pt",
95
+ return_dict=True
96
+ )
97
+ outputs = self.text_model.generate(
98
+ **inputs,
99
+ max_new_tokens=max_tokens,
100
+ temperature=temperature
101
+ )
102
+ generated_text = self.text_tokenizer.decode(outputs[0], skip_special_tokens=True)
103
+ print("Texte généré par Transformers :", generated_text)
104
+ return generated_text
105
+
106
+ def parse_presentation_content(self, content):
107
+ """Parse le contenu généré en sections pour les diapositives"""
108
+ slides = []
109
+ current_slide = None
110
+
111
+ for line in content.split('\n'):
112
+ line = line.strip()
113
+ print(f"#LOG supplémentaire: Parsing line: {line}") # LOG supplémentaire
114
+ if line.startswith('TITRE:'):
115
+ slides.append({'type': 'title', 'title': line[6:].strip()})
116
+ elif line.startswith('DIAPO'):
117
+ if current_slide:
118
+ slides.append(current_slide)
119
+ current_slide = {'type': 'content', 'title': '', 'points': []}
120
+ elif line.startswith('Titre:') and current_slide:
121
+ current_slide['title'] = line[6:].strip()
122
+ elif line.startswith('- ') and current_slide:
123
+ current_slide['points'].append(line[2:].strip())
124
+
125
+ if current_slide:
126
+ slides.append(current_slide)
127
+
128
+ print(f"#LOG supplémentaire: Parsed slides: {slides}") # LOG supplémentaire
129
+ return slides
130
+
131
+ def create_presentation(self, slides):
132
+ """Crée la présentation PowerPoint avec texte uniquement"""
133
+ prs = Presentation()
134
+
135
+ # Première diapo (titre)
136
+ title_slide = prs.slides.add_slide(prs.slide_layouts[0])
137
+ title_slide.shapes.title.text = slides[0]['title']
138
+
139
+ # Autres diapos
140
+ for slide in slides[1:]:
141
+ content_slide = prs.slides.add_slide(prs.slide_layouts[1])
142
+ content_slide.shapes.title.text = slide['title']
143
+
144
+ # Ajout du texte
145
+ if slide['points']:
146
+ body = content_slide.shapes.placeholders[1].text_frame
147
+ body.clear()
148
+ for point in slide['points']:
149
+ p = body.add_paragraph()
150
+ p.text = point
151
+ p.level = 0
152
+
153
+ return prs
154
+
155
+ def generate_presentation_with_progress(text, text_model_name, temperature, max_tokens):
156
+ """Fonction principale de génération avec suivi de progression"""
157
+ try:
158
+ start_time = time.time()
159
+ generator = PresentationGenerator()
160
+
161
+ # Chargement du modèle de texte uniquement
162
+ yield "Chargement du modèle...", None, None
163
+ generator.load_text_model(text_model_name)
164
+
165
+ # Génération du contenu
166
+ yield "Génération du contenu de la présentation...", None, None
167
+ full_prompt = PREPROMPT + "\n\n" + text
168
+ generated_content = generator.generate_text(full_prompt, temperature, max_tokens)
169
+
170
+ # Création de la présentation
171
+ yield "Création de la présentation PowerPoint...", generated_content, None
172
+ slides = generator.parse_presentation_content(generated_content)
173
+ prs = generator.create_presentation(slides)
174
+
175
+ # Sauvegarde avec chemin absolu
176
+ output_path = os.path.abspath("presentation.pptx")
177
+ prs.save(output_path)
178
+
179
+ # Vérification que le fichier existe
180
+ if not os.path.exists(output_path):
181
+ raise FileNotFoundError(f"Le fichier {output_path} n'a pas été créé correctement")
182
+
183
+ execution_time = time.time() - start_time
184
+ status = f"Présentation générée avec succès en {execution_time:.2f} secondes!"
185
+
186
+ # Retourne le statut, le contenu généré et le fichier
187
+ return status, generated_content, (output_path, "presentation.pptx")
188
+
189
+ except Exception as e:
190
+ print(f"Erreur lors de la génération: {str(e)}")
191
+ return f"Erreur: {str(e)}", None, None
192
+
193
+ # [Le reste du code (CSS et interface Gradio) reste identique à C141]
194
+ css = """
195
+ /* Thème sombre personnalisé */
196
+ .gradio-container {
197
+ background-color: #000000 !important;
198
+ color: #ffffff !important;
199
+ }
200
+
201
+ .gr-form, .gr-box, .gr-panel {
202
+ border-radius: 8px !important;
203
+ background-color: #1a1a1a !important;
204
+ border: 1px solid #333333 !important;
205
+ color: #ffffff !important;
206
+ }
207
+
208
+ .gr-input, .gr-textarea, .gr-dropdown {
209
+ background-color: #2d2d2d !important;
210
+ color: #ffffff !important;
211
+ border: 1px solid #404040 !important;
212
+ }
213
+
214
+ .gr-button {
215
+ background-color: #2d2d2d !important;
216
+ color: #ffffff !important;
217
+ border: 1px solid #404040 !important;
218
+ transition: all 0.3s ease !important;
219
+ }
220
+
221
+ .gr-button:hover {
222
+ background-color: #404040 !important;
223
+ transform: translateY(-2px) !important;
224
+ }
225
+
226
+ /* Textes et labels */
227
+ h1, h2, h3, p, label, .gr-text {
228
+ color: #ffffff !important;
229
+ }
230
+
231
+ /* Scrollbar */
232
+ ::-webkit-scrollbar {
233
+ width: 8px;
234
+ height: 8px;
235
+ }
236
+
237
+ ::-webkit-scrollbar-track {
238
+ background: #1a1a1a;
239
+ }
240
+
241
+ ::-webkit-scrollbar-thumb {
242
+ background: #404040;
243
+ border-radius: 4px;
244
+ }
245
+
246
+ ::-webkit-scrollbar-thumb:hover {
247
+ background: #4a4a4a;
248
+ }
249
+ """
250
+
251
+ with gr.Blocks(theme=gr.themes.Default(), css=css) as demo:
252
+ gr.Markdown(
253
+ """
254
+ # 🎯 Générateur de Présentations PowerPoint IA
255
+
256
+ Créez des présentations professionnelles automatiquement avec l'aide de l'IA.
257
+ """
258
+ )
259
+
260
+ with gr.Row():
261
+ with gr.Column(scale=1):
262
+ text_model_choice = gr.Dropdown(
263
+ choices=list(TEXT_MODELS.keys()),
264
+ value=list(TEXT_MODELS.keys())[0],
265
+ label="Modèle de génération de texte"
266
+ )
267
+ temperature = gr.Slider(
268
+ minimum=0.1,
269
+ maximum=1.0,
270
+ value=0.7,
271
+ step=0.1,
272
+ label="Température"
273
+ )
274
+ max_tokens = gr.Slider(
275
+ minimum=1000,
276
+ maximum=4096,
277
+ value=2048,
278
+ step=256,
279
+ label="Tokens maximum"
280
+ )
281
+
282
+ with gr.Row():
283
+ with gr.Column(scale=2):
284
+ input_text = gr.Textbox(
285
+ lines=10,
286
+ label="Votre texte",
287
+ placeholder="Décrivez le contenu que vous souhaitez pour votre présentation..."
288
+ )
289
+
290
+ with gr.Row():
291
+ generate_btn = gr.Button("🚀 Générer la présentation", variant="primary")
292
+
293
+ with gr.Row():
294
+ with gr.Column():
295
+ status_output = gr.Textbox(
296
+ label="Statut",
297
+ lines=2
298
+ )
299
+ generated_content = gr.Textbox(
300
+ label="Contenu généré",
301
+ lines=10,
302
+ show_copy_button=True
303
+ )
304
+ output_file = gr.File(
305
+ label="Présentation PowerPoint"
306
+ )
307
+
308
+ generate_btn.click(
309
+ fn=generate_presentation_with_progress,
310
+ inputs=[
311
+ input_text,
312
+ text_model_choice,
313
+ temperature,
314
+ max_tokens
315
+ ],
316
+ outputs=[
317
+ status_output,
318
+ generated_content,
319
+ output_file
320
+ ]
321
+ )
322
+
323
+ if __name__ == "__main__":
324
+ demo.launch()
325
+
326
+