import torch from diffusers import StableDiffusionXLPipeline import gradio as gr import spaces import random model_id = "kkntr/sdxl-kkntr" pipe = StableDiffusionXLPipeline.from_pretrained( model_id, torch_dtype=torch.float16, use_safetensors=True ).to("cuda") # --- Rekisteröidään pysyvät LoRAt ADAPTEREINA (ei painoja vielä) --- PERSISTENT_LORAS = { "base1": ("kkntr/lora12", 0.5), # oletuspaino; muutettavissa generate():ssa "base2": ("kkntr/lora13", 0.8), "base3": ("kkntr/lora17", 0.3), "base4": ("kkntr/lora1", 0.0), } for name, (repo, _) in PERSISTENT_LORAS.items(): pipe.load_lora_weights(repo, adapter_name=name) # --- Rekisteröidään tyyli-LoRAt ADAPTEREINA (ei painoja vielä) --- STYLE_LORAS = { "None": (None, 0.0, "", None), "Foreskin play": ("kkntr/lora5", 1.0, "foreskin insertion", "style_fp"), "Cum through clothing": ("kkntr/lora6", 1.0, "cum in clothing", "style_cc"), "Penis through leghole": ("kkntr/lora7", 1.0, "penis through leghole, loose shorts, poking out", "style_ptl"), "Frottage": ("kkntr/lora8", 1.0, "byfrottage, frottage", "style_fr"), "Penis towards viewer": ("kkntr/lora9", 1.0, "penis_towards_viewer", "style_ptv"), "Foreskin play closeup": ("kkntr/lora11", 0.8, "ZonkFS, tongue in foreskin, close-up, furry, anthro, faceless male, penis, foreskin, fellatio, oral, foreskin play, side view, steam", "style_fscl"), } for key, spec in STYLE_LORAS.items(): repo = spec[0] adapter_name = spec[3] if repo and adapter_name: pipe.load_lora_weights(repo, adapter_name=adapter_name) 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, 912), (1144, 912), (1184, 880), (1208, 864), (1248, 832), (1320, 784), (1392, 744), (1440, 720), (1544, 672), (1624, 640), (1696, 608), (1768, 592), ] @spaces.GPU def generate(prompt, negative_prompt, width, height, random_res, selected_style): if random_res: width, height = random.choice(resolutions) # Rakennetaan listat aktiivisista adaptereista ja niiden painoista adapter_names = [] adapter_weights = [] # 1) Pysyvät LoRAt for name, (_, w) in PERSISTENT_LORAS.items(): adapter_names.append(name) adapter_weights.append(w) # 2) Tyyli-LoRA + trigger if selected_style in STYLE_LORAS and selected_style != "None": repo, style_w, trigger, style_adapter = STYLE_LORAS[selected_style] prompt = f"{trigger}, {prompt}" adapter_names.append(style_adapter) adapter_weights.append(style_w) # esim. 7.0 jos haluat “mössöä” # jos "None", ei lisätä tyyliadapteria # Varmuuden vuoksi: ei fuseta, vaan käytetään dynaamisia painoja # Jos olet joskus fusennut, nollaa se ensin: try: pipe.unfuse_lora() except Exception: pass pipe.set_adapters(adapter_names, adapter_weights=adapter_weights) quality_suffix = ( ", (anthro), (male), (best quality), high resolution, (ultra detailed)," " 8k, (highly detailed), (masterpiece), (sharp focus), (intricate details)," " (perfect anatomy), (depth of field), high dynamic range, (smooth shading)," " (realistic shadows), (rich texture), professional color grading, (fine details)," " ultra sharp, HDR, (anatomically correct), painterly realism, 20r0j_2, civifur" ) full_prompt = prompt + quality_suffix image = pipe( prompt=full_prompt, negative_prompt=negative_prompt, width=width, height=height, num_inference_steps=35, guidance_scale=7.5 ).images[0] # (Valinnainen) palautetaan tekstiin näkyviin mitkä adapterit ja painot oli käytössä used = ", ".join([f"{n}:{w}" for n, w in zip(adapter_names, adapter_weights)]) return image, f"{full_prompt}\n\n[adapters] {used}" # UI sama kuin ennen gr.Interface( fn=generate, inputs=[ gr.Textbox(label="Prompt"), gr.Textbox( label="Negative Prompt", value="(worst quality), (low quality), (blurry), (bad anatomy), (fused fingers), (extra fingers), (missing fingers), (deformed), (jpeg artifacts), (watermark), (signature), text, error, out of frame, bad hands, bad feet, bad proportions, fused limbs, cropped, username, logo, bad perspective, lowres, overexposure, bad artist, bad composition, distorted, oversaturated, mutated, bad shadow, multiple limbs, extra arms, extra legs, bad background, tilted, bad lighting, bad face, ugly, bad eyes, disfigured, multiple pictures" ), gr.Slider(minimum=512, maximum=1024, step=64, value=768, label="Width"), gr.Slider(minimum=512, maximum=1024, step=64, value=768, label="Height"), gr.Checkbox(label="Random resolution mode (override sliders)", value=True), gr.Dropdown( choices=list(STYLE_LORAS.keys()), value="None", label="Select Style" ) ], outputs=[ gr.Image(label="Generated Image"), gr.Textbox(label="Used Prompt", lines=6) ], title="FURRYSTYLE", description="Give a prompt" ).launch()