Equityone commited on
Commit
9d0c061
·
verified ·
1 Parent(s): a51d71a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +198 -183
app.py CHANGED
@@ -113,215 +113,230 @@ class ImageGenerator:
113
  f"https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0"
114
  )
115
 
116
- # Chargement du token Hugging Face depuis les variables d'environnement
117
- token = os.getenv('HUGGINGFACE_TOKEN')
118
- if not token:
119
- logger.error("HUGGINGFACE_TOKEN non trouvé!")
120
- self.headers = {"Authorization": f"Bearer {token}"}
121
- logger.info("ImageGenerator initialisé")
 
 
 
122
 
123
- def _build_prompt(self, params: Dict[str, Any]) -> str:
124
- """Construction de prompt améliorée"""
125
- style_info = ART_STYLES.get(params["style"], ART_STYLES["Neo Vintage"])
126
- prompt = f"{style_info['prompt_prefix']}, {params['subject']}"
 
 
127
 
128
- # Ajout des paramètres de composition
129
- if params.get("layout"):
130
- prompt += f", {COMPOSITION_PARAMS['Layouts'][params['layout']]}"
131
- if params.get("ambiance"):
132
- prompt += f", {COMPOSITION_PARAMS['Ambiances'][params['ambiance']]}"
133
- if params.get("palette"):
134
- prompt += f", {COMPOSITION_PARAMS['Palette'][params['palette']]}"
 
 
135
 
136
- # Ajout des ajustements fins
137
- if params.get("detail_level"):
138
- detail_strength = params["detail_level"]
139
- prompt += f", {'highly detailed' if detail_strength > 7 else 'moderately detailed'}"
140
- if params.get("contrast"):
141
- contrast_strength = params["contrast"]
142
- prompt += f", {'high contrast' if contrast_strength > 7 else 'balanced contrast'}"
143
- if params.get("saturation"):
144
- saturation_strength = params["saturation"]
145
- prompt += f", {'vibrant colors' if saturation_strength > 7 else 'subtle colors'}"
 
 
146
 
147
- if params.get("title"):
148
- prompt += f", with text saying '{params['title']}'"
149
 
150
- logger.debug(f"Prompt final: {prompt}")
151
- return prompt
 
152
 
153
- def generate(self, params: Dict[str, Any]) -> Tuple[Optional[Image.Image], str]:
154
- try:
155
- logger.info(f"Début de génération avec paramètres: {json.dumps(params)}")
156
- if 'Bearer None' in self.headers['Authorization']:
157
- return None,"⚠️ Erreur: Token Hugging Face non configuré"
 
 
158
 
159
- prompt = self._build_prompt(params)
160
- payload = {
161
- # Construction de la requête pour l'API Hugging Face
162
- “inputs”: prompt,
163
- parameters”: {
164
- negative_prompt”: ART_STYLES[params["style"]]["negative_prompt"],
165
- num_inference_steps”: min(int(35 * (params["quality"]/100)), 40),
166
- guidance_scale”: min(7.5 * (params["creativity"]/10), 10.0),
167
- width”: 768,
168
- height”: 768 if params["orientation"] == “Portrait” else 512
169
- }
170
- }
 
171
 
172
- logger.debug(f"Payload: {json.dumps(payload)}")
173
- response = requests.post(self.API_URL,
174
- headers=self.headers,
175
- json=payload,
176
- timeout=30)
 
177
 
178
- if response.status_code == 200:
179
- image = Image.open(io.BytesIO(response.content))
180
- return image,"✨ Création réussie!"
181
- else:
182
- error_msg = f"⚠️ Erreur API {response.status_code}: {response.text}"
183
- logger.error(error_msg)
184
- return None,error_msg
185
 
186
- except Exception as e:
187
- error_msg = f"⚠️ Erreur: {str(e)}"
188
- logger.exception("Erreur pendant la génération:")
189
- return None,error_msg
190
 
191
- finally:
192
- gc.collect()
193
 
194
  def create_interface():
195
- logger.info("Création de l'interface Gradio")
196
- css = """
197
- .container { max-width: 1200px; margin: auto; }
198
- .welcome { text-align: center; margin: 20px 0; padding: 20px; background: #3498db; border-radius: 10px; color: white; }
199
- .controls-group { background: #ecf0f1; padding: 15px; border-radius: 5px; margin: 10px 0; color: #2c3e50; }
200
- .advanced-controls { background: #bdc3c7; padding: 12px; border-radius: 5px; margin: 8px 0; }
201
- .gradio-slider input[type="range"] { accent-color: #3498db; }
202
- .gradio-button { transition: all 0.3s ease; }
203
- .gradio-button:hover { transform: translateY(-2px); box-shadow: 0 4px 6px rgba(52, 152, 219, 0.11),
204
- 0 1px 3px rgba(0 ,0 ,0 ,0.08); }
205
- """
 
206
 
207
- generator = ImageGenerator()
208
 
209
- with gr.Blocks(css=css) as app:
210
- gr.HTML("""
211
- <div class="welcome">
212
- <h1>🎨 Equity Artisan 4.0</h1>
213
- <p>Assistant de création d'affiches professionnelles avancé</p>
214
- </div>
215
- """)
216
 
217
- with gr.Column(elem_classes="container"):
218
- with gr.Group(elem_classes="controls-group"):
219
- gr.Markdown("### 📐 Format et Orientation")
220
- with gr.Row():
221
- format_size = gr.Dropdown(choices=["A4",
222
- A3",
223
- A2",
224
- A1",
225
- A0"],
226
- value="A4", label="Format")
227
- orientation = gr.Radio(choices=["Portrait",
228
- Paysage"],
229
- value="Portrait", label="Orientation")
230
 
231
- with gr.Group(elem_classes="controls-group"):
232
- gr.Markdown("### 🎨 Style et Composition")
233
- with gr.Row():
234
- style = gr.Dropdown(choices=list(ART_STYLES.keys()), value="Neo Vintage", label="Style artistique")
235
- layout = gr.Dropdown(choices=list(COMPOSITION_PARAMS["Layouts"].keys()), value="Centré", label="Composition")
236
- with gr.Row():
237
- ambiance = gr.Dropdown(choices=list(COMPOSITION_PARAMS["Ambiances"].keys()), value="Dramatique", label="Ambiance")
238
- palette = gr.Dropdown(choices=list(COMPOSITION_PARAMS["Palette"].keys()), value="Contrasté", label="Palette")
239
 
240
- with gr.Group(elem_classes="controls-group"):
241
- gr.Markdown("### 📝 Contenu")
242
- subject = gr.Textbox(label="Description", placeholder="Décrivez votre vision...")
243
- title = gr.Textbox(label="Titre", placeholder="Titre de l'affiche...")
244
 
245
- with gr.Group(elem_classes="advanced-controls"):
246
- gr.Markdown("### 🎯 Ajustements Fins")
247
- with gr.Row():
248
- detail_level = gr.Slider(minimum=1,
249
- maximum=10,
250
- value=7,
251
- step=1,
252
- label="Niveau de Détail")
253
- contrast = gr.Slider(minimum=1,
254
- maximum=10,
255
- value=5,
256
- step=1,
257
- label="Contraste")
258
- saturation = gr.Slider(minimum=1,
259
- maximum=10,
260
- value=5,
261
- step=1,
262
- label="Saturation")
263
 
264
- with gr.Group(elem_classes="controls-group"):
265
- with gr.Row():
266
- quality = gr.Slider(minimum=30,
267
- maximum=50,
268
- value=35,
269
- label="Qualité")
270
- creativity = gr.Slider(minimum=5,
271
- maximum=15,
272
- value=7.5,
273
- label="Créativité")
274
 
275
- with gr.Row():
276
- generate_btn = gr.Button("✨ Générer", variant="primary")
277
- clear_btn = gr.Button("🗑️ Effacer", variant="secondary")
278
 
279
- image_output = gr.Image(label="Aperçu")
280
- status = gr.Textbox(label="Statut", interactive=False)
281
 
282
- def generate(*args):
283
- logger.info("Démarrage d'une nouvelle génération")
284
- params = {
285
- “format_size”: args[0],
286
- “orientation”: args[1],
287
- “style”: args[2],
288
- “layout”: args[3],
289
- “ambiance”: args[4],
290
- “palette”: args[5],
291
- “subject”: args[6],
292
- “title”: args[7],
293
- “detail_level”: args[8],
294
- “contrast”: args[9],
295
- “saturation”: args[10],
296
- “quality”: args[11],
297
- “creativity”: args[12]
298
- }
299
- result = generator.generate(params)
300
- logger.info(f"Génération terminée avec statut: {result[1]}")
301
- return result
302
 
303
- generate_btn.click(
304
- generate,
305
- inputs=[format_size,
306
- orientation,
307
- style,
308
- layout,
309
- ambiance,
310
- palette,
311
- subject,
312
- title,
313
- detail_level,
314
- contrast,
315
- saturation,
316
- quality,
317
- creativity],
318
- outputs=[image_output,status]
319
- )
320
 
321
- clear_btn.click(lambda: (None,"🗑️ Image effacée"), outputs=[image_output,status])
322
 
323
- logger.info("Interface créée avec succès")
324
- return app
325
 
326
  if __name__ == "__main__":
327
  app=create_interface()
 
113
  f"https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0"
114
  )
115
 
116
+ # Chargement du token Hugging Face depuis les variables d'environnement
117
+ token = os.getenv('HUGGINGFACE_TOKEN')
118
+
119
+ if not token:
120
+ logger.error("HUGGINGFACE_TOKEN non trouvé!")
121
+
122
+ self.headers = {"Authorization": f"Bearer {token}"}
123
+
124
+ logger.info("ImageGenerator initialisé")
125
 
126
+ def _build_prompt(self, params: Dict[str, Any]) -> str:
127
+ """Construction de prompt améliorée"""
128
+
129
+ style_info = ART_STYLES.get(params["style"], ART_STYLES["Neo Vintage"])
130
+
131
+ prompt = f"{style_info['prompt_prefix']}, {params['subject']}"
132
 
133
+ # Ajout des paramètres de composition
134
+ if params.get("layout"):
135
+ prompt += f", {COMPOSITION_PARAMS['Layouts'][params['layout']]}"
136
+
137
+ if params.get("ambiance"):
138
+ prompt += f", {COMPOSITION_PARAMS['Ambiances'][params['ambiance']]}"
139
+
140
+ if params.get("palette"):
141
+ prompt += f", {COMPOSITION_PARAMS['Palette'][params['palette']]}"
142
 
143
+ # Ajout des ajustements fins
144
+ if params.get("detail_level"):
145
+ detail_strength = params["detail_level"]
146
+ prompt += f", {'highly detailed' if detail_strength > 7 else 'moderately detailed'}"
147
+
148
+ if params.get("contrast"):
149
+ contrast_strength = params["contrast"]
150
+ prompt += f", {'high contrast' if contrast_strength > 7 else 'balanced contrast'}"
151
+
152
+ if params.get("saturation"):
153
+ saturation_strength = params["saturation"]
154
+ prompt += f", {'vibrant colors' if saturation_strength > 7 else 'subtle colors'}"
155
 
156
+ if params.get("title"):
157
+ prompt += f", with text saying '{params['title']}'"
158
 
159
+ logger.debug(f"Prompt final: {prompt}")
160
+
161
+ return prompt
162
 
163
+ def generate(self, params: Dict[str, Any]) -> Tuple[Optional[Image.Image], str]:
164
+
165
+ try:
166
+ logger.info(f"Début de génération avec paramètres: {json.dumps(params)}")
167
+
168
+ if 'Bearer None' in self.headers['Authorization']:
169
+ return None,"⚠️ Erreur: Token Hugging Face non configuré"
170
 
171
+ prompt = self._build_prompt(params)
172
+
173
+ payload = {
174
+ # Construction de la requête pour l'API Hugging Face
175
+ inputs”: prompt,
176
+ parameters”: {
177
+ negative_prompt”: ART_STYLES[params["style"]]["negative_prompt"],
178
+ num_inference_steps”: min(int(35 * (params["quality"]/100)), 40),
179
+ guidance_scale”: min(7.5 * (params["creativity"]/10), 10.0),
180
+ width”: 768,
181
+ “height”: 768 if params["orientation"] == “Portrait” else 512
182
+ }
183
+ }
184
 
185
+ logger.debug(f"Payload: {json.dumps(payload)}")
186
+
187
+ response = requests.post(self.API_URL,
188
+ headers=self.headers,
189
+ json=payload,
190
+ timeout=30)
191
 
192
+ if response.status_code == 200:
193
+ image = Image.open(io.BytesIO(response.content))
194
+ return image,"✨ Création réussie!"
195
+ else:
196
+ error_msg = f"⚠️ Erreur API {response.status_code}: {response.text}"
197
+ logger.error(error_msg)
198
+ return None,error_msg
199
 
200
+ except Exception as e:
201
+ error_msg = f"⚠️ Erreur: {str(e)}"
202
+ logger.exception("Erreur pendant la génération:")
203
+ return None,error_msg
204
 
205
+ finally:
206
+ gc.collect()
207
 
208
  def create_interface():
209
+
210
+ logger.info("Création de l'interface Gradio")
211
+ css = """
212
+ .container { max-width: 1200px; margin: auto; }
213
+ .welcome { text-align: center; margin: 20px 0; padding: 20px; background: #3498db; border-radius: 10px; color: white; }
214
+ .controls-group { background: #ecf0f1; padding: 15px; border-radius: 5px; margin: 10px 0; color: #2c3e50; }
215
+ .advanced-controls { background: #bdc3c7; padding: 12px; border-radius: 5px; margin: 8px 0; }
216
+ .gradio-slider input[type="range"] { accent-color: #3498db; }
217
+ .gradio-button { transition: all 0.3s ease; }
218
+ .gradio-button:hover { transform: translateY(-2px); box-shadow: 0 4px 6px rgba(52, 152, 219, 0.11),
219
+ 0 1px 3px rgba(0 ,0 ,0 ,0.08); }
220
+ """
221
 
222
+ generator = ImageGenerator()
223
 
224
+ with gr.Blocks(css=css) as app:
225
+ gr.HTML("""
226
+ <div class="welcome">
227
+ <h1>🎨 Equity Artisan 4.0</h1>
228
+ <p>Assistant de création d'affiches professionnelles avancé</p>
229
+ </div>
230
+ """)
231
 
232
+ with gr.Column(elem_classes="container"):
233
+ with gr.Group(elem_classes="controls-group"):
234
+ gr.Markdown("### 📐 Format et Orientation")
235
+ with gr.Row():
236
+ format_size = gr.Dropdown(choices=["A4",
237
+ A3",
238
+ A2",
239
+ A1",
240
+ A0"],
241
+ value="A4", label="Format")
242
+ orientation = gr.Radio(choices=["Portrait",
243
+ Paysage"],
244
+ value="Portrait", label="Orientation")
245
 
246
+ with gr.Group(elem_classes="controls-group"):
247
+ gr.Markdown("### 🎨 Style et Composition")
248
+ with gr.Row():
249
+ style = gr.Dropdown(choices=list(ART_STYLES.keys()), value="Neo Vintage", label="Style artistique")
250
+ layout = gr.Dropdown(choices=list(COMPOSITION_PARAMS["Layouts"].keys()), value="Centré", label="Composition")
251
+ with gr.Row():
252
+ ambiance = gr.Dropdown(choices=list(COMPOSITION_PARAMS["Ambiances"].keys()), value="Dramatique", label="Ambiance")
253
+ palette = gr.Dropdown(choices=list(COMPOSITION_PARAMS["Palette"].keys()), value="Contrasté", label="Palette")
254
 
255
+ with gr.Group(elem_classes="controls-group"):
256
+ gr.Markdown("### 📝 Contenu")
257
+ subject = gr.Textbox(label="Description", placeholder="Décrivez votre vision...")
258
+ title = gr.Textbox(label="Titre", placeholder="Titre de l'affiche...")
259
 
260
+ with gr.Group(elem_classes="advanced-controls"):
261
+ gr.Markdown("### 🎯 Ajustements Fins")
262
+ with gr.Row():
263
+ detail_level = gr.Slider(minimum=1,
264
+ maximum=10,
265
+ value=7,
266
+ step=1,
267
+ label="Niveau de Détail")
268
+ contrast = gr.Slider(minimum=1,
269
+ maximum=10,
270
+ value=5,
271
+ step=1,
272
+ label="Contraste")
273
+ saturation = gr.Slider(minimum=1,
274
+ maximum=10,
275
+ value=5,
276
+ step=1,
277
+ label="Saturation")
278
 
279
+ with gr.Group(elem_classes="controls-group"):
280
+ with gr.Row():
281
+ quality = gr.Slider(minimum=30,
282
+ maximum=50,
283
+ value=35,
284
+ label="Qualité")
285
+ creativity = gr.Slider(minimum=5,
286
+ maximum=15,
287
+ value=7.5,
288
+ label="Créativité")
289
 
290
+ with gr.Row():
291
+ generate_btn = gr.Button("✨ Générer", variant="primary")
292
+ clear_btn = gr.Button("🗑️ Effacer", variant="secondary")
293
 
294
+ image_output = gr.Image(label="Aperçu")
295
+ status = gr.Textbox(label="Statut", interactive=False)
296
 
297
+ def generate(*args):
298
+ logger.info("Démarrage d'une nouvelle génération")
299
+ params = {
300
+ “format_size”: args[0],
301
+ “orientation”: args[1],
302
+ “style”: args[2],
303
+ “layout”: args[3],
304
+ “ambiance”: args[4],
305
+ “palette”: args[5],
306
+ “subject”: args[6],
307
+ “title”: args[7],
308
+ “detail_level”: args[8],
309
+ “contrast”: args[9],
310
+ “saturation”: args[10],
311
+ “quality”: args[11],
312
+ “creativity”: args[12]
313
+ }
314
+ result = generator.generate(params)
315
+ logger.info(f"Génération terminée avec statut: {result[1]}")
316
+ return result
317
 
318
+ generate_btn.click(
319
+ generate,
320
+ inputs=[format_size,
321
+ orientation,
322
+ style,
323
+ layout,
324
+ ambiance,
325
+ palette,
326
+ subject,
327
+ title,
328
+ detail_level,
329
+ contrast,
330
+ saturation,
331
+ quality,
332
+ creativity],
333
+ outputs=[image_output,status]
334
+ )
335
 
336
+ clear_btn.click(lambda: (None,"🗑️ Image effacée"), outputs=[image_output,status])
337
 
338
+ logger.info("Interface créée avec succès")
339
+ return app
340
 
341
  if __name__ == "__main__":
342
  app=create_interface()