Equityone commited on
Commit
aa12eaa
·
verified ·
1 Parent(s): b09f3fe

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -154
app.py CHANGED
@@ -124,120 +124,97 @@ class ImageGenerator:
124
  logger.info("ImageGenerator initialisé")
125
 
126
  def _build_prompt(self, params: Dict[str, Any]) -> str:
 
127
  try:
 
128
  enhancer = PromptEnhancer()
 
 
129
  style_info = ART_STYLES.get(params["style"], ART_STYLES["Art Moderne"])
130
-
131
- # Détection du type de contenu
132
- content_type = self._detect_content_type(params["subject"])
133
-
134
- # Adaptation du style selon le contenu
135
- style_adjustments = {
136
- "anime_manga": {
137
- "prompt_prefix": "high quality anime artwork, detailed anime illustration, studio anime quality, professional anime art",
138
- "negative_prompt": "low quality, simple, poorly drawn, blurry"
139
- },
140
- "art_digital": {
141
- "prompt_prefix": "professional digital artwork, detailed digital illustration, modern digital art",
142
- "negative_prompt": "traditional art, poor quality, amateur"
143
- },
144
- "art_traditionnel": {
145
- "prompt_prefix": "traditional art masterpiece, fine art painting, artistic technique, professional artwork",
146
- "negative_prompt": "digital art, 3d render, poor quality"
147
- },
148
- "photo_realiste": {
149
- "prompt_prefix": "ultra realistic photograph, professional photography, high end photo, studio quality",
150
- "negative_prompt": "drawing, painting, artificial, digital art"
151
- },
152
- "graphisme": {
153
- "prompt_prefix": "professional graphic design, clean modern design, commercial quality artwork",
154
- "negative_prompt": "amateur, messy, unrefined"
155
- },
156
- "fantastique": {
157
- "prompt_prefix": "fantasy art masterpiece, mythical artwork, magical atmosphere, epic fantasy illustration",
158
- "negative_prompt": "realistic, mundane, ordinary"
159
- },
160
- "sci_fi": {
161
- "prompt_prefix": "futuristic sci-fi artwork, high tech aesthetic, advanced technology, science fiction art",
162
- "negative_prompt": "vintage, retro, traditional"
163
- },
164
- "art_abstrait": {
165
- "prompt_prefix": "abstract art composition, non-representational artwork, artistic expression",
166
- "negative_prompt": "realistic, figurative, literal"
167
- },
168
- "art_pop": {
169
- "prompt_prefix": "pop art style, bold colors, graphic art, contemporary pop culture",
170
- "negative_prompt": "classical, traditional, subtle"
171
- },
172
- "art_conceptuel": {
173
- "prompt_prefix": "concept art, professional design, detailed visualization, production quality",
174
- "negative_prompt": "amateur, unrefined, sketch"
175
- }
176
- }
177
 
178
- # Ajustement du style en fonction du contenu détecté
179
- if content_type in style_adjustments:
180
- style_info = style_adjustments[content_type]
181
-
182
- # Construction du contexte
183
  style_context = {
184
  "prompt_prefix": style_info['prompt_prefix'],
185
  "layout": COMPOSITION_PARAMS['Layouts'][params['layout']],
186
  "ambiance": COMPOSITION_PARAMS['Ambiances'][params['ambiance']],
187
  "palette": COMPOSITION_PARAMS['Palette'][params['palette']]
188
  }
189
-
 
190
  base_prompt = f"{params['subject']}"
191
  if params.get('title'):
192
  base_prompt += f", with text '{params['title']}'"
193
 
 
194
  enhanced_prompt = enhancer.enhance_prompt(base_prompt, style_context)
 
 
 
 
 
195
  return enhanced_prompt
196
 
197
  except Exception as e:
198
  logger.error(f"Erreur dans la construction du prompt: {str(e)}")
 
199
  return f"{style_info['prompt_prefix']}, {params['subject']}"
200
 
201
- def _detect_content_type(self, subject: str) -> str:
202
- """Détecte le type de contenu demandé pour adapter le style"""
203
- content_types = {
204
- "anime_manga": ["manga", "anime", "dragon ball", "naruto", "one piece", "pokemon"],
205
- "art_digital": ["pixel art", "digital", "vectoriel", "3d", "game art"],
206
- "art_traditionnel": ["peinture", "aquarelle", "huile", "acrylique", "dessin"],
207
- "photo_realiste": ["photo", "portrait", "paysage", "architecture", "produit"],
208
- "graphisme": ["logo", "affiche", "flyer", "branding", "typographie"],
209
- "fantastique": ["fantasy", "dragon", "magie", "heroic fantasy", "mythologie"],
210
- "sci_fi": ["science fiction", "futuriste", "cyberpunk", "space", "robot"],
211
- "art_abstrait": ["abstrait", "géométrique", "non-figuratif", "minimaliste"],
212
- "art_pop": ["pop art", "comics", "bande dessinée", "cartoon", "graffiti"],
213
- "art_conceptuel": ["concept art", "character design", "environment design", "matte painting"]
214
- }
215
-
216
- subject_lower = subject.lower()
217
- detected_types = []
218
-
219
- for content_type, keywords in content_types.items():
220
- if any(keyword in subject_lower for keyword in keywords):
221
- detected_types.append(content_type)
222
-
223
- if len(detected_types) > 1:
224
- if "photo_realiste" in detected_types and any(t in detected_types for t in ["art_digital", "anime_manga"]):
225
- return "photo_realiste"
226
-
227
- return detected_types[0] if detected_types else "general"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
 
229
  def create_interface():
230
  logger.info("Création de l'interface Gradio")
231
-
232
  css = """
233
  .container { max-width: 1200px; margin: auto; }
234
  .welcome { text-align: center; margin: 20px 0; padding: 20px; background: #1e293b; border-radius: 10px; }
235
  .controls-group { background: #2d3748; padding: 15px; border-radius: 5px; margin: 10px 0; }
236
  .advanced-controls { background: #374151; padding: 12px; border-radius: 5px; margin: 8px 0; }
237
  """
238
-
239
  generator = ImageGenerator()
240
-
241
  with gr.Blocks(css=css) as app:
242
  gr.HTML("""
243
  <div class="welcome">
@@ -245,7 +222,7 @@ def create_interface():
245
  <p>Assistant de création d'affiches professionnelles</p>
246
  </div>
247
  """)
248
-
249
  with gr.Column(elem_classes="container"):
250
  # Zone d'introduction et guide
251
  gr.Markdown("""
@@ -272,7 +249,7 @@ def create_interface():
272
  label="Orientation",
273
  info="Portrait (vertical) ou Paysage (horizontal)"
274
  )
275
-
276
  with gr.Group(elem_classes="controls-group"):
277
  gr.Markdown("### 🎨 Style et Composition")
278
  with gr.Row():
@@ -302,7 +279,7 @@ def create_interface():
302
  label="Palette",
303
  info="Les types de couleurs utilisées"
304
  )
305
-
306
  with gr.Group(elem_classes="controls-group"):
307
  gr.Markdown("""### 📝 Contenu
308
  *Conseils pour la description : soyez précis sur ce que vous souhaitez voir dans l'affiche*""")
@@ -316,7 +293,7 @@ def create_interface():
316
  placeholder="Le titre qui apparaîtra sur l'affiche...",
317
  info="Laissez vide si vous ne voulez pas de titre sur l'affiche"
318
  )
319
-
320
  with gr.Group(elem_classes="advanced-controls"):
321
  gr.Markdown("""### 🎯 Ajustements Fins
322
  *Ces paramètres permettent d'affiner le résultat final*""")
@@ -345,7 +322,7 @@ def create_interface():
345
  label="Saturation",
346
  info="Contrôle la vivacité des couleurs"
347
  )
348
-
349
  with gr.Group(elem_classes="controls-group"):
350
  gr.Markdown("### ⚙️ Paramètres de Génération")
351
  with gr.Row():
@@ -363,77 +340,35 @@ def create_interface():
363
  label="Créativité",
364
  info="Plus la valeur est élevée, plus l'IA prendra de libertés créatives"
365
  )
366
-
367
  with gr.Row():
368
  generate_btn = gr.Button("✨ Générer", variant="primary")
369
  clear_btn = gr.Button("🗑️ Effacer", variant="secondary")
370
-
371
  image_output = gr.Image(label="Aperçu")
372
  status = gr.Textbox(label="Statut", interactive=False)
373
-
374
- def generate(self, params: Dict[str, Any]) -> Tuple[Optional[Image.Image], str]:
375
- try:
376
- logger.info(f"Début de génération avec paramètres: {json.dumps(params, indent=2)}")
377
-
378
- if 'Bearer None' in self.headers['Authorization']:
379
- logger.error("Token Hugging Face manquant ou invalide")
380
- return None, "⚠️ Erreur: Token Hugging Face non configuré"
381
 
382
- prompt = self._build_prompt(params)
383
- logger.info(f"Prompt généré: {prompt}")
384
-
385
- content_type = self._detect_content_type(params["subject"])
386
- logger.info(f"Type de contenu détecté: {content_type}")
387
-
388
- payload = {
389
- "inputs": prompt,
390
- "parameters": {
391
- "negative_prompt": ART_STYLES[params["style"]]["negative_prompt"],
392
- "num_inference_steps": min(int(35 * (params["quality"]/100)), 40),
393
- "guidance_scale": min(7.5 * (params["creativity"]/10), 10.0),
394
- "width": 768,
395
- "height": 768 if params["orientation"] == "Portrait" else 512
396
- }
 
397
  }
398
-
399
- logger.debug(f"Payload pour l'API: {json.dumps(payload, indent=2)}")
400
-
401
- try:
402
- response = requests.post(
403
- self.API_URL,
404
- headers=self.headers,
405
- json=payload,
406
- timeout=30
407
- )
408
-
409
- logger.info(f"Statut de la réponse API: {response.status_code}")
410
- if response.status_code != 200:
411
- logger.error(f"Contenu de la réponse en erreur: {response.text}")
412
-
413
- if response.status_code == 200:
414
- image = Image.open(io.BytesIO(response.content))
415
- return image, "✨ Création réussie!"
416
- else:
417
- error_msg = f"⚠️ Erreur API {response.status_code}: {response.text}"
418
- logger.error(error_msg)
419
- return None, error_msg
420
-
421
- except requests.exceptions.Timeout:
422
- error_msg = "⚠️ Erreur: Le serveur met trop de temps à répondre"
423
- logger.error(error_msg)
424
- return None, error_msg
425
- except requests.exceptions.RequestException as e:
426
- error_msg = f"⚠️ Erreur de connexion: {str(e)}"
427
- logger.error(error_msg)
428
- return None, error_msg
429
 
430
- except Exception as e:
431
- error_msg = f"⚠️ Erreur inattendue: {str(e)}"
432
- logger.exception("Erreur détaillée pendant la génération:")
433
- return None, error_msg
434
- finally:
435
- gc.collect()
436
-
437
  generate_btn.click(
438
  generate,
439
  inputs=[
@@ -453,16 +388,16 @@ def create_interface():
453
  ],
454
  outputs=[image_output, status]
455
  )
456
-
457
  clear_btn.click(
458
  lambda: (None, "🗑️ Image effacée"),
459
  outputs=[image_output, status]
460
  )
461
-
462
  logger.info("Interface créée avec succès")
463
  return app
464
 
465
  if __name__ == "__main__":
466
  app = create_interface()
467
  logger.info("Démarrage de l'application")
468
- app.launch()
 
124
  logger.info("ImageGenerator initialisé")
125
 
126
  def _build_prompt(self, params: Dict[str, Any]) -> str:
127
+ """Construction de prompt améliorée avec le PromptEnhancer"""
128
  try:
129
+ # Initialisation du PromptEnhancer
130
  enhancer = PromptEnhancer()
131
+
132
+ # Récupération du style
133
  style_info = ART_STYLES.get(params["style"], ART_STYLES["Art Moderne"])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
+ # Construction du contexte de style
 
 
 
 
136
  style_context = {
137
  "prompt_prefix": style_info['prompt_prefix'],
138
  "layout": COMPOSITION_PARAMS['Layouts'][params['layout']],
139
  "ambiance": COMPOSITION_PARAMS['Ambiances'][params['ambiance']],
140
  "palette": COMPOSITION_PARAMS['Palette'][params['palette']]
141
  }
142
+
143
+ # Préparation du prompt initial
144
  base_prompt = f"{params['subject']}"
145
  if params.get('title'):
146
  base_prompt += f", with text '{params['title']}'"
147
 
148
+ # Amélioration du prompt
149
  enhanced_prompt = enhancer.enhance_prompt(base_prompt, style_context)
150
+
151
+ # Analyse de l'efficacité du prompt
152
+ prompt_analysis = enhancer.analyze_prompt_effectiveness(enhanced_prompt)
153
+ logger.debug(f"Analyse du prompt: {json.dumps(prompt_analysis, indent=2)}")
154
+
155
  return enhanced_prompt
156
 
157
  except Exception as e:
158
  logger.error(f"Erreur dans la construction du prompt: {str(e)}")
159
+ # Fallback sur le prompt basique en cas d'erreur
160
  return f"{style_info['prompt_prefix']}, {params['subject']}"
161
 
162
+ def generate(self, params: Dict[str, Any]) -> Tuple[Optional[Image.Image], str]:
163
+ try:
164
+ logger.info(f"Début de génération avec paramètres: {json.dumps(params, indent=2)}")
165
+
166
+ if 'Bearer None' in self.headers['Authorization']:
167
+ return None, "⚠️ Erreur: Token Hugging Face non configuré"
168
+
169
+ prompt = self._build_prompt(params)
170
+
171
+ payload = {
172
+ "inputs": prompt,
173
+ "parameters": {
174
+ "negative_prompt": ART_STYLES[params["style"]]["negative_prompt"],
175
+ "num_inference_steps": min(int(35 * (params["quality"]/100)), 40),
176
+ "guidance_scale": min(7.5 * (params["creativity"]/10), 10.0),
177
+ "width": 768,
178
+ "height": 768 if params["orientation"] == "Portrait" else 512
179
+ }
180
+ }
181
+
182
+ logger.debug(f"Payload: {json.dumps(payload, indent=2)}")
183
+
184
+ response = requests.post(
185
+ self.API_URL,
186
+ headers=self.headers,
187
+ json=payload,
188
+ timeout=30
189
+ )
190
+
191
+ if response.status_code == 200:
192
+ image = Image.open(io.BytesIO(response.content))
193
+ return image, "✨ Création réussie!"
194
+ else:
195
+ error_msg = f"⚠️ Erreur API {response.status_code}: {response.text}"
196
+ logger.error(error_msg)
197
+ return None, error_msg
198
+
199
+ except Exception as e:
200
+ error_msg = f"⚠️ Erreur: {str(e)}"
201
+ logger.exception("Erreur pendant la génération:")
202
+ return None, error_msg
203
+ finally:
204
+ gc.collect()
205
 
206
  def create_interface():
207
  logger.info("Création de l'interface Gradio")
208
+
209
  css = """
210
  .container { max-width: 1200px; margin: auto; }
211
  .welcome { text-align: center; margin: 20px 0; padding: 20px; background: #1e293b; border-radius: 10px; }
212
  .controls-group { background: #2d3748; padding: 15px; border-radius: 5px; margin: 10px 0; }
213
  .advanced-controls { background: #374151; padding: 12px; border-radius: 5px; margin: 8px 0; }
214
  """
215
+
216
  generator = ImageGenerator()
217
+
218
  with gr.Blocks(css=css) as app:
219
  gr.HTML("""
220
  <div class="welcome">
 
222
  <p>Assistant de création d'affiches professionnelles</p>
223
  </div>
224
  """)
225
+
226
  with gr.Column(elem_classes="container"):
227
  # Zone d'introduction et guide
228
  gr.Markdown("""
 
249
  label="Orientation",
250
  info="Portrait (vertical) ou Paysage (horizontal)"
251
  )
252
+
253
  with gr.Group(elem_classes="controls-group"):
254
  gr.Markdown("### 🎨 Style et Composition")
255
  with gr.Row():
 
279
  label="Palette",
280
  info="Les types de couleurs utilisées"
281
  )
282
+
283
  with gr.Group(elem_classes="controls-group"):
284
  gr.Markdown("""### 📝 Contenu
285
  *Conseils pour la description : soyez précis sur ce que vous souhaitez voir dans l'affiche*""")
 
293
  placeholder="Le titre qui apparaîtra sur l'affiche...",
294
  info="Laissez vide si vous ne voulez pas de titre sur l'affiche"
295
  )
296
+
297
  with gr.Group(elem_classes="advanced-controls"):
298
  gr.Markdown("""### 🎯 Ajustements Fins
299
  *Ces paramètres permettent d'affiner le résultat final*""")
 
322
  label="Saturation",
323
  info="Contrôle la vivacité des couleurs"
324
  )
325
+
326
  with gr.Group(elem_classes="controls-group"):
327
  gr.Markdown("### ⚙️ Paramètres de Génération")
328
  with gr.Row():
 
340
  label="Créativité",
341
  info="Plus la valeur est élevée, plus l'IA prendra de libertés créatives"
342
  )
343
+
344
  with gr.Row():
345
  generate_btn = gr.Button("✨ Générer", variant="primary")
346
  clear_btn = gr.Button("🗑️ Effacer", variant="secondary")
347
+
348
  image_output = gr.Image(label="Aperçu")
349
  status = gr.Textbox(label="Statut", interactive=False)
 
 
 
 
 
 
 
 
350
 
351
+ def generate(*args):
352
+ logger.info("Démarrage d'une nouvelle génération")
353
+ params = {
354
+ "format_size": args[0],
355
+ "orientation": args[1],
356
+ "style": args[2],
357
+ "layout": args[3],
358
+ "ambiance": args[4],
359
+ "palette": args[5],
360
+ "subject": args[6],
361
+ "title": args[7],
362
+ "detail_level": args[8],
363
+ "contrast": args[9],
364
+ "saturation": args[10],
365
+ "quality": args[11],
366
+ "creativity": args[12]
367
  }
368
+ result = generator.generate(params)
369
+ logger.info(f"Génération terminée avec statut: {result[1]}")
370
+ return result
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
371
 
 
 
 
 
 
 
 
372
  generate_btn.click(
373
  generate,
374
  inputs=[
 
388
  ],
389
  outputs=[image_output, status]
390
  )
391
+
392
  clear_btn.click(
393
  lambda: (None, "🗑️ Image effacée"),
394
  outputs=[image_output, status]
395
  )
396
+
397
  logger.info("Interface créée avec succès")
398
  return app
399
 
400
  if __name__ == "__main__":
401
  app = create_interface()
402
  logger.info("Démarrage de l'application")
403
+ app.launch()