garyuzair's picture
Update app.py
9550bd0 verified
import gradio as gr
from diffusers import StableDiffusionPipeline, EulerDiscreteScheduler
import torch
from datetime import datetime
# Check for GPU and set up the model
device = "cuda" if torch.cuda.is_available() else "cpu"
dtype = torch.float16 if device == "cuda" else torch.float32
# Use a smaller, faster model
model_id = "runwayml/stable-diffusion-v1-5"
# Load the pipeline with optimizations
scheduler = EulerDiscreteScheduler.from_pretrained(model_id, subfolder="scheduler")
pipe = StableDiffusionPipeline.from_pretrained(
model_id,
scheduler=scheduler,
torch_dtype=dtype,
safety_checker=None, # Disable safety checker for faster generation
requires_safety_checker=False
).to(device)
# Apply optimizations based on available hardware
if device == "cuda":
try:
pipe.enable_xformers_memory_efficient_attention() # Flash attention if available
except:
print("xformers not available, using default attention")
pipe.enable_attention_slicing(1) # Minimal slicing for balance between speed and memory
else:
pipe.enable_attention_slicing() # More aggressive slicing for CPU
# Warm up the model (important for consistent speed)
print("Warming up the model...")
with torch.inference_mode():
_ = pipe("warmup", num_inference_steps=1, guidance_scale=1)
def generate_image(
prompt: str,
negative_prompt: str = "",
steps: int = 20, # Slightly more steps for CPU
guidance_scale: float = 7.0,
seed: int = -1,
width: int = 512,
height: int = 512
):
# Start timer
start_time = datetime.now()
# Set random seed if provided
generator = None
if seed != -1:
generator = torch.Generator(device=device).manual_seed(seed)
# Generate image with optimizations
with torch.inference_mode(), torch.autocast(device) if device == "cuda" else torch.no_grad():
image = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
num_inference_steps=int(steps),
guidance_scale=guidance_scale,
generator=generator,
width=width,
height=height
).images[0]
# Calculate generation time
gen_time = (datetime.now() - start_time).total_seconds()
print(f"Generated image in {gen_time:.2f} seconds")
return image, f"Device: {device.upper()} | Time: {gen_time:.2f}s | Steps: {steps} | Size: {width}x{height}"
# Gradio interface
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# ⚡ Diffusion Image Generator
*Optimized for Hugging Face Spaces*
""")
with gr.Row():
with gr.Column():
prompt = gr.Textbox(
label="Prompt",
placeholder="A beautiful landscape with mountains and a lake",
max_lines=3
)
negative_prompt = gr.Textbox(
label="Negative Prompt",
placeholder="blurry, low quality, distorted",
max_lines=2
)
with gr.Accordion("Advanced Settings", open=False):
with gr.Row():
steps = gr.Slider(8, 30, value=20, step=1, label="Inference Steps")
guidance_scale = gr.Slider(1, 10, value=7.0, step=0.5, label="Guidance Scale")
with gr.Row():
seed = gr.Number(value=-1, label="Seed (-1 for random)")
width = gr.Slider(384, 512, value=512, step=64, label="Width")
height = gr.Slider(384, 512, value=512, step=64, label="Height")
generate_btn = gr.Button("Generate Image", variant="primary")
info_output = gr.Textbox(label="Generation Info", interactive=False)
with gr.Column():
output_image = gr.Image(label="Generated Image", type="pil", show_download_button=True)
# Examples for quick testing
gr.Examples(
examples=[
["A futuristic cyberpunk city at night, neon lights, rain reflections", "blurry, low quality", 20, 7.0, 42],
["A cute robot cat, digital art, vibrant colors", "ugly, deformed", 18, 7.5, -1],
["A majestic dragon flying over mountains at sunset, fantasy art", "cartoon, sketch", 25, 8.0, 123]
],
inputs=[prompt, negative_prompt, steps, guidance_scale, seed],
outputs=[output_image, info_output],
fn=generate_image,
cache_examples=True
)
generate_btn.click(
fn=generate_image,
inputs=[prompt, negative_prompt, steps, guidance_scale, seed, width, height],
outputs=[output_image, info_output]
)
# For Hugging Face Spaces
demo.queue(max_size=2) # More conservative queue size
demo.launch(debug=False)