tomiconic commited on
Commit
e389efe
Β·
verified Β·
1 Parent(s): ff6e57d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +236 -92
app.py CHANGED
@@ -4,67 +4,42 @@ from diffusers import StableDiffusionXLPipeline, DPMSolverMultistepScheduler
4
  from huggingface_hub import hf_hub_download
5
  import random
6
 
7
- # ── Device detection ───────────────────────────────────────────────────────────
8
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
9
- DTYPE = torch.float16 if DEVICE == "cuda" else torch.float32
 
10
 
11
- print(f"Running on: {DEVICE.upper()} | dtype: {DTYPE}")
12
-
13
- # ── Model ──────────────────────────────────────────────────────────────────────
14
  MODEL_REPO = "cyberdelia/CyberRealisticPony"
15
  MODEL_FILE = "CyberRealisticPony_V16.0_FP16.safetensors"
 
 
16
 
17
- # ── Pony quality tags ──────────────────────────────────────────────────────────
18
- PONY_POS_PREFIX = "score_9, score_8_up, score_7_up, "
19
- PONY_NEG_PREFIX = "score_6, score_5, score_4, "
20
-
21
- # ── Download then load from local path ────────────────────────────────────────
22
- print("Downloading model β€” this may take several minutes on first start...")
23
-
24
- local_path = hf_hub_download(
25
- repo_id=MODEL_REPO,
26
- filename=MODEL_FILE,
27
- )
28
-
29
- print(f"Model downloaded to: {local_path}")
30
- print("Loading pipeline...")
31
-
32
- pipe = StableDiffusionXLPipeline.from_single_file(
33
- local_path,
34
- torch_dtype=DTYPE,
35
- )
36
 
 
37
  pipe.scheduler = DPMSolverMultistepScheduler.from_config(
38
- pipe.scheduler.config,
39
- use_karras_sigmas=True,
40
  )
41
-
42
  pipe.enable_attention_slicing()
43
-
44
  if DEVICE == "cuda":
45
  pipe.enable_xformers_memory_efficient_attention()
46
-
47
  pipe = pipe.to(DEVICE)
 
48
 
49
- print("Model ready.")
50
-
51
- # ── Generation function ────────────────────────────────────────────────────────
52
- def generate_image(prompt, negative_prompt, width, height, steps, guidance, seed, randomize_seed):
53
- if not prompt or prompt.strip() == "":
54
- raise gr.Error("Please enter a prompt before generating.")
55
-
56
- if randomize_seed:
57
  seed = random.randint(0, 2**32 - 1)
58
-
59
  seed = int(seed)
60
  generator = torch.Generator(device=DEVICE).manual_seed(seed)
61
-
62
- full_prompt = PONY_POS_PREFIX + prompt.strip()
63
- full_negative = PONY_NEG_PREFIX + negative_prompt.strip()
64
-
65
- output = pipe(
66
- prompt=full_prompt,
67
- negative_prompt=full_negative,
68
  width=int(width),
69
  height=int(height),
70
  num_inference_steps=int(steps),
@@ -72,62 +47,231 @@ def generate_image(prompt, negative_prompt, width, height, steps, guidance, seed
72
  generator=generator,
73
  clip_skip=2,
74
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
- return output.images[0], seed
 
77
 
 
 
 
 
 
 
78
 
79
- # ── UI ─────────────────────────────────────────────────────────────────────────
80
- with gr.Blocks(title="CyberRealistic Pony", theme=gr.themes.Soft()) as demo:
81
 
82
- gr.Markdown("# 🐴 CyberRealistic Pony Generator")
83
- gr.Markdown(
84
- "> **Model:** CyberRealistic Pony v16.0 Β· SDXL / Pony architecture \n"
85
- "> ⚠️ **Running on CPU** β€” generation takes 30–90+ minutes per image. "
86
- "Upgrade to ZeroGPU in Space Settings for practical speeds.\n\n"
87
- "_Quality tags (`score_9, score_8_up, score_7_up`) are prepended to your prompt automatically._"
 
 
 
 
88
  )
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  with gr.Row():
91
- with gr.Column(scale=1):
92
-
93
- prompt = gr.Textbox(
94
- label="Prompt",
95
- placeholder="a woman in a futuristic city, cinematic lighting, highly detailed, photorealistic",
96
- lines=4,
97
- )
98
- negative_prompt = gr.Textbox(
99
- label="Negative Prompt",
100
- value=(
101
- "(worst quality:1.2), (low quality:1.2), (normal quality:1.2), "
102
- "lowres, bad anatomy, bad hands, signature, watermarks, "
103
- "ugly, imperfect eyes, skewed eyes, unnatural face, "
104
- "unnatural body, error, extra limb, missing limbs"
105
- ),
106
- lines=3,
107
- )
108
-
109
- gr.Markdown("### Image Size")
110
- with gr.Row():
111
- width = gr.Slider(minimum=512, maximum=896, value=768, step=64, label="Width")
112
- height = gr.Slider(minimum=512, maximum=1152, value=896, step=64, label="Height")
113
-
114
- gr.Markdown("### Sampling")
115
- steps = gr.Slider(minimum=10, maximum=30, value=20, step=1, label="Steps β€” keep low on CPU")
116
- guidance = gr.Slider(minimum=1.0, maximum=12.0, value=5.0, step=0.5, label="Guidance Scale (CFG) β€” recommended: 5")
117
-
118
- gr.Markdown("### Seed")
119
- with gr.Row():
120
- seed = gr.Number(label="Seed", value=42, precision=0, minimum=0, maximum=2**32 - 1)
121
- randomize_seed = gr.Checkbox(label="Randomise Seed", value=True)
122
-
123
- generate_btn = gr.Button("Generate Image πŸ–ΌοΈ", variant="primary", size="lg")
124
-
125
- with gr.Column(scale=1):
126
- output_image = gr.Image(label="Generated Image", type="pil", height=500)
127
- used_seed = gr.Number(label="Seed Used", interactive=False)
128
 
 
129
  generate_btn.click(
130
- fn=generate_image,
131
  inputs=[prompt, negative_prompt, width, height, steps, guidance, seed, randomize_seed],
132
  outputs=[output_image, used_seed],
133
  )
 
4
  from huggingface_hub import hf_hub_download
5
  import random
6
 
7
+ # ── Device ────────────────────────────────────────────────────────────────────
8
  DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
9
+ DTYPE = torch.float16 if DEVICE == "cuda" else torch.float32
10
+ print(f"Running on: {DEVICE.upper()}")
11
 
12
+ # ── Model ─────────────────────────────────────────────────────────────────────
 
 
13
  MODEL_REPO = "cyberdelia/CyberRealisticPony"
14
  MODEL_FILE = "CyberRealisticPony_V16.0_FP16.safetensors"
15
+ PONY_POS = "score_9, score_8_up, score_7_up, "
16
+ PONY_NEG = "score_6, score_5, score_4, "
17
 
18
+ print("Downloading model...")
19
+ local_path = hf_hub_download(repo_id=MODEL_REPO, filename=MODEL_FILE)
20
+ print(f"Loading from {local_path}...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
+ pipe = StableDiffusionXLPipeline.from_single_file(local_path, torch_dtype=DTYPE)
23
  pipe.scheduler = DPMSolverMultistepScheduler.from_config(
24
+ pipe.scheduler.config, use_karras_sigmas=True
 
25
  )
 
26
  pipe.enable_attention_slicing()
 
27
  if DEVICE == "cuda":
28
  pipe.enable_xformers_memory_efficient_attention()
 
29
  pipe = pipe.to(DEVICE)
30
+ print("Ready.")
31
 
32
+ # ── Generation ────────────────────────────────────────────────────────────────
33
+ def generate(prompt, negative_prompt, width, height, steps, guidance, seed, randomize):
34
+ if not prompt.strip():
35
+ raise gr.Error("Please enter a prompt.")
36
+ if randomize:
 
 
 
37
  seed = random.randint(0, 2**32 - 1)
 
38
  seed = int(seed)
39
  generator = torch.Generator(device=DEVICE).manual_seed(seed)
40
+ result = pipe(
41
+ prompt=PONY_POS + prompt.strip(),
42
+ negative_prompt=PONY_NEG + negative_prompt.strip(),
 
 
 
 
43
  width=int(width),
44
  height=int(height),
45
  num_inference_steps=int(steps),
 
47
  generator=generator,
48
  clip_skip=2,
49
  )
50
+ return result.images[0], seed
51
+
52
+ # ── CSS ───────────────────────────────────────────────────────────────────────
53
+ css = """
54
+ /* ── Base ── */
55
+ body, .gradio-container {
56
+ background: #0f0f13 !important;
57
+ font-family: 'Inter', system-ui, sans-serif !important;
58
+ }
59
+
60
+ /* ── Header ── */
61
+ .header-box {
62
+ background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
63
+ border: 1px solid #e94560;
64
+ border-radius: 16px;
65
+ padding: 20px;
66
+ text-align: center;
67
+ margin-bottom: 8px;
68
+ }
69
+ .header-box h1 {
70
+ color: #ffffff;
71
+ font-size: 1.8em;
72
+ font-weight: 800;
73
+ margin: 0 0 6px 0;
74
+ letter-spacing: -0.5px;
75
+ }
76
+ .header-box p {
77
+ color: #a0a0b8;
78
+ font-size: 0.85em;
79
+ margin: 0;
80
+ }
81
+ .header-box .badge {
82
+ display: inline-block;
83
+ background: #e94560;
84
+ color: white;
85
+ font-size: 0.7em;
86
+ font-weight: 700;
87
+ padding: 2px 10px;
88
+ border-radius: 20px;
89
+ margin-top: 8px;
90
+ text-transform: uppercase;
91
+ letter-spacing: 1px;
92
+ }
93
+
94
+ /* ── Output image ── */
95
+ .output-box {
96
+ background: #1a1a2e;
97
+ border: 2px dashed #2a2a4a;
98
+ border-radius: 16px;
99
+ overflow: hidden;
100
+ min-height: 300px;
101
+ }
102
+ .output-box img {
103
+ border-radius: 14px;
104
+ width: 100%;
105
+ }
106
+
107
+ /* ── Panel cards ── */
108
+ .panel-card {
109
+ background: #1a1a2e;
110
+ border: 1px solid #2a2a4a;
111
+ border-radius: 14px;
112
+ padding: 16px;
113
+ margin-bottom: 10px;
114
+ }
115
+ .section-label {
116
+ color: #e94560 !important;
117
+ font-size: 0.75em !important;
118
+ font-weight: 700 !important;
119
+ text-transform: uppercase !important;
120
+ letter-spacing: 1.5px !important;
121
+ margin-bottom: 10px !important;
122
+ }
123
+
124
+ /* ── Inputs ── */
125
+ textarea, input[type="number"] {
126
+ background: #0f0f13 !important;
127
+ border: 1px solid #2a2a4a !important;
128
+ border-radius: 10px !important;
129
+ color: #e0e0f0 !important;
130
+ font-size: 15px !important;
131
+ }
132
+ textarea:focus, input[type="number"]:focus {
133
+ border-color: #e94560 !important;
134
+ box-shadow: 0 0 0 2px rgba(233, 69, 96, 0.2) !important;
135
+ }
136
+
137
+ /* ── Sliders ── */
138
+ .gradio-slider input[type=range] {
139
+ accent-color: #e94560;
140
+ }
141
+
142
+ /* ── Generate button ── */
143
+ .generate-btn {
144
+ background: linear-gradient(135deg, #e94560, #c23152) !important;
145
+ border: none !important;
146
+ border-radius: 14px !important;
147
+ color: white !important;
148
+ font-size: 1.1em !important;
149
+ font-weight: 700 !important;
150
+ padding: 16px !important;
151
+ width: 100% !important;
152
+ letter-spacing: 0.5px !important;
153
+ box-shadow: 0 4px 20px rgba(233, 69, 96, 0.4) !important;
154
+ transition: all 0.2s ease !important;
155
+ }
156
+ .generate-btn:active {
157
+ transform: scale(0.98) !important;
158
+ box-shadow: 0 2px 10px rgba(233, 69, 96, 0.3) !important;
159
+ }
160
+
161
+ /* ── Seed row ── */
162
+ .seed-row {
163
+ display: flex;
164
+ align-items: center;
165
+ gap: 10px;
166
+ }
167
+
168
+ /* ── Used seed display ── */
169
+ .used-seed input {
170
+ background: #0f0f13 !important;
171
+ border: 1px solid #2a2a4a !important;
172
+ color: #606080 !important;
173
+ font-size: 0.85em !important;
174
+ text-align: center !important;
175
+ }
176
+
177
+ /* ── Labels ── */
178
+ label span, .gradio-label {
179
+ color: #a0a0c0 !important;
180
+ font-size: 0.82em !important;
181
+ font-weight: 600 !important;
182
+ text-transform: uppercase !important;
183
+ letter-spacing: 0.8px !important;
184
+ }
185
+
186
+ /* ── Mobile: stack columns ── */
187
+ @media (max-width: 768px) {
188
+ .gr-row { flex-direction: column !important; }
189
+ .gr-col { width: 100% !important; min-width: 100% !important; }
190
+ }
191
+ """
192
+
193
+ # ── UI ────────────────────────────────────────────────────────────────────────
194
+ with gr.Blocks(css=css, title="CyberRealistic Pony") as demo:
195
+
196
+ # Header
197
+ gr.HTML("""
198
+ <div class="header-box">
199
+ <h1>🐴 CyberRealistic Pony</h1>
200
+ <p>SDXL Β· Pony Architecture Β· v16.0</p>
201
+ <span class="badge">⚠ CPU Mode β€” Slow</span>
202
+ </div>
203
+ """)
204
+
205
+ # Output image β€” top on mobile so you see result first
206
+ with gr.Group(elem_classes="output-box"):
207
+ output_image = gr.Image(
208
+ label="",
209
+ type="pil",
210
+ show_label=False,
211
+ height=420,
212
+ )
213
+
214
+ used_seed = gr.Number(
215
+ label="Seed used β€” save to reproduce",
216
+ interactive=False,
217
+ elem_classes="used-seed",
218
+ )
219
 
220
+ # ── Prompt card ──
221
+ 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>')
222
 
223
+ prompt = gr.Textbox(
224
+ label="",
225
+ placeholder="a woman in a futuristic city, cinematic lighting, highly detailed, photorealistic",
226
+ lines=3,
227
+ show_label=False,
228
+ )
229
 
230
+ 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>')
 
231
 
232
+ negative_prompt = gr.Textbox(
233
+ label="",
234
+ value=(
235
+ "(worst quality:1.2), (low quality:1.2), (normal quality:1.2), "
236
+ "lowres, bad anatomy, bad hands, signature, watermarks, "
237
+ "ugly, imperfect eyes, skewed eyes, unnatural face, "
238
+ "unnatural body, error, extra limb, missing limbs"
239
+ ),
240
+ lines=2,
241
+ show_label=False,
242
  )
243
 
244
+ # ── Size card ──
245
+ 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>')
246
+
247
+ with gr.Row():
248
+ width = gr.Slider(512, 896, value=768, step=64, label="Width")
249
+ height = gr.Slider(512, 1152, value=896, step=64, label="Height")
250
+
251
+ # ── Sampling card ──
252
+ 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>')
253
+
254
+ steps = gr.Slider(10, 30, value=20, step=1, label="Steps")
255
+ guidance = gr.Slider(1.0, 12.0, value=5.0, step=0.5, label="CFG Scale")
256
+
257
+ # ── Seed card ──
258
+ 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>')
259
+
260
  with gr.Row():
261
+ seed = gr.Number(label="Seed", value=42, precision=0, minimum=0, maximum=2**32-1, scale=2)
262
+ randomize_seed = gr.Checkbox(label="Random", value=True, scale=1)
263
+
264
+ # ── Generate button ──
265
+ generate_btn = gr.Button(
266
+ "✦ Generate Image",
267
+ variant="primary",
268
+ size="lg",
269
+ elem_classes="generate-btn",
270
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
 
272
+ # ── Wire up ──
273
  generate_btn.click(
274
+ fn=generate,
275
  inputs=[prompt, negative_prompt, width, height, steps, guidance, seed, randomize_seed],
276
  outputs=[output_image, used_seed],
277
  )