| import spaces |
| import gradio as gr |
| import numpy as np |
| import random |
| import re |
| import torch |
| from diffusers import StableDiffusionXLPipeline |
| from huggingface_hub import list_repo_files |
|
|
| |
| import safetensors |
| from safetensors import safe_open as _orig_safe_open |
|
|
| class _SafeOpenWrapper: |
| def __init__(self, f): |
| self._f = f |
| def __enter__(self): |
| self._f.__enter__() |
| return self |
| def __exit__(self, *args): |
| return self._f.__exit__(*args) |
| def metadata(self): |
| m = self._f.metadata() |
| if not m or "format" not in m: |
| return {"format": "pt"} |
| return m |
| def __getattr__(self, name): |
| return getattr(self._f, name) |
|
|
| def _patched_safe_open(*args, **kwargs): |
| return _SafeOpenWrapper(_orig_safe_open(*args, **kwargs)) |
|
|
| safetensors.safe_open = _patched_safe_open |
| import transformers.modeling_utils |
| transformers.modeling_utils.safe_open = _patched_safe_open |
| |
| |
|
|
| device = "cuda" if torch.cuda.is_available() else "cpu" |
| model_repo_id = "kkntr/sdxl-kkntr" |
|
|
| pipe = StableDiffusionXLPipeline.from_pretrained( |
| model_repo_id, |
| torch_dtype=torch.float16, |
| use_safetensors=True, |
| ).to(device) |
|
|
| pipe.vae.enable_slicing() |
| pipe.enable_attention_slicing() |
|
|
| print("diffusers:", __import__('diffusers').__version__) |
|
|
| MAX_SEED = np.iinfo(np.int32).max |
| MAX_IMAGE_SIZE = 1024 |
|
|
| def apply_scratchpad(prompt): |
| def replace(match): |
| key = match.group(1).lower() |
| if key in scratchpad: |
| return random.choice(scratchpad[key]) |
| return match.group(0) |
| return re.sub(r"\[([^\]]+)\]", replace, prompt) |
|
|
| scratchpad = { |
| "animal": [ |
| "kangaroo", "kangaroo", "otter", "otter", "shark", "shark", "shark", "dolphin", "dolphin", "avian", "tiger", "lion", "wolf", "fox", "polar bear", "polar bear", "deer", "deer", "reindeer", "reindeer", "hyena", "bull", "bull", |
| "rabbit", "panther", "moose", "cheetah", "badger", "striped hyena", "rat", "leopard", "thylacine", "bighorn sheep", |
| "zebra", "horse", "horse", "donkey", "donkey", "unicorn", "white unicorn", "alligator", "western dragon", "lizard", "crocodile", "theropod", |
| "kangaroo", "otter", "tiger", "lion", "wolf", "fox", "polar bear", "deer", "reindeer", "hyena", "bull", |
| "rabbit", "panther", "moose", "cheetah", "badger", "striped hyena", "rat", "leopard", "thylacine", "bighorn sheep", |
| "zebra", "horse", "donkey", "unicorn", "white unicorn", "alligator", "western dragon", "lizard", "crocodile", "theropod", |
| "kangaroo", "otter", "tiger", "lion", "wolf", "fox", "polar bear", "deer", "reindeer", "hyena", "bull", |
| "rabbit", "panther", "moose", "cheetah", "badger", "striped hyena", "rat", "leopard", "thylacine", "bighorn sheep", |
| "zebra", "horse", "donkey", "unicorn", "white unicorn", "alligator", "western dragon", "lizard", "crocodile", "theropod", |
| "black russian terrier", "pit bull", "schnauzer", "dobermann", "mastiff", "molosser", "pinscher", "rottweiler", "tamaskan dog", |
| "wolfdog", "alaskan husky", "alaskan malamute", "canadian eskimo dog", "german shepherd", "labrador husky", "siberian husky", |
| "labrador", "golden retriever", "dalmatian", "border collie", "collie", "herding dog", "pastoral dog", "sheepdog", |
| "carolina dog", "rhodesian ridgeback", "nordic sled dog", "spitz", "husky", "akita", "mountain dog", "primitive dog", |
| "siberian retriever", "hunting dog", "australian cattle dog", "crash bandicoot", "montgomery gator, fnaf", "bear", |
| "parrot", "bison", "buffalo", "cattle", "muskox", "yak", "alpaca", "goat", "sheep", "deer", "elk", "moose", "reindeer", "white-tailed deer", |
| "raccoon", "skunk", "whale", "tasmanian devil", "badger", "ermine", "ferret", "marten", "mink", "otter", "weasel", "wolverine", "squirrel", |
| "white rabbit", "pegasus", "goat", "mouse", "cattle", "coyote", "owl", "charizard", "bandicoot", "giant panda", "panda", "ocelot", "panther", |
| "cheetah", "cougar", "puma", "pony", "camel", "llama", "penguin", "duck", "duck", "duck", |
| ], |
|
|
| "pose": [ |
| "flexing", "double biceps pose", "side chest pose", "front lat spread pose", "back double biceps pose", "side biceps pose", |
| "adonis pose", "arms akimbo", "crossed arms", "hands on hips", "hands behind head", "one hand behind head", "torso twist", "power stance", |
| "v-shape", "clenched fists", "palm open", "fist pump", "victory pose", "comic shrug", "superhero pose", "front double biceps pose", |
| "front lat spread pose", "side chest pose", "side triceps pose", "rear double biceps pose", "rear lat spread pose", |
| "most muscular pose", "abdominal and thigh pose", "hands-on hips pose", |
| ], |
|
|
| "swimwear": [ |
| "swimming trunks", "swim shorts", "swim briefs", "speedo", "boxer swim shorts", "bermuda swim shorts", "swimming thong", |
| "swim g-string", "board shorts", "jammers", "tight swim shorts", "loose swim shorts", "short swim trunks", |
| ], |
|
|
| "headwear": [ |
| "baseball cap", "backwards headwear", "backwards baseball cap", "snapback cap", "backwards snapback cap", "trucker hat", "backwards trucker hat", |
| "fitted cap", "beanie hat", "headband", |
| "bandana", |
| ], |
|
|
| "setting:private": [ |
| "bedroom", "bathroom", "shower", "bathtub" |
| "locker room", "changing room", "dressing room", |
| "communal shower", "forest", "tent", "poolside", |
| "sauna", "hot tub", "jacuzzi", |
| "gym locker room", "living room", "beach", |
| ], |
|
|
| "setting:semi": [ |
| "bedroom", "living room", "locker room", "beach", "tent", "beach", "gym", "fitness center", "weight room", "boxing gym", "martial arts dojo", |
| "yoga studio", "crossfit box", "track and field stadium", "football field", "soccer pitch", "basketball court", "tennis court", "volleyball court", |
| "basketball gym", "rugby field", "baseball field", "athletics track", "sports hall", "indoor sports arena", "climbing gym", "rowing machine area", |
| "boxing ring", "wrestling mat", "exercise studio", "outdoor running track", "forest jogging trail", "park running path", "mountain trail", |
| "soccer training field", "football practice field", "open field for sports", "stadium track", "indoor training facility", "cross-country track", |
| "school sports field", "college sports field", "stadium gym", "athletic training ground", "exercise park", "outdoor gym area", "hiking trail with training stations", |
| ], |
| |
| "setting:public": [ |
| "living room", "classroom", "bar", "street", "cafe", "restaurant", "mall", "supermarket", "bus stop", "train station", |
| "subway station", "office", "library", "parking lot", "cinema", "arcade", "amusement park", "gas station", "bookstore", "hardware store", |
| "coffee shop", "fast food restaurant", "pharmacy", "hotel lobby", "airport terminal", "shopping center", "convenience store", "train platform", |
| "bus station", "school hallway", "university campus", "city square", "playground", "arcade room", "movie theater lobby", "food court", "bakery", |
| "deli", "museum", "gallery", "ice cream shop", "pizzeria", "subway entrance", "train carriage", "bus interior", "train interior", "office lobby", |
| "conference room", "restaurant kitchen", "coffee bar", "shopping street", "nightclub", "bar", "club", "dance floor", "music festival", |
| "rooftop party", "late-night street party", "party", "summer party", "beach party", "dance club", "strip club", "rave club", "bar counter" |
| ], |
|
|
| "setting:party": [ |
| "nightclub", "bar", "club", "dance floor", "music festival", |
| "rooftop party", "late-night street party", "party", "summer party", "beach party", "dance club", "strip club", "rave club", "bar counter", |
| ], |
| |
| "setting:water": [ |
| "beach", "seashore", "lake shore", "riverbank", "swimming pool", "private pool", "poolside", |
| "deck by the pool", "beach lounge", "hot tub", "jacuzzi", |
| ], |
| |
| "setting:underwater": [ |
| "pool", "jacuzzi", "hot tub", "spa pool", "sea", "lake", "river", |
| ], |
|
|
| "hair": [ |
| "bald", "short hair", "medium hair", "long hair", "man bun", "ponytail", "crew cut", "undercut", "side part", "spiky hair", "messy hair", |
| "curly hair", "wavy hair", "straight hair", |
| ], |
|
|
| "accessories": [ |
| "earrings", "stud earrings", "diamond stud earrings", "hoop earrings", "small hoop earrings", "septum piercing", "eyebrow piercing", |
| "chain necklace", "beaded necklace", "pendant necklace", "sunglasses", "aviator sunglasses", "wayfarer sunglasses", "sports sunglasses", |
| "headphones", "earphones", |
| ], |
|
|
| "hairy:face": [ |
| "beard", "goatee", "soul patch", "sideburns", "stubble", "full beard", "short beard", "long beard", "chin strap", "van dyke", "mutton chops", "scruffy beard", "designer stubble", |
| ], |
|
|
| "hairy:body": [ |
| "chest hair", "armpit hair", "happy trail", "pubic hair", |
| "chest hair + armpit hair", "chest hair + happy trail", "chest hair + pubic hair", "armpit hair + happy trail", "armpit hair + pubic hair", |
| "happy trail + pubic hair", "chest hair + armpit hair + happy trail", "chest hair + armpit hair + pubic hair", "chest hair + happy trail + pubic hair", |
| "armpit hair + happy trail + pubic hair", "chest hair + armpit hair + happy trail + pubic hair", |
| ], |
|
|
| "body": [ |
| "very skinny", "lean", "fit", "toned", "athletic", "muscular", "broad-shouldered", "stocky", "solid", "heavily muscled", "chubby", "big and muscular", "obese", |
| ], |
|
|
| "underwear": [ |
| "boxer briefs", "briefs", "boxers", "trunks", "thong", "g-string", "string thong", "jockstrap", "low-rise briefs", "mid-rise briefs", |
| "high-rise briefs", "athletic briefs", |
| ], |
|
|
| "sex:anal": [ |
| "mating press", "chair position", "cowgirl position", "doggystyle", "leg glider position", "mastery position", |
| "Spoon Position", "reverse missionary position", "missionary position", "reverse cowgirl position", |
| "anvil Position", "guard Position", "stand and carry Position", "table lotus position" |
| ], |
|
|
| "sex:oral": [ |
| "69 position", "kneeling oral position", "sideways oral", "penis lick", "tongue in foreskin", "deepthroath", "tongue out blowjob", "irrumatio", |
| "ball lick", "kneeling and blow position", "lying and blow position", "north pole position", "sit and blow position", |
| ], |
|
|
| "topwear:under": [ |
| "tank top", "tank top", "loose tank top, extended armholes, draped sleeveless shirt", "oversized muscle tank, baggy sleeveless top, open armholes", |
| "t-shirt", "crew-neck t-shirt", "v-neck t-shirt", "sleeveless shirt", "cotton undershirt", |
| ], |
|
|
| "topwear:casual": [ |
| "long-sleeve t-shirt", "crew-neck long-sleeve shirt", "v-neck long-sleeve shirt", "henley long-sleeve", "hoodie", |
| "sweatshirt", "zip-up hoodie", "pullover sweater", "thermal shirt", "flannel shirt", |
| ], |
|
|
| "topwear:formal": [ |
| "button-up long-sleeve shirt", "collared shirt", "dress shirt", "oxford shirt", "polo shirt", "unbuttoned shirt, flannel shirt," |
| ], |
|
|
| "topwear:party": [ |
| "mesh tank top", "mesh shirt", "harness", "cage top", "leather vest", "rubber shirt", "tight tank top", "open shirt", "crop top", |
| "fishnet top", "bondage harness", "strappy top", "latex shirt", "transparent shirt", "studded vest", "festival top", "topless", "topless", |
| ], |
| |
| "bottomwear:formal": [ |
| "jeans", "chinos", "khaki pants", "linen trousers", "cotton trousers", "dress trousers", "slacks", "wool trousers", "formal pants", |
| ], |
|
|
| "bottomwear:casual": [ |
| "joggers", "sweatpants", "track pants", "gym shorts", "shorts", "linen shorts", "bermuda shorts", "cargo pants", "basketball shorts", "training pants", |
| ], |
|
|
| "bottomwear:party": [ |
| "camo pants", "leather pants", "rubber pants", "cargo pants", "denim pants", "tight jeans", "distressed jeans", "ripped jeans", "patent leather pants", |
| "bondage pants", "festival trousers", "shiny pants", "studded pants", "paint-splatter pants", "metallic pants", "faux leather pants", "tight cargo pants", |
| "plaid pants", |
| ], |
|
|
| "light": [ |
| "morning", "late morning", "noon", "early afternoon", "afternoon", "late afternoon", "evening", "dusk", "twilight", "sunrise", "sunset", |
| "day", "midday sun", "night", "midnight", "pre-dawn", "overcast", "cloudy", "foggy", "misty", "hazy", "dim light", "soft light", "ambient light", |
| "natural light", "diffused light", "soft daylight", "warm light", "cool light", "golden hour", "blue hour", "soft morning light", "soft evening light", |
| "fading light", "gentle light", "muted light", "soft shadows", "soft glow", |
| ], |
|
|
| "perspective": [ |
| "slightly low angle", "slightly high angle", "subtle birds-eye view", "gentle worm's-eye view", "slightly tilted", "soft dutch angle", |
| "subtle foreshortening", "soft overhead view", "slight top-down view", "gentle angled view", "slight perspective shift", "slightly slanted composition", |
| "soft three-quarter view", "slightly off-center view", "soft angled composition", "slightly tilted horizon", "subtle dynamic angle", "soft wide angle", |
| "centered composition", "neutral angle", "straight-on view", "slight zoom-in", "slight zoom-out", "slightly raised angle", "slightly lowered angle", |
| "gentle framing", "balanced composition", "softly framed subject", "slightly front-on", "slightly side-on", "soft mid-shot angle", "gentle medium shot", |
| "slightly elevated viewpoint", "slightly lowered viewpoint", |
| ], |
|
|
| "effect": [ |
| "grainy", "bokeh", "soft focus", "motion blur", "depth of field", "slight vignette", "subtle glow", "diffused light", "dusty", |
| "hazy", "slight fog", "light haze", "soft shadows", "backlight glow", "atmospheric haze", "slight bloom", "color gradient", "warm tone", |
| "cool tone", "slight desaturation", "light mist", "soft contrast", "light diffusion", "soft highlight", "subtle reflection", "ambient occlusion", |
| "soft rim light", "light scattering", "faded edges", "gentle flare", "soft vignette", "soft bokeh", "blurred background", "slight overexposure", |
| "slight underexposure", "faint glow", "soft illumination", "dust particles", "floating dust", "light specks", "tiny particles", "airborne dust", |
| "dust motes", "light haze with particles", "soft smoke", "pollen particles", "floating motes", "misty particles", "ambient dust", "soft airborne light particles", |
| ], |
|
|
| "face": [ |
| "flirty", "seductive", "playful flirt", "teasing look", "sultry gaze", "wink flirt", "one eye closed", "smoldering look", "cheeky flirt", "suggestive grin", |
| "mischievous smirk", "playful smirk", "tongue out flirty", "open mouth flirt", "eye contact flirt", "raised eyebrow flirt", "smiling", "grinning", "laughing", "happy", |
| "joyful", "playful", "quirky", "cheerful", "friendly smile", "tongue out", "winking", "raised eyebrows", "blushing", "embarrassed", "shy", "bashful", "surprised", |
| "curious", "amused", "satisfied smile", "soft smile", "teasing smile", "cheeky grin", "slight smirk", "mischievous grin", "open mouth smile", "excited", "delighted", |
| "flirty", "seductive", "playful flirt", "teasing look", "sultry gaze", "wink flirt", |
| ], |
|
|
| "color": [ |
| "red", "scarlet", "crimson", "pink", "magenta", "fuchsia", "orange", "tangerine", "yellow", "bright yellow", "lemon yellow color", "gold color", "green", "lime green color", |
| "emerald", "olive", "teal", "turquoise", "cyan", "blue", "sky blue", "royal blue", "navy blue", "indigo", "purple", "violet", "lavender", "lilac", "brown", "tan", |
| "beige", "bronze", "maroon", "burgundy", "white", "ivory", "black", "grey", "dark-grey", "light-grey", "silver", "reflecting chrome", "copper", "mint", "jade", |
| "peach color", "camo", "camouflage", "red-violet", "blue-green", "turquoise-blue", "yellow-orange", "pink-purple", "mustard color", |
| ], |
| } |
|
|
| QUALITY_SUFFIX = ", best quality, masterpiece, ultra detailed, sharp focus, perfect anatomy, 8k" |
|
|
| STYLE_LORAS = [ |
| {"repo": "kkntr/lora14", "name": "bakemonoy", "weight": 0.3}, |
| {"repo": "kkntr/pre", "name": "takahiro", "weight": 0.5}, |
| {"repo": "kkntr/hypermuscles", "name": "exfore", "weight": 0.1}, |
| ] |
|
|
| def load_any_lora(pipe, repo, adapter_name): |
| files = list_repo_files(repo) |
| weight = next(f for f in files if f.endswith(".safetensors")) |
| pipe.load_lora_weights(repo, weight_name=weight, adapter_name=adapter_name) |
| return True |
|
|
| adapter_names = [] |
| adapter_weights = [] |
|
|
| for lora in STYLE_LORAS: |
| try: |
| load_any_lora(pipe, lora["repo"], lora["name"]) |
| adapter_names.append(lora["name"]) |
| adapter_weights.append(lora["weight"]) |
| print(f"Loaded LoRA: {lora['repo']}") |
| except Exception as e: |
| print(f"Failed LoRA {lora['repo']}: {e}") |
|
|
| if adapter_names: |
| pipe.set_adapters(adapter_names, adapter_weights=adapter_weights) |
|
|
| @spaces.GPU |
| def infer(prompt, negative_prompt, seed, randomize_seed, random_resolution, width, height, guidance_scale, num_inference_steps, progress=gr.Progress(track_tqdm=True)): |
| if randomize_seed: |
| seed = random.randint(0, MAX_SEED) |
| generator = torch.Generator(device=device).manual_seed(seed) |
| if random_resolution: |
| resolutions = [(592,1768),(608,1696),(640,1624),(672,1544),(720,1440),(744,1392),(784,1320),(832,1248),(864,1208),(880,1184),(912,1144),(976,1072),(1024,1024),(1072,976),(1144,912),(1184,880),(1208,864),(1248,832),(1320,784),(1392,744),(1440,720),(1544,672),(1624,640),(1696,608),(1768,592)] |
| width, height = random.choice(resolutions) |
| final_prompt = apply_scratchpad(prompt) + QUALITY_SUFFIX |
| image = pipe(prompt=final_prompt, negative_prompt=negative_prompt, guidance_scale=guidance_scale, num_inference_steps=num_inference_steps, width=width, height=height, generator=generator).images[0] |
| return image, seed, final_prompt |
|
|
| examples = ["[animal], [body], [sex:anal/oral], [pose], [hairy:face/body], [topwear:under/casual/formal/party], [bottomwear:casual/formal/party], [underwear], [swimwear], [headwear], [hair], [accessories], [face], [light], [perspective], [effect], [setting:private/semi/public/party/water/underwater], [color]"] |
| ["[animal], [body], [color] [bottomwear:casual], [topwear:casual]"] |
|
|
| css = "#col-container {margin: 0 auto; max-width: 640px;}" |
|
|
| with gr.Blocks() as demo: |
| with gr.Column(elem_id="col-container"): |
| gr.Markdown(" # Text-to-Image Gradio Template") |
| with gr.Row(): |
| prompt = gr.Textbox( |
| label="Prompt", |
| show_label=False, |
| lines=4, |
| max_lines=10, |
| placeholder="Enter your prompt", |
| container=True, |
| scale=4 |
| ) |
| run_button = gr.Button("Run", scale=0, variant="primary") |
| result = gr.Image(label="Result", show_label=False) |
| used_prompt = gr.Textbox(label="Used Prompt", interactive=False, lines=4) |
| with gr.Accordion("Advanced Settings", open=False): |
| negative_prompt = gr.Textbox(label="Negative Prompt", lines=4, value="worst quality, low quality, lowres, blurry, pixelated, jpeg artifacts, bad anatomy, bad hands, extra fingers, missing fingers, malformed hands, deformed, mutated, poorly drawn face, poorly drawn eyes, cross-eyed, duplicate, extra limbs, cropped, watermark, text, logo, signature, username, out of frame") |
| 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(): |
| random_resolution = gr.Checkbox(label="Random resolution", value=True) |
| 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=10.0, step=0.1, value=7.5) |
| num_inference_steps = gr.Slider(label="Number of inference steps", minimum=1, maximum=50, step=1, value=20) |
| gr.Examples(examples=examples, inputs=[prompt]) |
| gr.on(triggers=[run_button.click, prompt.submit], fn=infer, inputs=[prompt, negative_prompt, seed, randomize_seed, random_resolution, width, height, guidance_scale, num_inference_steps], outputs=[result, seed, used_prompt]) |
|
|
| if __name__ == "__main__": |
| demo.launch(css=css, ssr_mode=False) |