Dax451 commited on
Commit
20cbb2a
·
verified ·
1 Parent(s): 6a39af6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +216 -184
app.py CHANGED
@@ -1,159 +1,213 @@
1
- """
2
- FLUX Image Generator - Nineteen.ai API (Versione HF Spaces)
3
- --------------------------------------
4
- Questo script utilizza l'API di Nineteen.ai per generare immagini
5
- con il modello FLUX.1-schnell, offrendo un'interfaccia grafica intuitiva.
6
- Versione ottimizzata per Hugging Face Spaces con autenticazione.
7
-
8
- Autore: Utente
9
- Data: 09/03/2025
10
- """
11
-
12
  import os
13
- import io
14
- import time
15
- import base64
16
- import requests
17
  import gradio as gr
 
18
  from PIL import Image
 
 
19
  from dotenv import load_dotenv
 
 
 
20
 
21
  # Carica le variabili d'ambiente (se presenti)
22
  load_dotenv()
23
 
24
  class FluxNineteenGenerator:
25
- """
26
- Classe per generare immagini utilizzando il modello FLUX.1-schnell
27
- attraverso l'API di Nineteen.ai.
28
- """
29
 
30
  def __init__(self):
31
- """
32
- Inizializza il generatore di immagini FLUX tramite API Nineteen.ai.
33
- """
34
  print("Inizializzazione del generatore di immagini FLUX Nineteen.ai...")
35
 
36
  # Ottieni l'API key da variabile d'ambiente
37
  self.api_key = os.getenv("NINETEEN_API_KEY")
38
  if not self.api_key:
39
- raise ValueError("È necessario configurare la variabile d'ambiente NINETEEN_API_KEY")
 
 
 
 
40
 
41
  # Configurazione dell'API
42
  self.api_endpoint = "https://api.nineteen.ai/v1/text-to-image"
43
  self.headers = {
44
  "Authorization": f"Bearer {self.api_key}",
45
- "accept": "application/json",
46
  "Content-Type": "application/json"
47
  }
48
 
49
- # Modelli disponibili
50
- self.models = ["black-forest-labs/FLUX.1-schnell", "black-forest-labs/FLUX.1-dev"]
51
  self.default_model = "black-forest-labs/FLUX.1-schnell"
52
-
53
  print(f"Generatore inizializzato con modello predefinito: {self.default_model}")
 
 
 
 
 
 
 
54
 
55
- def generate_image(self, prompt, model=None, steps=8, cfg_scale=3,
56
- height=1024, width=1024, negative_prompt=""):
57
  """
58
- Genera un'immagine utilizzando l'API di Nineteen.ai.
59
 
60
  Args:
61
- prompt (str): Descrizione testuale dell'immagine da generare
62
- model (str, optional): Modello da utilizzare
63
- steps (int): Numero di passi di inferenza
64
- cfg_scale (float): Scala di guidance per la generazione
65
- height (int): Altezza dell'immagine in pixel
66
- width (int): Larghezza dell'immagine in pixel
67
- negative_prompt (str): Prompt negativo per escludere elementi indesiderati
68
-
69
  Returns:
70
- PIL.Image: L'immagine generata
71
- str: Messaggio di stato
72
  """
73
- if not model:
74
- model = self.default_model
75
-
76
  try:
77
- # Prepara il payload
78
- data = {
 
 
 
 
 
 
 
 
79
  "prompt": prompt,
80
  "model": model,
81
- "steps": steps,
82
- "cfg_scale": cfg_scale,
83
  "height": height,
84
- "width": width,
85
- "negativePrompt": negative_prompt
86
  }
87
 
88
- # Log della richiesta
 
 
89
  print(f"Generazione immagine con prompt: '{prompt}'")
90
- print(f"Parametri: modello={model}, steps={steps}, cfg_scale={cfg_scale}, dimensioni={width}x{height}")
91
 
92
- # Effettua la chiamata API
93
  start_time = time.time()
94
- response = requests.post(self.api_endpoint, headers=self.headers, json=data)
95
- end_time = time.time()
96
 
97
- # Gestione degli errori
 
 
 
 
 
 
 
98
  if response.status_code != 200:
99
  error_message = f"Errore API: {response.status_code} - {response.text}"
100
  print(error_message)
101
  return None, error_message
102
 
103
- # Estrai l'immagine in formato base64 dalla risposta
 
104
  try:
105
  image_b64 = response.json()["image_b64"]
106
  image_data = base64.b64decode(image_b64)
107
- image = Image.open(io.BytesIO(image_data))
108
 
109
  print(f"Immagine generata in {end_time - start_time:.2f} secondi")
110
  return image, f"Immagine generata in {end_time - start_time:.2f} secondi"
111
- except KeyError:
112
- return None, f"Errore: La risposta API non contiene il campo 'image_b64'. Risposta: {response.json()}"
113
  except Exception as e:
114
- return None, f"Errore nel decodificare l'immagine: {str(e)}"
 
 
115
 
116
  except Exception as e:
117
- error_message = f"Errore durante la generazione dell'immagine: {str(e)}"
118
  print(error_message)
119
  return None, error_message
120
 
121
- def create_ui(generator):
122
- """
123
- Crea l'interfaccia utente Gradio.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
 
125
- Args:
126
- generator (FluxNineteenGenerator): Istanza del generatore
 
127
 
128
- Returns:
129
- gradio.Interface: L'interfaccia Gradio
130
- """
 
 
 
131
 
132
- def generate_image_ui(prompt, model, steps, cfg_scale, height, width, negative_prompt):
133
  """Funzione per generare immagini dall'interfaccia"""
134
- # Validazione dei parametri
135
- if not prompt or len(prompt.strip()) == 0:
136
- return None, "Il prompt non può essere vuoto."
137
-
138
  try:
139
- # Converti i parametri al tipo corretto
140
- steps = int(steps)
141
- cfg_scale = float(cfg_scale)
142
- height = int(height)
143
- width = int(width)
144
-
145
- # Validazione dei valori
146
- if steps < 1 or steps > 50:
147
- return None, "Il numero di passi deve essere compreso tra 1 e 50."
148
- if cfg_scale < 1 or cfg_scale > 30:
149
- return None, "La guidance scale deve essere compresa tra 1 e 30."
150
- if height < 512 or height > 1536:
151
- return None, "L'altezza deve essere compresa tra 512 e 1536 pixel."
152
- if width < 512 or width > 1536:
153
- return None, "La larghezza deve essere compresa tra 512 e 1536 pixel."
154
-
155
- # Genera l'immagine
156
- return generator.generate_image(
157
  prompt=prompt,
158
  model=model,
159
  steps=steps,
@@ -163,124 +217,102 @@ def create_ui(generator):
163
  negative_prompt=negative_prompt
164
  )
165
  except Exception as e:
166
- return None, f"Errore: {str(e)}"
167
 
168
- # Crea i componenti dell'interfaccia
169
- with gr.Blocks(title="FLUX Nineteen.ai Image Generator") as interface:
170
- gr.Markdown("# FLUX Nineteen.ai Image Generator")
171
- gr.Markdown("Genera immagini utilizzando il modello FLUX.1-schnell tramite l'API di Nineteen.ai")
172
 
173
  with gr.Row():
174
- with gr.Column(scale=3):
175
  prompt_input = gr.Textbox(
176
  label="Prompt",
177
- placeholder="Descrivi l'immagine che desideri generare...",
178
  lines=3
179
  )
180
 
181
- negative_prompt_input = gr.Textbox(
182
- label="Prompt Negativo (opzionale)",
183
- placeholder="Elementi da escludere dall'immagine...",
184
- lines=2
185
- )
186
-
187
- model_input = gr.Dropdown(
188
- generator.models,
189
- label="Modello",
190
- value=generator.default_model
191
- )
192
-
193
  with gr.Row():
 
 
 
 
 
 
 
 
 
 
194
  steps_input = gr.Slider(
195
  minimum=1,
196
- maximum=50,
197
- value=8,
198
  step=1,
199
- label="Passi di Inferenza"
200
  )
 
201
  cfg_input = gr.Slider(
202
  minimum=1.0,
203
- maximum=30.0,
204
- value=3.0,
205
- step=0.1,
206
- label="Guidance Scale (CFG)"
207
- )
208
-
209
- with gr.Row():
210
- height_input = gr.Slider(
211
- minimum=512,
212
- maximum=1536,
213
- value=1024,
214
- step=64,
215
- label="Altezza (px)"
216
  )
217
- width_input = gr.Slider(
218
- minimum=512,
219
- maximum=1536,
220
- value=1024,
221
- step=64,
222
- label="Larghezza (px)"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  )
224
 
225
- generate_button = gr.Button("Genera Immagine", variant="primary")
226
 
227
- with gr.Column(scale=4):
228
- output_image = gr.Image(label="Immagine Generata", type="pil")
229
- output_status = gr.Textbox(label="Stato", interactive=False)
230
 
231
- # Esempi di prompt
232
- with gr.Accordion("Esempi di Prompt", open=False):
233
- gr.Markdown("""
234
- ### Esempi di prompt ottimizzati per FLUX.1-schnell
235
-
236
- Clicca su uno degli esempi per utilizzarlo:
237
- """)
238
-
239
- examples = [
240
- ["A breathtaking view of the Dolomites at sunrise, golden light illuminating the jagged peaks, morning mist rising from the valley below, ultra-detailed, cinematic, 8K resolution, photorealistic"],
241
- ["Futuristic Tokyo cityscape at night, neon lights reflecting on wet streets after rain, towering skyscrapers with holographic advertisements, flying vehicles, photorealistic, cinematic lighting, 8K"],
242
- ["Portrait of a weathered old fisherman with deep wrinkles and piercing blue eyes, wearing a cable-knit sweater, salt and pepper beard, golden hour lighting, ultra-detailed skin texture, photorealistic"],
243
- ["Massive space station orbiting Jupiter, with Earth visible in the distance, detailed mechanical structures, solar panels, docking bays with spacecraft, photorealistic, NASA quality, 8K"],
244
- ["Bioluminescent forest at night with giant mushrooms, glowing plants, mystical atmosphere, small magical creatures, ultra-detailed vegetation, photorealistic textures, fantasy world with realistic lighting"]
245
- ]
246
-
247
- gr.Examples(
248
- examples=examples,
249
- inputs=prompt_input
250
- )
251
 
252
- # Collega il pulsante di generazione
253
- generate_button.click(
254
- generate_image_ui,
255
  inputs=[
256
- prompt_input,
257
- model_input,
258
- steps_input,
259
- cfg_input,
260
- height_input,
261
- width_input,
262
  negative_prompt_input
263
  ],
264
  outputs=[output_image, output_status]
265
  )
266
 
267
- return interface
268
-
269
- # Funzione principale
270
- def main():
271
- """Funzione principale"""
272
- # Crea il generatore
273
- generator = FluxNineteenGenerator()
274
-
275
- # Crea l'interfaccia
276
- interface = create_ui(generator)
277
-
278
- # Avvia l'interfaccia senza autenticazione (l'autenticazione sarà gestita da Hugging Face Spaces)
279
- # Utilizziamo i parametri necessari per Hugging Face Spaces
280
- interface.launch(
281
- server_name="0.0.0.0",
282
- share=False
283
- )
284
 
285
  if __name__ == "__main__":
286
- main()
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
 
 
 
 
2
  import gradio as gr
3
+ import requests
4
  from PIL import Image
5
+ from io import BytesIO
6
+ import google.generativeai as genai
7
  from dotenv import load_dotenv
8
+ import time
9
+ import base64
10
+ import random
11
 
12
  # Carica le variabili d'ambiente (se presenti)
13
  load_dotenv()
14
 
15
  class FluxNineteenGenerator:
16
+ """Generatore di immagini utilizzando l'API FLUX di Nineteen.ai"""
 
 
 
17
 
18
  def __init__(self):
19
+ """Inizializza il generatore"""
 
 
20
  print("Inizializzazione del generatore di immagini FLUX Nineteen.ai...")
21
 
22
  # Ottieni l'API key da variabile d'ambiente
23
  self.api_key = os.getenv("NINETEEN_API_KEY")
24
  if not self.api_key:
25
+ raise ValueError(
26
+ "È necessario configurare la variabile d'ambiente NINETEEN_API_KEY.\n"
27
+ "Su Hugging Face Spaces: Aggiungi la variabile nelle impostazioni dello Space.\n"
28
+ "In locale: Configura la variabile nel tuo ambiente di sviluppo."
29
+ )
30
 
31
  # Configurazione dell'API
32
  self.api_endpoint = "https://api.nineteen.ai/v1/text-to-image"
33
  self.headers = {
34
  "Authorization": f"Bearer {self.api_key}",
 
35
  "Content-Type": "application/json"
36
  }
37
 
38
+ # Modello predefinito
 
39
  self.default_model = "black-forest-labs/FLUX.1-schnell"
 
40
  print(f"Generatore inizializzato con modello predefinito: {self.default_model}")
41
+
42
+ # Lista dei modelli disponibili
43
+ self.models = {
44
+ "schnell": "black-forest-labs/FLUX.1-schnell",
45
+ "proteus": "dataautogpt3/ProteusV0.4-Lightning",
46
+ "dreamshaper": "Lykon/dreamshaper-xl-lightning"
47
+ }
48
 
49
+ def generate_image(self, prompt, model=None, steps=28, cfg_scale=7.0, height=1024, width=1024, negative_prompt=None):
 
50
  """
51
+ Genera un'immagine utilizzando l'API FLUX.
52
 
53
  Args:
54
+ prompt (str): Descrizione dell'immagine da generare
55
+ model (str, optional): Nome del modello da utilizzare. Default: None (usa il modello predefinito)
56
+ steps (int, optional): Numero di passi di inferenza. Default: 28
57
+ cfg_scale (float, optional): Guidance scale. Default: 7.0
58
+ height (int, optional): Altezza dell'immagine. Default: 1024
59
+ width (int, optional): Larghezza dell'immagine. Default: 1024
60
+ negative_prompt (str, optional): Prompt negativo. Default: None
61
+
62
  Returns:
63
+ tuple: (PIL.Image, str) L'immagine generata e un messaggio di stato
 
64
  """
 
 
 
65
  try:
66
+ # Usa il modello predefinito se non specificato
67
+ if not model:
68
+ model = self.default_model
69
+
70
+ # Se viene fornito un nome breve, usa il nome completo dal dizionario
71
+ if model in self.models:
72
+ model = self.models[model]
73
+
74
+ # Prepara i parametri per la richiesta
75
+ payload = {
76
  "prompt": prompt,
77
  "model": model,
78
+ "num_inference_steps": steps,
79
+ "guidance_scale": cfg_scale,
80
  "height": height,
81
+ "width": width
 
82
  }
83
 
84
+ if negative_prompt:
85
+ payload["negative_prompt"] = negative_prompt
86
+
87
  print(f"Generazione immagine con prompt: '{prompt}'")
88
+ print(f"Parametri: modello={model}, steps={steps}, cfg_scale={cfg_scale}, dimensioni={height}x{width}")
89
 
 
90
  start_time = time.time()
 
 
91
 
92
+ # Invia la richiesta all'API
93
+ response = requests.post(
94
+ self.api_endpoint,
95
+ headers=self.headers,
96
+ json=payload
97
+ )
98
+
99
+ # Gestisci gli errori HTTP
100
  if response.status_code != 200:
101
  error_message = f"Errore API: {response.status_code} - {response.text}"
102
  print(error_message)
103
  return None, error_message
104
 
105
+ # Decodifica l'immagine
106
+ end_time = time.time()
107
  try:
108
  image_b64 = response.json()["image_b64"]
109
  image_data = base64.b64decode(image_b64)
110
+ image = Image.open(BytesIO(image_data))
111
 
112
  print(f"Immagine generata in {end_time - start_time:.2f} secondi")
113
  return image, f"Immagine generata in {end_time - start_time:.2f} secondi"
 
 
114
  except Exception as e:
115
+ error_message = f"Errore nella decodifica dell'immagine: {str(e)}"
116
+ print(error_message)
117
+ return None, error_message
118
 
119
  except Exception as e:
120
+ error_message = f"Errore durante la generazione: {str(e)}"
121
  print(error_message)
122
  return None, error_message
123
 
124
+ class GeminiPromptGenerator:
125
+ """Generatore di prompt creativi utilizzando Gemini AI"""
126
+
127
+ def __init__(self):
128
+ """Inizializza il generatore di prompt"""
129
+ genai.configure(api_key=os.environ.get("GEMINI_API_KEY"))
130
+ self.model = genai.GenerativeModel(
131
+ model_name="gemini-1.5-flash-8b",
132
+ generation_config=genai.types.GenerationConfig(
133
+ temperature=1.4, # Aumentata per più creatività
134
+ top_p=0.99, # Aumentato per più variabilità
135
+ top_k=40, # Aumentato per considerare più opzioni
136
+ max_output_tokens=8192
137
+ )
138
+ )
139
+
140
+ # Lista di stili artistici per variare i prompt
141
+ self.art_styles = [
142
+ "hyperrealistic", "cinematic", "digital art", "oil painting",
143
+ "concept art", "fantasy art", "sci-fi", "surrealism",
144
+ "studio photography", "anime", "cyberpunk", "steampunk"
145
+ ]
146
+
147
+ # Lista di atmosfere per variare i prompt
148
+ self.moods = [
149
+ "ethereal", "mysterious", "dramatic", "peaceful",
150
+ "energetic", "melancholic", "whimsical", "epic",
151
+ "intimate", "nostalgic", "futuristic", "dreamy"
152
+ ]
153
+
154
+ def generate_creative_prompt(self):
155
+ """Genera un prompt creativo per la generazione di immagini"""
156
+ # Seleziona casualmente uno stile e un'atmosfera
157
+ style = random.choice(self.art_styles)
158
+ mood = random.choice(self.moods)
159
+
160
+ system_prompt = f"""You are an expert prompt engineer for artistic image generation.
161
+ Create a unique and creative prompt to generate an extraordinary image.
162
+ Current time: {time.strftime('%Y-%m-%d %H:%M:%S')}
163
+
164
+ The prompt must:
165
+ - Be in English
166
+ - Create a completely new and original scene, different from any previous ones
167
+ - Focus on the suggested style: {style}
168
+ - Incorporate the suggested mood: {mood}
169
+ - Include specific details about:
170
+ * Main subject and its unique characteristics
171
+ * Rich environmental details and setting
172
+ * Dynamic lighting and atmospheric effects
173
+ * Specific color palette and visual elements
174
+ * Camera angle or perspective
175
+ - Use vivid and evocative language
176
+ - Be about 2-3 lines long
177
+ - Include elements that work well with the FLUX.1-schnell model
178
+ - End with style keywords: {style}, {mood}, photorealistic, cinematic, 8K, ultra-detailed
179
+
180
+ Generate ONLY the prompt, without any explanations or introductions.
181
+ IMPORTANT: Create something completely different from previous prompts.
182
+ DO NOT include words like 'prompt' or 'description' in the response."""
183
+
184
+ try:
185
+ response = self.model.generate_content(system_prompt)
186
+ if response.text:
187
+ return response.text.strip()
188
+ else:
189
+ return "Sorry, I couldn't generate a creative prompt. Please try again."
190
+ except Exception as e:
191
+ return f"Error generating prompt: {str(e)}"
192
+
193
+ def create_ui():
194
+ """Crea l'interfaccia utente Gradio"""
195
 
196
+ # Inizializza i generatori
197
+ flux_gen = FluxNineteenGenerator()
198
+ gemini_gen = GeminiPromptGenerator()
199
 
200
+ def generate_random_prompt():
201
+ """Genera un prompt casuale usando Gemini"""
202
+ try:
203
+ return gemini_gen.generate_creative_prompt()
204
+ except Exception as e:
205
+ return f"Error: {str(e)}"
206
 
207
+ def generate_image(prompt, model, steps, cfg_scale, height, width, negative_prompt):
208
  """Funzione per generare immagini dall'interfaccia"""
 
 
 
 
209
  try:
210
+ return flux_gen.generate_image(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
  prompt=prompt,
212
  model=model,
213
  steps=steps,
 
217
  negative_prompt=negative_prompt
218
  )
219
  except Exception as e:
220
+ return None, str(e)
221
 
222
+ with gr.Blocks(title="FLUX Image Generator") as demo:
223
+ gr.Markdown("# 🎨 FLUX Image Generator")
224
+ gr.Markdown("Image generator with FLUX.1-schnell and Gemini AI")
 
225
 
226
  with gr.Row():
227
+ with gr.Column(scale=1):
228
  prompt_input = gr.Textbox(
229
  label="Prompt",
230
+ placeholder="Enter your image description or click 'Generate Creative Prompt'...",
231
  lines=3
232
  )
233
 
 
 
 
 
 
 
 
 
 
 
 
 
234
  with gr.Row():
235
+ generate_prompt_btn = gr.Button("🤖 Generate Creative Prompt", variant="secondary")
236
+ clear_prompt_btn = gr.Button("🗑️ Clear", variant="secondary")
237
+
238
+ with gr.Accordion("Advanced Settings", open=False):
239
+ model_input = gr.Dropdown(
240
+ choices=list(FluxNineteenGenerator().models.keys()),
241
+ value="schnell",
242
+ label="Model"
243
+ )
244
+
245
  steps_input = gr.Slider(
246
  minimum=1,
247
+ maximum=100,
248
+ value=28,
249
  step=1,
250
+ label="Steps"
251
  )
252
+
253
  cfg_input = gr.Slider(
254
  minimum=1.0,
255
+ maximum=20.0,
256
+ value=7.0,
257
+ step=0.5,
258
+ label="CFG Scale"
 
 
 
 
 
 
 
 
 
259
  )
260
+
261
+ with gr.Row():
262
+ height_input = gr.Slider(
263
+ minimum=512,
264
+ maximum=1536,
265
+ value=1024,
266
+ step=64,
267
+ label="Height (px)"
268
+ )
269
+ width_input = gr.Slider(
270
+ minimum=512,
271
+ maximum=1536,
272
+ value=1024,
273
+ step=64,
274
+ label="Width (px)"
275
+ )
276
+
277
+ negative_prompt_input = gr.Textbox(
278
+ label="Negative Prompt",
279
+ placeholder="Elements to avoid in the image...",
280
+ lines=2
281
  )
282
 
283
+ generate_image_btn = gr.Button("🎨 Generate Image", variant="primary")
284
 
285
+ with gr.Column(scale=1):
286
+ output_image = gr.Image(label="Generated Image")
287
+ output_status = gr.Textbox(label="Status", interactive=False)
288
 
289
+ # Eventi
290
+ generate_prompt_btn.click(
291
+ fn=generate_random_prompt,
292
+ outputs=prompt_input
293
+ )
294
+
295
+ clear_prompt_btn.click(
296
+ fn=lambda: "",
297
+ outputs=prompt_input
298
+ )
 
 
 
 
 
 
 
 
 
 
299
 
300
+ generate_image_btn.click(
301
+ fn=generate_image,
 
302
  inputs=[
303
+ prompt_input,
304
+ model_input,
305
+ steps_input,
306
+ cfg_input,
307
+ height_input,
308
+ width_input,
309
  negative_prompt_input
310
  ],
311
  outputs=[output_image, output_status]
312
  )
313
 
314
+ return demo
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
 
316
  if __name__ == "__main__":
317
+ demo = create_ui()
318
+ demo.launch()