artificialguybr commited on
Commit
a47f76d
·
1 Parent(s): a541d0e

Redesign UI with modern studio-style interface

Browse files

- Add hero section with gradient title and feature pills
- Implement numbered sections (Prompt, Result, Settings)
- Add custom CSS with purple/violet theme for anime aesthetic
- Add negative prompt as visible field with default value
- Add styled generate button with hover effects
- Add styled accordions for aspect ratio and metadata
- Improve overall layout with columns
- Add ZeroGPU badge and model info pills
- Use custom fonts (Outfit, Fira Code)
- Dark theme with gradient background effects

Files changed (1) hide show
  1. app.py +274 -92
app.py CHANGED
@@ -16,7 +16,7 @@ from diffusers import StableDiffusionXLPipeline, StableDiffusionXLImg2ImgPipelin
16
  logging.basicConfig(level=logging.INFO)
17
  logger = logging.getLogger(__name__)
18
 
19
- DESCRIPTION = "PonyDiffusion V6 XL"
20
  if not torch.cuda.is_available():
21
  DESCRIPTION += "\n<p>Running on CPU 🥶 This demo does not work on CPU. </p>"
22
  IS_COLAB = utils.is_google_colab() or os.getenv("IS_COLAB") == "1"
@@ -28,6 +28,11 @@ USE_TORCH_COMPILE = os.getenv("USE_TORCH_COMPILE") == "1"
28
  ENABLE_CPU_OFFLOAD = os.getenv("ENABLE_CPU_OFFLOAD") == "1"
29
  OUTPUT_DIR = os.getenv("OUTPUT_DIR", "./outputs")
30
 
 
 
 
 
 
31
  MODEL = os.getenv(
32
  "MODEL",
33
  "https://huggingface.co/AstraliteHeart/pony-diffusion-v6/blob/main/v6.safetensors",
@@ -176,52 +181,265 @@ if torch.cuda.is_available():
176
  else:
177
  pipe = None
178
 
179
- with gr.Blocks(css="style.css") as demo:
180
- title = gr.HTML(
181
- f"""<h1><span>{DESCRIPTION}</span></h1>""",
182
- elem_id="title",
183
- )
184
- gr.Markdown(
185
- f"""Gradio demo for [Pony Diffusion V6](https://civitai.com/models/257749/pony-diffusion-v6-xl/)""",
186
- elem_id="subtitle",
187
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
188
  gr.DuplicateButton(
189
  value="Duplicate Space for private use",
190
  elem_id="duplicate-button",
191
  visible=os.getenv("SHOW_DUPLICATE_BUTTON") == "1",
192
  )
193
- with gr.Group():
194
- with gr.Row():
195
- prompt = gr.Text(
196
- label="Prompt",
197
- show_label=False,
198
- max_lines=5,
199
- placeholder="Enter your prompt",
 
 
200
  container=False,
201
  )
202
- run_button = gr.Button(
203
- "Generate",
204
- variant="primary",
205
- scale=0
 
206
  )
207
- result = gr.Gallery(
208
- label="Result",
209
- columns=1,
210
- preview=True,
211
- show_label=False
212
- )
213
- with gr.Accordion(label="Advanced Settings", open=False):
214
- negative_prompt = gr.Text(
215
- label="Negative Prompt",
216
- max_lines=5,
217
- placeholder="Enter a negative prompt",
218
- value=""
219
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
  aspect_ratio_selector = gr.Radio(
221
- label="Aspect Ratio",
222
- choices=config.aspect_ratios,
223
- value="1024 x 1024",
224
- container=True,
225
  )
226
  with gr.Group(visible=False) as custom_resolution:
227
  with gr.Row():
@@ -239,68 +457,28 @@ with gr.Blocks(css="style.css") as demo:
239
  step=8,
240
  value=1024,
241
  )
242
- use_upscaler = gr.Checkbox(label="Use Upscaler", value=False)
243
- with gr.Row() as upscaler_row:
244
- upscaler_strength = gr.Slider(
245
- label="Strength",
246
- minimum=0,
247
- maximum=1,
248
- step=0.05,
249
- value=0.55,
250
- visible=False,
251
- )
252
- upscale_by = gr.Slider(
253
- label="Upscale by",
254
- minimum=1,
255
- maximum=1.5,
256
- step=0.1,
257
- value=1.5,
258
- visible=False,
259
- )
260
 
261
- sampler = gr.Dropdown(
262
- label="Sampler",
263
- choices=config.sampler_list,
264
- interactive=True,
265
- value="DPM++ 2M SDE Karras",
266
- )
267
- with gr.Row():
268
- seed = gr.Slider(
269
- label="Seed", minimum=0, maximum=utils.MAX_SEED, step=1, value=0
270
- )
271
- randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
272
- with gr.Group():
273
- with gr.Row():
274
- guidance_scale = gr.Slider(
275
- label="Guidance scale",
276
- minimum=1,
277
- maximum=12,
278
- step=0.1,
279
- value=7.0,
280
- )
281
- num_inference_steps = gr.Slider(
282
- label="Number of inference steps",
283
- minimum=1,
284
- maximum=50,
285
- step=1,
286
- value=28,
287
- )
288
- with gr.Accordion(label="Generation Parameters", open=False):
289
- gr_metadata = gr.JSON(label="Metadata", show_label=False)
290
  gr.Examples(
291
  examples=config.examples,
292
  inputs=prompt,
293
  outputs=[result, gr_metadata],
294
- fn=lambda *args, **kwargs: generate(*args, use_upscaler=True, **kwargs),
295
  cache_examples=CACHE_EXAMPLES,
296
  )
 
297
  use_upscaler.change(
298
- fn=lambda x: [gr.update(visible=x), gr.update(visible=x)],
299
  inputs=use_upscaler,
300
- outputs=[upscaler_strength, upscale_by],
301
  queue=False,
302
  api_name=False,
303
  )
 
304
  aspect_ratio_selector.change(
305
  fn=lambda x: gr.update(visible=x == "Custom"),
306
  inputs=aspect_ratio_selector,
@@ -333,9 +511,10 @@ with gr.Blocks(css="style.css") as demo:
333
  ).then(
334
  fn=generate,
335
  inputs=inputs,
336
- outputs=result,
337
  api_name="run",
338
  )
 
339
  negative_prompt.submit(
340
  fn=utils.randomize_seed_fn,
341
  inputs=[seed, randomize_seed],
@@ -345,10 +524,11 @@ with gr.Blocks(css="style.css") as demo:
345
  ).then(
346
  fn=generate,
347
  inputs=inputs,
348
- outputs=result,
349
  api_name=False,
350
  )
351
- run_button.click(
 
352
  fn=utils.randomize_seed_fn,
353
  inputs=[seed, randomize_seed],
354
  outputs=seed,
@@ -360,4 +540,6 @@ with gr.Blocks(css="style.css") as demo:
360
  outputs=[result, gr_metadata],
361
  api_name=False,
362
  )
363
- demo.queue(max_size=20).launch(debug=IS_COLAB, share=IS_COLAB)
 
 
 
16
  logging.basicConfig(level=logging.INFO)
17
  logger = logging.getLogger(__name__)
18
 
19
+ DESCRIPTION = "Pony Studio"
20
  if not torch.cuda.is_available():
21
  DESCRIPTION += "\n<p>Running on CPU 🥶 This demo does not work on CPU. </p>"
22
  IS_COLAB = utils.is_google_colab() or os.getenv("IS_COLAB") == "1"
 
28
  ENABLE_CPU_OFFLOAD = os.getenv("ENABLE_CPU_OFFLOAD") == "1"
29
  OUTPUT_DIR = os.getenv("OUTPUT_DIR", "./outputs")
30
 
31
+ DEFAULT_NEGATIVE = (
32
+ "(worst quality, low quality, normal quality, lowres, low details), "
33
+ "(watermark, signature, text, logo, words, letters), blurry, jpeg artifacts"
34
+ )
35
+
36
  MODEL = os.getenv(
37
  "MODEL",
38
  "https://huggingface.co/AstraliteHeart/pony-diffusion-v6/blob/main/v6.safetensors",
 
181
  else:
182
  pipe = None
183
 
184
+ CSS = """
185
+ @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800&family=Fira+Code:wght@400;500&display=swap');
186
+
187
+ :root {
188
+ --bg: #080a0e;
189
+ --surf: #0d1017;
190
+ --card: #111520;
191
+ --border: #1c2133;
192
+ --border2: #252d45;
193
+ --purple: #a78bfa;
194
+ --violet: #7c3aed;
195
+ --lavender: #c4b5fd;
196
+ --text: #e2e8f8;
197
+ --muted: #4a5578;
198
+ --r: 14px;
199
+ --r-sm: 8px;
200
+ }
201
+
202
+ *, *::before, *::after { box-sizing: border-box; }
203
+
204
+ body, .gradio-container {
205
+ background: var(--bg) !important;
206
+ font-family: 'Outfit', sans-serif !important;
207
+ color: var(--text) !important;
208
+ }
209
+
210
+ .gradio-container::before {
211
+ content: '';
212
+ position: fixed; inset: 0; pointer-events: none; z-index: 0;
213
+ background:
214
+ radial-gradient(ellipse 70% 50% at 50% -10%, rgba(167,139,250,0.07) 0%, transparent 65%),
215
+ radial-gradient(ellipse 40% 30% at 90% 90%, rgba(124,58,237,0.04) 0%, transparent 60%);
216
+ }
217
+
218
+ .app-hero { padding: 52px 0 28px; text-align: center; }
219
+
220
+ .app-hero h1 {
221
+ font-size: 3rem; font-weight: 800; letter-spacing: -0.05em;
222
+ line-height: 1; margin: 0 0 12px;
223
+ background: linear-gradient(135deg, var(--lavender) 0%, var(--purple) 40%, var(--violet) 100%);
224
+ -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text;
225
+ }
226
+
227
+ .app-hero .tagline {
228
+ color: var(--muted); font-size: 0.88rem; font-weight: 300;
229
+ letter-spacing: 0.06em; text-transform: uppercase; margin: 0 0 20px;
230
+ }
231
+
232
+ .app-hero .pills { display: flex; justify-content: center; gap: 8px; flex-wrap: wrap; }
233
+
234
+ .app-hero .pill {
235
+ background: var(--card); border: 1px solid var(--border2); border-radius: 100px;
236
+ padding: 4px 14px; font-size: 0.74rem; font-weight: 500; color: var(--muted);
237
+ font-family: 'Fira Code', monospace;
238
+ }
239
+
240
+ .app-hero .pill.violet { color: var(--purple); border-color: rgba(167,139,250,0.3); }
241
+
242
+ .sec-label {
243
+ font-size: 0.62rem !important; font-weight: 700 !important;
244
+ letter-spacing: 0.15em !important; text-transform: uppercase !important;
245
+ color: var(--purple) !important; margin: 0 0 8px !important; display: block;
246
+ }
247
+
248
+ label > span {
249
+ font-family: 'Outfit', sans-serif !important; font-size: 0.72rem !important;
250
+ font-weight: 500 !important; color: var(--muted) !important;
251
+ text-transform: uppercase; letter-spacing: 0.08em;
252
+ }
253
+
254
+ textarea, input[type="text"] {
255
+ background: var(--surf) !important; border: 1px solid var(--border) !important;
256
+ border-radius: var(--r-sm) !important; color: var(--text) !important;
257
+ font-family: 'Outfit', sans-serif !important; font-size: 0.95rem !important;
258
+ transition: border-color 0.2s, box-shadow 0.2s;
259
+ }
260
+
261
+ textarea:focus, input[type="text"]:focus {
262
+ border-color: var(--purple) !important;
263
+ box-shadow: 0 0 0 3px rgba(167,139,250,0.12) !important;
264
+ outline: none !important;
265
+ }
266
+
267
+ .gen-btn {
268
+ background: linear-gradient(135deg, var(--purple), var(--violet)) !important;
269
+ border: none !important; border-radius: var(--r) !important;
270
+ color: #fff !important; font-family: 'Outfit', sans-serif !important;
271
+ font-weight: 700 !important; font-size: 1rem !important;
272
+ height: 54px !important; width: 100% !important;
273
+ letter-spacing: 0.02em !important; cursor: pointer !important;
274
+ transition: opacity 0.18s, transform 0.15s, box-shadow 0.2s !important;
275
+ box-shadow: 0 4px 20px rgba(167,139,250,0.28) !important;
276
+ }
277
+
278
+ .gen-btn:hover {
279
+ opacity: 0.88 !important; transform: translateY(-1px) !important;
280
+ box-shadow: 0 8px 30px rgba(167,139,250,0.48) !important;
281
+ }
282
+
283
+ .gen-btn:active { transform: translateY(0) !important; }
284
+
285
+ .result-gallery .grid-wrap {
286
+ background: var(--surf) !important;
287
+ border: 1px solid var(--border) !important;
288
+ border-radius: var(--r) !important;
289
+ }
290
+
291
+ .result-gallery img { border-radius: 10px !important; }
292
+
293
+ .gr-accordion {
294
+ background: var(--card) !important; border: 1px solid var(--border) !important;
295
+ border-radius: var(--r) !important; margin-top: 10px !important;
296
+ }
297
+
298
+ .aspect-radio .wrap {
299
+ display: flex !important; flex-wrap: wrap !important; gap: 6px !important;
300
+ background: transparent !important; padding: 0 !important; border: none !important;
301
+ }
302
+
303
+ .aspect-radio label {
304
+ background: var(--surf) !important; border: 1px solid var(--border) !important;
305
+ border-radius: 100px !important; padding: 5px 12px !important;
306
+ font-size: 0.78rem !important; font-family: 'Fira Code', monospace !important;
307
+ color: var(--muted) !important; cursor: pointer !important;
308
+ transition: all 0.15s !important; white-space: nowrap !important;
309
+ }
310
+
311
+ .aspect-radio label:hover { border-color: var(--purple) !important; color: var(--text) !important; }
312
+
313
+ .aspect-radio label:has(input:checked) {
314
+ background: var(--purple) !important; border-color: var(--purple) !important;
315
+ color: #fff !important; font-weight: 600 !important;
316
+ }
317
+
318
+ .ghost-btn button {
319
+ background: transparent !important; border: 1px solid var(--border2) !important;
320
+ border-radius: var(--r-sm) !important; color: var(--muted) !important;
321
+ font-family: 'Outfit', sans-serif !important; font-size: 0.82rem !important;
322
+ height: 36px !important; transition: border-color 0.18s, color 0.18s !important;
323
+ }
324
+
325
+ .ghost-btn button:hover { border-color: var(--purple) !important; color: var(--text) !important; }
326
+
327
+ .upscaler-checkbox input:checked {
328
+ background-color: var(--purple) !important;
329
+ }
330
+
331
+ ::-webkit-scrollbar { width: 5px; }
332
+ ::-webkit-scrollbar-track { background: var(--surf); }
333
+ ::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 3px; }
334
+ ::-webkit-scrollbar-thumb:hover { background: var(--purple); }
335
+
336
+ #duplicate-button {
337
+ margin: auto;
338
+ color: #fff;
339
+ background: var(--violet);
340
+ border-radius: 100vh;
341
+ font-family: 'Outfit', sans-serif;
342
+ }
343
+ """
344
+
345
+ with gr.Blocks(theme=gr.themes.Base(), css=CSS) as demo:
346
+
347
+ gr.HTML("""
348
+ <div class="app-hero">
349
+ <h1>Pony Studio</h1>
350
+ <p class="tagline">Anime-style · High-fidelity · Text-to-image</p>
351
+ <div class="pills">
352
+ <span class="pill violet">ZeroGPU ⚡</span>
353
+ <span class="pill">Pony V6 XL</span>
354
+ <span class="pill">SDXL · fp16</span>
355
+ <span class="pill">safetensors</span>
356
+ </div>
357
+ </div>
358
+ """)
359
+
360
  gr.DuplicateButton(
361
  value="Duplicate Space for private use",
362
  elem_id="duplicate-button",
363
  visible=os.getenv("SHOW_DUPLICATE_BUTTON") == "1",
364
  )
365
+
366
+ with gr.Row():
367
+
368
+ with gr.Column(scale=2):
369
+ gr.HTML('<span class="sec-label">① Prompt</span>')
370
+ prompt = gr.Textbox(
371
+ label="",
372
+ lines=4,
373
+ placeholder="score_9, score_8_up, score_7_up, ... your anime-style prompt here",
374
  container=False,
375
  )
376
+ gr.HTML('<div style="height:8px"></div>')
377
+ negative_prompt = gr.Textbox(
378
+ label="Negative prompt",
379
+ lines=2,
380
+ value=DEFAULT_NEGATIVE
381
  )
382
+
383
+ gr.HTML('<div style="height:10px"></div>')
384
+ run_btn = gr.Button("▶ Generate", variant="primary", elem_classes=["gen-btn"])
385
+
386
+ gr.HTML('<div style="height:14px"></div>')
387
+ gr.HTML('<span class="sec-label">② Result</span>')
388
+ result = gr.Gallery(
389
+ label="", columns=1, preview=True,
390
+ container=False, elem_classes=["result-gallery"], height=600,
391
+ )
392
+
393
+ with gr.Column(scale=1, min_width=280):
394
+ gr.HTML('<span class="sec-label">③ Settings</span>')
395
+
396
+ use_upscaler = gr.Checkbox(label="Use Upscaler", value=False, elem_classes=["upscaler-checkbox"])
397
+ with gr.Row(visible=False) as upscaler_row:
398
+ upscaler_strength = gr.Slider(
399
+ label="Strength",
400
+ minimum=0,
401
+ maximum=1,
402
+ step=0.05,
403
+ value=0.55,
404
+ )
405
+ upscale_by = gr.Slider(
406
+ label="Upscale by",
407
+ minimum=1,
408
+ maximum=1.5,
409
+ step=0.1,
410
+ value=1.5,
411
+ )
412
+
413
+ gr.HTML('<div style="height:8px"></div>')
414
+ sampler = gr.Dropdown(
415
+ label="Sampler",
416
+ choices=config.sampler_list,
417
+ value="DPM++ 2M SDE Karras",
418
+ )
419
+
420
+ with gr.Row():
421
+ guidance_scale = gr.Slider(
422
+ label="Guidance scale",
423
+ minimum=1,
424
+ maximum=12,
425
+ step=0.1,
426
+ value=7.0,
427
+ )
428
+ num_inference_steps = gr.Slider(
429
+ label="Steps",
430
+ minimum=1,
431
+ maximum=50,
432
+ step=1,
433
+ value=28,
434
+ )
435
+
436
+ seed = gr.Slider(label="Seed", minimum=0, maximum=utils.MAX_SEED, step=1, value=0)
437
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
438
+
439
+ with gr.Accordion("⚙ Aspect ratio", open=False):
440
  aspect_ratio_selector = gr.Radio(
441
+ label="", choices=config.aspect_ratios, value="1024 x 1024",
442
+ container=False, elem_classes=["aspect-radio"],
 
 
443
  )
444
  with gr.Group(visible=False) as custom_resolution:
445
  with gr.Row():
 
457
  step=8,
458
  value=1024,
459
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
460
 
461
+ with gr.Accordion("📋 Generation metadata", open=False):
462
+ gr_metadata = gr.JSON(label="", show_label=False)
463
+
464
+ gr.HTML('<div style="height:12px"></div>')
465
+ gr.HTML('<span class="sec-label">Examples</span>')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
466
  gr.Examples(
467
  examples=config.examples,
468
  inputs=prompt,
469
  outputs=[result, gr_metadata],
470
+ fn=lambda *args, **kwargs: generate(*args, use_upscaler=False, **kwargs),
471
  cache_examples=CACHE_EXAMPLES,
472
  )
473
+
474
  use_upscaler.change(
475
+ fn=lambda x: gr.update(visible=x),
476
  inputs=use_upscaler,
477
+ outputs=upscaler_row,
478
  queue=False,
479
  api_name=False,
480
  )
481
+
482
  aspect_ratio_selector.change(
483
  fn=lambda x: gr.update(visible=x == "Custom"),
484
  inputs=aspect_ratio_selector,
 
511
  ).then(
512
  fn=generate,
513
  inputs=inputs,
514
+ outputs=[result, gr_metadata],
515
  api_name="run",
516
  )
517
+
518
  negative_prompt.submit(
519
  fn=utils.randomize_seed_fn,
520
  inputs=[seed, randomize_seed],
 
524
  ).then(
525
  fn=generate,
526
  inputs=inputs,
527
+ outputs=[result, gr_metadata],
528
  api_name=False,
529
  )
530
+
531
+ run_btn.click(
532
  fn=utils.randomize_seed_fn,
533
  inputs=[seed, randomize_seed],
534
  outputs=seed,
 
540
  outputs=[result, gr_metadata],
541
  api_name=False,
542
  )
543
+
544
+ demo.queue(max_size=20)
545
+ demo.launch(debug=IS_COLAB, share=IS_COLAB)