| import gradio as gr |
| import numpy as np |
| import random |
| import requests |
| import base64 |
| from PIL import Image |
| import io |
| import json |
| import os |
| import time |
|
|
| |
| import spaces |
| from diffusers import DiffusionPipeline |
| import torch |
| from huggingface_hub import login |
|
|
| print("🚀 Iniciando aplicación con ZeroGPU H200...") |
| print(f"📁 Directorio actual: {os.getcwd()}") |
| print(f"🐍 Python version: {os.sys.version}") |
|
|
| |
| HF_TOKEN = os.getenv("HF_TOKEN") or os.getenv("HUGGING_FACE_HUB_TOKEN") |
| if HF_TOKEN: |
| try: |
| print(f"🔑 Token detectado: {HF_TOKEN[:10]}...") |
| login(token=HF_TOKEN) |
| print("✅ Autenticado con Hugging Face") |
| print(f"🔑 Token configurado: {HF_TOKEN[:10]}...") |
| except Exception as e: |
| print(f"⚠️ Error de autenticación: {e}") |
| else: |
| print("⚠️ No se encontró HF_TOKEN - modelos gated no estarán disponibles") |
| print("💡 Para usar modelos FLUX, configura la variable de entorno HF_TOKEN en el Space") |
|
|
| |
| device = "cuda" if torch.cuda.is_available() else "cpu" |
| print(f"🖥️ Dispositivo detectado: {device}") |
| print(f"🔥 CUDA disponible: {torch.cuda.is_available()}") |
|
|
| if torch.cuda.is_available(): |
| print(f"🎮 GPU: {torch.cuda.get_device_name(0)}") |
| print(f"💾 Memoria GPU: {torch.cuda.get_device_properties(0).total_memory / 1024**3:.1f} GB") |
| print("🚀 ZeroGPU H200 detectado - Optimizando para máximo rendimiento") |
| |
| |
| torch_dtype = torch.float16 |
| print("⚡ Usando torch.float16 para H200") |
| |
| |
| torch.backends.cudnn.benchmark = True |
| torch.backends.cuda.matmul.allow_tf32 = True |
| torch.backends.cudnn.allow_tf32 = True |
| print("🔧 Optimizaciones CUDA habilitadas para H200") |
| else: |
| torch_dtype = torch.float32 |
| print("🐌 Usando torch.float32 para CPU") |
|
|
| |
| MODELS = { |
| "SDXL Turbo (stabilityai/sdxl-turbo)": "stabilityai/sdxl-turbo", |
| "SD Turbo (stabilityai/sd-turbo)": "stabilityai/sd-turbo", |
| "SDXL Base (stabilityai/stable-diffusion-xl-base-1.0)": "stabilityai/stable-diffusion-xl-base-1.0", |
| "Realistic Vision (SG161222/Realistic_Vision_V5.1_noVAE)": "SG161222/Realistic_Vision_V5.1_noVAE", |
| "OpenJourney v4 (prompthero/openjourney-v4)": "prompthero/openjourney-v4", |
| "Anything v3 (Linaqruf/anything-v3.0)": "Linaqruf/anything-v3.0", |
| "Waifu Diffusion (hakurei/waifu-diffusion)": "hakurei/waifu-diffusion", |
| "Deliberate v2 (XpucT/deliberate-v2)": "XpucT/deliberate-v2", |
| "Dreamlike Diffusion (dreamlike-art/dreamlike-diffusion-1.0)": "dreamlike-art/dreamlike-diffusion-1.0", |
| |
| "Stable Diffusion v1.5 (runwayml/stable-diffusion-v1-5)": "runwayml/stable-diffusion-v1-5", |
| "Stable Diffusion v1.4 (CompVis/stable-diffusion-v1-4)": "CompVis/stable-diffusion-v1-4", |
| "Midjourney Style (prompthero/openjourney)": "prompthero/openjourney", |
| "Orange Mixs (WarriorMama777/OrangeMixs)": "WarriorMama777/OrangeMixs", |
| "Kohaku V2.1 (KBlueLeaf/kohaku-v2.1)": "KBlueLeaf/kohaku-v2.1", |
| |
| "SDXL Lightning (ByteDance/SDXL-Lightning)": "ByteDance/SDXL-Lightning", |
| "FLUX.1-Kontext-Dev (API External)": "api_external", |
| } |
|
|
| |
| if HF_TOKEN: |
| FLUX_MODELS = { |
| "FLUX.1-dev (black-forest-labs/FLUX.1-dev)": "black-forest-labs/FLUX.1-dev", |
| "FLUX.1-schnell (black-forest-labs/FLUX.1-schnell)": "black-forest-labs/FLUX.1-schnell", |
| } |
| MODELS.update(FLUX_MODELS) |
| print("🔓 Modelos FLUX habilitados con autenticación") |
| print(f"📊 Total de modelos disponibles: {len(MODELS)}") |
| else: |
| print("🔒 Modelos FLUX deshabilitados - requiere HF_TOKEN") |
| print(f"📊 Total de modelos disponibles: {len(MODELS)}") |
|
|
| print("📋 Modelos cargados (optimizados para H200):") |
| for i, (name, model_id) in enumerate(MODELS.items(), 1): |
| status = "🔐" if "flux" in model_id.lower() or "black-forest" in model_id.lower() else "📦" |
| gpu_opt = "⚡" if "turbo" in model_id.lower() or "lightning" in model_id.lower() else "🎨" |
| print(f" {i:2d}. {status} {gpu_opt} {name}") |
|
|
| |
| pipe = None |
| current_model_id = None |
|
|
| MAX_SEED = np.iinfo(np.int32).max |
| MAX_IMAGE_SIZE = 1024 |
|
|
| |
| def load_model(model_id): |
| global pipe, current_model_id |
| print(f"\n🔄 Iniciando carga del modelo: {model_id}") |
| |
| if pipe is None or model_id != current_model_id: |
| try: |
| start_time = time.time() |
| |
| |
| use_fp16_variant = False |
| if torch.cuda.is_available(): |
| |
| fp16_supported_models = [ |
| "stabilityai/sdxl-turbo", |
| "stabilityai/sd-turbo", |
| "stabilityai/stable-diffusion-xl-base-1.0", |
| "runwayml/stable-diffusion-v1-5", |
| "CompVis/stable-diffusion-v1-4" |
| ] |
| use_fp16_variant = any(model in model_id for model in fp16_supported_models) |
| print(f"🔧 FP16 variant: {'✅ Habilitado' if use_fp16_variant else '❌ Deshabilitado'} para {model_id}") |
| |
| |
| if HF_TOKEN and ("flux" in model_id.lower() or "black-forest" in model_id.lower()): |
| print(f"🔐 Cargando modelo gated: {model_id}") |
| print(f"🔑 Usando token de autenticación...") |
| |
| |
| pipe = DiffusionPipeline.from_pretrained( |
| model_id, |
| torch_dtype=torch_dtype, |
| use_auth_token=HF_TOKEN, |
| variant="fp16" if use_fp16_variant else None |
| ) |
| else: |
| print(f"📦 Cargando modelo público: {model_id}") |
| pipe = DiffusionPipeline.from_pretrained( |
| model_id, |
| torch_dtype=torch_dtype, |
| variant="fp16" if use_fp16_variant else None |
| ) |
| |
| load_time = time.time() - start_time |
| print(f"⏱️ Tiempo de carga: {load_time:.2f} segundos") |
| |
| print(f"🚀 Moviendo modelo a dispositivo: {device}") |
| pipe = pipe.to(device) |
| |
| |
| if torch.cuda.is_available(): |
| print("🔧 Aplicando optimizaciones para H200...") |
| |
| |
| if hasattr(pipe, 'enable_attention_slicing'): |
| pipe.enable_attention_slicing() |
| print("✅ Attention slicing habilitado") |
| |
| |
| |
| |
| |
| |
| if hasattr(pipe, 'enable_vae_slicing'): |
| pipe.enable_vae_slicing() |
| print("✅ VAE slicing habilitado") |
| |
| |
| if hasattr(pipe, 'enable_xformers_memory_efficient_attention'): |
| |
| if "flux" in model_id.lower() or "black-forest" in model_id.lower(): |
| print("⚠️ XFormers deshabilitado para modelos FLUX (incompatible)") |
| else: |
| try: |
| pipe.enable_xformers_memory_efficient_attention() |
| print("✅ XFormers memory efficient attention habilitado") |
| except Exception as e: |
| print(f"⚠️ XFormers no disponible: {e}") |
| print("🔄 Usando atención estándar") |
| |
| current_model_id = model_id |
| print(f"✅ Modelo {model_id} cargado exitosamente") |
| |
| if torch.cuda.is_available(): |
| memory_used = torch.cuda.memory_allocated() / 1024**3 |
| memory_reserved = torch.cuda.memory_reserved() / 1024**3 |
| print(f"💾 Memoria GPU utilizada: {memory_used:.2f} GB") |
| print(f"💾 Memoria GPU reservada: {memory_reserved:.2f} GB") |
| |
| |
| if memory_used < 0.1: |
| print("⚠️ ADVERTENCIA: Memoria GPU muy baja - posible problema de carga") |
| else: |
| print("💾 Memoria CPU") |
| |
| except Exception as e: |
| print(f"❌ Error cargando modelo {model_id}: {e}") |
| print(f"🔍 Tipo de error: {type(e).__name__}") |
| |
| |
| if "variant" in str(e) and "fp16" in str(e): |
| print("🔄 Reintentando sin variant fp16...") |
| try: |
| pipe = DiffusionPipeline.from_pretrained( |
| model_id, |
| torch_dtype=torch_dtype, |
| use_auth_token=HF_TOKEN if HF_TOKEN and ("flux" in model_id.lower() or "black-forest" in model_id.lower()) else None |
| ) |
| pipe = pipe.to(device) |
| current_model_id = model_id |
| print(f"✅ Modelo {model_id} cargado exitosamente (sin fp16 variant)") |
| except Exception as e2: |
| print(f"❌ Error en segundo intento: {e2}") |
| raise e2 |
| else: |
| raise e |
| else: |
| print(f"♻️ Modelo {model_id} ya está cargado, reutilizando...") |
|
|
| |
| def use_external_api(prompt, negative_prompt, seed, randomize_seed, width, height, guidance_scale, num_inference_steps): |
| try: |
| print("\n🌐 Conectando a API externa FLUX.1-Kontext-Dev...") |
| print(f"📝 Prompt: {prompt[:50]}...") |
| print(f"🔧 Parámetros: {width}x{height}, guidance={guidance_scale}, steps={num_inference_steps}") |
| |
| start_time = time.time() |
| |
| |
| api_url = "https://black-forest-labs-flux-1-kontext-dev.hf.space/api/predict/" |
| |
| |
| print("🖼️ Creando imagen base para API...") |
| base_image = Image.new('RGB', (width, height), color='white') |
| img_byte_arr = io.BytesIO() |
| base_image.save(img_byte_arr, format='PNG') |
| img_byte_arr = img_byte_arr.getvalue() |
| |
| |
| print("📦 Preparando datos para API...") |
| files = { |
| 'data': (None, json.dumps([ |
| base64.b64encode(img_byte_arr).decode('utf-8'), |
| prompt, |
| seed, |
| randomize_seed, |
| guidance_scale, |
| num_inference_steps |
| ])) |
| } |
| |
| |
| print(f"🌐 Enviando petición a: {api_url}") |
| response = requests.post(api_url, files=files, timeout=60) |
| |
| api_time = time.time() - start_time |
| print(f"⏱️ Tiempo de respuesta API: {api_time:.2f} segundos") |
| |
| if response.status_code == 200: |
| print("✅ Respuesta exitosa de API") |
| result = response.json() |
| |
| image_data = result['data'][0] |
| new_seed = result['data'][1] |
| |
| print("🖼️ Decodificando imagen...") |
| |
| image_bytes = base64.b64decode(image_data.split(',')[1]) |
| image = Image.open(io.BytesIO(image_bytes)) |
| |
| total_time = time.time() - start_time |
| print(f"✅ API externa exitosa - Tiempo total: {total_time:.2f} segundos") |
| return image, new_seed |
| else: |
| print(f"❌ Error de API: {response.status_code}") |
| print(f"📄 Respuesta: {response.text[:200]}...") |
| raise Exception(f"API Error: {response.status_code} - {response.text}") |
| |
| except Exception as e: |
| print(f"❌ Error usando API externa: {e}") |
| print(f"🔍 Tipo de error: {type(e).__name__}") |
| |
| error_image = Image.new('RGB', (width, height), color='red') |
| return error_image, seed |
|
|
| |
| def get_model_info(model_name): |
| model_id = MODELS.get(model_name, "") |
| |
| if not model_id: |
| return "**Model Info:** Select a model to see its specific configuration recommendations." |
| |
| info = f"**Model Info:** {model_name}\n\n" |
| |
| |
| if "turbo" in model_id.lower(): |
| info += "⚡ **Fast Model** - Optimized for speed\n" |
| info += "• Recommended steps: 1-4\n" |
| info += "• Guidance scale: 0.0-1.0\n" |
| info += "• Best for: Quick iterations\n\n" |
| elif "lightning" in model_id.lower(): |
| info += "⚡ **Lightning Model** - Ultra fast\n" |
| info += "• Recommended steps: 4-8\n" |
| info += "• Guidance scale: 0.0-1.0\n" |
| info += "• Best for: Rapid prototyping\n\n" |
| elif "flux" in model_id.lower(): |
| info += "🔐 **FLUX Model** - High quality\n" |
| info += "• Recommended steps: 20-50\n" |
| info += "• Guidance scale: 3.5-7.5\n" |
| info += "• Best for: Professional results\n\n" |
| elif "realistic" in model_id.lower(): |
| info += "👤 **Realistic Model** - Photorealistic\n" |
| info += "• Recommended steps: 25-50\n" |
| info += "• Guidance scale: 7.5-12.0\n" |
| info += "• Best for: Realistic portraits\n\n" |
| elif "openjourney" in model_id.lower(): |
| info += "🎨 **OpenJourney Model** - Midjourney style\n" |
| info += "• Recommended steps: 20-30\n" |
| info += "• Guidance scale: 7.5-10.0\n" |
| info += "• Best for: Artistic styles\n\n" |
| elif "waifu" in model_id.lower(): |
| info += "🌸 **Waifu Model** - Anime style\n" |
| info += "• Recommended steps: 20-30\n" |
| info += "• Guidance scale: 7.5-10.0\n" |
| info += "• Best for: Anime characters\n\n" |
| elif "anything" in model_id.lower(): |
| info += "🎭 **Anything Model** - Versatile\n" |
| info += "• Recommended steps: 20-30\n" |
| info += "• Guidance scale: 7.5-10.0\n" |
| info += "• Best for: Creative concepts\n\n" |
| else: |
| info += "📦 **Standard Model**\n" |
| info += "• Recommended steps: 20-50\n" |
| info += "• Guidance scale: 7.5-12.0\n" |
| info += "• Best for: General use\n\n" |
| |
| info += f"**Model ID:** `{model_id}`\n" |
| info += "**Status:** ✅ Available" |
| |
| return info |
|
|
| |
| @spaces.GPU |
| def infer( |
| prompt, |
| negative_prompt, |
| seed, |
| randomize_seed, |
| width, |
| height, |
| guidance_scale, |
| num_inference_steps, |
| model_name, |
| eta=0.0, |
| strength=1.0, |
| num_images_per_prompt=1, |
| safety_checker=True, |
| progress=gr.Progress(track_tqdm=True), |
| ): |
| try: |
| print(f"\n🎨 Iniciando generación de imagen con H200...") |
| print(f"📝 Prompt: {prompt}") |
| print(f"🚫 Negative prompt: {negative_prompt}") |
| print(f"🎲 Seed: {seed} (randomize: {randomize_seed})") |
| print(f"📐 Dimensiones: {width}x{height}") |
| print(f"🎯 Guidance scale: {guidance_scale}") |
| print(f"🔄 Inference steps: {num_inference_steps}") |
| print(f"🎯 Eta: {eta}") |
| print(f"💪 Strength: {strength}") |
| print(f"🖼️ Images per prompt: {num_images_per_prompt}") |
| print(f"🛡️ Safety checker: {safety_checker}") |
| print(f"🎯 Modelo seleccionado: {model_name}") |
| |
| start_time = time.time() |
| |
| |
| if model_name == "FLUX.1-Kontext-Dev (API External)": |
| return use_external_api(prompt, negative_prompt, seed, randomize_seed, width, height, guidance_scale, num_inference_steps) |
| |
| |
| model_id = MODELS[model_name] |
| print(f"🔧 Cargando modelo: {model_id}") |
| load_model(model_id) |
| |
| if randomize_seed: |
| old_seed = seed |
| seed = random.randint(0, MAX_SEED) |
| print(f"🎲 Seed aleatorizado: {old_seed} → {seed}") |
|
|
| print(f"🎲 Configurando generador con seed: {seed}") |
| generator = torch.Generator(device=device).manual_seed(seed) |
|
|
| |
| |
| final_guidance_scale = guidance_scale |
| final_inference_steps = num_inference_steps |
| |
| |
| if "turbo" in model_id.lower(): |
| |
| if final_inference_steps < 1: |
| final_inference_steps = 1 |
| print(f"⚡ Modelo turbo - Ajustando steps mínimo: {num_inference_steps} → {final_inference_steps}") |
| elif "lightning" in model_id.lower(): |
| |
| if final_inference_steps < 4: |
| final_inference_steps = 4 |
| print(f"⚡ Modelo lightning - Ajustando steps mínimo: {num_inference_steps} → {final_inference_steps}") |
| |
| |
| if final_guidance_scale < 0.0: |
| final_guidance_scale = 0.0 |
| print(f"⚠️ Guidance scale ajustado al mínimo: {guidance_scale} → {final_guidance_scale}") |
| elif final_guidance_scale > 20.0: |
| final_guidance_scale = 20.0 |
| print(f"⚠️ Guidance scale ajustado al máximo: {guidance_scale} → {final_guidance_scale}") |
|
|
| print(f"⚙️ Parámetros finales (respetando configuración del usuario):") |
| print(f" - Guidance scale: {guidance_scale} → {final_guidance_scale}") |
| print(f" - Inference steps: {num_inference_steps} → {final_inference_steps}") |
| print(f" - Width: {width}, Height: {height}") |
| print(f" - Seed: {seed}") |
| print(f" - Eta: {eta}") |
| print(f" - Strength: {strength}") |
| print(f" - Images per prompt: {num_images_per_prompt}") |
|
|
| print("🎨 Iniciando generación de imagen con H200...") |
| inference_start = time.time() |
| |
| |
| additional_params = {} |
| |
| |
| if hasattr(pipe, 'scheduler') and hasattr(pipe.scheduler, 'beta_start'): |
| |
| additional_params['eta'] = eta |
| |
| if hasattr(pipe, 'vae') and hasattr(pipe.vae, 'scale_factor'): |
| |
| additional_params['output_type'] = 'pil' |
| |
| |
| if hasattr(pipe, 'safety_checker') and not safety_checker: |
| pipe.safety_checker = None |
| print("🛡️ Safety checker deshabilitado") |
| |
| |
| if num_images_per_prompt > 1: |
| additional_params['num_images_per_prompt'] = num_images_per_prompt |
| |
| |
| if torch.cuda.is_available(): |
| print("🚀 Aplicando optimizaciones específicas para H200...") |
| |
| |
| torch.cuda.empty_cache() |
| |
| |
| print("⚡ Generando imagen con H200...") |
| |
| |
| result = pipe( |
| prompt=prompt, |
| negative_prompt=negative_prompt, |
| guidance_scale=final_guidance_scale, |
| num_inference_steps=final_inference_steps, |
| width=width, |
| height=height, |
| generator=generator, |
| **additional_params |
| ) |
| |
| |
| if hasattr(result, 'images') and len(result.images) > 0: |
| image = result.images[0] |
| |
| |
| if image is not None: |
| |
| img_array = np.array(image) |
| if img_array.size > 0: |
| |
| if np.all(img_array == 0) or np.all(img_array < 10): |
| print("⚠️ ADVERTENCIA: Imagen generada es completamente negra") |
| print("🔄 Reintentando con parámetros ajustados...") |
| |
| |
| result = pipe( |
| prompt=prompt, |
| negative_prompt=negative_prompt, |
| guidance_scale=max(1.0, final_guidance_scale * 0.8), |
| num_inference_steps=max(10, final_inference_steps), |
| width=width, |
| height=height, |
| generator=generator |
| ) |
| image = result.images[0] |
| else: |
| print("✅ Imagen generada correctamente") |
| else: |
| print("❌ Error: Imagen vacía") |
| raise Exception("Imagen vacía generada") |
| else: |
| print("❌ Error: Imagen es None") |
| raise Exception("Imagen es None") |
| else: |
| print("❌ Error: No se generaron imágenes") |
| raise Exception("No se generaron imágenes") |
| else: |
| |
| result = pipe( |
| prompt=prompt, |
| negative_prompt=negative_prompt, |
| guidance_scale=final_guidance_scale, |
| num_inference_steps=final_inference_steps, |
| width=width, |
| height=height, |
| generator=generator, |
| **additional_params |
| ) |
| image = result.images[0] |
|
|
| inference_time = time.time() - inference_start |
| total_time = time.time() - start_time |
| |
| print(f"✅ Imagen generada exitosamente con H200!") |
| print(f"⏱️ Tiempo de inferencia: {inference_time:.2f} segundos") |
| print(f"⏱️ Tiempo total: {total_time:.2f} segundos") |
| print(f"🎲 Seed final: {seed}") |
| |
| if torch.cuda.is_available(): |
| print(f"💾 Memoria GPU utilizada: {torch.cuda.memory_allocated() / 1024**3:.2f} GB") |
| print(f"💾 Memoria GPU libre: {torch.cuda.memory_reserved() / 1024**3:.2f} GB") |
| print(f"🚀 Velocidad H200: {final_inference_steps/inference_time:.1f} steps/segundo") |
| else: |
| print("💾 Memoria CPU") |
|
|
| return image, seed |
| |
| except Exception as e: |
| print(f"❌ Error en inferencia: {e}") |
| print(f"🔍 Tipo de error: {type(e).__name__}") |
| print(f"📋 Detalles del error: {str(e)}") |
| |
| error_image = Image.new('RGB', (width, height), color='red') |
| return error_image, seed |
|
|
|
|
| examples = [ |
| "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k", |
| "An astronaut riding a green horse", |
| "A delicious ceviche cheesecake slice", |
| "Futuristic AI assistant in a glowing galaxy, neon lights, sci-fi style, cinematic", |
| "Portrait of a beautiful woman, realistic, high quality, detailed", |
| "Anime girl with blue hair, detailed, high quality", |
| "Cyberpunk city at night, neon lights, detailed, 8k", |
| "Fantasy landscape with mountains and dragons, epic, detailed", |
| ] |
|
|
| css = """ |
| #col-container { |
| margin: 0 auto; |
| max-width: 640px; |
| } |
| """ |
|
|
| with gr.Blocks(css=css) as demo: |
| with gr.Column(elem_id="col-container"): |
| gr.Markdown(" # Text-to-Image Gradio Template") |
|
|
| with gr.Row(): |
| prompt = gr.Text( |
| label="Prompt", |
| show_label=False, |
| max_lines=1, |
| placeholder="Enter your prompt", |
| container=False, |
| ) |
|
|
| run_button = gr.Button("Run", scale=0, variant="primary") |
|
|
| result = gr.Image(label="Result", show_label=False) |
|
|
| with gr.Accordion("Advanced Settings", open=False): |
| model_selector = gr.Dropdown( |
| choices=list(MODELS.keys()), |
| value=list(MODELS.keys())[0], |
| label="Model", |
| info="Select a high-quality model (FLUX models require HF_TOKEN)" |
| ) |
| |
| negative_prompt = gr.Text( |
| label="Negative prompt", |
| max_lines=2, |
| placeholder="Enter a negative prompt (optional)", |
| visible=True, |
| ) |
|
|
| with gr.Row(): |
| seed = gr.Slider( |
| label="Seed", |
| minimum=0, |
| maximum=MAX_SEED, |
| step=1, |
| value=0, |
| ) |
| randomize_seed = gr.Checkbox(label="Randomize seed", value=True) |
|
|
| with gr.Row(): |
| width = gr.Slider( |
| label="Width", |
| minimum=256, |
| maximum=MAX_IMAGE_SIZE, |
| step=32, |
| value=1024, |
| ) |
| height = gr.Slider( |
| label="Height", |
| minimum=256, |
| maximum=MAX_IMAGE_SIZE, |
| step=32, |
| value=1024, |
| ) |
|
|
| with gr.Row(): |
| guidance_scale = gr.Slider( |
| label="Guidance scale", |
| minimum=0.0, |
| maximum=20.0, |
| step=0.1, |
| value=7.5, |
| info="Controls how closely the image follows the prompt (higher = more adherence)" |
| ) |
| num_inference_steps = gr.Slider( |
| label="Number of inference steps", |
| minimum=1, |
| maximum=100, |
| step=1, |
| value=20, |
| info="More steps = higher quality but slower generation" |
| ) |
|
|
| with gr.Row(): |
| |
| eta = gr.Slider( |
| label="Eta (DDIM)", |
| minimum=0.0, |
| maximum=1.0, |
| step=0.01, |
| value=0.0, |
| info="DDIM eta parameter (0 = deterministic, 1 = stochastic)" |
| ) |
| strength = gr.Slider( |
| label="Strength", |
| minimum=0.0, |
| maximum=1.0, |
| step=0.01, |
| value=1.0, |
| info="Strength of the transformation (for img2img models)" |
| ) |
|
|
| with gr.Row(): |
| |
| num_images_per_prompt = gr.Slider( |
| label="Images per prompt", |
| minimum=1, |
| maximum=4, |
| step=1, |
| value=1, |
| info="Number of images to generate (may slow down generation)" |
| ) |
| safety_checker = gr.Checkbox( |
| label="Safety checker", |
| value=True, |
| info="Enable content safety filtering" |
| ) |
|
|
| |
| model_info = gr.Markdown( |
| value="**Model Info:** Select a model to see its specific configuration recommendations.", |
| label="Model Information" |
| ) |
|
|
| gr.Examples(examples=examples, inputs=[prompt]) |
| gr.on( |
| triggers=[run_button.click, prompt.submit], |
| fn=infer, |
| inputs=[ |
| prompt, |
| negative_prompt, |
| seed, |
| randomize_seed, |
| width, |
| height, |
| guidance_scale, |
| num_inference_steps, |
| model_selector, |
| eta, |
| strength, |
| num_images_per_prompt, |
| safety_checker, |
| ], |
| outputs=[result, seed], |
| ) |
|
|
| |
| model_selector.change( |
| fn=get_model_info, |
| inputs=[model_selector], |
| outputs=[model_info] |
| ) |
|
|
| if __name__ == "__main__": |
| print("🚀 Iniciando Gradio app...") |
| demo.launch() |
|
|