Equityone commited on
Commit
c45b5a3
·
verified ·
1 Parent(s): 3adc659

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +150 -31
app.py CHANGED
@@ -9,7 +9,7 @@ from typing import Tuple, Optional, Dict, Any
9
  import logging
10
  from dotenv import load_dotenv
11
 
12
- # Configuration du logging détaillé
13
  logging.basicConfig(
14
  level=logging.DEBUG,
15
  format='%(asctime)s - %(levelname)s - %(message)s'
@@ -19,7 +19,7 @@ logger = logging.getLogger(__name__)
19
  # Chargement des variables d'environnement
20
  load_dotenv()
21
 
22
- # Styles pour la génération
23
  ART_STYLES = {
24
  "Art Moderne": {
25
  "prompt_prefix": "modern art style poster, professional design",
@@ -36,6 +36,47 @@ ART_STYLES = {
36
  "Minimaliste": {
37
  "prompt_prefix": "minimalist design poster, clean composition",
38
  "negative_prompt": "complex, detailed, ornate, busy"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  }
40
  }
41
 
@@ -44,39 +85,56 @@ class ImageGenerator:
44
  self.API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0"
45
  token = os.getenv('HUGGINGFACE_TOKEN')
46
  if not token:
47
- logger.error("HUGGINGFACE_TOKEN non trouvé dans les variables d'environnement!")
48
  self.headers = {"Authorization": f"Bearer {token}"}
49
  logger.info("ImageGenerator initialisé")
50
 
51
  def _build_prompt(self, params: Dict[str, Any]) -> str:
 
52
  style_info = ART_STYLES.get(params["style"], ART_STYLES["Neo Vintage"])
53
  prompt = f"{style_info['prompt_prefix']}, {params['subject']}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  if params.get("title"):
55
  prompt += f", with text saying '{params['title']}'"
56
- logger.debug(f"Prompt construit: {prompt}")
57
- return prompt
58
 
59
- def _get_negative_prompt(self, style: str) -> str:
60
- return ART_STYLES.get(style, ART_STYLES["Neo Vintage"])["negative_prompt"]
61
 
62
  def generate(self, params: Dict[str, Any]) -> Tuple[Optional[Image.Image], str]:
63
  try:
64
- # Log des paramètres
65
  logger.info(f"Début de génération avec paramètres: {json.dumps(params, indent=2)}")
66
 
67
- # Vérification du token
68
  if 'Bearer None' in self.headers['Authorization']:
69
  return None, "⚠️ Erreur: Token Hugging Face non configuré"
70
 
71
- # Construction du prompt
72
  prompt = self._build_prompt(params)
73
- logger.debug(f"Prompt final: {prompt}")
74
-
75
- # Configuration de la requête
76
  payload = {
77
  "inputs": prompt,
78
  "parameters": {
79
- "negative_prompt": self._get_negative_prompt(params["style"]),
80
  "num_inference_steps": min(int(35 * (params["quality"]/100)), 40),
81
  "guidance_scale": min(7.5 * (params["creativity"]/10), 10.0),
82
  "width": 768,
@@ -84,10 +142,8 @@ class ImageGenerator:
84
  }
85
  }
86
 
87
- logger.debug(f"Payload de la requête: {json.dumps(payload, indent=2)}")
88
 
89
- # Requête API
90
- logger.info("Envoi de la requête à l'API...")
91
  response = requests.post(
92
  self.API_URL,
93
  headers=self.headers,
@@ -95,12 +151,8 @@ class ImageGenerator:
95
  timeout=30
96
  )
97
 
98
- logger.debug(f"Statut de la réponse: {response.status_code}")
99
- logger.debug(f"Contenu de la réponse: {response.text[:200]}...") # Premiers 200 caractères
100
-
101
  if response.status_code == 200:
102
  image = Image.open(io.BytesIO(response.content))
103
- logger.info("Image générée avec succès")
104
  return image, "✨ Création réussie!"
105
  else:
106
  error_msg = f"⚠️ Erreur API {response.status_code}: {response.text}"
@@ -111,15 +163,17 @@ class ImageGenerator:
111
  error_msg = f"⚠️ Erreur: {str(e)}"
112
  logger.exception("Erreur pendant la génération:")
113
  return None, error_msg
 
 
114
 
115
  def create_interface():
116
- """Crée l'interface utilisateur Gradio avec logging"""
117
  logger.info("Création de l'interface Gradio")
118
 
119
  css = """
120
  .container { max-width: 1200px; margin: auto; }
121
  .welcome { text-align: center; margin: 20px 0; padding: 20px; background: #1e293b; border-radius: 10px; }
122
  .controls-group { background: #2d3748; padding: 15px; border-radius: 5px; margin: 10px 0; }
 
123
  """
124
 
125
  generator = ImageGenerator()
@@ -133,7 +187,9 @@ def create_interface():
133
  """)
134
 
135
  with gr.Column(elem_classes="container"):
 
136
  with gr.Group(elem_classes="controls-group"):
 
137
  with gr.Row():
138
  format_size = gr.Dropdown(
139
  choices=["A4", "A3", "A2", "A1", "A0"],
@@ -146,14 +202,36 @@ def create_interface():
146
  label="Orientation"
147
  )
148
 
 
149
  with gr.Group(elem_classes="controls-group"):
150
- style = gr.Dropdown(
151
- choices=list(ART_STYLES.keys()),
152
- value="Neo Vintage",
153
- label="Style artistique"
154
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
 
 
156
  with gr.Group(elem_classes="controls-group"):
 
157
  subject = gr.Textbox(
158
  label="Description",
159
  placeholder="Décrivez votre vision..."
@@ -163,6 +241,33 @@ def create_interface():
163
  placeholder="Titre de l'affiche..."
164
  )
165
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
166
  with gr.Group(elem_classes="controls-group"):
167
  with gr.Row():
168
  quality = gr.Slider(
@@ -178,10 +283,12 @@ def create_interface():
178
  label="Créativité"
179
  )
180
 
 
181
  with gr.Row():
182
  generate_btn = gr.Button("✨ Générer", variant="primary")
183
  clear_btn = gr.Button("🗑️ Effacer", variant="secondary")
184
 
 
185
  image_output = gr.Image(label="Aperçu")
186
  status = gr.Textbox(label="Statut", interactive=False)
187
 
@@ -191,10 +298,16 @@ def create_interface():
191
  "format_size": args[0],
192
  "orientation": args[1],
193
  "style": args[2],
194
- "subject": args[3],
195
- "title": args[4],
196
- "quality": args[5],
197
- "creativity": args[6]
 
 
 
 
 
 
198
  }
199
  result = generator.generate(params)
200
  logger.info(f"Génération terminée avec statut: {result[1]}")
@@ -206,8 +319,14 @@ def create_interface():
206
  format_size,
207
  orientation,
208
  style,
 
 
 
209
  subject,
210
  title,
 
 
 
211
  quality,
212
  creativity
213
  ],
 
9
  import logging
10
  from dotenv import load_dotenv
11
 
12
+ # Configuration du logging
13
  logging.basicConfig(
14
  level=logging.DEBUG,
15
  format='%(asctime)s - %(levelname)s - %(message)s'
 
19
  # Chargement des variables d'environnement
20
  load_dotenv()
21
 
22
+ # Styles artistiques étendus
23
  ART_STYLES = {
24
  "Art Moderne": {
25
  "prompt_prefix": "modern art style poster, professional design",
 
36
  "Minimaliste": {
37
  "prompt_prefix": "minimalist design poster, clean composition",
38
  "negative_prompt": "complex, detailed, ornate, busy"
39
+ },
40
+ "Cyberpunk": {
41
+ "prompt_prefix": "cyberpunk style poster, neon lights, futuristic design",
42
+ "negative_prompt": "vintage, natural, rustic, traditional"
43
+ },
44
+ "Aquarelle": {
45
+ "prompt_prefix": "watercolor art style poster, fluid artistic design",
46
+ "negative_prompt": "digital, sharp, photorealistic"
47
+ },
48
+ "Art Déco": {
49
+ "prompt_prefix": "art deco style poster, geometric patterns, luxury design",
50
+ "negative_prompt": "modern, minimalist, casual"
51
+ },
52
+ "Japonais": {
53
+ "prompt_prefix": "japanese art style poster, ukiyo-e inspired design",
54
+ "negative_prompt": "western, modern, photographic"
55
+ }
56
+ }
57
+
58
+ # Paramètres de composition
59
+ COMPOSITION_PARAMS = {
60
+ "Layouts": {
61
+ "Centré": "centered composition, balanced layout",
62
+ "Asymétrique": "dynamic asymmetrical composition",
63
+ "Grille": "grid-based layout, structured composition",
64
+ "Diagonal": "diagonal dynamic composition",
65
+ "Minimaliste": "minimal composition, lots of whitespace"
66
+ },
67
+ "Ambiances": {
68
+ "Dramatique": "dramatic lighting, high contrast",
69
+ "Doux": "soft lighting, gentle atmosphere",
70
+ "Vibrant": "vibrant colors, energetic mood",
71
+ "Mystérieux": "mysterious atmosphere, moody lighting",
72
+ "Serein": "peaceful atmosphere, calm mood"
73
+ },
74
+ "Palette": {
75
+ "Monochrome": "monochromatic color scheme",
76
+ "Contrasté": "high contrast color palette",
77
+ "Pastel": "soft pastel color palette",
78
+ "Terre": "earthy color palette",
79
+ "Néon": "neon color palette"
80
  }
81
  }
82
 
 
85
  self.API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0"
86
  token = os.getenv('HUGGINGFACE_TOKEN')
87
  if not token:
88
+ logger.error("HUGGINGFACE_TOKEN non trouvé!")
89
  self.headers = {"Authorization": f"Bearer {token}"}
90
  logger.info("ImageGenerator initialisé")
91
 
92
  def _build_prompt(self, params: Dict[str, Any]) -> str:
93
+ """Construction de prompt améliorée"""
94
  style_info = ART_STYLES.get(params["style"], ART_STYLES["Neo Vintage"])
95
  prompt = f"{style_info['prompt_prefix']}, {params['subject']}"
96
+
97
+ # Ajout des paramètres de composition
98
+ if params.get("layout"):
99
+ prompt += f", {COMPOSITION_PARAMS['Layouts'][params['layout']]}"
100
+ if params.get("ambiance"):
101
+ prompt += f", {COMPOSITION_PARAMS['Ambiances'][params['ambiance']]}"
102
+ if params.get("palette"):
103
+ prompt += f", {COMPOSITION_PARAMS['Palette'][params['palette']]}"
104
+
105
+ # Ajout des ajustements fins
106
+ if params.get("detail_level"):
107
+ detail_strength = params["detail_level"]
108
+ prompt += f", {'highly detailed' if detail_strength > 7 else 'moderately detailed'}"
109
+
110
+ if params.get("contrast"):
111
+ contrast_strength = params["contrast"]
112
+ prompt += f", {'high contrast' if contrast_strength > 7 else 'balanced contrast'}"
113
+
114
+ if params.get("saturation"):
115
+ saturation_strength = params["saturation"]
116
+ prompt += f", {'vibrant colors' if saturation_strength > 7 else 'subtle colors'}"
117
+
118
  if params.get("title"):
119
  prompt += f", with text saying '{params['title']}'"
 
 
120
 
121
+ logger.debug(f"Prompt final: {prompt}")
122
+ return prompt
123
 
124
  def generate(self, params: Dict[str, Any]) -> Tuple[Optional[Image.Image], str]:
125
  try:
 
126
  logger.info(f"Début de génération avec paramètres: {json.dumps(params, indent=2)}")
127
 
 
128
  if 'Bearer None' in self.headers['Authorization']:
129
  return None, "⚠️ Erreur: Token Hugging Face non configuré"
130
 
 
131
  prompt = self._build_prompt(params)
132
+
133
+ # Configuration de base
 
134
  payload = {
135
  "inputs": prompt,
136
  "parameters": {
137
+ "negative_prompt": ART_STYLES[params["style"]]["negative_prompt"],
138
  "num_inference_steps": min(int(35 * (params["quality"]/100)), 40),
139
  "guidance_scale": min(7.5 * (params["creativity"]/10), 10.0),
140
  "width": 768,
 
142
  }
143
  }
144
 
145
+ logger.debug(f"Payload: {json.dumps(payload, indent=2)}")
146
 
 
 
147
  response = requests.post(
148
  self.API_URL,
149
  headers=self.headers,
 
151
  timeout=30
152
  )
153
 
 
 
 
154
  if response.status_code == 200:
155
  image = Image.open(io.BytesIO(response.content))
 
156
  return image, "✨ Création réussie!"
157
  else:
158
  error_msg = f"⚠️ Erreur API {response.status_code}: {response.text}"
 
163
  error_msg = f"⚠️ Erreur: {str(e)}"
164
  logger.exception("Erreur pendant la génération:")
165
  return None, error_msg
166
+ finally:
167
+ gc.collect()
168
 
169
  def create_interface():
 
170
  logger.info("Création de l'interface Gradio")
171
 
172
  css = """
173
  .container { max-width: 1200px; margin: auto; }
174
  .welcome { text-align: center; margin: 20px 0; padding: 20px; background: #1e293b; border-radius: 10px; }
175
  .controls-group { background: #2d3748; padding: 15px; border-radius: 5px; margin: 10px 0; }
176
+ .advanced-controls { background: #374151; padding: 12px; border-radius: 5px; margin: 8px 0; }
177
  """
178
 
179
  generator = ImageGenerator()
 
187
  """)
188
 
189
  with gr.Column(elem_classes="container"):
190
+ # Format et Orientation
191
  with gr.Group(elem_classes="controls-group"):
192
+ gr.Markdown("### 📐 Format et Orientation")
193
  with gr.Row():
194
  format_size = gr.Dropdown(
195
  choices=["A4", "A3", "A2", "A1", "A0"],
 
202
  label="Orientation"
203
  )
204
 
205
+ # Style et Composition
206
  with gr.Group(elem_classes="controls-group"):
207
+ gr.Markdown("### 🎨 Style et Composition")
208
+ with gr.Row():
209
+ style = gr.Dropdown(
210
+ choices=list(ART_STYLES.keys()),
211
+ value="Neo Vintage",
212
+ label="Style artistique"
213
+ )
214
+ layout = gr.Dropdown(
215
+ choices=list(COMPOSITION_PARAMS["Layouts"].keys()),
216
+ value="Centré",
217
+ label="Composition"
218
+ )
219
+
220
+ with gr.Row():
221
+ ambiance = gr.Dropdown(
222
+ choices=list(COMPOSITION_PARAMS["Ambiances"].keys()),
223
+ value="Dramatique",
224
+ label="Ambiance"
225
+ )
226
+ palette = gr.Dropdown(
227
+ choices=list(COMPOSITION_PARAMS["Palette"].keys()),
228
+ value="Contrasté",
229
+ label="Palette"
230
+ )
231
 
232
+ # Contenu
233
  with gr.Group(elem_classes="controls-group"):
234
+ gr.Markdown("### 📝 Contenu")
235
  subject = gr.Textbox(
236
  label="Description",
237
  placeholder="Décrivez votre vision..."
 
241
  placeholder="Titre de l'affiche..."
242
  )
243
 
244
+ # Ajustements fins
245
+ with gr.Group(elem_classes="advanced-controls"):
246
+ gr.Markdown("### 🎯 Ajustements Fins")
247
+ with gr.Row():
248
+ detail_level = gr.Slider(
249
+ minimum=1,
250
+ maximum=10,
251
+ value=7,
252
+ step=1,
253
+ label="Niveau de Détail"
254
+ )
255
+ contrast = gr.Slider(
256
+ minimum=1,
257
+ maximum=10,
258
+ value=5,
259
+ step=1,
260
+ label="Contraste"
261
+ )
262
+ saturation = gr.Slider(
263
+ minimum=1,
264
+ maximum=10,
265
+ value=5,
266
+ step=1,
267
+ label="Saturation"
268
+ )
269
+
270
+ # Paramètres de génération
271
  with gr.Group(elem_classes="controls-group"):
272
  with gr.Row():
273
  quality = gr.Slider(
 
283
  label="Créativité"
284
  )
285
 
286
+ # Boutons
287
  with gr.Row():
288
  generate_btn = gr.Button("✨ Générer", variant="primary")
289
  clear_btn = gr.Button("🗑️ Effacer", variant="secondary")
290
 
291
+ # Sortie
292
  image_output = gr.Image(label="Aperçu")
293
  status = gr.Textbox(label="Statut", interactive=False)
294
 
 
298
  "format_size": args[0],
299
  "orientation": args[1],
300
  "style": args[2],
301
+ "layout": args[3],
302
+ "ambiance": args[4],
303
+ "palette": args[5],
304
+ "subject": args[6],
305
+ "title": args[7],
306
+ "detail_level": args[8],
307
+ "contrast": args[9],
308
+ "saturation": args[10],
309
+ "quality": args[11],
310
+ "creativity": args[12]
311
  }
312
  result = generator.generate(params)
313
  logger.info(f"Génération terminée avec statut: {result[1]}")
 
319
  format_size,
320
  orientation,
321
  style,
322
+ layout,
323
+ ambiance,
324
+ palette,
325
  subject,
326
  title,
327
+ detail_level,
328
+ contrast,
329
+ saturation,
330
  quality,
331
  creativity
332
  ],