paezdev/EduDiff-EA3
0
1"""2═══════════════════════════════════════════════════════════════════════════════3EduDiff XL — Generador de Material Educativo con IA Generativa4═══════════════════════════════════════════════════════════════════════════════5Proyecto: EA3 - Generación de Contenido con IA Generativa6Arquitectura: Modelos de Difusión (Stable Diffusion XL via Together AI)7Dominio: Educación - Generación de infografías, diagramas y material didáctico8═══════════════════════════════════════════════════════════════════════════════9"""10 11import gradio as gr12from together import Together13import os14import base6415from io import BytesIO16from PIL import Image17import tempfile18 19# ═══════════════════════════════════════════════════════════════════════════════20# CONFIGURACIÓN21# ═══════════════════════════════════════════════════════════════════════════════22 23ESTILOS = {24 "📊 Infografía Profesional": "professional infographic, clean vector design, labeled diagram, white background, high contrast, modern educational material, sharp details",25 "🎨 Ilustración Didáctica": "digital educational illustration, vibrant colors, child-friendly, engaging visual, cartoon style, clear shapes",26 "🔬 Científico Detallado": "scientific illustration, anatomical detail, textbook quality, precise rendering, labeled parts, medical illustration style",27 "📐 Diagrama Técnico": "technical diagram, blueprint style, precise lines, schematic view, engineering drawing, measurements",28 "✏️ Dibujo Escolar": "hand-drawn sketch, simple shapes, colorful crayons, classroom style, easy to understand, friendly",29 "🌈 Mapa Conceptual": "concept map, connected ideas, colorful nodes, mind map style, organized layout, arrows and connections"30}31 32# ═══════════════════════════════════════════════════════════════════════════════33# FUNCIÓN DE GENERACIÓN CON TOGETHER AI34# ═══════════════════════════════════════════════════════════════════════════════35 36def generar_imagen(prompt: str, estilo: str, guidance_scale: float, num_steps: int, seed: int) -> tuple:37 """38 Genera una imagen educativa usando Stable Diffusion XL via Together AI.39 40 Args:41 prompt: Descripción del contenido educativo42 estilo: Estilo visual seleccionado43 guidance_scale: Control de adherencia al prompt (1-20)44 num_steps: Número de pasos de inferencia (10-50)45 seed: Semilla para reproducibilidad (-1 = aleatorio)46 47 Returns:48 tuple: (imagen, mensaje de estado)49 """50 if not prompt or not prompt.strip():51 return None, "⚠️ Por favor, ingresa una descripción del contenido educativo."52 53 # Verificar API Key54 api_key = os.environ.get("TOGETHER_API_KEY", "")55 if not api_key:56 return None, "❌ Error: API Key de Together AI no configurada. Añade TOGETHER_API_KEY en los Secrets del Space."57 58 # Construir prompt completo59 estilo_prompt = ESTILOS.get(estilo, ESTILOS["📊 Infografía Profesional"])60 prompt_completo = f"{prompt}, {estilo_prompt}, masterpiece, best quality, highly detailed"61 62 try:63 # Crear cliente de Together AI64 client = Together(api_key=api_key)65 66 # Generar imagen con SDXL67 response = client.images.generate(68 prompt=prompt_completo,69 model="stabilityai/stable-diffusion-xl-base-1.0",70 steps=num_steps,71 n=1,72 width=1024,73 height=102474 )75 76 if response.data and len(response.data) > 0:77 # Obtener imagen en base6478 img_b64 = response.data[0].b64_json79 80 if img_b64:81 # Decodificar y guardar82 img_data = base64.b64decode(img_b64)83 img = Image.open(BytesIO(img_data))84 85 temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png")86 img.save(temp_file.name)87 88 return temp_file.name, f"✅ Generado con SDXL | Steps: {num_steps} | Guidance: {guidance_scale}"89 else:90 # Si hay URL en lugar de base6491 img_url = response.data[0].url92 if img_url:93 import requests94 img_response = requests.get(img_url)95 img = Image.open(BytesIO(img_response.content))96 97 temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png")98 img.save(temp_file.name)99 100 return temp_file.name, f"✅ Generado con SDXL | Steps: {num_steps}"101 102 return None, "❌ No se recibió imagen en la respuesta"103 104 except Exception as e:105 error_msg = str(e)106 if "401" in error_msg or "unauthorized" in error_msg.lower():107 return None, "❌ API Key inválida. Verifica tu TOGETHER_API_KEY."108 elif "429" in error_msg or "rate" in error_msg.lower():109 return None, "⏳ Límite de API alcanzado. Espera unos segundos."110 elif "insufficient" in error_msg.lower() or "balance" in error_msg.lower():111 return None, "💰 Créditos agotados en Together AI."112 else:113 return None, f"❌ Error: {error_msg[:200]}"114 115# ═══════════════════════════════════════════════════════════════════════════════116# INTERFAZ DE USUARIO117# ═══════════════════════════════════════════════════════════════════════════════118 119with gr.Blocks() as demo:120 121 # Header122 gr.Markdown("""123 # 🎓 EduDiff XL124 ### Generador de Material Educativo con Inteligencia Artificial125 126 Crea imágenes educativas de alta calidad usando **Stable Diffusion XL** via Together AI.127 """)128 129 with gr.Row():130 # Panel izquierdo - Controles131 with gr.Column(scale=1):132 gr.Markdown("### 📝 Configuración")133 134 prompt_input = gr.Textbox(135 label="Descripción del contenido",136 placeholder="Ej: Diagrama de célula vegetal mostrando cloroplastos, vacuola central, pared celular y núcleo con etiquetas claras",137 lines=4138 )139 140 estilo_input = gr.Dropdown(141 choices=list(ESTILOS.keys()),142 value="📊 Infografía Profesional",143 label="Estilo visual"144 )145 146 gr.Markdown("### ⚙️ Parámetros")147 148 guidance_input = gr.Slider(149 minimum=1.0,150 maximum=20.0,151 value=7.5,152 step=0.5,153 label="Guidance Scale (adherencia al prompt)",154 info="Bajo (1-5): más creativo | Medio (6-9): balanceado | Alto (10+): más literal"155 )156 157 steps_input = gr.Slider(158 minimum=10,159 maximum=50,160 value=25,161 step=5,162 label="Inference Steps (calidad)",163 info="Más pasos = mejor calidad pero más lento"164 )165 166 seed_input = gr.Number(167 value=-1,168 label="Seed (-1 = aleatorio)",169 precision=0170 )171 172 generar_btn = gr.Button("🚀 Generar Imagen", variant="primary", size="lg")173 174 gr.Markdown("""175 ---176 ### 💡 Consejos177 - **Guidance 7-9**: Balance óptimo para contenido educativo178 - **Steps 25-35**: Buena calidad sin esperar mucho179 - Guarda el **seed** para reproducir resultados180 """)181 182 # Panel derecho - Resultado183 with gr.Column(scale=1):184 gr.Markdown("### 🖼️ Resultado")185 186 output_image = gr.Image(187 label="Imagen Generada",188 type="filepath",189 height=500190 )191 192 status_output = gr.Textbox(193 label="Estado",194 interactive=False195 )196 197 # Ejemplos198 gr.Markdown("### 📚 Ejemplos de uso")199 gr.Examples(200 examples=[201 ["Diagrama de célula animal con núcleo, mitocondrias, ribosomas y membrana celular etiquetados", "🔬 Científico Detallado", 7.5, 30, -1],202 ["Ciclo del agua mostrando evaporación, condensación, precipitación con flechas y etiquetas", "📊 Infografía Profesional", 8.0, 25, -1],203 ["Sistema solar con los 8 planetas en orden, con nombres y tamaños relativos", "🎨 Ilustración Didáctica", 7.0, 25, -1],204 ["Pirámide alimenticia con grupos de alimentos y porciones recomendadas", "📊 Infografía Profesional", 7.5, 25, -1],205 ["Anatomía del corazón humano con aurículas, ventrículos y válvulas etiquetados", "🔬 Científico Detallado", 8.5, 35, -1],206 ],207 inputs=[prompt_input, estilo_input, guidance_input, steps_input, seed_input],208 cache_examples=False209 )210 211 # Footer212 gr.Markdown("""213 ---214 **EduDiff XL** — Proyecto EA3: Generación de Contenido con IA Generativa215 216 Modelo: Stable Diffusion XL via Together AI | ⚠️ Verificar contenido antes de uso educativo217 """)218 219 # Evento de generación220 generar_btn.click(221 fn=generar_imagen,222 inputs=[prompt_input, estilo_input, guidance_input, steps_input, seed_input],223 outputs=[output_image, status_output]224 )225 226# ═══════════════════════════════════════════════════════════════════════════════227# INICIO228# ═══════════════════════════════════════════════════════════════════════════════229 230if __name__ == "__main__":231 demo.launch()232 