BestPrompt / app.py
Javijavigon's picture
Update app.py
288a576 verified
"""
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 = """---
<div style="text-align: center;">
<strong>Prompt Enhancer Pro</strong> | Creado para la comunidad de generación de imágenes con IA<br>
Compatible con: Stable Diffusion, SDXL, FLUX, Midjourney y DALL-E 3
</div>
"""
HEADER_HTML = """
<div style="text-align: center; margin-bottom: 1.5em;">
<h1 style="color: #2563eb; margin-bottom: 0.3em;">🎨 Prompt Enhancer Pro</h1>
<p style="color: #6b7280; font-size: 1.1em;">Mejora y optimiza tus prompts para generación de imágenes con IA</p>
</div>
"""
# ===== 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()