MisterAI commited on
Commit
a89c810
·
verified ·
1 Parent(s): 44c2395

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +144 -36
app.py CHANGED
@@ -3,7 +3,6 @@
3
 
4
 
5
 
6
- # [Imports et configuration des modèles restent identiques]
7
  import os
8
  import gradio as gr
9
  from huggingface_hub import hf_hub_download, login
@@ -14,7 +13,7 @@ import torch
14
  from llama_cpp import Llama
15
  import time
16
 
17
- # Configuration des modèles et PREPROMPT [inchangés]
18
  TEXT_MODELS = {
19
  "Utter-Project_EuroLLM-1.7B": "utter-project/EuroLLM-1.7B",
20
  "Mistral Nemo 2407 (GGUF)": "MisterAI/Bartowski_MistralAI_Mistral-Nemo-Instruct-2407-IQ4_XS.gguf",
@@ -23,7 +22,7 @@ TEXT_MODELS = {
23
  }
24
 
25
  PREPROMPT = """Vous êtes un assistant IA expert en création de présentations PowerPoint professionnelles.
26
- Générez une présentation structurée et détaillée en suivant ce format EXACT:
27
 
28
  TITRE: [Titre principal de la présentation]
29
 
@@ -45,31 +44,147 @@ Points:
45
 
46
  Analysez le texte suivant et créez une présentation professionnelle :"""
47
 
48
- # [La classe PresentationGenerator reste inchangée]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  class PresentationGenerator:
50
- # [Le code de la classe reste identique]
51
- [...]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
- # Correction des fonctions de génération pour gérer correctement le progress
54
  def generate_skeleton(text, text_model_name, temperature, max_tokens):
55
  """Génère le squelette de la présentation"""
56
  try:
57
  start_time = time.time()
58
  generator = PresentationGenerator()
59
-
60
- # Chargement du modèle de texte uniquement
61
- generator.load_text_model(text_model_name)
62
-
63
  # Génération du contenu
64
  full_prompt = PREPROMPT + "\n\n" + text
65
- generated_content = generator.generate_text(full_prompt, temperature, max_tokens)
66
-
67
  execution_time = time.time() - start_time
68
  status = f"Squelette généré avec succès en {execution_time:.2f} secondes!"
69
-
70
- # Retourne le statut et le contenu généré
71
  return status, generated_content, gr.update(visible=True)
72
-
73
  except Exception as e:
74
  print(f"Erreur lors de la génération: {str(e)}")
75
  return f"Erreur: {str(e)}", None, gr.update(visible=False)
@@ -78,35 +193,35 @@ def create_presentation_file(generated_content):
78
  """Crée le fichier PowerPoint à partir du contenu généré"""
79
  try:
80
  generator = PresentationGenerator()
81
-
82
  # Création de la présentation
83
  slides = generator.parse_presentation_content(generated_content)
84
  prs = generator.create_presentation(slides)
85
-
86
  # Sauvegarde avec chemin absolu
87
  output_path = os.path.abspath("presentation.pptx")
88
  prs.save(output_path)
89
-
90
  # Vérification que le fichier existe
91
  if not os.path.exists(output_path):
92
  raise FileNotFoundError(f"Le fichier {output_path} n'a pas été créé correctement")
93
-
94
  return output_path
95
-
96
  except Exception as e:
97
  print(f"Erreur lors de la création du fichier: {str(e)}")
98
  return None
99
 
100
- # Interface Gradio corrigée
101
  with gr.Blocks(theme=gr.themes.Glass()) as demo:
102
  gr.Markdown(
103
  """
104
  # Générateur de Présentations PowerPoint IA
105
-
106
  Créez des présentations professionnelles automatiquement avec l'aide de l'IA.
107
  """
108
  )
109
-
110
  with gr.Row():
111
  with gr.Column(scale=1):
112
  text_model_choice = gr.Dropdown(
@@ -128,7 +243,7 @@ with gr.Blocks(theme=gr.themes.Glass()) as demo:
128
  step=256,
129
  label="Tokens maximum"
130
  )
131
-
132
  with gr.Row():
133
  with gr.Column(scale=2):
134
  input_text = gr.Textbox(
@@ -136,10 +251,10 @@ with gr.Blocks(theme=gr.themes.Glass()) as demo:
136
  label="Votre texte",
137
  placeholder="Décrivez le contenu que vous souhaitez pour votre présentation..."
138
  )
139
-
140
  with gr.Row():
141
  generate_skeleton_btn = gr.Button("Générer le Squelette de la Présentation", variant="primary")
142
-
143
  with gr.Row():
144
  with gr.Column():
145
  status_output = gr.Textbox(
@@ -155,8 +270,7 @@ with gr.Blocks(theme=gr.themes.Glass()) as demo:
155
  output_file = gr.File(
156
  label="Présentation PowerPoint"
157
  )
158
-
159
- # Correction des événements click
160
  generate_skeleton_btn.click(
161
  fn=generate_skeleton,
162
  inputs=[
@@ -171,7 +285,7 @@ with gr.Blocks(theme=gr.themes.Glass()) as demo:
171
  create_presentation_btn
172
  ]
173
  )
174
-
175
  create_presentation_btn.click(
176
  fn=create_presentation_file,
177
  inputs=[generated_content],
@@ -183,9 +297,3 @@ if __name__ == "__main__":
183
 
184
 
185
 
186
-
187
-
188
-
189
-
190
-
191
-
 
3
 
4
 
5
 
 
6
  import os
7
  import gradio as gr
8
  from huggingface_hub import hf_hub_download, login
 
13
  from llama_cpp import Llama
14
  import time
15
 
16
+ # Configuration des modèles disponibles
17
  TEXT_MODELS = {
18
  "Utter-Project_EuroLLM-1.7B": "utter-project/EuroLLM-1.7B",
19
  "Mistral Nemo 2407 (GGUF)": "MisterAI/Bartowski_MistralAI_Mistral-Nemo-Instruct-2407-IQ4_XS.gguf",
 
22
  }
23
 
24
  PREPROMPT = """Vous êtes un assistant IA expert en création de présentations PowerPoint professionnelles.
25
+ Générez une présentation structurée et détaillée au format Markdown en suivant ce format EXACT:
26
 
27
  TITRE: [Titre principal de la présentation]
28
 
 
44
 
45
  Analysez le texte suivant et créez une présentation professionnelle :"""
46
 
47
+ class ModelManager:
48
+ _instance = None
49
+
50
+ def __new__(cls):
51
+ if cls._instance is None:
52
+ cls._instance = super(ModelManager, cls).__new__(cls)
53
+ cls._instance.initialized = False
54
+ return cls._instance
55
+
56
+ def __init__(self):
57
+ if not self.initialized:
58
+ self.token = os.getenv('Authentification_HF')
59
+ if not self.token:
60
+ raise ValueError("Token d'authentification HuggingFace non trouvé")
61
+ login(self.token)
62
+ self.loaded_models = {}
63
+ self.loaded_tokenizers = {}
64
+ self.initialized = True
65
+
66
+ def get_model(self, model_name):
67
+ """Charge ou récupère un modèle déjà chargé"""
68
+ if model_name not in self.loaded_models:
69
+ print(f"Chargement du modèle {model_name}...")
70
+ model_id = TEXT_MODELS[model_name]
71
+
72
+ if model_id.endswith('.gguf'):
73
+ model_path = hf_hub_download(
74
+ repo_id=model_id.split('/')[0] + '/' + model_id.split('/')[1],
75
+ filename=model_id.split('/')[-1],
76
+ token=self.token
77
+ )
78
+ self.loaded_models[model_name] = Llama(
79
+ model_path=model_path,
80
+ n_ctx=4096,
81
+ n_batch=512,
82
+ verbose=False
83
+ )
84
+ print(f"Modèle GGUF {model_id} chargé avec succès!")
85
+ else:
86
+ self.loaded_tokenizers[model_name] = AutoTokenizer.from_pretrained(model_id, token=self.token)
87
+ self.loaded_models[model_name] = AutoModelForCausalLM.from_pretrained(
88
+ model_id,
89
+ torch_dtype=torch.bfloat16,
90
+ device_map="auto",
91
+ token=self.token
92
+ )
93
+ print(f"Modèle Transformers {model_id} chargé avec succès!")
94
+
95
+ return self.loaded_models[model_name], self.loaded_tokenizers.get(model_name)
96
+
97
  class PresentationGenerator:
98
+ def __init__(self):
99
+ self.model_manager = ModelManager()
100
+
101
+ def generate_text(self, prompt, model_name, temperature=0.7, max_tokens=4096):
102
+ """Génère le texte de la présentation"""
103
+ model, tokenizer = self.model_manager.get_model(model_name)
104
+
105
+ if isinstance(model, Llama):
106
+ response = model(
107
+ prompt,
108
+ max_tokens=max_tokens,
109
+ temperature=temperature,
110
+ echo=False
111
+ )
112
+ return response['choices'][0]['text']
113
+ else:
114
+ inputs = tokenizer.apply_chat_template(
115
+ [{"role": "user", "content": prompt}],
116
+ return_tensors="pt",
117
+ return_dict=True
118
+ )
119
+ outputs = model.generate(
120
+ **inputs,
121
+ max_new_tokens=max_tokens,
122
+ temperature=temperature
123
+ )
124
+ return tokenizer.decode(outputs[0], skip_special_tokens=True)
125
+
126
+ def parse_presentation_content(self, content):
127
+ """Parse le contenu généré en sections pour les diapositives"""
128
+ slides = []
129
+ current_slide = None
130
+
131
+ for line in content.split('\n'):
132
+ line = line.strip()
133
+ if line.startswith('TITRE:'):
134
+ slides.append({'type': 'title', 'title': line[6:].strip()})
135
+ elif line.startswith('DIAPO'):
136
+ if current_slide:
137
+ slides.append(current_slide)
138
+ current_slide = {'type': 'content', 'title': '', 'points': []}
139
+ elif line.startswith('Titre:') and current_slide:
140
+ current_slide['title'] = line[6:].strip()
141
+ elif line.startswith('- ') and current_slide:
142
+ current_slide['points'].append(line[2:].strip())
143
+
144
+ if current_slide:
145
+ slides.append(current_slide)
146
+
147
+ return slides
148
+
149
+ def create_presentation(self, slides):
150
+ """Crée la présentation PowerPoint avec texte uniquement"""
151
+ prs = Presentation()
152
+
153
+ # Première diapo (titre)
154
+ title_slide = prs.slides.add_slide(prs.slide_layouts[0])
155
+ title_slide.shapes.title.text = slides[0]['title']
156
+
157
+ # Autres diapos
158
+ for slide in slides[1:]:
159
+ content_slide = prs.slides.add_slide(prs.slide_layouts[1])
160
+ content_slide.shapes.title.text = slide['title']
161
+
162
+ # Ajout du texte
163
+ if slide['points']:
164
+ body = content_slide.shapes.placeholders[1].text_frame
165
+ body.clear()
166
+ for point in slide['points']:
167
+ p = body.add_paragraph()
168
+ p.text = point
169
+ p.level = 0
170
+
171
+ return prs
172
 
 
173
  def generate_skeleton(text, text_model_name, temperature, max_tokens):
174
  """Génère le squelette de la présentation"""
175
  try:
176
  start_time = time.time()
177
  generator = PresentationGenerator()
178
+
 
 
 
179
  # Génération du contenu
180
  full_prompt = PREPROMPT + "\n\n" + text
181
+ generated_content = generator.generate_text(full_prompt, text_model_name, temperature, max_tokens)
182
+
183
  execution_time = time.time() - start_time
184
  status = f"Squelette généré avec succès en {execution_time:.2f} secondes!"
185
+
 
186
  return status, generated_content, gr.update(visible=True)
187
+
188
  except Exception as e:
189
  print(f"Erreur lors de la génération: {str(e)}")
190
  return f"Erreur: {str(e)}", None, gr.update(visible=False)
 
193
  """Crée le fichier PowerPoint à partir du contenu généré"""
194
  try:
195
  generator = PresentationGenerator()
196
+
197
  # Création de la présentation
198
  slides = generator.parse_presentation_content(generated_content)
199
  prs = generator.create_presentation(slides)
200
+
201
  # Sauvegarde avec chemin absolu
202
  output_path = os.path.abspath("presentation.pptx")
203
  prs.save(output_path)
204
+
205
  # Vérification que le fichier existe
206
  if not os.path.exists(output_path):
207
  raise FileNotFoundError(f"Le fichier {output_path} n'a pas été créé correctement")
208
+
209
  return output_path
210
+
211
  except Exception as e:
212
  print(f"Erreur lors de la création du fichier: {str(e)}")
213
  return None
214
 
215
+ # Interface Gradio
216
  with gr.Blocks(theme=gr.themes.Glass()) as demo:
217
  gr.Markdown(
218
  """
219
  # Générateur de Présentations PowerPoint IA
220
+
221
  Créez des présentations professionnelles automatiquement avec l'aide de l'IA.
222
  """
223
  )
224
+
225
  with gr.Row():
226
  with gr.Column(scale=1):
227
  text_model_choice = gr.Dropdown(
 
243
  step=256,
244
  label="Tokens maximum"
245
  )
246
+
247
  with gr.Row():
248
  with gr.Column(scale=2):
249
  input_text = gr.Textbox(
 
251
  label="Votre texte",
252
  placeholder="Décrivez le contenu que vous souhaitez pour votre présentation..."
253
  )
254
+
255
  with gr.Row():
256
  generate_skeleton_btn = gr.Button("Générer le Squelette de la Présentation", variant="primary")
257
+
258
  with gr.Row():
259
  with gr.Column():
260
  status_output = gr.Textbox(
 
270
  output_file = gr.File(
271
  label="Présentation PowerPoint"
272
  )
273
+
 
274
  generate_skeleton_btn.click(
275
  fn=generate_skeleton,
276
  inputs=[
 
285
  create_presentation_btn
286
  ]
287
  )
288
+
289
  create_presentation_btn.click(
290
  fn=create_presentation_file,
291
  inputs=[generated_content],
 
297
 
298
 
299