Spaces:
Running
on
Zero
Running
on
Zero
File size: 8,270 Bytes
4a1aee0 011e303 4a1aee0 011e303 4a1aee0 011e303 4a1aee0 011e303 4a1aee0 011e303 4a1aee0 011e303 4a1aee0 011e303 4a1aee0 011e303 4a1aee0 011e303 4a1aee0 011e303 3233d92 011e303 4a1aee0 011e303 4a1aee0 011e303 4a1aee0 011e303 4a1aee0 011e303 4a1aee0 011e303 9263383 024f747 2aee3d5 ad15efa 81d89aa 9b87569 052eb6e 011e303 356e2fe 011e303 4a1aee0 011e303 4a1aee0 011e303 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
import os
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 SETUP
# ------------------------------------------------------------
# Prefer GPU when the Space provides it, otherwise CPU
# `@spaces.GPU` takes care of binding the call itself, but we still
# need a device handle for manual ops.
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 important sub-modules to fp16 for VRAM efficiency (GPU) or
# reduce RAM (CPU). The model itself already sits in fp16, we just
# mirror that for sub-components explicitly to avoid silent fp32
# promotions that eat memory on ZeroGPU.
for sub in (pipe.text_encoder, pipe.text_encoder_2, pipe.vae, pipe.unet):
sub.to(torch.float16)
# ------------------------------------------------------------
# LIGHTWEIGHT KOR→ENG TRANSLATOR (CPU-ONLY)
# ------------------------------------------------------------
# * Hugging Face Spaces occasionally trips over the full MarianMT
# weights on ZeroGPU, resulting in the _untyped_storage_new_register
# error you just saw. We wrap initialisation in try/except and fall
# back to an identity function if the model cannot be loaded.
# * If you need translation and have a custom HF token, set the env
# HF_API_TOKEN so the smaller *small100* model can be pulled.
#
translator = None # default stub → "no translator"
try:
# First try the 60 MB Marian model.
translator = transformers_pipeline(
"translation",
model="Helsinki-NLP/opus-mt-ko-en",
device=-1, # force CPU so CUDA never initialises in the main proc
)
except Exception as marian_err:
print("[WARN] MarianMT load failed →", marian_err)
# Second chance: use compact multilingual SMaLL-100 (≈35 MB).
try:
translator = transformers_pipeline(
"translation",
model="alirezamsh/small100",
src_lang="ko_Kore",
tgt_lang="en_XX",
device=-1,
)
except Exception as small_err:
print("[WARN] SMaLL-100 load failed →", small_err)
# Final fallback: identity – no translation, but the app still runs.
translator = None
korean_regex = re.compile(r"[\uac00-\ud7af]+")
def maybe_translate(text: str) -> str:
"""Translate Korean → English if Korean chars present and translator ready."""
if translator is not None and korean_regex.search(text):
try:
out = translator(text, max_length=256, clean_up_tokenization_spaces=True)
return out[0]["translation_text"]
except Exception as e:
print("[WARN] Translation failed at runtime →", e)
return text
# ------------------------------------------------------------
# SDXL INFERENCE WRAPPER
# ------------------------------------------------------------
MAX_SEED = np.iinfo(np.int32).max
MAX_IMAGE_SIZE = 1216
@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("[WARN] Prompt >60 words — CLIP may truncate it.")
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] Diffusion failed → {e}")
return Image.new("RGB", (width, height), color=(0, 0, 0))
# ------------------------------------------------------------
# UI LAYOUT + THEME (Pastel Lavender Background)
# ------------------------------------------------------------
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: #fff; border-radius: 8px;}
#prompt-box textarea {font-size: 1.1rem; height: 3rem; background: #fff; color: #222;}
"""
author_note = (
"**ℹ️ Automatic translation** — Korean prompts are translated to English "
"only if translation weights could be loaded. If not, Korean input will be "
"sent unchanged."
)
with gr.Blocks(css=css, theme=gr.themes.Soft()) as demo:
gr.Markdown(
f"""
## 🖌️ Stable Diffusion XL Playground
{author_note}
"""
)
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 (Korean or English, 60 words max)",
)
run_button = gr.Button("Generate", scale=0)
result = gr.Image(label="", show_label=False)
examples = gr.Examples(
examples=[
["Her skirt rose a little higher with each gentle push, a soft blush of blush spreading across her cheeks as she felt the satisfying warmth of his breath on her cheek."],
["a girl in a school uniform having her skirt pulled up by a boy, and then being fucked"],
["Moody mature anime scene of two lovers fuck under neon rain, sensual atmosphere"],
["Moody mature anime scene of two lovers kissing under neon rain, sensual atmosphere"],
["The girl sits on the boy's lap by the window, his hands resting on her waist. She is unbuttoning his shirt, her expression focused and intense."],
["A girl with long, black hair is sleeping on her desk in the classroom. Her skirt has ridden up, revealing her thighs, and a trail of drool escapes her slightly parted lips."],
[""The waves rolled gently, a slow, sweet kiss of the lip, a slow, slow build of anticipation as their toes bumped gently – a slow, sweet kiss of the lip, a promise of more to come.""],
],
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="text, talk bubble, 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()
|