Equityone commited on
Commit
2513859
·
verified ·
1 Parent(s): 0c4498a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -134
app.py CHANGED
@@ -5,6 +5,7 @@ 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
@@ -17,75 +18,14 @@ logger = logging.getLogger(__name__)
17
  load_dotenv()
18
 
19
  # Constantes
20
- MAX_STEPS = 40
21
- MAX_GUIDANCE_SCALE = 10.0
22
  DEFAULT_WIDTH = 768
23
  DEFAULT_HEIGHT = 768
24
 
25
- # Styles artistiques étendus
26
- ART_STYLES = {
27
- "Art Moderne": {
28
- "prompt_prefix": "modern art style poster, professional design",
29
- "negative_prompt": "traditional, photorealistic, cluttered, busy design"
30
- },
31
- "Neo Vintage": {
32
- "prompt_prefix": "vintage style advertising poster, retro design",
33
- "negative_prompt": "modern, digital, contemporary style"
34
- },
35
- "Pop Art": {
36
- "prompt_prefix": "pop art style poster, bold design",
37
- "negative_prompt": "subtle, realistic, traditional art"
38
- },
39
- "Minimaliste": {
40
- "prompt_prefix": "minimalist design poster, clean composition",
41
- "negative_prompt": "complex, detailed, ornate, busy"
42
- },
43
- "Cyberpunk": {
44
- "prompt_prefix": "cyberpunk style poster, neon lights, futuristic design",
45
- "negative_prompt": "vintage, natural, rustic, traditional"
46
- },
47
- "Aquarelle": {
48
- "prompt_prefix": "watercolor art style poster, fluid artistic design",
49
- "negative_prompt": "digital, sharp, photorealistic"
50
- },
51
- "Art Déco": {
52
- "prompt_prefix": "art deco style poster, geometric patterns, luxury design",
53
- "negative_prompt": "modern, minimalist, casual"
54
- },
55
- "Japonais": {
56
- "prompt_prefix": "japanese art style poster, ukiyo-e inspired design",
57
- "negative_prompt": "western, modern, photographic"
58
- },
59
- "Ultra Réaliste": {
60
- "prompt_prefix": "hyper-realistic poster, photographic quality, extremely detailed",
61
- "negative_prompt": "cartoon, illustration, stylized, abstract"
62
- }
63
- }
64
-
65
- # Paramètres de composition
66
- COMPOSITION_PARAMS = {
67
- "Layouts": {
68
- "Centré": "centered composition, balanced layout",
69
- "Asymétrique": "dynamic asymmetrical composition",
70
- "Grille": "grid-based layout, structured composition",
71
- "Diagonal": "diagonal dynamic composition",
72
- "Minimaliste": "minimal composition, lots of whitespace"
73
- },
74
- "Ambiances": {
75
- "Dramatique": "dramatic lighting, high contrast",
76
- "Doux": "soft lighting, gentle atmosphere",
77
- "Vibrant": "vibrant colors, energetic mood",
78
- "Mystérieux": "mysterious atmosphere, moody lighting",
79
- "Serein": "peaceful atmosphere, calm mood"
80
- },
81
- "Palette": {
82
- "Monochrome": "monochromatic color scheme",
83
- "Contrasté": "high contrast color palette",
84
- "Pastel": "soft pastel color palette",
85
- "Terre": "earthy color palette",
86
- "Néon": "neon color palette"
87
- }
88
- }
89
 
90
  class ImageGenerator:
91
  def __init__(self):
@@ -99,11 +39,11 @@ class ImageGenerator:
99
  def _build_prompt(self, params: Dict[str, Any]) -> str:
100
  style_info = ART_STYLES.get(params["style"], ART_STYLES["Neo Vintage"])
101
  prompt = f"{style_info['prompt_prefix']}, {params['subject']}"
102
-
103
  for param_type in ['layout', 'ambiance', 'palette']:
104
  if params.get(param_type):
105
  prompt += f", {COMPOSITION_PARAMS[param_type.capitalize() + 's'][params[param_type]]}"
106
-
107
  for param, description in [
108
  ("detail_level", "highly detailed" if params.get("detail_level", 0) > 7 else "moderately detailed"),
109
  ("contrast", "high contrast" if params.get("contrast", 0) > 7 else "balanced contrast"),
@@ -111,47 +51,52 @@ class ImageGenerator:
111
  ]:
112
  if params.get(param):
113
  prompt += f", {description}"
114
-
115
  if params.get("title"):
116
  prompt += f", with text saying '{params['title']}'"
117
-
118
  logger.debug(f"Prompt final: {prompt}")
119
  return prompt
120
 
121
  def generate(self, params: Dict[str, Any]) -> Tuple[Optional[Image.Image], str]:
122
- try:
123
- logger.info(f"Début de génération avec paramètres: {json.dumps(params, indent=2)}")
124
- if 'Bearer None' in self.headers['Authorization']:
125
- return None, "⚠️ Erreur: Token Hugging Face non configuré"
126
-
127
- prompt = self._build_prompt(params)
128
- payload = {
129
- "inputs": prompt,
130
- "parameters": {
131
- "negative_prompt": ART_STYLES[params["style"]]["negative_prompt"],
132
- "num_inference_steps": min(int(35 * (params["quality"]/100)), MAX_STEPS),
133
- "guidance_scale": min(7.5 * (params["creativity"]/10), MAX_GUIDANCE_SCALE),
134
- "width": DEFAULT_WIDTH,
135
- "height": DEFAULT_HEIGHT if params["orientation"] == "Portrait" else DEFAULT_WIDTH
 
 
136
  }
137
- }
138
-
139
- logger.debug(f"Payload: {json.dumps(payload, indent=2)}")
140
- response = requests.post(self.API_URL, headers=self.headers, json=payload, timeout=30)
141
-
142
- if response.status_code == 200:
143
  image = Image.open(io.BytesIO(response.content))
144
  return image, "✨ Création réussie!"
145
- else:
146
- error_msg = f"⚠️ Erreur API {response.status_code}: {response.text}"
147
- logger.error(error_msg)
148
- return None, error_msg
149
- except Exception as e:
150
- error_msg = f"⚠️ Erreur: {str(e)}"
151
- logger.exception("Erreur pendant la génération:")
152
- return None, error_msg
153
- finally:
154
- gc.collect()
 
 
 
 
155
 
156
  def create_interface():
157
  logger.info("Création de l'interface Gradio")
@@ -160,9 +105,6 @@ def create_interface():
160
  .welcome { text-align: center; margin: 20px 0; padding: 20px; background: #1e293b; border-radius: 10px; color: white; }
161
  .controls-group { background: #2d3748; padding: 15px; border-radius: 5px; margin: 10px 0; color: white; }
162
  .advanced-controls { background: #374151; padding: 12px; border-radius: 5px; margin: 8px 0; }
163
- .gradio-slider input[type="range"] { accent-color: #4a5568; }
164
- .gradio-button { transition: all 0.3s ease; }
165
- .gradio-button:hover { transform: translateY(-2px); box-shadow: 0 4px 6px rgba(50, 50, 93, 0.11), 0 1px 3px rgba(0, 0, 0, 0.08); }
166
  """
167
 
168
  generator = ImageGenerator()
@@ -176,37 +118,8 @@ def create_interface():
176
  """)
177
 
178
  with gr.Column(elem_classes="container"):
179
- with gr.Group(elem_classes="controls-group"):
180
- gr.Markdown("### 📐 Format et Orientation")
181
- with gr.Row():
182
- format_size = gr.Dropdown(choices=["A4", "A3", "A2", "A1", "A0"], value="A4", label="Format")
183
- orientation = gr.Radio(choices=["Portrait", "Paysage"], value="Portrait", label="Orientation")
184
-
185
- with gr.Group(elem_classes="controls-group"):
186
- gr.Markdown("### 🎨 Style et Composition")
187
- with gr.Row():
188
- style = gr.Dropdown(choices=list(ART_STYLES.keys()), value="Neo Vintage", label="Style artistique")
189
- layout = gr.Dropdown(choices=list(COMPOSITION_PARAMS["Layouts"].keys()), value="Centré", label="Composition")
190
- with gr.Row():
191
- ambiance = gr.Dropdown(choices=list(COMPOSITION_PARAMS["Ambiances"].keys()), value="Dramatique", label="Ambiance")
192
- palette = gr.Dropdown(choices=list(COMPOSITION_PARAMS["Palette"].keys()), value="Contrasté", label="Palette")
193
-
194
- with gr.Group(elem_classes="controls-group"):
195
- gr.Markdown("### 📝 Contenu")
196
- subject = gr.Textbox(label="Description", placeholder="Décrivez votre vision...")
197
- title = gr.Textbox(label="Titre", placeholder="Titre de l'affiche...")
198
-
199
- with gr.Group(elem_classes="advanced-controls"):
200
- gr.Markdown("### 🎯 Ajustements Fins")
201
- with gr.Row():
202
- detail_level = gr.Slider(minimum=1, maximum=10, value=7, step=1, label="Niveau de Détail")
203
- contrast = gr.Slider(minimum=1, maximum=10, value=5, step=1, label="Contraste")
204
- saturation = gr.Slider(minimum=1, maximum=10, value=5, step=1, label="Saturation")
205
-
206
- with gr.Group(elem_classes="controls-group"):
207
- with gr.Row():
208
- quality = gr.Slider(minimum=30, maximum=50, value=35, label="Qualité")
209
- creativity = gr.Slider(minimum=5, maximum=15, value=7.5, label="Créativité")
210
 
211
  with gr.Row():
212
  generate_btn = gr.Button("✨ Générer", variant="primary")
 
5
  import io
6
  import gc
7
  import json
8
+ import time
9
  from typing import Tuple, Optional, Dict, Any
10
  import logging
11
  from dotenv import load_dotenv
 
18
  load_dotenv()
19
 
20
  # Constantes
21
+ MAX_RETRIES = 3
22
+ TIMEOUT = 60
23
  DEFAULT_WIDTH = 768
24
  DEFAULT_HEIGHT = 768
25
 
26
+ # Styles artistiques et paramètres de composition (inchangés)
27
+ ART_STYLES = {...} # Gardez la définition existante
28
+ COMPOSITION_PARAMS = {...} # Gardez la définition existante
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
  class ImageGenerator:
31
  def __init__(self):
 
39
  def _build_prompt(self, params: Dict[str, Any]) -> str:
40
  style_info = ART_STYLES.get(params["style"], ART_STYLES["Neo Vintage"])
41
  prompt = f"{style_info['prompt_prefix']}, {params['subject']}"
42
+
43
  for param_type in ['layout', 'ambiance', 'palette']:
44
  if params.get(param_type):
45
  prompt += f", {COMPOSITION_PARAMS[param_type.capitalize() + 's'][params[param_type]]}"
46
+
47
  for param, description in [
48
  ("detail_level", "highly detailed" if params.get("detail_level", 0) > 7 else "moderately detailed"),
49
  ("contrast", "high contrast" if params.get("contrast", 0) > 7 else "balanced contrast"),
 
51
  ]:
52
  if params.get(param):
53
  prompt += f", {description}"
54
+
55
  if params.get("title"):
56
  prompt += f", with text saying '{params['title']}'"
57
+
58
  logger.debug(f"Prompt final: {prompt}")
59
  return prompt
60
 
61
  def generate(self, params: Dict[str, Any]) -> Tuple[Optional[Image.Image], str]:
62
+ for attempt in range(MAX_RETRIES):
63
+ try:
64
+ logger.info(f"Tentative de génération {attempt + 1}/{MAX_RETRIES}")
65
+ if 'Bearer None' in self.headers['Authorization']:
66
+ return None, "⚠️ Erreur: Token Hugging Face non configuré"
67
+
68
+ prompt = self._build_prompt(params)
69
+ payload = {
70
+ "inputs": prompt,
71
+ "parameters": {
72
+ "negative_prompt": ART_STYLES[params["style"]]["negative_prompt"],
73
+ "num_inference_steps": min(int(35 * (params["quality"]/100)), 50),
74
+ "guidance_scale": min(7.5 * (params["creativity"]/10), 15.0),
75
+ "width": DEFAULT_WIDTH,
76
+ "height": DEFAULT_HEIGHT if params["orientation"] == "Portrait" else DEFAULT_WIDTH
77
+ }
78
  }
79
+
80
+ logger.debug(f"Payload: {json.dumps(payload, indent=2)}")
81
+ response = requests.post(self.API_URL, headers=self.headers, json=payload, timeout=TIMEOUT)
82
+ response.raise_for_status()
83
+
 
84
  image = Image.open(io.BytesIO(response.content))
85
  return image, "✨ Création réussie!"
86
+
87
+ except requests.exceptions.RequestException as e:
88
+ logger.warning(f"Erreur de requête à la tentative {attempt + 1}: {str(e)}")
89
+ if attempt < MAX_RETRIES - 1:
90
+ time.sleep(2 ** attempt) # Attente exponentielle
91
+ else:
92
+ return None, f"⚠️ Erreur de connexion après {MAX_RETRIES} tentatives: {str(e)}"
93
+
94
+ except Exception as e:
95
+ logger.exception("Erreur inattendue pendant la génération:")
96
+ return None, f"⚠️ Erreur inattendue: {str(e)}"
97
+
98
+ finally:
99
+ gc.collect()
100
 
101
  def create_interface():
102
  logger.info("Création de l'interface Gradio")
 
105
  .welcome { text-align: center; margin: 20px 0; padding: 20px; background: #1e293b; border-radius: 10px; color: white; }
106
  .controls-group { background: #2d3748; padding: 15px; border-radius: 5px; margin: 10px 0; color: white; }
107
  .advanced-controls { background: #374151; padding: 12px; border-radius: 5px; margin: 8px 0; }
 
 
 
108
  """
109
 
110
  generator = ImageGenerator()
 
118
  """)
119
 
120
  with gr.Column(elem_classes="container"):
121
+ # Ajoutez ici les éléments d'interface comme dans votre code original
122
+ # (format_size, orientation, style, layout, ambiance, palette, subject, title, etc.)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
  with gr.Row():
125
  generate_btn = gr.Button("✨ Générer", variant="primary")