""" App de Mejora de Prompts para Generación de Imágenes Compatible con Gradio 6.0+ """ import gradio as gr from prompt_engine import PromptEnhancer, PromptBuilder, PromptAnalyzer from model_configs import MODEL_CONFIGS, ARTIST_STYLES, ENHANCEMENT_RULES # Inicializar componentes enhancer = PromptEnhancer() analyzer = PromptAnalyzer() # ===== FUNCIONES PRINCIPALES ===== def enhance_prompt(prompt: str, model: str, style: str, add_quality: bool, add_negative: bool) -> tuple: """Función principal de mejora de prompts""" if not prompt or not prompt.strip(): return ("⚠️ Por favor, ingresa un prompt", "", "", "", "") model_map = { "Stable Diffusion 1.5": "stable-diffusion-1.5", "Stable Diffusion XL": "sdxl", "FLUX.1": "flux", "Midjourney": "midjourney", "DALL-E 3": "dall-e-3" } model_key = model_map.get(model, "stable-diffusion-1.5") style_key = style.lower() if style and style != "Ninguno" else None result = enhancer.enhance_for_model( prompt=prompt, model=model_key, style=style_key, add_quality=add_quality, add_negative=add_negative ) analysis = result["analysis"] score_emoji = "🟢" if analysis["score"] >= 70 else "🟡" if analysis["score"] >= 40 else "🔴" suggestions_text = '\n'.join(analysis['suggestions']) if analysis['suggestions'] else '✅ ¡El prompt está bien estructurado!' analysis_text = f"""### 📊 Análisis del Prompt **Puntuación:** {score_emoji} {analysis['score']}/100 **Estadísticas:** - Palabras: {analysis['word_count']} - Caracteres: {analysis['char_count']} - Tokens estimados: {result['tokens_estimate']}/{result['max_tokens']} **Sugerencias:** {suggestions_text} """ variations = enhancer.suggest_variations(result["enhanced"], 3) variations_text = "\n\n".join([f"**Variación {i+1}:**\n`{v}`" for i, v in enumerate(variations)]) return ( result["enhanced"], result["negative_prompt"], analysis_text, variations_text, f"✅ Optimizado para: **{result['model']}**" ) def fix_prompt(prompt: str) -> tuple: """Corrige errores comunes en el prompt""" if not prompt or not prompt.strip(): return ("⚠️ Por favor, ingresa un prompt", "") fixed, fixes = enhancer.fix_common_errors(prompt) if fixes: fixes_text = "### 🔧 Correcciones aplicadas:\n" + "\n".join([f"- {f}" for f in fixes]) else: fixes_text = "### ✅ No se encontraron errores que corregir" return fixed, fixes_text def build_prompt(subject: str, style: str, lighting: str, mood: str, camera: str, quality_opts: list, extra_details: str) -> str: """Construye un prompt desde componentes""" if not subject or not subject.strip(): return "⚠️ Por favor, ingresa al menos un sujeto" builder = PromptBuilder() builder.set_subject(subject) if style and style != "Ninguno": builder.set_style(style.lower()) if lighting and lighting != "Ninguno": builder.set_lighting(lighting.lower()) if mood and mood != "Ninguno": builder.set_mood(mood.lower()) if camera and camera != "Ninguno": builder.set_camera(camera.lower()) if quality_opts: quality_map = { "Alta definición (8K)": ["8k uhd", "high resolution"], "Muy detallado": ["highly detailed", "intricate details"], "Masterpiece": ["masterpiece", "best quality"], "Fotografía profesional": ["professional photography", "DSLR"], "Arte de alta calidad": ["high quality art", "artstation"] } quality_terms = [] for opt in quality_opts: if opt in quality_map: quality_terms.extend(quality_map[opt]) builder.add_quality(quality_terms) if extra_details and extra_details.strip(): builder.add_details([extra_details.strip()]) return builder.build() def analyze_only(prompt: str) -> str: """Solo analiza el prompt sin mejorarlo""" if not prompt or not prompt.strip(): return "⚠️ Por favor, ingresa un prompt para analizar" analysis = analyzer.analyze(prompt) score = analysis["score"] if score >= 80: grade = "🏆 Excelente" elif score >= 60: grade = "👍 Bueno" elif score >= 40: grade = "⚠️ Mejorable" else: grade = "❌ Necesita trabajo" if analysis["issues"]: issue_names = { "muy_corto": "❌ Prompt muy corto", "sin_estilo": "🎨 Falta especificar estilo artístico", "sin_calidad": "✨ Faltan modificadores de calidad", "sin_iluminacion": "💡 No se describe la iluminación", "sin_composicion": "📷 Falta información de composición/encuadre", "palabras_vagas": "📝 Contiene palabras demasiado vagas" } issues_text = "\n".join([issue_names.get(i, i) for i in analysis["issues"]]) else: issues_text = "✅ No se detectaron problemas" suggestions_text = '\n'.join(analysis['suggestions']) if analysis['suggestions'] else '¡El prompt está bien estructurado!' report = f"""## 📊 Análisis Detallado ### Calificación: {grade} ({score}/100) --- ### 📈 Estadísticas | Métrica | Valor | |---------|-------| | Palabras | {analysis['word_count']} | | Caracteres | {analysis['char_count']} | --- ### 🔍 Problemas Detectados {issues_text} --- ### 💡 Sugerencias de Mejora {suggestions_text} --- ### 📚 Tips Generales - Los prompts más efectivos tienen entre 15-40 palabras - Incluye siempre el estilo visual deseado - Especifica la iluminación para mayor control - Usa modificadores de calidad al inicio del prompt - Evita palabras genéricas como "bonito" o "bueno" """ return report def get_style_examples(style: str) -> str: """Muestra ejemplos para un estilo específico""" if not style or style == "Ninguno": return "Selecciona un estilo para ver ejemplos" examples = { "Fotorealista": ( "**Ejemplos de prompts fotorealistas:**\n\n" "1. `professional photograph of a woman, natural lighting, 85mm lens, shallow depth of field, photorealistic, 8k uhd`\n\n" "2. `hyperrealistic photo of a mountain landscape, golden hour, dramatic clouds, raw photo, high dynamic range`\n\n" "3. `product photography of a luxury watch, studio lighting, macro shot, commercial photography, pristine details`" ), "Anime": ( "**Ejemplos de prompts anime:**\n\n" "1. `anime girl with blue hair, cherry blossom background, studio ghibli style, vibrant colors, detailed eyes, key visual`\n\n" "2. `epic anime battle scene, dynamic action pose, energy effects, dramatic lighting, anime key visual, trending on pixiv`\n\n" "3. `cozy anime room interior, warm lighting, detailed background, slice of life aesthetic, makoto shinkai style`" ), "Arte Digital": ( "**Ejemplos de arte digital:**\n\n" "1. `digital painting of a fantasy castle, dramatic sky, concept art, artstation trending, highly detailed, epic composition`\n\n" "2. `character design, full body portrait, detailed armor, digital art, fantasy warrior, professional illustration`\n\n" "3. `environment concept art, alien planet, sci-fi landscape, matte painting, cinematic, artstation winner`" ), "Pintura": ( "**Ejemplos de pintura:**\n\n" "1. `oil painting of a serene lake, impressionist style, visible brush strokes, golden hour lighting, museum quality`\n\n" "2. `renaissance portrait, classical technique, dramatic chiaroscuro, oil on canvas, by old masters`\n\n" "3. `watercolor landscape, soft edges, wet on wet technique, delicate colors, paper texture visible`" ), "3D": ( "**Ejemplos de 3D/CGI:**\n\n" "1. `3D render of a cute robot character, octane render, subsurface scattering, studio lighting, pixar style`\n\n" "2. `architectural visualization, modern house, ray tracing, unreal engine 5, photorealistic materials`\n\n" "3. `3D character model, fantasy creature, zbrush detail, substance painter textures, turntable view`" ), "Cinematico": ( "**Ejemplos cinematográficos:**\n\n" "1. `cinematic still from a sci-fi movie, anamorphic lens, dramatic lighting, movie poster composition, 4k`\n\n" "2. `film noir scene, high contrast, dramatic shadows, mysterious atmosphere, classic hollywood style`\n\n" "3. `epic movie landscape, sweeping vista, volumetric fog, golden hour, widescreen composition`" ) } return examples.get(style, "No hay ejemplos disponibles para este estilo") # ===== TEXTOS LARGOS ===== GUIDE_TEXT = """## 📖 Guía Rápida de Prompts ### Estructura recomendada: [Calidad] + [Sujeto principal] + [Estilo] + [Detalles] + [Iluminación] + [Composición] ### Ejemplo práctico: masterpiece, best quality, a beautiful elven princess with silver hair, fantasy art style, intricate jewelry, magical forest background, ethereal lighting, portrait shot, highly detailed --- ### ⚡ Diferencias entre modelos: | Modelo | Tokens | Pesos | Estilo de prompt | |--------|--------|-------|------------------| | SD 1.5 | 77 | ✅ (word:1.2) | Tags separados por comas | | SDXL | 77 | ✅ (word:1.2) | Similar a SD, más natural | | FLUX | 256 | ❌ | Descripciones naturales | | Midjourney | 500 | ✅ ::peso | Natural + parámetros | | DALL-E 3 | 4000 | ❌ | Oraciones descriptivas | --- ### 🎯 Palabras clave por categoría: **Calidad:** masterpiece, best quality, highly detailed, 8k, uhd, professional **Iluminación:** dramatic lighting, soft light, golden hour, studio lighting, rim light **Composición:** portrait, full body, close-up, wide shot, bird's eye view **Estilos:** oil painting, digital art, photograph, 3d render, watercolor, sketch """ TIPS_TEXT = """### 💡 Tips para cada componente: - **Sujeto**: Sé específico. "young woman with curly red hair" > "woman" - **Estilo**: Define la estética visual del resultado - **Iluminación**: Afecta dramáticamente el mood de la imagen - **Ambiente**: Establece el tono emocional - **Encuadre**: Controla la composición de la imagen """ FOOTER_TEXT = """---
Prompt Enhancer Pro | Creado para la comunidad de generación de imágenes con IA
Compatible con: Stable Diffusion, SDXL, FLUX, Midjourney y DALL-E 3
""" HEADER_HTML = """

🎨 Prompt Enhancer Pro

Mejora y optimiza tus prompts para generación de imágenes con IA

""" # ===== INTERFAZ GRADIO 6.0+ ===== def create_app(): """Crea la aplicación Gradio""" with gr.Blocks(title="Prompt Enhancer Pro") as app: gr.HTML(HEADER_HTML) with gr.Tabs(): # ===== TAB 1: MEJORAR PROMPT ===== with gr.TabItem("✨ Mejorar Prompt"): gr.Markdown("### Transforma tu prompt simple en uno profesional") with gr.Row(): with gr.Column(scale=1): input_prompt = gr.Textbox( label="Tu prompt original", placeholder="Escribe tu prompt aquí... (puede ser en español o inglés)", lines=3 ) with gr.Row(): model_select = gr.Dropdown( choices=["Stable Diffusion 1.5", "Stable Diffusion XL", "FLUX.1", "Midjourney", "DALL-E 3"], value="Stable Diffusion XL", label="Modelo destino" ) style_select = gr.Dropdown( choices=["Ninguno", "Fotorealista", "Anime", "Arte Digital", "Pintura", "3D", "Cinematico", "Minimalista", "Fantasia"], value="Ninguno", label="Estilo artístico" ) with gr.Row(): add_quality = gr.Checkbox(label="Añadir tokens de calidad", value=True) add_negative = gr.Checkbox(label="Generar negative prompt", value=True) enhance_btn = gr.Button("🚀 Mejorar Prompt", variant="primary") with gr.Column(scale=1): output_prompt = gr.Textbox( label="✅ Prompt mejorado", lines=4, interactive=False ) output_negative = gr.Textbox( label="❌ Negative prompt", lines=2, interactive=False ) model_info = gr.Markdown("") with gr.Row(): with gr.Column(): analysis_output = gr.Markdown(label="Análisis") with gr.Column(): variations_output = gr.Markdown(label="Variaciones sugeridas") enhance_btn.click( fn=enhance_prompt, inputs=[input_prompt, model_select, style_select, add_quality, add_negative], outputs=[output_prompt, output_negative, analysis_output, variations_output, model_info] ) # ===== TAB 2: CORRECTOR ===== with gr.TabItem("🔧 Corrector de Errores"): gr.Markdown("### Detecta y corrige errores comunes en tus prompts") with gr.Row(): with gr.Column(): fix_input = gr.Textbox( label="Prompt con posibles errores", placeholder="Pega aquí un prompt que quieras revisar...", lines=4 ) fix_btn = gr.Button("🔍 Analizar y Corregir", variant="primary") with gr.Column(): fix_output = gr.Textbox( label="Prompt corregido", lines=4, interactive=False ) fixes_log = gr.Markdown("") fix_btn.click( fn=fix_prompt, inputs=[fix_input], outputs=[fix_output, fixes_log] ) # ===== TAB 3: CONSTRUCTOR ===== with gr.TabItem("🏗️ Constructor de Prompts"): gr.Markdown("### Construye un prompt paso a paso") with gr.Row(): with gr.Column(): build_subject = gr.Textbox( label="Sujeto principal *", placeholder="Ej: a young woman with red hair, a futuristic city..." ) with gr.Row(): build_style = gr.Dropdown( choices=["Ninguno", "Clasico", "Impresionista", "Surrealista", "Pop Art", "Art Nouveau", "Concept Art", "Anime", "Fantasia", "Sci-fi", "Horror"], value="Ninguno", label="Estilo artístico" ) build_lighting = gr.Dropdown( choices=["Ninguno", "Dramatica", "Suave", "Natural", "Estudio", "Neon", "Cinematica"], value="Ninguno", label="Iluminación" ) with gr.Row(): build_mood = gr.Dropdown( choices=["Ninguno", "Oscuro", "Alegre", "Melancolico", "Epico", "Sereno", "Intenso"], value="Ninguno", label="Ambiente/Mood" ) build_camera = gr.Dropdown( choices=["Ninguno", "Cercano", "Lejano", "Retrato", "Aereo", "Bajo", "Alto"], value="Ninguno", label="Ángulo/Encuadre" ) build_quality = gr.CheckboxGroup( choices=["Alta definición (8K)", "Muy detallado", "Masterpiece", "Fotografía profesional", "Arte de alta calidad"], label="Calidad" ) build_extra = gr.Textbox( label="Detalles adicionales", placeholder="Añade cualquier detalle extra..." ) build_btn = gr.Button("🔨 Construir Prompt", variant="primary") with gr.Column(): build_output = gr.Textbox( label="Prompt construido", lines=6, interactive=False ) gr.Markdown(TIPS_TEXT) build_btn.click( fn=build_prompt, inputs=[build_subject, build_style, build_lighting, build_mood, build_camera, build_quality, build_extra], outputs=[build_output] ) # ===== TAB 4: ANALIZADOR ===== with gr.TabItem("📊 Analizador"): gr.Markdown("### Analiza la calidad y estructura de tu prompt") with gr.Row(): with gr.Column(): analyze_input = gr.Textbox( label="Prompt a analizar", placeholder="Pega cualquier prompt para obtener un análisis detallado...", lines=4 ) analyze_btn = gr.Button("📊 Analizar", variant="primary") with gr.Column(): analyze_output = gr.Markdown("") analyze_btn.click( fn=analyze_only, inputs=[analyze_input], outputs=[analyze_output] ) # ===== TAB 5: EJEMPLOS Y GUÍA ===== with gr.TabItem("📚 Guía y Ejemplos"): gr.Markdown("### Aprende a crear mejores prompts") with gr.Row(): with gr.Column(): example_style = gr.Dropdown( choices=["Fotorealista", "Anime", "Arte Digital", "Pintura", "3D", "Cinematico"], value="Fotorealista", label="Selecciona un estilo" ) show_examples_btn = gr.Button("Ver ejemplos", variant="secondary") with gr.Column(): examples_output = gr.Markdown("") show_examples_btn.click( fn=get_style_examples, inputs=[example_style], outputs=[examples_output] ) gr.Markdown("---") gr.Markdown(GUIDE_TEXT) # Footer gr.Markdown(FOOTER_TEXT) return app # Crear y lanzar la aplicación app = create_app() if __name__ == "__main__": app.launch()