Ntdeseb commited on
Commit
5fe24d7
·
1 Parent(s): e2e454a

Optimizar configuración de modelos - Respetar configuraciones del usuario y agregar más parámetros

Browse files
Files changed (1) hide show
  1. app.py +287 -60
app.py CHANGED
@@ -7,16 +7,22 @@ from PIL import Image
7
  import io
8
  import json
9
  import os
 
10
 
11
  # import spaces #[uncomment to use ZeroGPU]
12
  from diffusers import DiffusionPipeline
13
  import torch
14
  from huggingface_hub import login
15
 
 
 
 
 
16
  # Configurar autenticación con Hugging Face
17
  HF_TOKEN = os.getenv("HF_TOKEN") or os.getenv("HUGGING_FACE_HUB_TOKEN")
18
  if HF_TOKEN:
19
  try:
 
20
  login(token=HF_TOKEN)
21
  print("✅ Autenticado con Hugging Face")
22
  print(f"🔑 Token configurado: {HF_TOKEN[:10]}...")
@@ -27,12 +33,15 @@ else:
27
  print("💡 Para usar modelos FLUX, configura la variable de entorno HF_TOKEN en el Space")
28
 
29
  device = "cuda" if torch.cuda.is_available() else "cpu"
 
 
 
 
 
30
 
31
- # Modelos disponibles de alta calidad
32
  MODELS = {
33
  "SDXL Turbo (stabilityai/sdxl-turbo)": "stabilityai/sdxl-turbo",
34
- "SDXL Lightning (ByteDance/SDXL-Lightning)": "ByteDance/SDXL-Lightning",
35
- "SDXL Lightning 4Step (ByteDance/SDXL-Lightning-4Step)": "ByteDance/SDXL-Lightning-4Step",
36
  "SD Turbo (stabilityai/sd-turbo)": "stabilityai/sd-turbo",
37
  "SDXL Base (stabilityai/stable-diffusion-xl-base-1.0)": "stabilityai/stable-diffusion-xl-base-1.0",
38
  "Realistic Vision (SG161222/Realistic_Vision_V5.1_noVAE)": "SG161222/Realistic_Vision_V5.1_noVAE",
@@ -41,6 +50,12 @@ MODELS = {
41
  "Waifu Diffusion (hakurei/waifu-diffusion)": "hakurei/waifu-diffusion",
42
  "Deliberate v2 (XpucT/deliberate-v2)": "XpucT/deliberate-v2",
43
  "Dreamlike Diffusion (dreamlike-art/dreamlike-diffusion-1.0)": "dreamlike-art/dreamlike-diffusion-1.0",
 
 
 
 
 
 
44
  "FLUX.1-Kontext-Dev (API External)": "api_external",
45
  }
46
 
@@ -52,8 +67,15 @@ if HF_TOKEN:
52
  }
53
  MODELS.update(FLUX_MODELS)
54
  print("🔓 Modelos FLUX habilitados con autenticación")
 
55
  else:
56
  print("🔒 Modelos FLUX deshabilitados - requiere HF_TOKEN")
 
 
 
 
 
 
57
 
58
  # Estado del pipeline
59
  pipe = None
@@ -61,8 +83,10 @@ current_model_id = None
61
 
62
  if torch.cuda.is_available():
63
  torch_dtype = torch.float16
 
64
  else:
65
  torch_dtype = torch.float32
 
66
 
67
  MAX_SEED = np.iinfo(np.int32).max
68
  MAX_IMAGE_SIZE = 1024
@@ -70,11 +94,16 @@ MAX_IMAGE_SIZE = 1024
70
  # Función para cargar el modelo
71
  def load_model(model_id):
72
  global pipe, current_model_id
 
 
73
  if pipe is None or model_id != current_model_id:
74
  try:
 
 
75
  # Usar token de autenticación si está disponible
76
  if HF_TOKEN and ("flux" in model_id.lower() or "black-forest" in model_id.lower()):
77
  print(f"🔐 Cargando modelo gated: {model_id}")
 
78
  pipe = DiffusionPipeline.from_pretrained(
79
  model_id,
80
  torch_dtype=torch_dtype,
@@ -86,27 +115,45 @@ def load_model(model_id):
86
  model_id,
87
  torch_dtype=torch_dtype
88
  )
 
 
 
 
 
89
  pipe = pipe.to(device)
 
90
  current_model_id = model_id
91
  print(f"✅ Modelo {model_id} cargado exitosamente")
 
 
92
  except Exception as e:
93
  print(f"❌ Error cargando modelo {model_id}: {e}")
 
94
  raise e
 
 
95
 
96
  # Función para usar la API externa de FLUX.1-Kontext-Dev
97
  def use_external_api(prompt, negative_prompt, seed, randomize_seed, width, height, guidance_scale, num_inference_steps):
98
  try:
99
- print("🌐 Conectando a API externa FLUX.1-Kontext-Dev...")
 
 
 
 
 
100
  # URL de la API del Space externo
101
  api_url = "https://black-forest-labs-flux-1-kontext-dev.hf.space/api/predict/"
102
 
103
  # Crear una imagen base simple para la API (requiere input_image)
 
104
  base_image = Image.new('RGB', (width, height), color='white')
105
  img_byte_arr = io.BytesIO()
106
  base_image.save(img_byte_arr, format='PNG')
107
  img_byte_arr = img_byte_arr.getvalue()
108
 
109
  # Preparar los datos para la API
 
110
  files = {
111
  'data': (None, json.dumps([
112
  base64.b64encode(img_byte_arr).decode('utf-8'), # input_image
@@ -119,29 +166,95 @@ def use_external_api(prompt, negative_prompt, seed, randomize_seed, width, heigh
119
  }
120
 
121
  # Hacer la petición a la API
 
122
  response = requests.post(api_url, files=files, timeout=60)
123
 
 
 
 
124
  if response.status_code == 200:
 
125
  result = response.json()
126
  # La API devuelve [image_data, seed]
127
  image_data = result['data'][0]
128
  new_seed = result['data'][1]
129
 
 
130
  # Decodificar la imagen
131
  image_bytes = base64.b64decode(image_data.split(',')[1])
132
  image = Image.open(io.BytesIO(image_bytes))
133
 
134
- print("✅ API externa exitosa")
 
135
  return image, new_seed
136
  else:
 
 
137
  raise Exception(f"API Error: {response.status_code} - {response.text}")
138
 
139
  except Exception as e:
140
  print(f"❌ Error usando API externa: {e}")
 
141
  # Fallback: crear una imagen de error
142
  error_image = Image.new('RGB', (width, height), color='red')
143
  return error_image, seed
144
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  # @spaces.GPU #[uncomment to use ZeroGPU]
146
  def infer(
147
  prompt,
@@ -153,70 +266,131 @@ def infer(
153
  guidance_scale,
154
  num_inference_steps,
155
  model_name,
 
 
 
 
156
  progress=gr.Progress(track_tqdm=True),
157
  ):
158
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  # Verificar si es el modelo externo
160
  if model_name == "FLUX.1-Kontext-Dev (API External)":
161
  return use_external_api(prompt, negative_prompt, seed, randomize_seed, width, height, guidance_scale, num_inference_steps)
162
 
163
  # Cargar el modelo seleccionado
164
  model_id = MODELS[model_name]
 
165
  load_model(model_id)
166
 
167
  if randomize_seed:
 
168
  seed = random.randint(0, MAX_SEED)
 
169
 
 
170
  generator = torch.Generator().manual_seed(seed)
171
 
172
- # Configuraciones específicas según el modelo
173
- if "turbo" in model_id.lower() or "lightning" in model_id.lower():
174
- # Modelos rápidos
175
- guidance_scale = 0.0
176
- num_inference_steps = 1 if "turbo" in model_id.lower() else 4
177
- elif "flux" in model_id.lower():
178
- # Modelos FLUX
179
- guidance_scale = 7.5
180
- num_inference_steps = 20
181
- elif "realistic" in model_id.lower():
182
- # Realistic Vision
183
- guidance_scale = 7.5
184
- num_inference_steps = 25
185
- elif "openjourney" in model_id.lower():
186
- # OpenJourney
187
- guidance_scale = 7.5
188
- num_inference_steps = 20
189
- elif "anything" in model_id.lower():
190
- # Anything v3
191
- guidance_scale = 7.5
192
- num_inference_steps = 20
193
- elif "waifu" in model_id.lower():
194
- # Waifu Diffusion
195
- guidance_scale = 7.5
196
- num_inference_steps = 20
197
- elif "deliberate" in model_id.lower():
198
- # Deliberate v2
199
- guidance_scale = 7.5
200
- num_inference_steps = 20
201
- elif "dreamlike" in model_id.lower():
202
- # Dreamlike Diffusion
203
- guidance_scale = 7.5
204
- num_inference_steps = 20
205
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  image = pipe(
207
  prompt=prompt,
208
  negative_prompt=negative_prompt,
209
- guidance_scale=guidance_scale,
210
- num_inference_steps=num_inference_steps,
211
  width=width,
212
  height=height,
213
  generator=generator,
 
214
  ).images[0]
215
 
 
 
 
 
 
 
 
 
 
216
  return image, seed
217
 
218
  except Exception as e:
219
  print(f"❌ Error en inferencia: {e}")
 
 
220
  # Crear imagen de error
221
  error_image = Image.new('RGB', (width, height), color='red')
222
  return error_image, seed
@@ -267,20 +441,20 @@ with gr.Blocks(css=css) as demo:
267
 
268
  negative_prompt = gr.Text(
269
  label="Negative prompt",
270
- max_lines=1,
271
- placeholder="Enter a negative prompt",
272
- visible=False,
273
- )
274
-
275
- seed = gr.Slider(
276
- label="Seed",
277
- minimum=0,
278
- maximum=MAX_SEED,
279
- step=1,
280
- value=0,
281
  )
282
 
283
- randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
 
 
 
 
 
 
 
 
284
 
285
  with gr.Row():
286
  width = gr.Slider(
@@ -288,34 +462,75 @@ with gr.Blocks(css=css) as demo:
288
  minimum=256,
289
  maximum=MAX_IMAGE_SIZE,
290
  step=32,
291
- value=1024, # Replace with defaults that work for your model
292
  )
293
-
294
  height = gr.Slider(
295
  label="Height",
296
  minimum=256,
297
  maximum=MAX_IMAGE_SIZE,
298
  step=32,
299
- value=1024, # Replace with defaults that work for your model
300
  )
301
 
302
  with gr.Row():
303
  guidance_scale = gr.Slider(
304
  label="Guidance scale",
305
  minimum=0.0,
306
- maximum=10.0,
307
  step=0.1,
308
- value=0.0, # Replace with defaults that work for your model
 
309
  )
310
-
311
  num_inference_steps = gr.Slider(
312
  label="Number of inference steps",
313
  minimum=1,
314
- maximum=50,
315
  step=1,
316
- value=2, # Replace with defaults that work for your model
 
317
  )
318
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
319
  gr.Examples(examples=examples, inputs=[prompt])
320
  gr.on(
321
  triggers=[run_button.click, prompt.submit],
@@ -330,9 +545,21 @@ with gr.Blocks(css=css) as demo:
330
  guidance_scale,
331
  num_inference_steps,
332
  model_selector,
 
 
 
 
333
  ],
334
  outputs=[result, seed],
335
  )
336
 
 
 
 
 
 
 
 
337
  if __name__ == "__main__":
 
338
  demo.launch()
 
7
  import io
8
  import json
9
  import os
10
+ import time
11
 
12
  # import spaces #[uncomment to use ZeroGPU]
13
  from diffusers import DiffusionPipeline
14
  import torch
15
  from huggingface_hub import login
16
 
17
+ print("🚀 Iniciando aplicación...")
18
+ print(f"📁 Directorio actual: {os.getcwd()}")
19
+ print(f"🐍 Python version: {os.sys.version}")
20
+
21
  # Configurar autenticación con Hugging Face
22
  HF_TOKEN = os.getenv("HF_TOKEN") or os.getenv("HUGGING_FACE_HUB_TOKEN")
23
  if HF_TOKEN:
24
  try:
25
+ print(f"🔑 Token detectado: {HF_TOKEN[:10]}...")
26
  login(token=HF_TOKEN)
27
  print("✅ Autenticado con Hugging Face")
28
  print(f"🔑 Token configurado: {HF_TOKEN[:10]}...")
 
33
  print("💡 Para usar modelos FLUX, configura la variable de entorno HF_TOKEN en el Space")
34
 
35
  device = "cuda" if torch.cuda.is_available() else "cpu"
36
+ print(f"🖥️ Dispositivo detectado: {device}")
37
+ print(f"🔥 CUDA disponible: {torch.cuda.is_available()}")
38
+ if torch.cuda.is_available():
39
+ print(f"🎮 GPU: {torch.cuda.get_device_name(0)}")
40
+ print(f"💾 Memoria GPU: {torch.cuda.get_device_properties(0).total_memory / 1024**3:.1f} GB")
41
 
42
+ # Modelos disponibles de alta calidad (optimizados - solo los que funcionan)
43
  MODELS = {
44
  "SDXL Turbo (stabilityai/sdxl-turbo)": "stabilityai/sdxl-turbo",
 
 
45
  "SD Turbo (stabilityai/sd-turbo)": "stabilityai/sd-turbo",
46
  "SDXL Base (stabilityai/stable-diffusion-xl-base-1.0)": "stabilityai/stable-diffusion-xl-base-1.0",
47
  "Realistic Vision (SG161222/Realistic_Vision_V5.1_noVAE)": "SG161222/Realistic_Vision_V5.1_noVAE",
 
50
  "Waifu Diffusion (hakurei/waifu-diffusion)": "hakurei/waifu-diffusion",
51
  "Deliberate v2 (XpucT/deliberate-v2)": "XpucT/deliberate-v2",
52
  "Dreamlike Diffusion (dreamlike-art/dreamlike-diffusion-1.0)": "dreamlike-art/dreamlike-diffusion-1.0",
53
+ # Modelos adicionales que funcionan bien en CPU
54
+ "Stable Diffusion v1.5 (runwayml/stable-diffusion-v1-5)": "runwayml/stable-diffusion-v1-5",
55
+ "Stable Diffusion v1.4 (CompVis/stable-diffusion-v1-4)": "CompVis/stable-diffusion-v1-4",
56
+ "Midjourney Style (prompthero/openjourney)": "prompthero/openjourney",
57
+ "Orange Mixs (WarriorMama777/OrangeMixs)": "WarriorMama777/OrangeMixs",
58
+ "Kohaku V2.1 (KBlueLeaf/kohaku-v2.1)": "KBlueLeaf/kohaku-v2.1",
59
  "FLUX.1-Kontext-Dev (API External)": "api_external",
60
  }
61
 
 
67
  }
68
  MODELS.update(FLUX_MODELS)
69
  print("🔓 Modelos FLUX habilitados con autenticación")
70
+ print(f"📊 Total de modelos disponibles: {len(MODELS)}")
71
  else:
72
  print("🔒 Modelos FLUX deshabilitados - requiere HF_TOKEN")
73
+ print(f"📊 Total de modelos disponibles: {len(MODELS)}")
74
+
75
+ print("📋 Modelos cargados:")
76
+ for i, (name, model_id) in enumerate(MODELS.items(), 1):
77
+ status = "🔐" if "flux" in model_id.lower() or "black-forest" in model_id.lower() else "📦"
78
+ print(f" {i:2d}. {status} {name}")
79
 
80
  # Estado del pipeline
81
  pipe = None
 
83
 
84
  if torch.cuda.is_available():
85
  torch_dtype = torch.float16
86
+ print("⚡ Usando torch.float16 para GPU")
87
  else:
88
  torch_dtype = torch.float32
89
+ print("🐌 Usando torch.float32 para CPU")
90
 
91
  MAX_SEED = np.iinfo(np.int32).max
92
  MAX_IMAGE_SIZE = 1024
 
94
  # Función para cargar el modelo
95
  def load_model(model_id):
96
  global pipe, current_model_id
97
+ print(f"\n🔄 Iniciando carga del modelo: {model_id}")
98
+
99
  if pipe is None or model_id != current_model_id:
100
  try:
101
+ start_time = time.time()
102
+
103
  # Usar token de autenticación si está disponible
104
  if HF_TOKEN and ("flux" in model_id.lower() or "black-forest" in model_id.lower()):
105
  print(f"🔐 Cargando modelo gated: {model_id}")
106
+ print(f"🔑 Usando token de autenticación...")
107
  pipe = DiffusionPipeline.from_pretrained(
108
  model_id,
109
  torch_dtype=torch_dtype,
 
115
  model_id,
116
  torch_dtype=torch_dtype
117
  )
118
+
119
+ load_time = time.time() - start_time
120
+ print(f"⏱️ Tiempo de carga: {load_time:.2f} segundos")
121
+
122
+ print(f"🚀 Moviendo modelo a dispositivo: {device}")
123
  pipe = pipe.to(device)
124
+
125
  current_model_id = model_id
126
  print(f"✅ Modelo {model_id} cargado exitosamente")
127
+ print(f"💾 Memoria utilizada: {torch.cuda.memory_allocated() / 1024**3:.2f} GB" if torch.cuda.is_available() else "💾 Memoria CPU")
128
+
129
  except Exception as e:
130
  print(f"❌ Error cargando modelo {model_id}: {e}")
131
+ print(f"🔍 Tipo de error: {type(e).__name__}")
132
  raise e
133
+ else:
134
+ print(f"♻️ Modelo {model_id} ya está cargado, reutilizando...")
135
 
136
  # Función para usar la API externa de FLUX.1-Kontext-Dev
137
  def use_external_api(prompt, negative_prompt, seed, randomize_seed, width, height, guidance_scale, num_inference_steps):
138
  try:
139
+ print("\n🌐 Conectando a API externa FLUX.1-Kontext-Dev...")
140
+ print(f"📝 Prompt: {prompt[:50]}...")
141
+ print(f"🔧 Parámetros: {width}x{height}, guidance={guidance_scale}, steps={num_inference_steps}")
142
+
143
+ start_time = time.time()
144
+
145
  # URL de la API del Space externo
146
  api_url = "https://black-forest-labs-flux-1-kontext-dev.hf.space/api/predict/"
147
 
148
  # Crear una imagen base simple para la API (requiere input_image)
149
+ print("🖼️ Creando imagen base para API...")
150
  base_image = Image.new('RGB', (width, height), color='white')
151
  img_byte_arr = io.BytesIO()
152
  base_image.save(img_byte_arr, format='PNG')
153
  img_byte_arr = img_byte_arr.getvalue()
154
 
155
  # Preparar los datos para la API
156
+ print("📦 Preparando datos para API...")
157
  files = {
158
  'data': (None, json.dumps([
159
  base64.b64encode(img_byte_arr).decode('utf-8'), # input_image
 
166
  }
167
 
168
  # Hacer la petición a la API
169
+ print(f"🌐 Enviando petición a: {api_url}")
170
  response = requests.post(api_url, files=files, timeout=60)
171
 
172
+ api_time = time.time() - start_time
173
+ print(f"⏱️ Tiempo de respuesta API: {api_time:.2f} segundos")
174
+
175
  if response.status_code == 200:
176
+ print("✅ Respuesta exitosa de API")
177
  result = response.json()
178
  # La API devuelve [image_data, seed]
179
  image_data = result['data'][0]
180
  new_seed = result['data'][1]
181
 
182
+ print("🖼️ Decodificando imagen...")
183
  # Decodificar la imagen
184
  image_bytes = base64.b64decode(image_data.split(',')[1])
185
  image = Image.open(io.BytesIO(image_bytes))
186
 
187
+ total_time = time.time() - start_time
188
+ print(f"✅ API externa exitosa - Tiempo total: {total_time:.2f} segundos")
189
  return image, new_seed
190
  else:
191
+ print(f"❌ Error de API: {response.status_code}")
192
+ print(f"📄 Respuesta: {response.text[:200]}...")
193
  raise Exception(f"API Error: {response.status_code} - {response.text}")
194
 
195
  except Exception as e:
196
  print(f"❌ Error usando API externa: {e}")
197
+ print(f"🔍 Tipo de error: {type(e).__name__}")
198
  # Fallback: crear una imagen de error
199
  error_image = Image.new('RGB', (width, height), color='red')
200
  return error_image, seed
201
 
202
+ # Función para mostrar información del modelo seleccionado
203
+ def get_model_info(model_name):
204
+ model_id = MODELS.get(model_name, "")
205
+
206
+ if not model_id:
207
+ return "**Model Info:** Select a model to see its specific configuration recommendations."
208
+
209
+ info = f"**Model Info:** {model_name}\n\n"
210
+
211
+ # Información específica por modelo
212
+ if "turbo" in model_id.lower():
213
+ info += "⚡ **Fast Model** - Optimized for speed\n"
214
+ info += "• Recommended steps: 1-4\n"
215
+ info += "• Guidance scale: 0.0-1.0\n"
216
+ info += "• Best for: Quick iterations\n\n"
217
+ elif "lightning" in model_id.lower():
218
+ info += "⚡ **Lightning Model** - Ultra fast\n"
219
+ info += "• Recommended steps: 4-8\n"
220
+ info += "• Guidance scale: 0.0-1.0\n"
221
+ info += "• Best for: Rapid prototyping\n\n"
222
+ elif "flux" in model_id.lower():
223
+ info += "🔐 **FLUX Model** - High quality\n"
224
+ info += "• Recommended steps: 20-50\n"
225
+ info += "• Guidance scale: 3.5-7.5\n"
226
+ info += "• Best for: Professional results\n\n"
227
+ elif "realistic" in model_id.lower():
228
+ info += "👤 **Realistic Model** - Photorealistic\n"
229
+ info += "• Recommended steps: 25-50\n"
230
+ info += "• Guidance scale: 7.5-12.0\n"
231
+ info += "• Best for: Realistic portraits\n\n"
232
+ elif "openjourney" in model_id.lower():
233
+ info += "🎨 **OpenJourney Model** - Midjourney style\n"
234
+ info += "• Recommended steps: 20-30\n"
235
+ info += "• Guidance scale: 7.5-10.0\n"
236
+ info += "• Best for: Artistic styles\n\n"
237
+ elif "waifu" in model_id.lower():
238
+ info += "🌸 **Waifu Model** - Anime style\n"
239
+ info += "• Recommended steps: 20-30\n"
240
+ info += "• Guidance scale: 7.5-10.0\n"
241
+ info += "• Best for: Anime characters\n\n"
242
+ elif "anything" in model_id.lower():
243
+ info += "🎭 **Anything Model** - Versatile\n"
244
+ info += "• Recommended steps: 20-30\n"
245
+ info += "• Guidance scale: 7.5-10.0\n"
246
+ info += "• Best for: Creative concepts\n\n"
247
+ else:
248
+ info += "📦 **Standard Model**\n"
249
+ info += "• Recommended steps: 20-50\n"
250
+ info += "• Guidance scale: 7.5-12.0\n"
251
+ info += "• Best for: General use\n\n"
252
+
253
+ info += f"**Model ID:** `{model_id}`\n"
254
+ info += "**Status:** ✅ Available"
255
+
256
+ return info
257
+
258
  # @spaces.GPU #[uncomment to use ZeroGPU]
259
  def infer(
260
  prompt,
 
266
  guidance_scale,
267
  num_inference_steps,
268
  model_name,
269
+ eta=0.0,
270
+ strength=1.0,
271
+ num_images_per_prompt=1,
272
+ safety_checker=True,
273
  progress=gr.Progress(track_tqdm=True),
274
  ):
275
  try:
276
+ print(f"\n🎨 Iniciando generación de imagen...")
277
+ print(f"📝 Prompt: {prompt}")
278
+ print(f"🚫 Negative prompt: {negative_prompt}")
279
+ print(f"🎲 Seed: {seed} (randomize: {randomize_seed})")
280
+ print(f"📐 Dimensiones: {width}x{height}")
281
+ print(f"🎯 Guidance scale: {guidance_scale}")
282
+ print(f"🔄 Inference steps: {num_inference_steps}")
283
+ print(f"🎯 Eta: {eta}")
284
+ print(f"💪 Strength: {strength}")
285
+ print(f"🖼️ Images per prompt: {num_images_per_prompt}")
286
+ print(f"🛡️ Safety checker: {safety_checker}")
287
+ print(f"🎯 Modelo seleccionado: {model_name}")
288
+
289
+ start_time = time.time()
290
+
291
  # Verificar si es el modelo externo
292
  if model_name == "FLUX.1-Kontext-Dev (API External)":
293
  return use_external_api(prompt, negative_prompt, seed, randomize_seed, width, height, guidance_scale, num_inference_steps)
294
 
295
  # Cargar el modelo seleccionado
296
  model_id = MODELS[model_name]
297
+ print(f"🔧 Cargando modelo: {model_id}")
298
  load_model(model_id)
299
 
300
  if randomize_seed:
301
+ old_seed = seed
302
  seed = random.randint(0, MAX_SEED)
303
+ print(f"🎲 Seed aleatorizado: {old_seed} → {seed}")
304
 
305
+ print(f"🎲 Configurando generador con seed: {seed}")
306
  generator = torch.Generator().manual_seed(seed)
307
 
308
+ # RESPETAR LAS CONFIGURACIONES DEL USUARIO
309
+ # Solo aplicar límites mínimos para modelos específicos si es necesario
310
+ final_guidance_scale = guidance_scale
311
+ final_inference_steps = num_inference_steps
312
+
313
+ # Aplicar límites mínimos solo para modelos que lo requieren
314
+ if "turbo" in model_id.lower():
315
+ # Para modelos turbo, asegurar al menos 1 paso
316
+ if final_inference_steps < 1:
317
+ final_inference_steps = 1
318
+ print(f"⚡ Modelo turbo - Ajustando steps mínimo: {num_inference_steps} → {final_inference_steps}")
319
+ elif "lightning" in model_id.lower():
320
+ # Para modelos lightning, asegurar al menos 4 pasos
321
+ if final_inference_steps < 4:
322
+ final_inference_steps = 4
323
+ print(f"⚡ Modelo lightning - Ajustando steps mínimo: {num_inference_steps} → {final_inference_steps}")
324
+
325
+ # Aplicar límites de guidance scale solo si es necesario
326
+ if final_guidance_scale < 0.0:
327
+ final_guidance_scale = 0.0
328
+ print(f"⚠️ Guidance scale ajustado al mínimo: {guidance_scale} → {final_guidance_scale}")
329
+ elif final_guidance_scale > 20.0:
330
+ final_guidance_scale = 20.0
331
+ print(f"⚠️ Guidance scale ajustado al máximo: {guidance_scale} {final_guidance_scale}")
332
+
333
+ print(f"⚙️ Parámetros finales (respetando configuración del usuario):")
334
+ print(f" - Guidance scale: {guidance_scale} → {final_guidance_scale}")
335
+ print(f" - Inference steps: {num_inference_steps} → {final_inference_steps}")
336
+ print(f" - Width: {width}, Height: {height}")
337
+ print(f" - Seed: {seed}")
338
+ print(f" - Eta: {eta}")
339
+ print(f" - Strength: {strength}")
340
+ print(f" - Images per prompt: {num_images_per_prompt}")
341
 
342
+ print("🎨 Iniciando generación de imagen...")
343
+ inference_start = time.time()
344
+
345
+ # Preparar parámetros adicionales para modelos que los soporten
346
+ additional_params = {}
347
+
348
+ # Agregar parámetros adicionales según el modelo
349
+ if hasattr(pipe, 'scheduler') and hasattr(pipe.scheduler, 'beta_start'):
350
+ # Algunos modelos soportan parámetros de scheduler
351
+ additional_params['eta'] = eta
352
+
353
+ if hasattr(pipe, 'vae') and hasattr(pipe.vae, 'scale_factor'):
354
+ # Algunos modelos soportan parámetros de VAE
355
+ additional_params['output_type'] = 'pil'
356
+
357
+ # Configurar safety checker
358
+ if hasattr(pipe, 'safety_checker') and not safety_checker:
359
+ pipe.safety_checker = None
360
+ print("🛡️ Safety checker deshabilitado")
361
+
362
+ # Configurar número de imágenes
363
+ if num_images_per_prompt > 1:
364
+ additional_params['num_images_per_prompt'] = num_images_per_prompt
365
+
366
+ print(f"🔧 Parámetros adicionales: {additional_params}")
367
+
368
  image = pipe(
369
  prompt=prompt,
370
  negative_prompt=negative_prompt,
371
+ guidance_scale=final_guidance_scale,
372
+ num_inference_steps=final_inference_steps,
373
  width=width,
374
  height=height,
375
  generator=generator,
376
+ **additional_params
377
  ).images[0]
378
 
379
+ inference_time = time.time() - inference_start
380
+ total_time = time.time() - start_time
381
+
382
+ print(f"✅ Imagen generada exitosamente!")
383
+ print(f"⏱️ Tiempo de inferencia: {inference_time:.2f} segundos")
384
+ print(f"⏱️ Tiempo total: {total_time:.2f} segundos")
385
+ print(f"🎲 Seed final: {seed}")
386
+ print(f"💾 Memoria utilizada: {torch.cuda.memory_allocated() / 1024**3:.2f} GB" if torch.cuda.is_available() else "💾 Memoria CPU")
387
+
388
  return image, seed
389
 
390
  except Exception as e:
391
  print(f"❌ Error en inferencia: {e}")
392
+ print(f"🔍 Tipo de error: {type(e).__name__}")
393
+ print(f"📋 Detalles del error: {str(e)}")
394
  # Crear imagen de error
395
  error_image = Image.new('RGB', (width, height), color='red')
396
  return error_image, seed
 
441
 
442
  negative_prompt = gr.Text(
443
  label="Negative prompt",
444
+ max_lines=2,
445
+ placeholder="Enter a negative prompt (optional)",
446
+ visible=True,
 
 
 
 
 
 
 
 
447
  )
448
 
449
+ with gr.Row():
450
+ seed = gr.Slider(
451
+ label="Seed",
452
+ minimum=0,
453
+ maximum=MAX_SEED,
454
+ step=1,
455
+ value=0,
456
+ )
457
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
458
 
459
  with gr.Row():
460
  width = gr.Slider(
 
462
  minimum=256,
463
  maximum=MAX_IMAGE_SIZE,
464
  step=32,
465
+ value=1024,
466
  )
 
467
  height = gr.Slider(
468
  label="Height",
469
  minimum=256,
470
  maximum=MAX_IMAGE_SIZE,
471
  step=32,
472
+ value=1024,
473
  )
474
 
475
  with gr.Row():
476
  guidance_scale = gr.Slider(
477
  label="Guidance scale",
478
  minimum=0.0,
479
+ maximum=20.0,
480
  step=0.1,
481
+ value=7.5,
482
+ info="Controls how closely the image follows the prompt (higher = more adherence)"
483
  )
 
484
  num_inference_steps = gr.Slider(
485
  label="Number of inference steps",
486
  minimum=1,
487
+ maximum=100,
488
  step=1,
489
+ value=20,
490
+ info="More steps = higher quality but slower generation"
491
  )
492
 
493
+ with gr.Row():
494
+ # Parámetros adicionales para modelos avanzados
495
+ eta = gr.Slider(
496
+ label="Eta (DDIM)",
497
+ minimum=0.0,
498
+ maximum=1.0,
499
+ step=0.01,
500
+ value=0.0,
501
+ info="DDIM eta parameter (0 = deterministic, 1 = stochastic)"
502
+ )
503
+ strength = gr.Slider(
504
+ label="Strength",
505
+ minimum=0.0,
506
+ maximum=1.0,
507
+ step=0.01,
508
+ value=1.0,
509
+ info="Strength of the transformation (for img2img models)"
510
+ )
511
+
512
+ with gr.Row():
513
+ # Configuraciones de calidad
514
+ num_images_per_prompt = gr.Slider(
515
+ label="Images per prompt",
516
+ minimum=1,
517
+ maximum=4,
518
+ step=1,
519
+ value=1,
520
+ info="Number of images to generate (may slow down generation)"
521
+ )
522
+ safety_checker = gr.Checkbox(
523
+ label="Safety checker",
524
+ value=True,
525
+ info="Enable content safety filtering"
526
+ )
527
+
528
+ # Información del modelo seleccionado
529
+ model_info = gr.Markdown(
530
+ value="**Model Info:** Select a model to see its specific configuration recommendations.",
531
+ label="Model Information"
532
+ )
533
+
534
  gr.Examples(examples=examples, inputs=[prompt])
535
  gr.on(
536
  triggers=[run_button.click, prompt.submit],
 
545
  guidance_scale,
546
  num_inference_steps,
547
  model_selector,
548
+ eta,
549
+ strength,
550
+ num_images_per_prompt,
551
+ safety_checker,
552
  ],
553
  outputs=[result, seed],
554
  )
555
 
556
+ # Actualizar información del modelo cuando se seleccione
557
+ model_selector.change(
558
+ fn=get_model_info,
559
+ inputs=[model_selector],
560
+ outputs=[model_info]
561
+ )
562
+
563
  if __name__ == "__main__":
564
+ print("🚀 Iniciando Gradio app...")
565
  demo.launch()