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 โ€“ bright pastel theme css = """ body {background: #f2f1f7; color: #222; font-family: 'Noto Sans', sans-serif;} #col-container {margin: 0 auto; max-width: 640px;} .gr-button {background: #7fbdf6; color: #ffffff; border-radius: 8px;} #prompt-box textarea {font-size: 1.1rem; height: 3rem; background: #ffffff; color: #222;} """ 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) # Adult animeโ€‘style example prompts examples = gr.Examples( examples=[ ["Seductive anime woman lounging in a dimly lit bar, adult anime style, ultraโ€‘detail"], ["Moody mature anime scene of two lovers kissing under neon rain, sensual atmosphere"], ["๊ธฐ๋ชจ๋…ธ๋ฅผ ์ž…์€ ์ผ๋ณธ ์—ฌ์ž๋ฅผ ๋‚จ์ž๊ฐ€ ๋’ค์—์„œ ๊ฐ•๊ฐ„ํ•œ๋‹ค , candleโ€‘lit boudoir, adult anime aesthetic"], ["์†์˜ท๋งŒ ์ž…์€ ๋‚จ๋…€๊ฐ€ ๊ฒฉ์ •์ ์ธ ํ‚ค์Šค๋ฅผ ํ•˜๊ณ ์žˆ๋‹ค, vibrant neon, adult anime"], ["์•„๋ฆ„๋‹ค์šด ๋Ÿฌ์‹œ์•„ ์—ฌ์ž๊ฐ€ ์„น์‹œํ•œ ์†์˜ท์„ ์ž…๊ณ  ๋ฌ˜ํ•œ ํฌ์ฆˆ๋กœ ์นจ๋Œ€์— ์•‰์•„์žˆ๋‹ค, dramatic spotlight, adult anime style"], ], 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()