akhaliq HF Staff commited on
Commit
df326d3
·
verified ·
1 Parent(s): c4bf22d

Update app.py from anycoder

Browse files
Files changed (1) hide show
  1. app.py +67 -11
app.py CHANGED
@@ -4,19 +4,45 @@ A Gradio 6 application for image-to-image editing using the GLM-Image model.
4
 
5
  This app allows users to upload an image and provide a prompt to transform
6
  the image using the GLM-Image diffusion model.
 
7
  """
8
 
9
  import gradio as gr
10
  import torch
11
  from diffusers.pipelines.glm_image import GlmImagePipeline
12
  from PIL import Image
 
 
13
 
14
- # Initialize the model at startup
15
- pipe = GlmImagePipeline.from_pretrained(
16
- "zai-org/GLM-Image",
17
- torch_dtype=torch.bfloat16,
18
- device_map="cuda"
19
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
  def validate_dimensions(height: int, width: int) -> tuple:
22
  """
@@ -31,6 +57,7 @@ def get_image_dimensions(image: Image.Image) -> tuple:
31
  """Get the dimensions of an uploaded PIL image."""
32
  return image.size[1], image.size[0] # height, width
33
 
 
34
  def process_image(
35
  image: Image.Image,
36
  prompt: str,
@@ -43,6 +70,7 @@ def process_image(
43
  ) -> tuple:
44
  """
45
  Process the image through the GLM-Image pipeline.
 
46
 
47
  Args:
48
  image: Input PIL Image
@@ -69,13 +97,16 @@ def process_image(
69
  if adjusted_height != height or adjusted_width != width:
70
  height, width = adjusted_height, adjusted_width
71
 
72
- progress(0.1, desc="Processing image...")
 
 
 
73
  input_image = image.convert("RGB")
74
 
75
  generator = torch.Generator(device="cuda").manual_seed(seed)
76
 
77
- progress(0.3, desc="Generating image...")
78
- result = pipe(
79
  prompt=prompt,
80
  image=[input_image],
81
  height=height,
@@ -110,6 +141,10 @@ def generate_random_seed() -> int:
110
  import random
111
  return random.randint(0, 2**32 - 1)
112
 
 
 
 
 
113
  custom_theme = gr.themes.Soft(
114
  primary_hue="indigo",
115
  secondary_hue="blue",
@@ -215,6 +250,11 @@ with gr.Blocks(fill_height=True) as demo:
215
  size="sm",
216
  variant="secondary"
217
  )
 
 
 
 
 
218
 
219
  with gr.Row():
220
  generate_btn = gr.Button(
@@ -243,7 +283,7 @@ with gr.Blocks(fill_height=True) as demo:
243
 
244
  status = gr.Textbox(
245
  label="Status",
246
- value="Ready to generate!",
247
  interactive=False,
248
  show_label=True
249
  )
@@ -299,6 +339,13 @@ with gr.Blocks(fill_height=True) as demo:
299
  api_visibility="private"
300
  )
301
 
 
 
 
 
 
 
 
302
  generate_btn.click(
303
  fn=process_image,
304
  inputs=[
@@ -331,7 +378,7 @@ with gr.Blocks(fill_height=True) as demo:
331
  input_image: None,
332
  prompt: "",
333
  output_image: None,
334
- status: "Ready to generate!",
335
  download_btn: gr.DownloadButton(interactive=False)
336
  }
337
 
@@ -369,6 +416,14 @@ demo.launch(
369
  color: #ffd700 !important;
370
  text-decoration: underline;
371
  }
 
 
 
 
 
 
 
 
372
  #input-image, #output-image {
373
  border: 2px dashed var(--neutral-300);
374
  border-radius: var(--radius-lg);
@@ -380,6 +435,7 @@ demo.launch(
380
  footer_links=[
381
  {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"},
382
  {"label": "GLM-Image Model", "url": "https://huggingface.co/zai-org/GLM-Image"},
 
383
  {"label": "Diffusers Library", "url": "https://github.com/huggingface/diffusers"}
384
  ],
385
  server_name="0.0.0.0",
 
4
 
5
  This app allows users to upload an image and provide a prompt to transform
6
  the image using the GLM-Image diffusion model.
7
+ Features ZeroGPU support for dynamic GPU allocation on Hugging Face Spaces.
8
  """
9
 
10
  import gradio as gr
11
  import torch
12
  from diffusers.pipelines.glm_image import GlmImagePipeline
13
  from PIL import Image
14
+ from gradio import spaces
15
+ import time
16
 
17
+ # Global pipeline variable
18
+ pipe = None
19
+
20
+ def load_model():
21
+ """Load the GLM-Image model with bfloat16 precision."""
22
+ global pipe
23
+ if pipe is None:
24
+ pipe = GlmImagePipeline.from_pretrained(
25
+ "zai-org/GLM-Image",
26
+ torch_dtype=torch.bfloat16,
27
+ device_map="auto"
28
+ )
29
+ return pipe
30
+
31
+ def estimate_duration(num_inference_steps: int) -> str:
32
+ """
33
+ Estimate the processing duration based on inference steps.
34
+ Returns a human-readable time estimate.
35
+ """
36
+ base_time = 30 # Base processing time in seconds
37
+ step_factor = 0.8 # Seconds per inference step
38
+ estimated_seconds = base_time + (num_inference_steps * step_factor)
39
+
40
+ if estimated_seconds < 60:
41
+ return f"~{int(estimated_seconds)}s"
42
+ else:
43
+ minutes = estimated_seconds // 60
44
+ seconds = estimated_seconds % 60
45
+ return f"~{int(minutes)}m {int(seconds)}s"
46
 
47
  def validate_dimensions(height: int, width: int) -> tuple:
48
  """
 
57
  """Get the dimensions of an uploaded PIL image."""
58
  return image.size[1], image.size[0] # height, width
59
 
60
+ @spaces.GPU(environment="HF_SPACE", memory=8, timeout=1200, queue=True)
61
  def process_image(
62
  image: Image.Image,
63
  prompt: str,
 
70
  ) -> tuple:
71
  """
72
  Process the image through the GLM-Image pipeline.
73
+ Uses ZeroGPU for dynamic GPU allocation.
74
 
75
  Args:
76
  image: Input PIL Image
 
97
  if adjusted_height != height or adjusted_width != width:
98
  height, width = adjusted_height, adjusted_width
99
 
100
+ progress(0.1, desc="Loading model...")
101
+ pipeline = load_model()
102
+
103
+ progress(0.2, desc="Preparing image...")
104
  input_image = image.convert("RGB")
105
 
106
  generator = torch.Generator(device="cuda").manual_seed(seed)
107
 
108
+ progress(0.4, desc="Generating image...", visible=True)
109
+ result = pipeline(
110
  prompt=prompt,
111
  image=[input_image],
112
  height=height,
 
141
  import random
142
  return random.randint(0, 2**32 - 1)
143
 
144
+ def update_time_estimate(num_steps: int) -> str:
145
+ """Update the estimated processing time display."""
146
+ return f"Estimated time: {estimate_duration(num_steps)}"
147
+
148
  custom_theme = gr.themes.Soft(
149
  primary_hue="indigo",
150
  secondary_hue="blue",
 
250
  size="sm",
251
  variant="secondary"
252
  )
253
+
254
+ time_estimate = gr.Markdown(
255
+ value=f"**Estimated time:** {estimate_duration(50)}",
256
+ elem_classes=["time-estimate"]
257
+ )
258
 
259
  with gr.Row():
260
  generate_btn = gr.Button(
 
283
 
284
  status = gr.Textbox(
285
  label="Status",
286
+ value="Ready to generate! GPU will be allocated automatically.",
287
  interactive=False,
288
  show_label=True
289
  )
 
339
  api_visibility="private"
340
  )
341
 
342
+ num_inference_steps.change(
343
+ fn=update_time_estimate,
344
+ inputs=num_inference_steps,
345
+ outputs=time_estimate,
346
+ api_visibility="private"
347
+ )
348
+
349
  generate_btn.click(
350
  fn=process_image,
351
  inputs=[
 
378
  input_image: None,
379
  prompt: "",
380
  output_image: None,
381
+ status: "Ready to generate! GPU will be allocated automatically.",
382
  download_btn: gr.DownloadButton(interactive=False)
383
  }
384
 
 
416
  color: #ffd700 !important;
417
  text-decoration: underline;
418
  }
419
+ .time-estimate {
420
+ font-size: 0.9em;
421
+ color: var(--neutral-600);
422
+ padding: 0.5rem;
423
+ background: var(--neutral-100);
424
+ border-radius: var(--radius-sm);
425
+ margin-top: 0.5rem;
426
+ }
427
  #input-image, #output-image {
428
  border: 2px dashed var(--neutral-300);
429
  border-radius: var(--radius-lg);
 
435
  footer_links=[
436
  {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"},
437
  {"label": "GLM-Image Model", "url": "https://huggingface.co/zai-org/GLM-Image"},
438
+ {"label": "ZeroGPU", "url": "https://huggingface.co/docs/spaces/spaces-sdks/gradio-zerogpu"},
439
  {"label": "Diffusers Library", "url": "https://github.com/huggingface/diffusers"}
440
  ],
441
  server_name="0.0.0.0",