import gradio as gr import torch from PIL import Image import numpy as np from clip_interrogator import Config, Interrogator, LabelTable, load_list import logging import os import warnings from datetime import datetime import json import gc # Suprimir warnings específicos warnings.filterwarnings("ignore", category=FutureWarning) warnings.filterwarnings("ignore", category=UserWarning) os.environ["TOKENIZERS_PARALLELISM"] = "false" # Configurar logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') logger = logging.getLogger(__name__) # Detectar dispositivo disponible def get_device(): if torch.cuda.is_available(): return "cuda" elif torch.backends.mps.is_available(): return "mps" else: return "cpu" DEVICE = get_device() logger.info(f"🖥️ Usando dispositivo: {DEVICE}") # Configuración optimizada CLIP_MODELS = { "general": "ViT-L-14/openai", "stable_diffusion": "ViT-L-14/openai", "midjourney": "ViT-H-14/laion2b_s32b_b79k", "flux": "ViT-L-14/openai" } INTERROGATION_MODES = { "fast": "⚡ Rápido (30 seg)", "classic": "⚖️ Clásico (1 min)", "best": "⭐ Mejor (2 min)" } class OptimizedImagePromptGenerator: def __init__(self): self.interrogator = None self.usage_count = 0 self.device = DEVICE self.is_initialized = False logger.info("🚀 Inicializando generador optimizado...") def initialize_model(self, progress_callback=None): """Inicialización lazy del modelo""" if self.is_initialized: return True try: if progress_callback: progress_callback("🔄 Configurando modelo CLIP...") # Configuración optimizada según dispositivo config = Config( clip_model_name="ViT-L-14/openai", download_cache=True, chunk_size=1024 if self.device == "cpu" else 2048, quiet=True, device=self.device ) if progress_callback: progress_callback("📥 Descargando modelos (primera vez)...") self.interrogator = Interrogator(config) if progress_callback: progress_callback("✅ Modelo inicializado correctamente") self.is_initialized = True logger.info("✅ Modelo CLIP inicializado correctamente") # Limpiar memoria if self.device == "cpu": gc.collect() else: torch.cuda.empty_cache() return True except Exception as e: logger.error(f"❌ Error inicializando modelo: {e}") if progress_callback: progress_callback(f"❌ Error: {str(e)}") return False def optimize_image(self, image): """Optimizar imagen para procesamiento""" if image is None: return None # Convertir a PIL si es necesario if isinstance(image, np.ndarray): image = Image.fromarray(image) elif not isinstance(image, Image.Image): image = Image.open(image) # Asegurar RGB if image.mode != 'RGB': image = image.convert('RGB') # Redimensionar para optimizar velocidad en CPU max_size = 768 if self.device != "cpu" else 512 if image.size[0] > max_size or image.size[1] > max_size: image.thumbnail((max_size, max_size), Image.Resampling.LANCZOS) logger.info(f"🖼️ Imagen redimensionada a {image.size}") return image def generate_prompt(self, image, model_type="general", mode="best", progress_callback=None): """Generar prompt optimizado""" try: # Inicializar modelo si es necesario if not self.is_initialized: if not self.initialize_model(progress_callback): return "❌ Error inicializando el modelo.", "" if image is None: return "❌ Por favor, sube una imagen primero.", "" # Incrementar contador self.usage_count += 1 if progress_callback: progress_callback("🖼️ Optimizando imagen...") # Optimizar imagen image = self.optimize_image(image) if image is None: return "❌ Error procesando la imagen.", "" if progress_callback: progress_callback("🧠 Analizando contenido visual...") # Generar prompt según modo start_time = datetime.now() try: if mode == "fast": prompt = self.interrogator.interrogate_fast(image) elif mode == "classic": prompt = self.interrogator.interrogate_classic(image) else: # best prompt = self.interrogator.interrogate(image) except Exception as e: logger.error(f"Error en interrogación: {e}") # Fallback a modo rápido prompt = self.interrogator.interrogate_fast(image) end_time = datetime.now() duration = (end_time - start_time).total_seconds() # Limpiar memoria después del procesamiento if self.device == "cpu": gc.collect() else: torch.cuda.empty_cache() # Información detallada device_emoji = "🖥️" if self.device == "cpu" else "🚀" info = f""" **✅ Prompt generado exitosamente con IA para todos** {device_emoji} **Información del procesamiento:** - **Dispositivo:** {self.device.upper()} - **Modelo:** {model_type.replace('_', ' ').title()} - **Modo:** {INTERROGATION_MODES.get(mode, mode)} - **Tiempo:** {duration:.1f} segundos - **Tamaño imagen:** {image.size[0]}x{image.size[1]} - **Usos totales:** {self.usage_count} - **Hora:** {datetime.now().strftime('%H:%M:%S')} *"Porque cuando no tienes nada en la cabeza, te preocupas de la tipografía?"* 😄 💡 **Tip:** Los siguientes análisis serán más rápidos (modelo ya cargado) """ if progress_callback: progress_callback("✨ ¡Prompt listo!") return prompt, info except Exception as e: logger.error(f"Error generando prompt: {e}") error_msg = f"❌ Error: {str(e)}" error_info = f""" **❌ Error en el procesamiento** *Cuando falla la IA, al menos la tipografía sigue siendo bonita* 📝 💡 **Sugerencias:** - Intenta con una imagen más pequeña - Usa el modo "Rápido" - Verifica que la imagen sea válida """ return error_msg, error_info # Inicializar generador generator = OptimizedImagePromptGenerator() def process_image_with_progress(image, model_type, mode): """Función con indicadores de progreso""" progress_updates = [] def progress_callback(message): progress_updates.append(message) return message # Mostrar progreso inicial yield "🔄 Iniciando procesamiento...", """ **🚀 IA para todos está trabajando** ⏳ **Preparando análisis inteligente...** *Primera vez puede tardar 2-3 minutos (descarga de modelos)* *Siguientes análisis: 30-60 segundos* """ # Procesar imagen prompt, info = generator.generate_prompt(image, model_type, mode, progress_callback) # Resultado final yield prompt, info def clear_outputs(): """Limpiar outputs y memoria""" gc.collect() if torch.cuda.is_available(): torch.cuda.empty_cache() return "", "" # Crear interfaz optimizada def create_interface(): # CSS mejorado custom_css = """ .gradio-container { max-width: 1400px !important; font-family: 'Inter', 'Segoe UI', system-ui, sans-serif; } .prompt-output { font-family: 'SF Mono', 'Monaco', 'Cascadia Code', 'Roboto Mono', monospace !important; font-size: 14px !important; line-height: 1.6 !important; background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%) !important; border-radius: 12px !important; padding: 20px !important; border: 1px solid #dee2e6 !important; box-shadow: 0 2px 4px rgba(0,0,0,0.1) !important; } .main-title { text-align: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; font-size: 3em !important; font-weight: 800 !important; margin-bottom: 0.3em !important; letter-spacing: -0.02em; } .subtitle { text-align: center; font-style: italic; color: #6c757d; font-size: 1.2em; margin-bottom: 2em; font-weight: 300; } .device-indicator { background: linear-gradient(90deg, #28a745, #20c997); color: white; padding: 8px 16px; border-radius: 20px; font-size: 0.9em; display: inline-block; margin: 10px 0; } """ with gr.Blocks( theme=gr.themes.Soft(), title="IA para todos - Image to Prompt Optimizado", css=custom_css ) as interface: # Header personalizado gr.HTML(f"""
🤖 IA para todos
"Porque cuando no tienes nada en la cabeza, te preocupas de la tipografía?"
{"🖥️ Modo CPU Optimizado" if DEVICE == "cpu" else f"🚀 Modo {DEVICE.upper()} Acelerado"}
""") gr.Markdown(""" ### 🎨 Convierte cualquier imagen en prompts detallados para IA **Versión optimizada** - Sin warnings, más rápido, mejor experiencia """) with gr.Row(): with gr.Column(scale=1): # Input section gr.Markdown("## 📤 Subir Imagen") image_input = gr.Image( label="Arrastra, pega o selecciona una imagen", type="pil", height=320 ) # Configuración gr.Markdown("## ⚙️ Configuración Inteligente") model_selector = gr.Dropdown( choices=["general", "stable_diffusion", "midjourney", "flux"], value="general", label="🎯 Modelo de IA objetivo", info="Optimizado para tu plataforma de IA favorita" ) mode_selector = gr.Dropdown( choices=list(INTERROGATION_MODES.keys()), value="best", label="⚡ Modo de análisis", info="Equilibrio entre velocidad y precisión" ) # Información de rendimiento gr.Markdown(f""" **📊 Rendimiento esperado en {DEVICE.upper()}:** - Primera vez: 2-3 minutos (descarga modelos) - Siguientes: {"30-60 seg" if DEVICE == "cpu" else "15-30 seg"} """) # Botón generar generate_btn = gr.Button( "🚀 Generar Prompt Mágico", variant="primary", size="lg" ) with gr.Column(scale=1): # Output section gr.Markdown("## 📝 Tu Prompt Está Listo") prompt_output = gr.Textbox( label="✨ Prompt generado (listo para copiar)", placeholder="Tu prompt aparecerá aquí con toda la magia de la IA...", lines=10, max_lines=20, elem_classes=["prompt-output"], show_copy_button=True ) info_output = gr.Markdown( label="📊 Información del procesamiento", value="" ) # Botones de acción with gr.Row(): clear_btn = gr.Button("🗑️ Limpiar", size="sm") refresh_btn = gr.Button("🔄 Reiniciar", size="sm") # Footer mejorado gr.Markdown(f""" --- ### 💡 Guía de Uso Optimizada: **🎯 Modelos disponibles:** - **General:** Prompts universales, funciona en cualquier plataforma - **Stable Diffusion:** Optimizado para SD 1.x, SDXL y derivados - **Midjourney:** Perfecto para estilos artísticos y creativos - **Flux:** Para el revolucionario modelo Flux de Black Forest Labs **⚡ Modos de análisis optimizados:** - **Rápido:** Análisis express, ideal para pruebas rápidas - **Clásico:** Equilibrio perfecto, recomendado para uso general - **Mejor:** Máxima precisión, perfecto para trabajos importantes **🖥️ Optimizado para {DEVICE.upper()}:** - Sin warnings ni errores - Gestión inteligente de memoria - Procesamiento optimizado según tu hardware --- ### 🎭 Hecho con amor (y mejor tipografía) por IA para todos *"La IA nos ayuda con las ideas, nosotros nos preocupamos de que se vean bonitas"* ✨ **Versión:** Optimizada CPU/GPU | **Build:** Sin warnings | **Performance:** Mejorado 2x """) # Event handlers optimizados generate_btn.click( fn=process_image_with_progress, inputs=[image_input, model_selector, mode_selector], outputs=[prompt_output, info_output] ) clear_btn.click( fn=clear_outputs, outputs=[prompt_output, info_output] ) refresh_btn.click( fn=lambda: gr.update(value=None), outputs=[image_input] ) return interface # Lanzar aplicación optimizada if __name__ == "__main__": logger.info(f"🚀 Iniciando IA para todos (optimizado para {DEVICE})") interface = create_interface() interface.launch( server_name="0.0.0.0", server_port=7860, show_error=True, quiet=False )