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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +88 -77
app.py CHANGED
@@ -4,105 +4,127 @@ from PIL import Image
4
  import requests
5
  import io
6
  import gc
 
7
  from typing import Tuple, Optional, Dict, Any
8
  import logging
9
  from dotenv import load_dotenv
10
 
11
- # Configuration du logging
12
- logging.basicConfig(level=logging.INFO)
 
 
 
13
  logger = logging.getLogger(__name__)
14
 
15
  # Chargement des variables d'environnement
16
  load_dotenv()
17
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  class ImageGenerator:
19
- """Gestionnaire de génération d'images optimisé pour les ressources limitées"""
20
-
21
  def __init__(self):
22
  self.API_URL = "https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-xl-base-1.0"
23
- self.headers = {"Authorization": f"Bearer {os.getenv('HUGGINGFACE_TOKEN')}"}
24
-
25
- # Configurations optimisées pour les ressources limitées
26
- self.MAX_IMAGE_SIZE = 768 # Limite la taille maximale pour la mémoire
27
- self.MAX_STEPS = 40 # Limite les steps pour optimiser le temps
28
- self.DEFAULT_TIMEOUT = 30
29
-
30
- @staticmethod
31
- def get_image_dimensions(format_size: str, orientation: str) -> Tuple[int, int]:
32
- """Calcule les dimensions optimisées selon le format"""
33
- base_dimensions = {
34
- "A4": (768, 1024),
35
- "A3": (768, 1024),
36
- "A2": (768, 1024),
37
- "A1": (768, 1024),
38
- "A0": (768, 1024)
39
- }
40
- width, height = base_dimensions.get(format_size, (768, 768))
41
- return (height, width) if orientation == "Paysage" else (width, height)
42
 
43
  def generate(self, params: Dict[str, Any]) -> Tuple[Optional[Image.Image], str]:
44
- """Génère une image avec gestion optimisée des ressources"""
45
  try:
46
- # Nettoyage mémoire préventif
47
- gc.collect()
48
-
49
- # Préparation des dimensions
50
- width, height = self.get_image_dimensions(params["format_size"], params["orientation"])
51
 
 
 
 
 
52
  # Construction du prompt
53
  prompt = self._build_prompt(params)
54
-
 
55
  # Configuration de la requête
56
  payload = {
57
  "inputs": prompt,
58
  "parameters": {
59
  "negative_prompt": self._get_negative_prompt(params["style"]),
60
- "num_inference_steps": min(int(35 * (params["quality"]/100)), self.MAX_STEPS),
61
  "guidance_scale": min(7.5 * (params["creativity"]/10), 10.0),
62
- "width": width,
63
- "height": height
64
  }
65
  }
66
 
67
- logger.info(f"Génération avec prompt: {prompt}")
68
-
69
- # Requête API avec gestion d'erreur
 
70
  response = requests.post(
71
  self.API_URL,
72
  headers=self.headers,
73
  json=payload,
74
- timeout=self.DEFAULT_TIMEOUT
75
  )
76
 
 
 
 
77
  if response.status_code == 200:
78
  image = Image.open(io.BytesIO(response.content))
 
79
  return image, "✨ Création réussie!"
80
  else:
81
- logger.error(f"Erreur API: {response.status_code} - {response.text}")
82
- return None, f"⚠️ Erreur {response.status_code}: Ajustez les paramètres"
83
-
 
84
  except Exception as e:
85
- logger.error(f"Erreur de génération: {str(e)}")
86
- return None, f"⚠️ Erreur: {str(e)}"
87
- finally:
88
- gc.collect() # Nettoyage final
89
 
90
  def create_interface():
91
- """Crée l'interface utilisateur Gradio"""
 
92
 
93
- # CSS optimisé
94
  css = """
95
  .container { max-width: 1200px; margin: auto; }
96
  .welcome { text-align: center; margin: 20px 0; padding: 20px; background: #1e293b; border-radius: 10px; }
97
  .controls-group { background: #2d3748; padding: 15px; border-radius: 5px; margin: 10px 0; }
98
  """
99
 
100
- # Initialisation du générateur
101
  generator = ImageGenerator()
102
 
103
- # Interface Gradio optimisée
104
  with gr.Blocks(css=css) as app:
105
- # En-tête
106
  gr.HTML("""
107
  <div class="welcome">
108
  <h1>🎨 Equity Artisan 3.0</h1>
@@ -110,9 +132,7 @@ def create_interface():
110
  </div>
111
  """)
112
 
113
- # Conteneur principal
114
  with gr.Column(elem_classes="container"):
115
- # Groupe Format
116
  with gr.Group(elem_classes="controls-group"):
117
  with gr.Row():
118
  format_size = gr.Dropdown(
@@ -126,21 +146,13 @@ def create_interface():
126
  label="Orientation"
127
  )
128
 
129
- # Groupe Style
130
  with gr.Group(elem_classes="controls-group"):
131
- with gr.Row():
132
- style = gr.Dropdown(
133
- choices=["Art Moderne", "Neo Vintage", "Pop Art", "Minimaliste"],
134
- value="Neo Vintage",
135
- label="Style artistique"
136
- )
137
- text_effect = gr.Dropdown(
138
- choices=["Standard", "Néon", "3D", "Métallique", "Graffiti"],
139
- value="Standard",
140
- label="Effet de texte"
141
- )
142
 
143
- # Groupe Contenu
144
  with gr.Group(elem_classes="controls-group"):
145
  subject = gr.Textbox(
146
  label="Description",
@@ -151,7 +163,6 @@ def create_interface():
151
  placeholder="Titre de l'affiche..."
152
  )
153
 
154
- # Groupe Qualité
155
  with gr.Group(elem_classes="controls-group"):
156
  with gr.Row():
157
  quality = gr.Slider(
@@ -167,37 +178,35 @@ def create_interface():
167
  label="Créativité"
168
  )
169
 
170
- # Boutons
171
  with gr.Row():
172
  generate_btn = gr.Button("✨ Générer", variant="primary")
173
  clear_btn = gr.Button("🗑️ Effacer", variant="secondary")
174
 
175
- # Sortie
176
  image_output = gr.Image(label="Aperçu")
177
  status = gr.Textbox(label="Statut", interactive=False)
178
 
179
- # Événements
180
  def generate(*args):
 
181
  params = {
182
  "format_size": args[0],
183
  "orientation": args[1],
184
- "subject": args[2],
185
- "style": args[3],
186
- "text_effect": args[4],
187
- "title": args[5],
188
- "quality": args[6],
189
- "creativity": args[7]
190
  }
191
- return generator.generate(params)
 
 
192
 
193
  generate_btn.click(
194
  generate,
195
  inputs=[
196
  format_size,
197
  orientation,
198
- subject,
199
  style,
200
- text_effect,
201
  title,
202
  quality,
203
  creativity
@@ -210,8 +219,10 @@ def create_interface():
210
  outputs=[image_output, status]
211
  )
212
 
 
213
  return app
214
 
215
  if __name__ == "__main__":
216
  app = create_interface()
 
217
  app.launch()
 
4
  import requests
5
  import io
6
  import gc
7
+ import json
8
  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'
16
+ )
17
  logger = logging.getLogger(__name__)
18
 
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",
26
+ "negative_prompt": "traditional, photorealistic, cluttered, busy design"
27
+ },
28
+ "Neo Vintage": {
29
+ "prompt_prefix": "vintage style advertising poster, retro design",
30
+ "negative_prompt": "modern, digital, contemporary style"
31
+ },
32
+ "Pop Art": {
33
+ "prompt_prefix": "pop art style poster, bold design",
34
+ "negative_prompt": "subtle, realistic, traditional art"
35
+ },
36
+ "Minimaliste": {
37
+ "prompt_prefix": "minimalist design poster, clean composition",
38
+ "negative_prompt": "complex, detailed, ornate, busy"
39
+ }
40
+ }
41
+
42
  class ImageGenerator:
 
 
43
  def __init__(self):
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,
83
+ "height": 768 if params["orientation"] == "Portrait" else 512
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,
94
  json=payload,
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}"
107
+ logger.error(error_msg)
108
+ return None, error_msg
109
+
110
  except Exception as e:
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()
126
 
 
127
  with gr.Blocks(css=css) as app:
 
128
  gr.HTML("""
129
  <div class="welcome">
130
  <h1>🎨 Equity Artisan 3.0</h1>
 
132
  </div>
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(
 
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",
 
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
  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
 
 
188
  def generate(*args):
189
+ logger.info("Démarrage d'une nouvelle génération")
190
  params = {
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]}")
201
+ return result
202
 
203
  generate_btn.click(
204
  generate,
205
  inputs=[
206
  format_size,
207
  orientation,
 
208
  style,
209
+ subject,
210
  title,
211
  quality,
212
  creativity
 
219
  outputs=[image_output, status]
220
  )
221
 
222
+ logger.info("Interface créée avec succès")
223
  return app
224
 
225
  if __name__ == "__main__":
226
  app = create_interface()
227
+ logger.info("Démarrage de l'application")
228
  app.launch()