| import gradio as gr |
| import torch |
| from diffusers import StableDiffusionXLPipeline, DPMSolverMultistepScheduler |
| from huggingface_hub import hf_hub_download |
| import random |
|
|
| |
| DEVICE = "cuda" if torch.cuda.is_available() else "cpu" |
| DTYPE = torch.float16 if DEVICE == "cuda" else torch.float32 |
| print(f"Running on: {DEVICE.upper()}") |
|
|
| |
| MODEL_REPO = "cyberdelia/CyberRealisticPony" |
| MODEL_FILE = "CyberRealisticPony_V16.0_FP16.safetensors" |
| PONY_POS = "score_9, score_8_up, score_7_up, " |
| PONY_NEG = "score_6, score_5, score_4, " |
|
|
| print("Downloading model...") |
| local_path = hf_hub_download(repo_id=MODEL_REPO, filename=MODEL_FILE) |
| print(f"Loading from {local_path}...") |
|
|
| pipe = StableDiffusionXLPipeline.from_single_file(local_path, torch_dtype=DTYPE) |
| pipe.scheduler = DPMSolverMultistepScheduler.from_config( |
| pipe.scheduler.config, use_karras_sigmas=True |
| ) |
| pipe.enable_attention_slicing() |
| if DEVICE == "cuda": |
| pipe.enable_xformers_memory_efficient_attention() |
| pipe = pipe.to(DEVICE) |
| print("Ready.") |
|
|
| |
| def generate(prompt, negative_prompt, width, height, steps, guidance, seed, randomize): |
| if not prompt.strip(): |
| raise gr.Error("Please enter a prompt.") |
| if randomize: |
| seed = random.randint(0, 2**32 - 1) |
| seed = int(seed) |
| generator = torch.Generator(device=DEVICE).manual_seed(seed) |
| result = pipe( |
| prompt=PONY_POS + prompt.strip(), |
| negative_prompt=PONY_NEG + negative_prompt.strip(), |
| width=int(width), |
| height=int(height), |
| num_inference_steps=int(steps), |
| guidance_scale=float(guidance), |
| generator=generator, |
| clip_skip=2, |
| ) |
| return result.images[0], seed |
|
|
| |
| css = """ |
| /* ββ Base ββ */ |
| body, .gradio-container { |
| background: #0f0f13 !important; |
| font-family: 'Inter', system-ui, sans-serif !important; |
| } |
| |
| /* ββ Header ββ */ |
| .header-box { |
| background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%); |
| border: 1px solid #e94560; |
| border-radius: 16px; |
| padding: 20px; |
| text-align: center; |
| margin-bottom: 8px; |
| } |
| .header-box h1 { |
| color: #ffffff; |
| font-size: 1.8em; |
| font-weight: 800; |
| margin: 0 0 6px 0; |
| letter-spacing: -0.5px; |
| } |
| .header-box p { |
| color: #a0a0b8; |
| font-size: 0.85em; |
| margin: 0; |
| } |
| .header-box .badge { |
| display: inline-block; |
| background: #e94560; |
| color: white; |
| font-size: 0.7em; |
| font-weight: 700; |
| padding: 2px 10px; |
| border-radius: 20px; |
| margin-top: 8px; |
| text-transform: uppercase; |
| letter-spacing: 1px; |
| } |
| |
| /* ββ Output image ββ */ |
| .output-box { |
| background: #1a1a2e; |
| border: 2px dashed #2a2a4a; |
| border-radius: 16px; |
| overflow: hidden; |
| min-height: 300px; |
| } |
| .output-box img { |
| border-radius: 14px; |
| width: 100%; |
| } |
| |
| /* ββ Panel cards ββ */ |
| .panel-card { |
| background: #1a1a2e; |
| border: 1px solid #2a2a4a; |
| border-radius: 14px; |
| padding: 16px; |
| margin-bottom: 10px; |
| } |
| .section-label { |
| color: #e94560 !important; |
| font-size: 0.75em !important; |
| font-weight: 700 !important; |
| text-transform: uppercase !important; |
| letter-spacing: 1.5px !important; |
| margin-bottom: 10px !important; |
| } |
| |
| /* ββ Inputs ββ */ |
| textarea, input[type="number"] { |
| background: #0f0f13 !important; |
| border: 1px solid #2a2a4a !important; |
| border-radius: 10px !important; |
| color: #e0e0f0 !important; |
| font-size: 15px !important; |
| } |
| textarea:focus, input[type="number"]:focus { |
| border-color: #e94560 !important; |
| box-shadow: 0 0 0 2px rgba(233, 69, 96, 0.2) !important; |
| } |
| |
| /* ββ Sliders ββ */ |
| .gradio-slider input[type=range] { |
| accent-color: #e94560; |
| } |
| |
| /* ββ Generate button ββ */ |
| .generate-btn { |
| background: linear-gradient(135deg, #e94560, #c23152) !important; |
| border: none !important; |
| border-radius: 14px !important; |
| color: white !important; |
| font-size: 1.1em !important; |
| font-weight: 700 !important; |
| padding: 16px !important; |
| width: 100% !important; |
| letter-spacing: 0.5px !important; |
| box-shadow: 0 4px 20px rgba(233, 69, 96, 0.4) !important; |
| transition: all 0.2s ease !important; |
| } |
| .generate-btn:active { |
| transform: scale(0.98) !important; |
| box-shadow: 0 2px 10px rgba(233, 69, 96, 0.3) !important; |
| } |
| |
| /* ββ Seed row ββ */ |
| .seed-row { |
| display: flex; |
| align-items: center; |
| gap: 10px; |
| } |
| |
| /* ββ Used seed display ββ */ |
| .used-seed input { |
| background: #0f0f13 !important; |
| border: 1px solid #2a2a4a !important; |
| color: #606080 !important; |
| font-size: 0.85em !important; |
| text-align: center !important; |
| } |
| |
| /* ββ Labels ββ */ |
| label span, .gradio-label { |
| color: #a0a0c0 !important; |
| font-size: 0.82em !important; |
| font-weight: 600 !important; |
| text-transform: uppercase !important; |
| letter-spacing: 0.8px !important; |
| } |
| |
| /* ββ Mobile: stack columns ββ */ |
| @media (max-width: 768px) { |
| .gr-row { flex-direction: column !important; } |
| .gr-col { width: 100% !important; min-width: 100% !important; } |
| } |
| """ |
|
|
| |
| with gr.Blocks(css=css, title="CyberRealistic Pony") as demo: |
|
|
| |
| gr.HTML(""" |
| <div class="header-box"> |
| <h1>π΄ CyberRealistic Pony</h1> |
| <p>SDXL Β· Pony Architecture Β· v16.0</p> |
| <span class="badge">β CPU Mode β Slow</span> |
| </div> |
| """) |
|
|
| |
| with gr.Group(elem_classes="output-box"): |
| output_image = gr.Image( |
| label="", |
| type="pil", |
| show_label=False, |
| height=420, |
| ) |
|
|
| used_seed = gr.Number( |
| label="Seed used β save to reproduce", |
| interactive=False, |
| elem_classes="used-seed", |
| ) |
|
|
| |
| gr.HTML('<div class="section-label" style="margin-top:14px;color:#e94560;font-size:0.75em;font-weight:700;text-transform:uppercase;letter-spacing:1.5px;">βοΈ Prompt</div>') |
|
|
| prompt = gr.Textbox( |
| label="", |
| placeholder="a woman in a futuristic city, cinematic lighting, highly detailed, photorealistic", |
| lines=3, |
| show_label=False, |
| ) |
|
|
| gr.HTML('<div class="section-label" style="margin-top:10px;color:#e94560;font-size:0.75em;font-weight:700;text-transform:uppercase;letter-spacing:1.5px;">π« Negative Prompt</div>') |
|
|
| negative_prompt = gr.Textbox( |
| label="", |
| value=( |
| "(worst quality:1.2), (low quality:1.2), (normal quality:1.2), " |
| "lowres, bad anatomy, bad hands, signature, watermarks, " |
| "ugly, imperfect eyes, skewed eyes, unnatural face, " |
| "unnatural body, error, extra limb, missing limbs" |
| ), |
| lines=2, |
| show_label=False, |
| ) |
|
|
| |
| gr.HTML('<div class="section-label" style="margin-top:14px;color:#e94560;font-size:0.75em;font-weight:700;text-transform:uppercase;letter-spacing:1.5px;">π Size</div>') |
|
|
| with gr.Row(): |
| width = gr.Slider(512, 896, value=768, step=64, label="Width") |
| height = gr.Slider(512, 1152, value=896, step=64, label="Height") |
|
|
| |
| gr.HTML('<div class="section-label" style="margin-top:14px;color:#e94560;font-size:0.75em;font-weight:700;text-transform:uppercase;letter-spacing:1.5px;">βοΈ Sampling</div>') |
|
|
| steps = gr.Slider(10, 30, value=20, step=1, label="Steps") |
| guidance = gr.Slider(1.0, 12.0, value=5.0, step=0.5, label="CFG Scale") |
|
|
| |
| gr.HTML('<div class="section-label" style="margin-top:14px;color:#e94560;font-size:0.75em;font-weight:700;text-transform:uppercase;letter-spacing:1.5px;">π² Seed</div>') |
|
|
| with gr.Row(): |
| seed = gr.Number(label="Seed", value=42, precision=0, minimum=0, maximum=2**32-1, scale=2) |
| randomize_seed = gr.Checkbox(label="Random", value=True, scale=1) |
|
|
| |
| generate_btn = gr.Button( |
| "β¦ Generate Image", |
| variant="primary", |
| size="lg", |
| elem_classes="generate-btn", |
| ) |
|
|
| |
| generate_btn.click( |
| fn=generate, |
| inputs=[prompt, negative_prompt, width, height, steps, guidance, seed, randomize_seed], |
| outputs=[output_image, used_seed], |
| ) |
|
|
| demo.launch() |
|
|