import spaces import gradio as gr import numpy as np from PIL import Image import random from diffusers import StableDiffusionXLPipeline, EulerAncestralDiscreteScheduler import torch from transformers import pipeline as transformers_pipeline import re # Device selection for image generation (GPU if available) device = torch.device("cuda" if torch.cuda.is_available() else "cpu") # Stable Diffusion XL pipeline pipe = StableDiffusionXLPipeline.from_pretrained( "votepurchase/waiNSFWIllustrious_v120", torch_dtype=torch.float16, variant="fp16", use_safetensors=True, ) pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe.scheduler.config) pipe.to(device) # Force modules to fp16 for memory efficiency pipe.text_encoder.to(torch.float16) pipe.text_encoder_2.to(torch.float16) pipe.vae.to(torch.float16) pipe.unet.to(torch.float16) # Korean β†’ English translator (CPU only) translator = transformers_pipeline( "translation", model="Helsinki-NLP/opus-mt-ko-en", device=-1, # -1 forces CPU ) MAX_SEED = np.iinfo(np.int32).max MAX_IMAGE_SIZE = 1216 korean_regex = re.compile("[\uac00-\ud7af]+") def maybe_translate(text: str) -> str: """Translate Korean text to English if Korean characters are detected.""" if korean_regex.search(text): translation = translator(text, max_length=256, clean_up_tokenization_spaces=True) return translation[0]["translation_text"] return text @spaces.GPU def infer(prompt, negative_prompt, seed, randomize_seed, width, height, guidance_scale, num_inference_steps): prompt = maybe_translate(prompt) negative_prompt = maybe_translate(negative_prompt) if len(prompt.split()) > 60: print("Warning: Prompt may be too long and will be truncated by the model") if randomize_seed: seed = random.randint(0, MAX_SEED) generator = torch.Generator(device=device).manual_seed(seed) try: output_image = pipe( prompt=prompt, negative_prompt=negative_prompt, guidance_scale=guidance_scale, num_inference_steps=num_inference_steps, width=width, height=height, generator=generator, ).images[0] return output_image except RuntimeError as e: print(f"Error during generation: {e}") error_img = Image.new("RGB", (width, height), color=(0, 0, 0)) return error_img # Custom styling css = """ body {background: #0f0f0f; color: #fafafa; font-family: 'Noto Sans', sans-serif;} #col-container {margin: 0 auto; max-width: 640px;} .gr-button {background: #2563eb; color: #ffffff; border-radius: 8px;} #prompt-box textarea {font-size: 1.1rem; height: 3rem;} """ with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo: gr.Markdown( """ ## πŸ–ŒοΈ Stable Diffusion XL Playground Generate high quality illustrations with a single prompt. **Tip:** Write in Korean or English. Korean will be translated automatically. """ ) with gr.Column(elem_id="col-container"): with gr.Row(): prompt = gr.Text( label="Prompt", elem_id="prompt-box", show_label=False, max_lines=1, placeholder="Enter your prompt (60 words max)", ) run_button = gr.Button("Generate", scale=0) result = gr.Image(label="", show_label=False) examples = gr.Examples( examples=[ ["μ–΄λ‘μš΄ 재즈 λ°”μ—μ„œ λ‹΄λ°° μ—°κΈ°λ₯Ό λ‚΄λΏœλŠ” λ―ΈμŠ€ν„°λ¦¬ν•œ νŒœνŒŒνƒˆ, μ„±μΈμš© μ• λ‹ˆλ©”μ΄μ…˜ μŠ€νƒ€μΌ"], ["λ…ΈμΆœμ΄ κ°•μ‘°λœ λ“œλ ˆμŠ€λ₯Ό μž…μ€ κ³ λ”• λ±€νŒŒμ΄μ–΄ μ—¬μ™•, λ“œλΌλ§ˆν‹± μ‘°λͺ…, 성인 μ• λ‹ˆ μ•„νŠΈ"], ["μ€μ€ν•œ μ‘°λͺ…μ˜ μ˜¨μ²œμ—μ„œ 두 연인이 마주 μ„œ μžˆλŠ” κ΄€λŠ₯적 μž₯λ©΄, μ„±μΈμš© μ• λ‹ˆλ©”μ΄μ…˜"], ["λ„€μ˜¨μ΄ λΉ›λ‚˜λŠ” μ‚¬μ΄λ²„νŽ‘ν¬ 클럽 λ¬΄λŒ€μ—μ„œ λ„λ°œμ μΈ μ˜μƒμ„ μž…μ€ λŒ„μ„œ, 성인 μ• λ‹ˆ μŠ€νƒ€μΌ"], ["달빛 μ•„λž˜ μš”μ—Όν•œ λ§ˆλ²•μ‚¬κ°€ 주문을 μ™Έμš°λŠ” νŒνƒ€μ§€ μž₯λ©΄, μ„±μΈμš© μ• λ‹ˆ 일러슀트"], ], inputs=[prompt], ) with gr.Accordion("Advanced Settings", open=False): negative_prompt = gr.Text( label="Negative prompt", max_lines=1, placeholder="Enter a negative prompt", value="nsfw, low quality, watermark, signature", ) 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 ) num_inference_steps = gr.Slider( label="Inference steps", minimum=1, maximum=28, step=1, value=28 ) run_button.click( fn=infer, inputs=[ prompt, negative_prompt, seed, randomize_seed, width, height, guidance_scale, num_inference_steps, ], outputs=[result], ) demo.queue().launch()