Update app.py
Browse files
app.py
CHANGED
|
@@ -1,19 +1,15 @@
|
|
| 1 |
-
#
|
| 2 |
|
| 3 |
import os
|
| 4 |
import gradio as gr
|
| 5 |
from huggingface_hub import hf_hub_download, login
|
| 6 |
-
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 7 |
from pptx import Presentation
|
| 8 |
from pptx.util import Inches, Pt
|
| 9 |
from pptx.enum.text import PP_ALIGN
|
| 10 |
import torch
|
| 11 |
from llama_cpp import Llama
|
| 12 |
import time
|
| 13 |
-
from PIL import Image
|
| 14 |
-
import io
|
| 15 |
-
import requests
|
| 16 |
-
#from diffusers import FluxPipeline
|
| 17 |
|
| 18 |
# Configuration des modèles disponibles
|
| 19 |
TEXT_MODELS = {
|
|
@@ -22,12 +18,13 @@ TEXT_MODELS = {
|
|
| 22 |
"Lucie 7B": "OpenLLM-France/Lucie-7B"
|
| 23 |
}
|
| 24 |
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
|
|
|
| 29 |
|
| 30 |
-
# Préprompt
|
| 31 |
PREPROMPT = """Vous êtes un assistant IA expert en création de présentations PowerPoint professionnelles.
|
| 32 |
Générez une présentation structurée et détaillée en suivant ce format EXACT:
|
| 33 |
|
|
@@ -39,10 +36,6 @@ Points:
|
|
| 39 |
- Point 1
|
| 40 |
- Point 2
|
| 41 |
- Point 3
|
| 42 |
-
Image: [Description détaillée de l'image souhaitée pour cette diapo. Soyez très précis dans la description pour permettre
|
| 43 |
-
une génération d'image de qualité. Par exemple : "Une illustration professionnelle montrant un concept clé de cybersécurité
|
| 44 |
-
avec des éléments visuels modernes, un style épuré et des couleurs corporate (fond noir, couleurs bleu électrique, rouge, gris, blanc).
|
| 45 |
-
L'image doit être claire, minimaliste et adaptée à une présentation professionnelle."]
|
| 46 |
|
| 47 |
DIAPO 2:
|
| 48 |
Titre: [Titre de la diapo]
|
|
@@ -50,11 +43,10 @@ Points:
|
|
| 50 |
- Point 1
|
| 51 |
- Point 2
|
| 52 |
- Point 3
|
| 53 |
-
Image: [Description détaillée de l'image souhaitée pour cette diapo]
|
| 54 |
|
| 55 |
[Continuez avec ce format pour chaque diapositive]
|
| 56 |
|
| 57 |
-
Analysez le texte suivant et créez une présentation professionnelle
|
| 58 |
|
| 59 |
class PresentationGenerator:
|
| 60 |
def __init__(self):
|
|
@@ -64,7 +56,7 @@ class PresentationGenerator:
|
|
| 64 |
login(self.token)
|
| 65 |
self.text_model = None
|
| 66 |
self.text_tokenizer = None
|
| 67 |
-
self.image_pipeline = None
|
| 68 |
|
| 69 |
def load_text_model(self, model_name):
|
| 70 |
"""Charge le modèle de génération de texte"""
|
|
@@ -94,11 +86,12 @@ class PresentationGenerator:
|
|
| 94 |
)
|
| 95 |
print(f"Modèle Transformers {model_id} chargé avec succès!")
|
| 96 |
|
| 97 |
-
#
|
| 98 |
-
#
|
| 99 |
-
#
|
| 100 |
-
#
|
| 101 |
-
#
|
|
|
|
| 102 |
|
| 103 |
def generate_text(self, prompt, temperature=0.7, max_tokens=4096):
|
| 104 |
"""Génère le texte de la présentation"""
|
|
@@ -126,18 +119,19 @@ class PresentationGenerator:
|
|
| 126 |
print("Texte généré par Transformers :", generated_text)
|
| 127 |
return generated_text
|
| 128 |
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
|
|
|
| 141 |
|
| 142 |
def parse_presentation_content(self, content):
|
| 143 |
"""Parse le contenu généré en sections pour les diapositives"""
|
|
@@ -151,13 +145,14 @@ class PresentationGenerator:
|
|
| 151 |
elif line.startswith('DIAPO'):
|
| 152 |
if current_slide:
|
| 153 |
slides.append(current_slide)
|
| 154 |
-
current_slide = {'type': 'content', 'title': '', 'points': []
|
| 155 |
elif line.startswith('Titre:') and current_slide:
|
| 156 |
current_slide['title'] = line[6:].strip()
|
| 157 |
elif line.startswith('- ') and current_slide:
|
| 158 |
current_slide['points'].append(line[2:].strip())
|
| 159 |
-
|
| 160 |
-
|
|
|
|
| 161 |
|
| 162 |
if current_slide:
|
| 163 |
slides.append(current_slide)
|
|
@@ -165,7 +160,7 @@ class PresentationGenerator:
|
|
| 165 |
return slides
|
| 166 |
|
| 167 |
def create_presentation(self, slides):
|
| 168 |
-
"""Crée la présentation PowerPoint avec texte
|
| 169 |
prs = Presentation()
|
| 170 |
|
| 171 |
# Première diapo (titre)
|
|
@@ -186,34 +181,28 @@ class PresentationGenerator:
|
|
| 186 |
p.text = point
|
| 187 |
p.level = 0
|
| 188 |
|
| 189 |
-
#
|
| 190 |
-
if slide.get('image_prompt'):
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
top = Inches(2.5)
|
| 200 |
-
content_slide.shapes.add_picture(img_path, left, top, height=Inches(4))
|
| 201 |
-
|
| 202 |
-
# Suppression du fichier temporaire
|
| 203 |
-
os.remove(img_path)
|
| 204 |
|
| 205 |
return prs
|
| 206 |
|
| 207 |
-
def generate_presentation_with_progress(text, text_model_name,
|
| 208 |
"""Fonction principale de génération avec suivi de progression"""
|
| 209 |
try:
|
| 210 |
start_time = time.time()
|
| 211 |
generator = PresentationGenerator()
|
| 212 |
|
| 213 |
-
# Chargement
|
| 214 |
-
yield "Chargement
|
| 215 |
generator.load_text_model(text_model_name)
|
| 216 |
-
generator.load_image_model(image_model_name)
|
| 217 |
|
| 218 |
# Génération du contenu
|
| 219 |
yield "Génération du contenu de la présentation...", None, None
|
|
@@ -311,11 +300,6 @@ with gr.Blocks(theme=gr.themes.Default(), css=css) as demo:
|
|
| 311 |
value=list(TEXT_MODELS.keys())[0],
|
| 312 |
label="Modèle de génération de texte"
|
| 313 |
)
|
| 314 |
-
image_model_choice = gr.Dropdown(
|
| 315 |
-
choices=list(IMAGE_MODELS.keys()),
|
| 316 |
-
value=list(IMAGE_MODELS.keys())[0],
|
| 317 |
-
label="Modèle de génération d'images"
|
| 318 |
-
)
|
| 319 |
temperature = gr.Slider(
|
| 320 |
minimum=0.1,
|
| 321 |
maximum=1.0,
|
|
@@ -330,11 +314,6 @@ with gr.Blocks(theme=gr.themes.Default(), css=css) as demo:
|
|
| 330 |
step=256,
|
| 331 |
label="Tokens maximum"
|
| 332 |
)
|
| 333 |
-
negative_prompt = gr.Textbox(
|
| 334 |
-
lines=2,
|
| 335 |
-
label="Prompt négatif pour les images",
|
| 336 |
-
placeholder="Ce que vous ne voulez pas voir dans les images..."
|
| 337 |
-
)
|
| 338 |
|
| 339 |
with gr.Row():
|
| 340 |
with gr.Column(scale=2):
|
|
@@ -343,12 +322,12 @@ with gr.Blocks(theme=gr.themes.Default(), css=css) as demo:
|
|
| 343 |
label="Votre texte",
|
| 344 |
placeholder="Décrivez le contenu que vous souhaitez pour votre présentation..."
|
| 345 |
)
|
| 346 |
-
#
|
| 347 |
-
file_upload = gr.File(
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
)
|
| 352 |
|
| 353 |
with gr.Row():
|
| 354 |
generate_btn = gr.Button("🚀 Générer la présentation", variant="primary")
|
|
@@ -373,10 +352,8 @@ with gr.Blocks(theme=gr.themes.Default(), css=css) as demo:
|
|
| 373 |
inputs=[
|
| 374 |
input_text,
|
| 375 |
text_model_choice,
|
| 376 |
-
image_model_choice,
|
| 377 |
temperature,
|
| 378 |
-
max_tokens
|
| 379 |
-
negative_prompt
|
| 380 |
],
|
| 381 |
outputs=[
|
| 382 |
status_output,
|
|
@@ -386,4 +363,4 @@ with gr.Blocks(theme=gr.themes.Default(), css=css) as demo:
|
|
| 386 |
)
|
| 387 |
|
| 388 |
if __name__ == "__main__":
|
| 389 |
-
demo.launch()
|
|
|
|
| 1 |
+
#141
|
| 2 |
|
| 3 |
import os
|
| 4 |
import gradio as gr
|
| 5 |
from huggingface_hub import hf_hub_download, login
|
| 6 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 7 |
from pptx import Presentation
|
| 8 |
from pptx.util import Inches, Pt
|
| 9 |
from pptx.enum.text import PP_ALIGN
|
| 10 |
import torch
|
| 11 |
from llama_cpp import Llama
|
| 12 |
import time
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
# Configuration des modèles disponibles
|
| 15 |
TEXT_MODELS = {
|
|
|
|
| 18 |
"Lucie 7B": "OpenLLM-France/Lucie-7B"
|
| 19 |
}
|
| 20 |
|
| 21 |
+
# Commenté : Configuration des modèles d'images
|
| 22 |
+
# IMAGE_MODELS = {
|
| 23 |
+
# "FLUX.1": "black-forest-labs/FLUX.1-schnell",
|
| 24 |
+
# "ArtifyAI": "ImageInception/ArtifyAI-v1.1"
|
| 25 |
+
# }
|
| 26 |
|
| 27 |
+
# Préprompt modifié pour ne pas inclure la génération d'images
|
| 28 |
PREPROMPT = """Vous êtes un assistant IA expert en création de présentations PowerPoint professionnelles.
|
| 29 |
Générez une présentation structurée et détaillée en suivant ce format EXACT:
|
| 30 |
|
|
|
|
| 36 |
- Point 1
|
| 37 |
- Point 2
|
| 38 |
- Point 3
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
DIAPO 2:
|
| 41 |
Titre: [Titre de la diapo]
|
|
|
|
| 43 |
- Point 1
|
| 44 |
- Point 2
|
| 45 |
- Point 3
|
|
|
|
| 46 |
|
| 47 |
[Continuez avec ce format pour chaque diapositive]
|
| 48 |
|
| 49 |
+
Analysez le texte suivant et créez une présentation professionnelle :"""
|
| 50 |
|
| 51 |
class PresentationGenerator:
|
| 52 |
def __init__(self):
|
|
|
|
| 56 |
login(self.token)
|
| 57 |
self.text_model = None
|
| 58 |
self.text_tokenizer = None
|
| 59 |
+
# Commenté : self.image_pipeline = None
|
| 60 |
|
| 61 |
def load_text_model(self, model_name):
|
| 62 |
"""Charge le modèle de génération de texte"""
|
|
|
|
| 86 |
)
|
| 87 |
print(f"Modèle Transformers {model_id} chargé avec succès!")
|
| 88 |
|
| 89 |
+
# Commenté : Fonction de chargement du modèle d'images
|
| 90 |
+
# def load_image_model(self, model_name):
|
| 91 |
+
# """Charge le modèle de génération d'images"""
|
| 92 |
+
# model_id = IMAGE_MODELS[model_name]
|
| 93 |
+
# self.image_pipeline = gr.load("models/black-forest-labs/FLUX.1-schnell")
|
| 94 |
+
# print(f"Modèle d'image FLUX chargé : {model_id}")
|
| 95 |
|
| 96 |
def generate_text(self, prompt, temperature=0.7, max_tokens=4096):
|
| 97 |
"""Génère le texte de la présentation"""
|
|
|
|
| 119 |
print("Texte généré par Transformers :", generated_text)
|
| 120 |
return generated_text
|
| 121 |
|
| 122 |
+
# Commenté : Fonction de génération d'images
|
| 123 |
+
# def generate_image(self, prompt, negative_prompt="", num_inference_steps=30):
|
| 124 |
+
# """Génère une image pour la diapositive"""
|
| 125 |
+
# try:
|
| 126 |
+
# image = self.image_pipeline(
|
| 127 |
+
# prompt=prompt,
|
| 128 |
+
# negative_prompt=negative_prompt,
|
| 129 |
+
# num_inference_steps=num_inference_steps
|
| 130 |
+
# )[0]
|
| 131 |
+
# return image
|
| 132 |
+
# except Exception as e:
|
| 133 |
+
# print(f"Erreur lors de la génération de l'image: {str(e)}")
|
| 134 |
+
# return None
|
| 135 |
|
| 136 |
def parse_presentation_content(self, content):
|
| 137 |
"""Parse le contenu généré en sections pour les diapositives"""
|
|
|
|
| 145 |
elif line.startswith('DIAPO'):
|
| 146 |
if current_slide:
|
| 147 |
slides.append(current_slide)
|
| 148 |
+
current_slide = {'type': 'content', 'title': '', 'points': []}
|
| 149 |
elif line.startswith('Titre:') and current_slide:
|
| 150 |
current_slide['title'] = line[6:].strip()
|
| 151 |
elif line.startswith('- ') and current_slide:
|
| 152 |
current_slide['points'].append(line[2:].strip())
|
| 153 |
+
# Commenté : Parsing des prompts d'images
|
| 154 |
+
# elif line.startswith('Image:') and current_slide:
|
| 155 |
+
# current_slide['image_prompt'] = line[6:].strip()
|
| 156 |
|
| 157 |
if current_slide:
|
| 158 |
slides.append(current_slide)
|
|
|
|
| 160 |
return slides
|
| 161 |
|
| 162 |
def create_presentation(self, slides):
|
| 163 |
+
"""Crée la présentation PowerPoint avec texte uniquement"""
|
| 164 |
prs = Presentation()
|
| 165 |
|
| 166 |
# Première diapo (titre)
|
|
|
|
| 181 |
p.text = point
|
| 182 |
p.level = 0
|
| 183 |
|
| 184 |
+
# Commenté : Ajout des images
|
| 185 |
+
# if slide.get('image_prompt'):
|
| 186 |
+
# image = self.generate_image(slide['image_prompt'])
|
| 187 |
+
# if image:
|
| 188 |
+
# img_path = f"temp_slide_{slides.index(slide)}.png"
|
| 189 |
+
# image.save(img_path)
|
| 190 |
+
# left = Inches(1)
|
| 191 |
+
# top = Inches(2.5)
|
| 192 |
+
# content_slide.shapes.add_picture(img_path, left, top, height=Inches(4))
|
| 193 |
+
# os.remove(img_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
|
| 195 |
return prs
|
| 196 |
|
| 197 |
+
def generate_presentation_with_progress(text, text_model_name, temperature, max_tokens):
|
| 198 |
"""Fonction principale de génération avec suivi de progression"""
|
| 199 |
try:
|
| 200 |
start_time = time.time()
|
| 201 |
generator = PresentationGenerator()
|
| 202 |
|
| 203 |
+
# Chargement du modèle de texte uniquement
|
| 204 |
+
yield "Chargement du modèle...", None, None
|
| 205 |
generator.load_text_model(text_model_name)
|
|
|
|
| 206 |
|
| 207 |
# Génération du contenu
|
| 208 |
yield "Génération du contenu de la présentation...", None, None
|
|
|
|
| 300 |
value=list(TEXT_MODELS.keys())[0],
|
| 301 |
label="Modèle de génération de texte"
|
| 302 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 303 |
temperature = gr.Slider(
|
| 304 |
minimum=0.1,
|
| 305 |
maximum=1.0,
|
|
|
|
| 314 |
step=256,
|
| 315 |
label="Tokens maximum"
|
| 316 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 317 |
|
| 318 |
with gr.Row():
|
| 319 |
with gr.Column(scale=2):
|
|
|
|
| 322 |
label="Votre texte",
|
| 323 |
placeholder="Décrivez le contenu que vous souhaitez pour votre présentation..."
|
| 324 |
)
|
| 325 |
+
# Commenté : Upload de fichiers
|
| 326 |
+
# file_upload = gr.File(
|
| 327 |
+
# label="Documents de référence (PDF, Images)",
|
| 328 |
+
# file_types=["pdf", "png", "jpg", "jpeg"],
|
| 329 |
+
# type="binary"
|
| 330 |
+
# )
|
| 331 |
|
| 332 |
with gr.Row():
|
| 333 |
generate_btn = gr.Button("🚀 Générer la présentation", variant="primary")
|
|
|
|
| 352 |
inputs=[
|
| 353 |
input_text,
|
| 354 |
text_model_choice,
|
|
|
|
| 355 |
temperature,
|
| 356 |
+
max_tokens
|
|
|
|
| 357 |
],
|
| 358 |
outputs=[
|
| 359 |
status_output,
|
|
|
|
| 363 |
)
|
| 364 |
|
| 365 |
if __name__ == "__main__":
|
| 366 |
+
demo.launch()
|