lichorosario commited on
Commit
452a02d
·
verified ·
1 Parent(s): 557c413

Update app.py from anycoder

Browse files
Files changed (1) hide show
  1. app.py +400 -383
app.py CHANGED
@@ -1,446 +1,463 @@
1
  import gradio as gr
2
- import spaces
3
- import math
4
- import subprocess
5
- import sys
6
  from PIL import Image
7
- import os
 
8
 
9
- # Try to import diffsynth_engine, provide helpful error if not installed
10
- try:
11
- from diffsynth_engine import fetch_model, QwenImagePipeline, QwenImagePipelineConfig
12
- DIFFSYNTH_AVAILABLE = True
13
- except ImportError:
14
- DIFFSYNTH_AVAILABLE = False
15
- # Fallback placeholders for type hints
16
- class QwenImagePipelineConfig:
17
- @staticmethod
18
- def basic_config(**kwargs):
19
- pass
20
-
21
- class QwenImagePipeline:
22
- @staticmethod
23
- def from_pretrained(config):
24
- pass
25
 
26
- def load_lora(self, **kwargs):
27
- pass
 
 
 
 
 
 
28
 
29
- def apply_scheduler_config(self, **kwargs):
30
- pass
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
- def __call__(self, **kwargs):
33
- pass
34
-
35
- def get_pipeline():
36
- """Initialize and return the Qwen Image Pipeline."""
37
- global pipe
38
- if pipe is not None:
39
  return pipe
40
-
41
- if not DIFFSYNTH_AVAILABLE:
42
- raise ImportError(
43
- "diffsynth_engine is not installed. Please install it using:\n"
44
- "pip install git+https://github.com/tencent-ailab/diffsynth-engine.git"
45
- )
46
-
47
- # Create pipeline configuration
48
- config = QwenImagePipelineConfig.basic_config(
49
- model_path=fetch_model("Qwen/Qwen-Image-2512", path="transformer/*.safetensors"),
50
- encoder_path=fetch_model("Qwen/Qwen-Image-2512", path="text_encoder/*.safetensors"),
51
- vae_path=fetch_model("Qwen/Qwen-Image-2512", path="vae/*.safetensors"),
52
- offload_mode="cpu_offload",
53
- )
54
-
55
- # Create and return pipeline
56
- pipe = QwenImagePipeline.from_pretrained(config)
57
-
58
- # Load the turbo LoRA
59
- pipe.load_lora(
60
- path=fetch_model("Wuli-Art/Qwen-Image-2512-Turbo-LoRA", path="Wuli-Qwen-Image-2512-Turbo-LoRA-4steps-V1.0-bf16.safetensors"),
61
- scale=1.0,
62
- fused=True,
63
- )
64
-
65
- # Apply scheduler config for exponential shifting
66
- scheduler_config = {
67
- "exponential_shift_mu": math.log(2.5),
68
- "use_dynamic_shifting": True,
69
- "shift_terminal": None
70
- }
71
- pipe.apply_scheduler_config(scheduler_config)
72
-
73
- return pipe
74
 
75
- # Global pipeline variable to avoid reloading
76
- pipe = None
77
 
78
- @spaces.GPU(duration=120, memory=40)
79
  def generate_image(
80
  prompt: str,
81
- negative_prompt: str,
82
- num_inference_steps: int,
83
- seed: int,
84
- width: int,
85
- height: int,
86
- cfg_scale: float
87
- ):
88
  """
89
- Generate an image using Qwen-Image-2512-Turbo with LoRA.
90
 
91
  Args:
92
- prompt: Text prompt describing the image to generate
93
- negative_prompt: Text describing what to avoid in the image
94
- num_inference_steps: Number of diffusion steps (4-8 recommended)
 
95
  seed: Random seed for reproducibility
96
- width: Image width (multiple of 16)
97
- height: Image height (multiple of 16)
98
- cfg_scale: Classifier-free guidance scale (1.0 for turbo models)
99
 
100
  Returns:
101
  Generated PIL Image
102
  """
103
- # Check if diffsynth_engine is available
104
- if not DIFFSYNTH_AVAILABLE:
105
- raise gr.Error(
106
- "diffsynth_engine is not installed. Please install it using:\n\n"
107
- "pip install git+https://github.com/tencent-ailab/diffsynth-engine.git"
108
- )
109
-
110
- # Validate inputs
111
- if not prompt or len(prompt.strip()) == 0:
112
- raise gr.Error("Please enter a prompt")
113
 
114
- if num_inference_steps < 1 or num_inference_steps > 20:
115
- raise gr.Error("Number of steps must be between 1 and 20")
 
 
116
 
117
- if width < 64 or width > 2048 or height < 64 or height > 2048:
118
- raise gr.Error("Width and height must be between 64 and 2048 pixels")
 
 
 
119
 
120
- # Get pipeline
121
- pipeline = get_pipeline()
122
-
123
- # Generate image
124
- output = pipeline(
125
- prompt=prompt,
126
- negative_prompt=negative_prompt if negative_prompt else None,
127
- cfg_scale=cfg_scale,
128
- num_inference_steps=num_inference_steps,
129
- seed=seed,
130
- width=width,
131
- height=height
132
- )
133
-
134
- # Save to temp file and return
135
- output_path = "/tmp/output.png"
136
- output.save(output_path)
137
-
138
- return output_path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
 
140
- def update_seed():
141
- """Generate a new random seed."""
142
- import random
143
- return random.randint(0, 2147483647)
144
 
145
- def clear_inputs():
146
- """Clear all input fields."""
147
- return "", "", 4, 42, 1328, 1328, 1.0
 
 
148
 
149
- def check_dependencies():
150
- """Check if all required dependencies are installed."""
151
- if not DIFFSYNTH_AVAILABLE:
152
- return False, (
153
- "Missing: diffsynth_engine\n\n"
154
- "Install with:\n"
155
- "pip install git+https://github.com/tencent-ailab/diffsynth-engine.git"
156
- )
157
- return True, "All dependencies available"
158
 
159
- # Gradio 6 - NO parameters in gr.Blocks() constructor
160
- with gr.Blocks() as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  # Header with branding
162
- gr.HTML("""
163
- <div style="text-align: center; padding: 10px 0;">
164
- <h1 style="margin-bottom: 5px;">🎨 Qwen Image Generator Turbo</h1>
165
- <p style="color: var(--body-text-color-secondary); margin-top: 0;">
166
- Generate high-quality images with Qwen-Image-2512-Turbo & LoRA
167
- </p>
168
- <p style="font-size: 12px; margin-top: 10px;">
169
- <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color: var(--link-text-color);">
170
- Built with anycoder
171
- </a>
172
- </p>
173
- </div>
174
- """)
175
-
176
- # Dependency check status
177
- dep_status = gr.Textbox(
178
- label="Dependency Status",
179
- interactive=False,
180
- visible=True
181
- )
182
-
183
- # Update dependency status on load
184
- def update_dep_status():
185
- available, message = check_dependencies()
186
- if available:
187
- return {"value": "✅ All dependencies are available", "visible": True}
188
- else:
189
- return {"value": f"❌ {message}", "visible": True}
190
-
191
- demo.load(update_dep_status, outputs=dep_status)
192
-
193
  with gr.Row():
194
- # Left column - Input controls
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  with gr.Column(scale=1, min_width=350):
196
- gr.Markdown("### 📝 Prompt")
197
- prompt = gr.Textbox(
 
 
198
  label="Prompt",
199
- placeholder="Describe your image in detail...",
200
  lines=4,
201
- info="Be descriptive for best results",
202
  interactive=True
203
  )
204
 
 
205
  negative_prompt = gr.Textbox(
206
- label="Negative Prompt",
207
- placeholder="What to avoid (e.g., blurry, low quality, distorted)",
208
  lines=2,
209
- info="Optional - helps avoid unwanted elements",
210
  interactive=True
211
  )
212
 
213
- with gr.Accordion("⚙️ Advanced Settings", open=True):
214
- with gr.Row():
215
- with gr.Column(scale=1):
216
- num_inference_steps = gr.Slider(
217
- label="Inference Steps",
218
- minimum=1,
219
- maximum=20,
220
- value=4,
221
- step=1,
222
- info="4-8 steps recommended for turbo model"
223
- )
224
-
225
- with gr.Column(scale=1):
226
- cfg_scale = gr.Slider(
227
- label="CFG Scale",
228
- minimum=0.5,
229
- maximum=2.0,
230
- value=1.0,
231
- step=0.1,
232
- info="1.0 is optimal for turbo models"
233
- )
234
-
235
- with gr.Row():
236
- with gr.Column(scale=1):
237
- seed = gr.Number(
238
- label="Seed",
239
- value=42,
240
- minimum=0,
241
- maximum=2147483647,
242
- info="Use same seed for reproducible results"
243
- )
244
-
245
- with gr.Column(scale=1):
246
- gr.Button(
247
- "🎲 Random Seed",
248
- size="sm",
249
- variant="secondary"
250
- ).click(
251
- fn=update_seed,
252
- outputs=seed,
253
- api_visibility="private"
254
- )
255
 
256
- with gr.Row():
257
- with gr.Column(scale=1):
258
- width = gr.Slider(
259
- label="Width",
260
- minimum=256,
261
- maximum=2048,
262
- value=1328,
263
- step=16,
264
- info="Must be multiple of 16"
265
- )
266
-
267
- with gr.Column(scale=1):
268
- height = gr.Slider(
269
- label="Height",
270
- minimum=256,
271
- maximum=2048,
272
- value=1328,
273
- step=16,
274
- info="Must be multiple of 16"
275
- )
276
 
277
  with gr.Row():
278
- generate_btn = gr.Button(
279
- "✨ Generate Image",
280
- variant="primary",
281
- size="lg",
282
- scale=2
 
 
 
 
283
  )
284
- clear_btn = gr.Button(
285
- "🗑️ Clear",
286
- variant="stop",
287
- size="lg",
288
- scale=1
 
 
 
 
 
289
  )
290
 
291
- # Tips section
292
- with gr.Accordion("💡 Tips for Best Results", open=False):
293
- gr.Markdown("""
294
- - **Be descriptive**: Include details about subjects, style, lighting, and mood
295
- - **Recommended steps**: 4 steps for speed, 8 steps for higher quality
296
- - **Optimal resolution**: 1328x1328 for this model
297
- - **LoRA style**: This model is tuned for portrait/character images
298
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
 
300
- # Right column - Output
301
- with gr.Column(scale=1, min_width=400):
302
  gr.Markdown("### 🖼️ Generated Image")
303
 
304
- result_image = gr.Image(
305
- label="Result",
306
- type="filepath",
 
307
  interactive=False,
308
- height=500
 
 
 
309
  )
310
 
311
- # Download button
312
- download_btn = gr.DownloadButton(
313
- value=None,
314
- label="⬇️ Download Image",
315
- variant="secondary",
316
- interactive=False
317
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
 
319
- # Generation info
320
- generation_info = gr.Textbox(
321
- label="Generation Info",
322
- interactive=False,
323
- visible=False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
324
  )
 
 
 
 
 
 
 
 
 
 
325
 
326
- # Set up event handlers
 
 
 
 
327
  generate_btn.click(
328
- fn=generate_image,
329
- inputs=[
330
- prompt,
331
- negative_prompt,
332
- num_inference_steps,
333
- seed,
334
- width,
335
- height,
336
- cfg_scale
337
- ],
338
- outputs=[result_image, download_btn],
339
- api_visibility="public",
340
- show_progress="full"
341
  )
342
 
343
- # Clear button handler
344
  clear_btn.click(
345
- fn=clear_inputs,
346
- outputs=[
347
- prompt,
348
- negative_prompt,
349
- num_inference_steps,
350
- seed,
351
- width,
352
- height,
353
- cfg_scale
354
- ],
355
  api_visibility="private"
356
  )
357
 
358
- # Example prompts
359
- gr.Markdown("---")
360
- gr.Markdown("### 📋 Example Prompts")
361
-
362
- examples = gr.Examples(
363
- examples=[
364
- [
365
- "a young girl with flowing long hair, wearing a white halter dress and smiling sweetly. The background features a blue seaside where seagulls fly freely.",
366
- "",
367
- 4,
368
- 42,
369
- 1328,
370
- 1328,
371
- 1.0
372
- ],
373
- [
374
- "portrait of a beautiful woman with golden hour lighting, soft natural glow, elegant makeup, cinematic style, professional photography",
375
- "blurry, low quality, distorted, deformed",
376
- 4,
377
- 12345,
378
- 1328,
379
- 1328,
380
- 1.0
381
- ],
382
- [
383
- "an astronaut riding a horse on mars, dramatic red landscape, futuristic space suit, cinematic composition, detailed",
384
- "",
385
- 8,
386
- 99999,
387
- 1328,
388
- 1328,
389
- 1.0
390
- ],
391
- [
392
- "close-up portrait of a cute cat with big expressive eyes, soft fur, pastel colors, dreamy atmosphere, artistic style",
393
- "blurry, noise, artifacts",
394
- 4,
395
- 54321,
396
- 1024,
397
- 1024,
398
- 1.0
399
- ]
400
- ],
401
- inputs=[
402
- prompt,
403
- negative_prompt,
404
- num_inference_steps,
405
- seed,
406
- width,
407
- height,
408
- cfg_scale
409
- ],
410
- fn=generate_image,
411
- outputs=[result_image, download_btn],
412
- cache_examples=True,
413
- api_visibility="private"
414
- )
415
 
416
- # Gradio 6 - ALL app parameters go in launch()
417
- demo.launch(
418
- theme=gr.themes.Soft(
419
- primary_hue="indigo",
420
- secondary_hue="purple",
421
- neutral_hue="slate",
422
- font=gr.themes.GoogleFont("Inter"),
423
- text_size="lg",
424
- spacing_size="md",
425
- radius_size="md"
426
- ).set(
427
- button_primary_background_fill="*primary_600",
428
- button_primary_background_fill_hover="*primary_700",
429
- block_title_text_weight="600",
430
- body_text_weight="400"
431
- ),
432
- footer_links=[
433
- {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"},
434
- {"label": "Model Card", "url": "https://huggingface.co/Wuli-Art/Qwen-Image-2512-Turbo-LoRA"},
435
- {"label": "diffsynth-engine", "url": "https://github.com/tencent-ailab/diffsynth-engine"}
436
- ],
437
- css="""
438
- .gradio-container {
439
- max-width: 1400px !important;
440
- margin: 0 auto;
441
- }
442
- .primary-hue-indigo {
443
- --primary-hue: 250deg;
444
- }
445
- """
446
- )
 
1
  import gradio as gr
2
+ import torch
 
 
 
3
  from PIL import Image
4
+ from io import BytesIO
5
+ import math
6
 
7
+ # ZeroGPU decorator pattern
8
+ def get_zero_gpu_wrapper():
9
+ """Create ZeroGPU-compatible wrapper for the model"""
10
+ try:
11
+ from zero_gpu import ZeroGPU
12
+ return ZeroGPU
13
+ except ImportError:
14
+ return None
15
+
16
+ def create_qwen_pipeline():
17
+ """
18
+ Create and configure the Qwen Image Pipeline.
19
+ This function loads the model only when needed to save memory.
20
+ """
21
+ try:
22
+ from diffsynth_engine import fetch_model, QwenImagePipeline, QwenImagePipelineConfig
23
 
24
+ # Create pipeline
25
+ config = QwenImagePipelineConfig.basic_config(
26
+ model_path=fetch_model("Qwen/Qwen-Image-2512", path="transformer/*.safetensors"),
27
+ encoder_path=fetch_model("Qwen/Qwen-Image-2512", path="text_encoder/*.safetensors"),
28
+ vae_path=fetch_model("Qwen/Qwen-Image-2512", path="vae/*.safetensors"),
29
+ offload_mode="cpu_offload",
30
+ )
31
+ pipe = QwenImagePipeline.from_pretrained(config)
32
 
33
+ # Load turbo LoRA
34
+ pipe.load_lora(
35
+ path=fetch_model("Wuli-Art/Qwen-Image-2512-Turbo-LoRA",
36
+ path="Wuli-Qwen-Image-2512-Turbo-LoRA-4steps-V1.0-bf16.safetensors"),
37
+ scale=1.0,
38
+ fused=True,
39
+ )
40
+
41
+ # Change scheduler config
42
+ scheduler_config = {
43
+ "exponential_shift_mu": math.log(2.5),
44
+ "use_dynamic_shifting": True,
45
+ "shift_terminal": None
46
+ }
47
+ pipe.apply_scheduler_config(scheduler_config)
48
 
 
 
 
 
 
 
 
49
  return pipe
50
+ except Exception as e:
51
+ print(f"Error creating pipeline: {e}")
52
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
 
 
54
 
 
55
  def generate_image(
56
  prompt: str,
57
+ negative_prompt: str = "",
58
+ cfg_scale: float = 1.0,
59
+ num_inference_steps: int = 4,
60
+ seed: int = 42,
61
+ width: int = 1328,
62
+ height: int = 1328
63
+ ) -> Image.Image:
64
  """
65
+ Generate an image using Qwen Image Pipeline.
66
 
67
  Args:
68
+ prompt: Text description of the image to generate
69
+ negative_prompt: Things to avoid in the image
70
+ cfg_scale: Classifier-free guidance scale
71
+ num_inference_steps: Number of denoising steps
72
  seed: Random seed for reproducibility
73
+ width: Image width
74
+ height: Image height
 
75
 
76
  Returns:
77
  Generated PIL Image
78
  """
79
+ # Initialize pipeline
80
+ pipe = create_qwen_pipeline()
 
 
 
 
 
 
 
 
81
 
82
+ if pipe is None:
83
+ # Return a placeholder image if pipeline fails
84
+ error_img = Image.new('RGB', (512, 512), color='red')
85
+ return error_img
86
 
87
+ # Set random seed for reproducibility
88
+ if seed >= 0:
89
+ torch.manual_seed(seed)
90
+ if torch.cuda.is_available():
91
+ torch.cuda.manual_seed(seed)
92
 
93
+ try:
94
+ # Generate image
95
+ output = pipe(
96
+ prompt=prompt if prompt else "a beautiful landscape",
97
+ negative_prompt=negative_prompt if negative_prompt else None,
98
+ cfg_scale=cfg_scale,
99
+ num_inference_steps=num_inference_steps,
100
+ seed=seed,
101
+ width=width,
102
+ height=height
103
+ )
104
+
105
+ # Ensure output is a PIL Image
106
+ if hasattr(output, 'save'):
107
+ return output
108
+ elif isinstance(output, (list, tuple)):
109
+ return output[0]
110
+ else:
111
+ # Convert tensor or array to PIL Image
112
+ import numpy as np
113
+ if hasattr(output, 'cpu'):
114
+ output = output.cpu()
115
+ if isinstance(output, torch.Tensor):
116
+ output = output.float()
117
+ if output.dim() == 4:
118
+ output = output[0]
119
+ if output.dim() == 3:
120
+ output = output.permute(1, 2, 0)
121
+ # Handle different channel orders
122
+ if output.shape[-1] == 1 or output.shape[-1] == 3:
123
+ output = output.numpy()
124
+
125
+ if isinstance(output, np.ndarray):
126
+ if output.dtype != np.uint8:
127
+ output = (np.clip(output, 0, 1) * 255).astype(np.uint8)
128
+ if output.ndim == 3 and output.shape[-1] == 1:
129
+ output = output[:, :, 0]
130
+ if output.ndim == 3 and output.shape[-1] == 4:
131
+ output = output[:, :, :3] # Remove alpha channel
132
+ return Image.fromarray(output)
133
+
134
+ return Image.fromarray(output)
135
+
136
+ except Exception as e:
137
+ print(f"Error during generation: {e}")
138
+ # Return error image
139
+ error_img = Image.new('RGB', (512, 512), color='orange')
140
+ return error_img
141
 
 
 
 
 
142
 
143
+ def pil_to_bytes(img: Image.Image, format: str = 'PNG') -> bytes:
144
+ """Convert PIL Image to bytes"""
145
+ buffer = BytesIO()
146
+ img.save(buffer, format=format)
147
+ return buffer.getvalue()
148
 
 
 
 
 
 
 
 
 
 
149
 
150
+ # Create custom theme for AnyCoder
151
+ custom_theme = gr.themes.Soft(
152
+ primary_hue="blue",
153
+ secondary_hue="indigo",
154
+ neutral_hue="slate",
155
+ font=gr.themes.GoogleFont("Inter"),
156
+ text_size="lg",
157
+ spacing_size="md",
158
+ radius_size="md"
159
+ ).set(
160
+ button_primary_background_fill="*primary_600",
161
+ button_primary_background_fill_hover="*primary_700",
162
+ block_title_text_weight="600",
163
+ )
164
+
165
+
166
+ # Build the Gradio Interface
167
+ with gr.Blocks(
168
+ title="AnyCoder - Qwen Image Generator",
169
+ fill_height=True,
170
+ fill_width=True
171
+ ) as demo:
172
  # Header with branding
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  with gr.Row():
174
+ gr.Markdown(
175
+ """
176
+ <div style="text-align: center; padding: 10px;">
177
+ <h1 style="margin: 0; color: #4F46E5;">🎨 AnyCoder</h1>
178
+ <p style="margin: 5px 0; color: #6B7280;">Qwen Image Generator by Choquinlabs</p>
179
+ <p style="margin: 0; font-size: 12px; color: #9CA3AF;">
180
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="color: #6366F1;">Built with anycoder</a>
181
+ </p>
182
+ </div>
183
+ """
184
+ )
185
+
186
+ # Main content area
187
+ with gr.Row(equal_height=True):
188
+ # Left panel - Controls
189
  with gr.Column(scale=1, min_width=350):
190
+ gr.Markdown("### ⚙️ Generation Settings")
191
+
192
+ # Prompt input
193
+ prompt_input = gr.Textbox(
194
  label="Prompt",
195
+ placeholder="Describe your image...",
196
  lines=4,
197
+ info="Be descriptive and specific",
198
  interactive=True
199
  )
200
 
201
+ # Negative prompt
202
  negative_prompt = gr.Textbox(
203
+ label="Negative Prompt (Optional)",
204
+ placeholder="Things to avoid...",
205
  lines=2,
206
+ info="Common: low quality, blurry, distorted",
207
  interactive=True
208
  )
209
 
210
+ with gr.Row():
211
+ # Width
212
+ width_input = gr.Slider(
213
+ label="Width",
214
+ minimum=512,
215
+ maximum=2048,
216
+ value=1328,
217
+ step=64,
218
+ interactive=True
219
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
220
 
221
+ # Height
222
+ height_input = gr.Slider(
223
+ label="Height",
224
+ minimum=512,
225
+ maximum=2048,
226
+ value=1328,
227
+ step=64,
228
+ interactive=True
229
+ )
 
 
 
 
 
 
 
 
 
 
 
230
 
231
  with gr.Row():
232
+ # Steps
233
+ steps_input = gr.Slider(
234
+ label="Steps",
235
+ minimum=1,
236
+ maximum=8,
237
+ value=4,
238
+ step=1,
239
+ info="4 steps = fast, 8 steps = better quality",
240
+ interactive=True
241
  )
242
+
243
+ # CFG Scale
244
+ cfg_input = gr.Slider(
245
+ label="CFG Scale",
246
+ minimum=0.5,
247
+ maximum=2.0,
248
+ value=1.0,
249
+ step=0.1,
250
+ info="Lower = more creative, Higher = closer to prompt",
251
+ interactive=True
252
  )
253
 
254
+ with gr.Row():
255
+ # Seed
256
+ seed_input = gr.Number(
257
+ label="Seed",
258
+ value=42,
259
+ step=1,
260
+ minimum=-1,
261
+ info="-1 for random",
262
+ interactive=True
263
+ )
264
+
265
+ # Generate button
266
+ generate_btn = gr.Button(
267
+ value="✨ Generate Image",
268
+ variant="primary",
269
+ size="lg",
270
+ interactive=True
271
+ )
272
+
273
+ # Clear button
274
+ clear_btn = gr.Button(
275
+ value="🗑️ Clear",
276
+ variant="secondary",
277
+ size="md",
278
+ interactive=True
279
+ )
280
 
281
+ # Right panel - Output
282
+ with gr.Column(scale=1.5):
283
  gr.Markdown("### 🖼️ Generated Image")
284
 
285
+ # Image output component (not file-based)
286
+ image_output = gr.Image(
287
+ label="Your Image",
288
+ type="pil",
289
  interactive=False,
290
+ height=512,
291
+ elem_id="output_image",
292
+ show_download_button=True,
293
+ show_share_button=True
294
  )
295
 
296
+ # Status message
297
+ status_msg = gr.Markdown(
298
+ value="Ready to generate! Enter a prompt and click the button above.",
299
+ elem_classes=["status-message"]
 
 
300
  )
301
+
302
+ # Examples section
303
+ with gr.Accordion("📝 Example Prompts", open=False):
304
+ gr.Markdown("""
305
+ ### Try these prompts:
306
+
307
+ 1. **Portrait**: "a young girl with flowing long hair, wearing a white halter dress and smiling sweetly. The background features a blue seaside where seagulls fly freely."
308
+
309
+ 2. **Landscape**: "majestic mountain range at sunset, golden light illuminating snow-capped peaks, pine forests in the foreground, crystal clear lake reflecting the sky"
310
+
311
+ 3. **Fantasy**: "enchanted forest with glowing mushrooms, fireflies dancing around ancient trees, magical atmosphere, ethereal lighting"
312
+
313
+ 4. **Architecture**: "modern glass skyscraper at night, city lights reflecting off the surface, sleek and futuristic design"
314
+ """)
315
+
316
+ # Example buttons
317
+ with gr.Row():
318
+ example_btns = []
319
+ examples = [
320
+ ("👩 Portrait", "a young girl with flowing long hair, wearing a white halter dress and smiling sweetly. The background features a blue seaside where seagulls fly freely."),
321
+ ("🏔️ Landscape", "majestic mountain range at sunset, golden light illuminating snow-capped peaks, pine forests in the foreground, crystal clear lake reflecting the sky"),
322
+ ("🏰 Fantasy", "enchanted forest with glowing mushrooms, fireflies dancing around ancient trees, magical atmosphere, ethereal lighting"),
323
+ ("🏙️ Architecture", "modern glass skyscraper at night, city lights reflecting off the surface, sleek and futuristic design"),
324
+ ]
325
 
326
+ for label, prompt in examples:
327
+ btn = gr.Button(label, variant="secondary", size="sm")
328
+ example_btns.append((btn, prompt))
329
+
330
+ # User info and logout
331
+ with gr.Row():
332
+ gr.Markdown(
333
+ """
334
+ <div style="display: flex; justify-content: space-between; align-items: center; padding: 10px 0;">
335
+ <span style="color: #6B7280;">Logged in as: <strong>lichorosario</strong></span>
336
+ <a href="#" style="color: #EF4444; text-decoration: none;">Logout</a>
337
+ </div>
338
+ """
339
+ )
340
+
341
+ # CSS styling
342
+ demo.load(
343
+ None,
344
+ None,
345
+ None,
346
+ js="""
347
+ () => {
348
+ const style = document.createElement('style');
349
+ style.textContent = `
350
+ .gradio-container {
351
+ max-width: 1400px !important;
352
+ margin: 0 auto;
353
+ }
354
+ .status-message {
355
+ text-align: center;
356
+ padding: 10px;
357
+ background-color: #F3F4F6;
358
+ border-radius: 8px;
359
+ color: #374151;
360
+ }
361
+ #output_image {
362
+ border: 2px solid #E5E7EB;
363
+ border-radius: 12px;
364
+ }
365
+ h1 {
366
+ font-weight: 700;
367
+ }
368
+ h3 {
369
+ font-weight: 600;
370
+ color: #374151;
371
+ }
372
+ .gr-button.primary {
373
+ background: linear-gradient(135deg, #6366F1 0%, #4F46E5 100%) !important;
374
+ border: none !important;
375
+ font-weight: 600 !important;
376
+ }
377
+ .gr-button.primary:hover {
378
+ background: linear-gradient(135deg, #4F46E5 0%, #4338CA 100%) !important;
379
+ }
380
+ `;
381
+ document.head.appendChild(style);
382
+ }
383
+ """
384
+ )
385
+
386
+ # Event handlers
387
+ def generate_handler(prompt, negative_prompt, cfg_scale, steps, seed, width, height):
388
+ """Handle image generation"""
389
+ if not prompt or prompt.strip() == "":
390
+ return None, "⚠️ Please enter a prompt first!"
391
+
392
+ # Update status
393
+ yield None, "⏳ Generating your image... This may take a moment..."
394
+
395
+ try:
396
+ # Generate the image
397
+ img = generate_image(
398
+ prompt=prompt,
399
+ negative_prompt=negative_prompt if negative_prompt else None,
400
+ cfg_scale=cfg_scale,
401
+ num_inference_steps=steps,
402
+ seed=seed if seed >= 0 else None,
403
+ width=width,
404
+ height=height
405
  )
406
+
407
+ yield img, "✅ Image generated successfully!"
408
+
409
+ except Exception as e:
410
+ error_msg = f"❌ Error: {str(e)}"
411
+ yield None, error_msg
412
+
413
+ def clear_handler():
414
+ """Clear all inputs and outputs"""
415
+ return None, "Ready to generate! Enter a prompt and click the button above."
416
 
417
+ def set_prompt(prompt_text):
418
+ """Set the prompt from example button"""
419
+ return prompt_text, "Ready to generate!"
420
+
421
+ # Connect events
422
  generate_btn.click(
423
+ fn=generate_handler,
424
+ inputs=[prompt_input, negative_prompt, cfg_input, steps_input, seed_input, width_input, height_input],
425
+ outputs=[image_output, status_msg],
426
+ show_progress="full",
427
+ api_visibility="public"
 
 
 
 
 
 
 
 
428
  )
429
 
 
430
  clear_btn.click(
431
+ fn=clear_handler,
432
+ inputs=None,
433
+ outputs=[image_output, status_msg],
 
 
 
 
 
 
 
434
  api_visibility="private"
435
  )
436
 
437
+ # Example button handlers
438
+ for btn, prompt in example_btns:
439
+ btn.click(
440
+ fn=set_prompt,
441
+ inputs=gr.Textbox(value=prompt, visible=False),
442
+ outputs=[prompt_input, status_msg],
443
+ api_visibility="private"
444
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
 
446
+ # Launch the application
447
+ if __name__ == "__main__":
448
+ demo.launch(
449
+ theme=custom_theme,
450
+ inline=True,
451
+ inbrowser=False,
452
+ show_error=True,
453
+ quiet=False,
454
+ css="""
455
+ .gradio-container {
456
+ max-width: 1400px !important;
457
+ }
458
+ """,
459
+ footer_links=[
460
+ {"label": "AnyCoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"},
461
+ {"label": "Choquinlabs", "url": "https://huggingface.co/choquinlabs"}
462
+ ]
463
+ )