Phramer_AI / app.py
Malaji71's picture
Update app.py
3f0776a verified
raw
history blame
15 kB
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"""
<div class="main-title">
🤖 IA para todos
</div>
<div class="subtitle">
"Porque cuando no tienes nada en la cabeza, te preocupas de la tipografía?"
</div>
<div style="text-align: center;">
<span class="device-indicator">
{"🖥️ Modo CPU Optimizado" if DEVICE == "cpu" else f"🚀 Modo {DEVICE.upper()} Acelerado"}
</span>
</div>
""")
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
)