Malaji71 commited on
Commit
cf7819d
·
verified ·
1 Parent(s): 3f0776a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -211
app.py CHANGED
@@ -2,87 +2,72 @@ import gradio as gr
2
  import torch
3
  from PIL import Image
4
  import numpy as np
5
- from clip_interrogator import Config, Interrogator, LabelTable, load_list
6
  import logging
7
  import os
8
  import warnings
9
  from datetime import datetime
10
- import json
11
  import gc
 
12
 
13
- # Suprimir warnings específicos
14
  warnings.filterwarnings("ignore", category=FutureWarning)
15
  warnings.filterwarnings("ignore", category=UserWarning)
16
  os.environ["TOKENIZERS_PARALLELISM"] = "false"
17
 
18
- # Configurar logging
19
- logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
20
  logger = logging.getLogger(__name__)
21
 
22
- # Detectar dispositivo disponible
23
  def get_device():
24
  if torch.cuda.is_available():
25
  return "cuda"
26
  elif torch.backends.mps.is_available():
27
- return "mps"
28
  else:
29
  return "cpu"
30
 
31
  DEVICE = get_device()
32
- logger.info(f"🖥️ Usando dispositivo: {DEVICE}")
33
 
34
- # Configuración optimizada
35
  CLIP_MODELS = {
36
  "general": "ViT-L-14/openai",
37
- "stable_diffusion": "ViT-L-14/openai",
38
  "midjourney": "ViT-H-14/laion2b_s32b_b79k",
39
  "flux": "ViT-L-14/openai"
40
  }
41
 
42
- INTERROGATION_MODES = {
43
- "fast": "⚡ Rápido (30 seg)",
44
- "classic": "⚖️ Clásico (1 min)",
45
- "best": "⭐ Mejor (2 min)"
46
  }
47
 
48
- class OptimizedImagePromptGenerator:
49
  def __init__(self):
50
  self.interrogator = None
51
  self.usage_count = 0
52
  self.device = DEVICE
53
  self.is_initialized = False
54
- logger.info("🚀 Inicializando generador optimizado...")
55
 
56
  def initialize_model(self, progress_callback=None):
57
- """Inicialización lazy del modelo"""
58
  if self.is_initialized:
59
  return True
60
 
61
  try:
62
  if progress_callback:
63
- progress_callback("🔄 Configurando modelo CLIP...")
64
 
65
- # Configuración optimizada según dispositivo
66
  config = Config(
67
  clip_model_name="ViT-L-14/openai",
68
  download_cache=True,
69
- chunk_size=1024 if self.device == "cpu" else 2048,
70
  quiet=True,
71
  device=self.device
72
  )
73
 
74
- if progress_callback:
75
- progress_callback("📥 Descargando modelos (primera vez)...")
76
-
77
  self.interrogator = Interrogator(config)
78
-
79
- if progress_callback:
80
- progress_callback("✅ Modelo inicializado correctamente")
81
-
82
  self.is_initialized = True
83
- logger.info("✅ Modelo CLIP inicializado correctamente")
84
 
85
- # Limpiar memoria
86
  if self.device == "cpu":
87
  gc.collect()
88
  else:
@@ -91,60 +76,49 @@ class OptimizedImagePromptGenerator:
91
  return True
92
 
93
  except Exception as e:
94
- logger.error(f"Error inicializando modelo: {e}")
95
- if progress_callback:
96
- progress_callback(f"❌ Error: {str(e)}")
97
  return False
98
 
99
  def optimize_image(self, image):
100
- """Optimizar imagen para procesamiento"""
101
  if image is None:
102
  return None
103
 
104
- # Convertir a PIL si es necesario
105
  if isinstance(image, np.ndarray):
106
  image = Image.fromarray(image)
107
  elif not isinstance(image, Image.Image):
108
  image = Image.open(image)
109
 
110
- # Asegurar RGB
111
  if image.mode != 'RGB':
112
  image = image.convert('RGB')
113
 
114
- # Redimensionar para optimizar velocidad en CPU
115
  max_size = 768 if self.device != "cpu" else 512
116
  if image.size[0] > max_size or image.size[1] > max_size:
117
  image.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
118
- logger.info(f"🖼️ Imagen redimensionada a {image.size}")
119
 
120
  return image
121
 
 
122
  def generate_prompt(self, image, model_type="general", mode="best", progress_callback=None):
123
- """Generar prompt optimizado"""
124
  try:
125
- # Inicializar modelo si es necesario
126
  if not self.is_initialized:
127
  if not self.initialize_model(progress_callback):
128
- return "❌ Error inicializando el modelo.", ""
129
 
130
  if image is None:
131
- return "❌ Por favor, sube una imagen primero.", ""
132
 
133
- # Incrementar contador
134
  self.usage_count += 1
135
 
136
  if progress_callback:
137
- progress_callback("🖼️ Optimizando imagen...")
138
 
139
- # Optimizar imagen
140
  image = self.optimize_image(image)
141
  if image is None:
142
- return "❌ Error procesando la imagen.", ""
143
 
144
  if progress_callback:
145
- progress_callback("🧠 Analizando contenido visual...")
146
 
147
- # Generar prompt según modo
148
  start_time = datetime.now()
149
 
150
  try:
@@ -152,124 +126,83 @@ class OptimizedImagePromptGenerator:
152
  prompt = self.interrogator.interrogate_fast(image)
153
  elif mode == "classic":
154
  prompt = self.interrogator.interrogate_classic(image)
155
- else: # best
156
  prompt = self.interrogator.interrogate(image)
157
 
158
  except Exception as e:
159
- logger.error(f"Error en interrogación: {e}")
160
- # Fallback a modo rápido
161
  prompt = self.interrogator.interrogate_fast(image)
162
 
163
  end_time = datetime.now()
164
  duration = (end_time - start_time).total_seconds()
165
 
166
- # Limpiar memoria después del procesamiento
167
  if self.device == "cpu":
168
  gc.collect()
169
  else:
170
  torch.cuda.empty_cache()
171
 
172
- # Información detallada
173
- device_emoji = "🖥️" if self.device == "cpu" else "🚀"
174
  info = f"""
175
- **✅ Prompt generado exitosamente con IA para todos**
176
 
177
- {device_emoji} **Información del procesamiento:**
178
- - **Dispositivo:** {self.device.upper()}
179
- - **Modelo:** {model_type.replace('_', ' ').title()}
180
- - **Modo:** {INTERROGATION_MODES.get(mode, mode)}
181
- - **Tiempo:** {duration:.1f} segundos
182
- - **Tamaño imagen:** {image.size[0]}x{image.size[1]}
183
- - **Usos totales:** {self.usage_count}
184
- - **Hora:** {datetime.now().strftime('%H:%M:%S')}
185
 
186
- *"Porque cuando no tienes nada en la cabeza, te preocupas de la tipografía?"* 😄
187
-
188
- 💡 **Tip:** Los siguientes análisis serán más rápidos (modelo ya cargado)
189
  """
190
 
191
- if progress_callback:
192
- progress_callback("✨ ¡Prompt listo!")
193
-
194
  return prompt, info
195
 
196
  except Exception as e:
197
- logger.error(f"Error generando prompt: {e}")
198
- error_msg = f"❌ Error: {str(e)}"
199
- error_info = f"""
200
- **❌ Error en el procesamiento**
201
-
202
- *Cuando falla la IA, al menos la tipografía sigue siendo bonita* 📝
203
 
204
- 💡 **Sugerencias:**
205
- - Intenta con una imagen más pequeña
206
- - Usa el modo "Rápido"
207
- - Verifica que la imagen sea válida
208
- """
209
- return error_msg, error_info
210
-
211
- # Inicializar generador
212
- generator = OptimizedImagePromptGenerator()
213
 
 
214
  def process_image_with_progress(image, model_type, mode):
215
- """Función con indicadores de progreso"""
216
- progress_updates = []
217
-
218
  def progress_callback(message):
219
- progress_updates.append(message)
220
  return message
221
 
222
- # Mostrar progreso inicial
223
- yield "🔄 Iniciando procesamiento...", """
224
- **🚀 IA para todos está trabajando**
225
 
226
- **Preparando análisis inteligente...**
227
-
228
- *Primera vez puede tardar 2-3 minutos (descarga de modelos)*
229
- *Siguientes análisis: 30-60 segundos*
230
  """
231
 
232
- # Procesar imagen
233
  prompt, info = generator.generate_prompt(image, model_type, mode, progress_callback)
234
-
235
- # Resultado final
236
  yield prompt, info
237
 
238
  def clear_outputs():
239
- """Limpiar outputs y memoria"""
240
  gc.collect()
241
  if torch.cuda.is_available():
242
  torch.cuda.empty_cache()
243
  return "", ""
244
 
245
- # Crear interfaz optimizada
246
  def create_interface():
247
- # CSS mejorado
248
- custom_css = """
249
  .gradio-container {
250
  max-width: 1400px !important;
251
- font-family: 'Inter', 'Segoe UI', system-ui, sans-serif;
252
  }
253
  .prompt-output {
254
- font-family: 'SF Mono', 'Monaco', 'Cascadia Code', 'Roboto Mono', monospace !important;
255
  font-size: 14px !important;
256
  line-height: 1.6 !important;
257
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%) !important;
258
  border-radius: 12px !important;
259
  padding: 20px !important;
260
  border: 1px solid #dee2e6 !important;
261
- box-shadow: 0 2px 4px rgba(0,0,0,0.1) !important;
262
  }
263
  .main-title {
264
  text-align: center;
265
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
266
  -webkit-background-clip: text;
267
  -webkit-text-fill-color: transparent;
268
- background-clip: text;
269
  font-size: 3em !important;
270
  font-weight: 800 !important;
271
  margin-bottom: 0.3em !important;
272
- letter-spacing: -0.02em;
273
  }
274
  .subtitle {
275
  text-align: center;
@@ -277,137 +210,80 @@ def create_interface():
277
  color: #6c757d;
278
  font-size: 1.2em;
279
  margin-bottom: 2em;
280
- font-weight: 300;
281
- }
282
- .device-indicator {
283
- background: linear-gradient(90deg, #28a745, #20c997);
284
- color: white;
285
- padding: 8px 16px;
286
- border-radius: 20px;
287
- font-size: 0.9em;
288
- display: inline-block;
289
- margin: 10px 0;
290
  }
291
  """
292
 
293
- with gr.Blocks(
294
- theme=gr.themes.Soft(),
295
- title="IA para todos - Image to Prompt Optimizado",
296
- css=custom_css
297
- ) as interface:
298
 
299
- # Header personalizado
300
- gr.HTML(f"""
301
- <div class="main-title">
302
- 🤖 IA para todos
303
- </div>
304
- <div class="subtitle">
305
- "Porque cuando no tienes nada en la cabeza, te preocupas de la tipografía?"
306
- </div>
307
- <div style="text-align: center;">
308
- <span class="device-indicator">
309
- {"🖥️ Modo CPU Optimizado" if DEVICE == "cpu" else f"🚀 Modo {DEVICE.upper()} Acelerado"}
310
- </span>
311
- </div>
312
  """)
313
 
314
- gr.Markdown("""
315
- ### 🎨 Convierte cualquier imagen en prompts detallados para IA
316
- **Versión optimizada** - Sin warnings, más rápido, mejor experiencia
317
- """)
318
 
319
  with gr.Row():
320
  with gr.Column(scale=1):
321
- # Input section
322
- gr.Markdown("## 📤 Subir Imagen")
323
  image_input = gr.Image(
324
- label="Arrastra, pega o selecciona una imagen",
325
  type="pil",
326
- height=320
327
  )
328
 
329
- # Configuración
330
- gr.Markdown("## ⚙️ Configuración Inteligente")
331
  model_selector = gr.Dropdown(
332
  choices=["general", "stable_diffusion", "midjourney", "flux"],
333
  value="general",
334
- label="🎯 Modelo de IA objetivo",
335
- info="Optimizado para tu plataforma de IA favorita"
336
  )
337
 
338
  mode_selector = gr.Dropdown(
339
- choices=list(INTERROGATION_MODES.keys()),
340
- value="best",
341
- label="Modo de análisis",
342
- info="Equilibrio entre velocidad y precisión"
343
  )
344
 
345
- # Información de rendimiento
346
- gr.Markdown(f"""
347
- **📊 Rendimiento esperado en {DEVICE.upper()}:**
348
- - Primera vez: 2-3 minutos (descarga modelos)
349
- - Siguientes: {"30-60 seg" if DEVICE == "cpu" else "15-30 seg"}
350
- """)
351
-
352
- # Botón generar
353
- generate_btn = gr.Button(
354
- "🚀 Generar Prompt Mágico",
355
- variant="primary",
356
- size="lg"
357
- )
358
 
359
  with gr.Column(scale=1):
360
- # Output section
361
- gr.Markdown("## 📝 Tu Prompt Está Listo")
362
  prompt_output = gr.Textbox(
363
- label="Prompt generado (listo para copiar)",
364
- placeholder="Tu prompt aparecerá aquí con toda la magia de la IA...",
365
  lines=10,
366
- max_lines=20,
367
  elem_classes=["prompt-output"],
368
  show_copy_button=True
369
  )
370
 
371
- info_output = gr.Markdown(
372
- label="📊 Información del procesamiento",
373
- value=""
374
- )
375
 
376
- # Botones de acción
377
  with gr.Row():
378
  clear_btn = gr.Button("🗑️ Limpiar", size="sm")
379
- refresh_btn = gr.Button("🔄 Reiniciar", size="sm")
380
-
381
- # Footer mejorado
382
- gr.Markdown(f"""
383
- ---
384
- ### 💡 Guía de Uso Optimizada:
385
-
386
- **🎯 Modelos disponibles:**
387
- - **General:** Prompts universales, funciona en cualquier plataforma
388
- - **Stable Diffusion:** Optimizado para SD 1.x, SDXL y derivados
389
- - **Midjourney:** Perfecto para estilos artísticos y creativos
390
- - **Flux:** Para el revolucionario modelo Flux de Black Forest Labs
391
-
392
- **⚡ Modos de análisis optimizados:**
393
- - **Rápido:** Análisis express, ideal para pruebas rápidas
394
- - **Clásico:** Equilibrio perfecto, recomendado para uso general
395
- - **Mejor:** Máxima precisión, perfecto para trabajos importantes
396
-
397
- **🖥️ Optimizado para {DEVICE.upper()}:**
398
- - Sin warnings ni errores
399
- - Gestión inteligente de memoria
400
- - Procesamiento optimizado según tu hardware
401
-
402
- ---
403
 
404
- ### 🎭 Hecho con amor (y mejor tipografía) por IA para todos
405
- *"La IA nos ayuda con las ideas, nosotros nos preocupamos de que se vean bonitas"* ✨
406
-
407
- **Versión:** Optimizada CPU/GPU | **Build:** Sin warnings | **Performance:** Mejorado 2x
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
408
  """)
409
 
410
- # Event handlers optimizados
411
  generate_btn.click(
412
  fn=process_image_with_progress,
413
  inputs=[image_input, model_selector, mode_selector],
@@ -418,21 +294,14 @@ def create_interface():
418
  fn=clear_outputs,
419
  outputs=[prompt_output, info_output]
420
  )
421
-
422
- refresh_btn.click(
423
- fn=lambda: gr.update(value=None),
424
- outputs=[image_input]
425
- )
426
 
427
  return interface
428
 
429
- # Lanzar aplicación optimizada
430
  if __name__ == "__main__":
431
- logger.info(f"🚀 Iniciando IA para todos (optimizado para {DEVICE})")
432
  interface = create_interface()
433
  interface.launch(
434
  server_name="0.0.0.0",
435
  server_port=7860,
436
- show_error=True,
437
- quiet=False
438
  )
 
2
  import torch
3
  from PIL import Image
4
  import numpy as np
5
+ from clip_interrogator import Config, Interrogator
6
  import logging
7
  import os
8
  import warnings
9
  from datetime import datetime
 
10
  import gc
11
+ import spaces
12
 
13
+ # Suprimir warnings
14
  warnings.filterwarnings("ignore", category=FutureWarning)
15
  warnings.filterwarnings("ignore", category=UserWarning)
16
  os.environ["TOKENIZERS_PARALLELISM"] = "false"
17
 
18
+ logging.basicConfig(level=logging.INFO)
 
19
  logger = logging.getLogger(__name__)
20
 
21
+ # Detectar dispositivo
22
  def get_device():
23
  if torch.cuda.is_available():
24
  return "cuda"
25
  elif torch.backends.mps.is_available():
26
+ return "mps"
27
  else:
28
  return "cpu"
29
 
30
  DEVICE = get_device()
 
31
 
 
32
  CLIP_MODELS = {
33
  "general": "ViT-L-14/openai",
34
+ "stable_diffusion": "ViT-L-14/openai",
35
  "midjourney": "ViT-H-14/laion2b_s32b_b79k",
36
  "flux": "ViT-L-14/openai"
37
  }
38
 
39
+ MODES = {
40
+ "fast": "⚡ Rápido",
41
+ "classic": "⚖️ Clásico",
42
+ "best": "⭐ Mejor"
43
  }
44
 
45
+ class ImagePromptGenerator:
46
  def __init__(self):
47
  self.interrogator = None
48
  self.usage_count = 0
49
  self.device = DEVICE
50
  self.is_initialized = False
 
51
 
52
  def initialize_model(self, progress_callback=None):
 
53
  if self.is_initialized:
54
  return True
55
 
56
  try:
57
  if progress_callback:
58
+ progress_callback("🔄 Cargando CLIP Interrogator...")
59
 
 
60
  config = Config(
61
  clip_model_name="ViT-L-14/openai",
62
  download_cache=True,
63
+ chunk_size=2048,
64
  quiet=True,
65
  device=self.device
66
  )
67
 
 
 
 
68
  self.interrogator = Interrogator(config)
 
 
 
 
69
  self.is_initialized = True
 
70
 
 
71
  if self.device == "cpu":
72
  gc.collect()
73
  else:
 
76
  return True
77
 
78
  except Exception as e:
79
+ logger.error(f"Error: {e}")
 
 
80
  return False
81
 
82
  def optimize_image(self, image):
 
83
  if image is None:
84
  return None
85
 
 
86
  if isinstance(image, np.ndarray):
87
  image = Image.fromarray(image)
88
  elif not isinstance(image, Image.Image):
89
  image = Image.open(image)
90
 
 
91
  if image.mode != 'RGB':
92
  image = image.convert('RGB')
93
 
 
94
  max_size = 768 if self.device != "cpu" else 512
95
  if image.size[0] > max_size or image.size[1] > max_size:
96
  image.thumbnail((max_size, max_size), Image.Resampling.LANCZOS)
 
97
 
98
  return image
99
 
100
+ @spaces.GPU
101
  def generate_prompt(self, image, model_type="general", mode="best", progress_callback=None):
 
102
  try:
 
103
  if not self.is_initialized:
104
  if not self.initialize_model(progress_callback):
105
+ return "❌ Error inicializando modelo.", ""
106
 
107
  if image is None:
108
+ return "❌ Sube una imagen.", ""
109
 
 
110
  self.usage_count += 1
111
 
112
  if progress_callback:
113
+ progress_callback("🖼️ Procesando imagen...")
114
 
 
115
  image = self.optimize_image(image)
116
  if image is None:
117
+ return "❌ Error procesando imagen.", ""
118
 
119
  if progress_callback:
120
+ progress_callback("🧠 Generando prompt...")
121
 
 
122
  start_time = datetime.now()
123
 
124
  try:
 
126
  prompt = self.interrogator.interrogate_fast(image)
127
  elif mode == "classic":
128
  prompt = self.interrogator.interrogate_classic(image)
129
+ else:
130
  prompt = self.interrogator.interrogate(image)
131
 
132
  except Exception as e:
 
 
133
  prompt = self.interrogator.interrogate_fast(image)
134
 
135
  end_time = datetime.now()
136
  duration = (end_time - start_time).total_seconds()
137
 
 
138
  if self.device == "cpu":
139
  gc.collect()
140
  else:
141
  torch.cuda.empty_cache()
142
 
143
+ gpu_status = "🚀 ZeroGPU" if torch.cuda.is_available() else "🖥️ CPU"
144
+
145
  info = f"""
146
+ **✅ Prompt generado - Pariente AI**
147
 
148
+ {gpu_status} **|** {model_type.replace('_', ' ').title()} **|** {MODES.get(mode, mode)} **|** {duration:.1f}s
149
+ **Uso #{self.usage_count}** - {datetime.now().strftime('%H:%M')}
 
 
 
 
 
 
150
 
151
+ *"Porque cuando no tienes nada en la cabeza, te preocupas de la tipografía"*
 
 
152
  """
153
 
 
 
 
154
  return prompt, info
155
 
156
  except Exception as e:
157
+ return f"Error: {str(e)}", "💡 Intenta con modo rápido o imagen más pequeña"
 
 
 
 
 
158
 
159
+ generator = ImagePromptGenerator()
 
 
 
 
 
 
 
 
160
 
161
+ @spaces.GPU
162
  def process_image_with_progress(image, model_type, mode):
 
 
 
163
  def progress_callback(message):
 
164
  return message
165
 
166
+ yield "🚀 Activando ZeroGPU...", """
167
+ **🚀 Pariente AI - Procesando**
 
168
 
169
+ ZeroGPU gratuito activado
170
+ 🎯 Código abierto honesto
171
+ 💡 Research real, no marketing
 
172
  """
173
 
 
174
  prompt, info = generator.generate_prompt(image, model_type, mode, progress_callback)
 
 
175
  yield prompt, info
176
 
177
  def clear_outputs():
 
178
  gc.collect()
179
  if torch.cuda.is_available():
180
  torch.cuda.empty_cache()
181
  return "", ""
182
 
 
183
  def create_interface():
184
+ css = """
 
185
  .gradio-container {
186
  max-width: 1400px !important;
187
+ font-family: 'Inter', system-ui, sans-serif;
188
  }
189
  .prompt-output {
190
+ font-family: 'SF Mono', 'Monaco', monospace !important;
191
  font-size: 14px !important;
192
  line-height: 1.6 !important;
193
  background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%) !important;
194
  border-radius: 12px !important;
195
  padding: 20px !important;
196
  border: 1px solid #dee2e6 !important;
 
197
  }
198
  .main-title {
199
  text-align: center;
200
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
201
  -webkit-background-clip: text;
202
  -webkit-text-fill-color: transparent;
 
203
  font-size: 3em !important;
204
  font-weight: 800 !important;
205
  margin-bottom: 0.3em !important;
 
206
  }
207
  .subtitle {
208
  text-align: center;
 
210
  color: #6c757d;
211
  font-size: 1.2em;
212
  margin-bottom: 2em;
 
 
 
 
 
 
 
 
 
 
213
  }
214
  """
215
 
216
+ with gr.Blocks(theme=gr.themes.Soft(), title="Pariente AI - Image to Prompt", css=css) as interface:
 
 
 
 
217
 
218
+ gr.HTML("""
219
+ <div class="main-title">🤖 Pariente AI</div>
220
+ <div class="subtitle">"Porque cuando no tienes nada en la cabeza, te preocupas de la tipografía"</div>
 
 
 
 
 
 
 
 
 
 
221
  """)
222
 
223
+ gr.Markdown("### 🎨 Image to Prompt - Research real, no marketing")
 
 
 
224
 
225
  with gr.Row():
226
  with gr.Column(scale=1):
227
+ gr.Markdown("## 📤 Imagen")
 
228
  image_input = gr.Image(
229
+ label="Sube tu imagen",
230
  type="pil",
231
+ height=300
232
  )
233
 
234
+ gr.Markdown("## ⚙️ Config")
 
235
  model_selector = gr.Dropdown(
236
  choices=["general", "stable_diffusion", "midjourney", "flux"],
237
  value="general",
238
+ label="Modelo objetivo"
 
239
  )
240
 
241
  mode_selector = gr.Dropdown(
242
+ choices=list(MODES.keys()),
243
+ value="best",
244
+ label="Modo"
 
245
  )
246
 
247
+ generate_btn = gr.Button("🚀 Generar Prompt", variant="primary", size="lg")
 
 
 
 
 
 
 
 
 
 
 
 
248
 
249
  with gr.Column(scale=1):
250
+ gr.Markdown("## 📝 Resultado")
 
251
  prompt_output = gr.Textbox(
252
+ label="Prompt generado",
253
+ placeholder="Tu prompt aparecerá aquí...",
254
  lines=10,
 
255
  elem_classes=["prompt-output"],
256
  show_copy_button=True
257
  )
258
 
259
+ info_output = gr.Markdown(value="")
 
 
 
260
 
 
261
  with gr.Row():
262
  clear_btn = gr.Button("🗑️ Limpiar", size="sm")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
263
 
264
+ gr.Markdown("""
265
+ ---
266
+ ### 💡 Realidad vs Marketing
267
+
268
+ **¿Ves esto? ZeroGPU gratuito. ¿Tu startup cobra $50/mes por lo mismo? Si lo pagas es señal de que eres gilipollas**
269
+
270
+ **🔬 Pariente AI hace research real:**
271
+ - Creamos modelos desde cero
272
+ - Publicamos papers de verdad
273
+ - Mostramos el código siempre
274
+ - Innovamos, no copiamos
275
+
276
+ **🤡 Startup típica hace marketing:**
277
+ - Copia código de GitHub
278
+ - Lo envuelve en CSS bonito
279
+ - Cobra como "innovación"
280
+ - Busca inversores con PowerPoints
281
+
282
+ ---
283
+
284
+ **⚡ Powered by Pariente AI** - *Research real, no bullshit*
285
  """)
286
 
 
287
  generate_btn.click(
288
  fn=process_image_with_progress,
289
  inputs=[image_input, model_selector, mode_selector],
 
294
  fn=clear_outputs,
295
  outputs=[prompt_output, info_output]
296
  )
 
 
 
 
 
297
 
298
  return interface
299
 
 
300
  if __name__ == "__main__":
301
+ logger.info("🚀 Iniciando Pariente AI")
302
  interface = create_interface()
303
  interface.launch(
304
  server_name="0.0.0.0",
305
  server_port=7860,
306
+ show_error=True
 
307
  )