retronic commited on
Commit
aa90eb6
Β·
verified Β·
1 Parent(s): 6172c76

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +88 -55
app.py CHANGED
@@ -1,17 +1,16 @@
1
- import os
2
  import gc
3
  import random
4
  import threading
5
  import traceback
6
 
7
  import gradio as gr
8
- import torch
9
  import spaces
 
10
 
11
  from diffusers import QwenImage21Pipeline
12
 
13
  # ============================================================
14
- # CONFIGURATION
15
  # ============================================================
16
 
17
  BASE_MODEL = "Qwen/Qwen-Image-2.1"
@@ -25,7 +24,7 @@ pipe = None
25
  generation_lock = threading.Lock()
26
 
27
  # ============================================================
28
- # MODEL LOADING
29
  # ============================================================
30
 
31
  def load_pipeline():
@@ -34,7 +33,7 @@ def load_pipeline():
34
  if pipe is not None:
35
  return pipe
36
 
37
- print("Loading Qwen Image 2.1...", flush=True)
38
 
39
  pipeline = QwenImage21Pipeline.from_pretrained(
40
  BASE_MODEL,
@@ -42,7 +41,7 @@ def load_pipeline():
42
  low_cpu_mem_usage=True,
43
  )
44
 
45
- print("Loading Pixelship LoRA...", flush=True)
46
 
47
  pipeline.load_lora_weights(
48
  LORA_REPO,
@@ -58,18 +57,19 @@ def load_pipeline():
58
 
59
  pipe = pipeline
60
 
61
- print("Pixelship 2 ready!", flush=True)
62
 
63
  return pipe
64
 
65
 
66
  # ============================================================
67
- # GENERATION
68
  # ============================================================
69
 
70
  @spaces.GPU(duration=120)
71
  def generate(
72
  prompt,
 
73
  negative_prompt,
74
  width,
75
  height,
@@ -80,13 +80,13 @@ def generate(
80
  random_seed,
81
  progress=gr.Progress(),
82
  ):
83
- if not prompt or not prompt.strip():
84
- raise gr.Error("Please enter a prompt.")
85
 
86
  with generation_lock:
87
 
88
  try:
89
- progress(0, desc="Loading Pixelship 2")
90
 
91
  pipeline = load_pipeline()
92
 
@@ -106,74 +106,84 @@ def generate(
106
 
107
  kwargs = {
108
  "prompt": prompt,
109
- "width": int(width),
110
- "height": int(height),
111
  "num_inference_steps": int(steps),
112
  "true_cfg_scale": float(true_cfg),
113
  "generator": generator,
114
  }
115
 
 
 
 
 
 
 
116
  if float(true_cfg) > 1.0:
117
- kwargs["negative_prompt"] = negative_prompt or ""
 
 
118
 
119
- progress(0.1, desc="Generating image")
120
 
121
  with torch.no_grad():
122
  result = pipeline(**kwargs)
123
 
124
  image = result.images[0]
125
 
126
- progress(1, desc="Generation complete")
 
 
 
 
 
 
127
 
128
  return (
129
  image,
130
- f"Seed: {seed} | Steps: {steps} | "
131
- f"True CFG: {true_cfg} | "
132
- f"LoRA Strength: {lora_strength}"
 
133
  )
134
 
135
  except torch.cuda.OutOfMemoryError:
 
136
  gc.collect()
137
 
138
  if torch.cuda.is_available():
139
  torch.cuda.empty_cache()
140
 
141
  raise gr.Error(
142
- "GPU ran out of memory. "
143
- "Try reducing the resolution."
144
  )
145
 
146
  except Exception as e:
 
147
  traceback.print_exc()
 
148
  raise gr.Error(
149
- f"Generation failed: {e}"
150
  )
151
 
152
 
153
  # ============================================================
154
- # INTERFACE
155
  # ============================================================
156
 
157
  CSS = """
158
  .gradio-container {
159
- max-width: 1500px !important;
160
  margin: auto !important;
161
  }
162
 
163
  #prompt-box textarea {
164
- min-height: 260px !important;
165
  font-family: monospace !important;
166
- font-size: 14px !important;
167
  }
168
 
169
  #generate-button {
170
  font-size: 18px !important;
171
  font-weight: 700 !important;
172
  }
173
-
174
- #output-image {
175
- min-height: 550px;
176
- }
177
  """
178
 
179
  with gr.Blocks(
@@ -186,32 +196,49 @@ with gr.Blocks(
186
  """
187
  # 🎨 Pixelship 2
188
 
189
- ### Powered by Qwen Image 2.1
 
 
190
 
191
- Generate images using the Pixelship 2 LoRA.
192
 
193
- **LoRA loaded directly from Hugging Face β€’ ZeroGPU**
 
 
 
 
194
  """
195
  )
196
 
197
  with gr.Row():
198
 
 
 
 
 
199
  with gr.Column(scale=5):
200
 
201
  prompt = gr.Textbox(
202
  label="Prompt",
203
- placeholder="Describe your image in as much detail as you want...",
204
  lines=12,
205
  max_lines=40,
206
  max_length=None,
207
  elem_id="prompt-box",
 
 
 
 
 
 
 
 
208
  )
209
 
210
  negative_prompt = gr.Textbox(
211
  label="Negative Prompt",
212
- placeholder="Optional negative prompt...",
213
  lines=3,
214
  max_length=None,
 
215
  )
216
 
217
  with gr.Accordion(
@@ -222,16 +249,16 @@ Generate images using the Pixelship 2 LoRA.
222
  with gr.Row():
223
 
224
  width = gr.Slider(
225
- minimum=256,
226
- maximum=2048,
227
  value=1024,
228
  step=64,
229
  label="Width",
230
  )
231
 
232
  height = gr.Slider(
233
- minimum=256,
234
- maximum=2048,
235
  value=1024,
236
  step=64,
237
  label="Height",
@@ -240,24 +267,24 @@ Generate images using the Pixelship 2 LoRA.
240
  with gr.Row():
241
 
242
  steps = gr.Slider(
243
- minimum=1,
244
- maximum=100,
245
  value=30,
246
  step=1,
247
- label="Inference Steps",
248
  )
249
 
250
  true_cfg = gr.Slider(
251
- minimum=1.0,
252
- maximum=10.0,
253
  value=1.0,
254
  step=0.1,
255
- label="True CFG Scale",
256
  )
257
 
258
  lora_strength = gr.Slider(
259
- minimum=0.0,
260
- maximum=2.0,
261
  value=0.75,
262
  step=0.05,
263
  label="LoRA Strength",
@@ -277,25 +304,27 @@ Generate images using the Pixelship 2 LoRA.
277
  )
278
 
279
  generate_button = gr.Button(
280
- "Generate Image",
281
  variant="primary",
282
  size="lg",
283
  elem_id="generate-button",
284
  )
285
 
 
 
 
 
286
  with gr.Column(scale=5):
287
 
288
  output_image = gr.Image(
289
- label="Generated Image",
290
  type="pil",
291
  format="png",
292
- interactive=False,
293
- height=650,
294
- elem_id="output-image",
295
  )
296
 
297
  status = gr.Textbox(
298
- label="Generation Status",
299
  interactive=False,
300
  )
301
 
@@ -303,6 +332,7 @@ Generate images using the Pixelship 2 LoRA.
303
  fn=generate,
304
  inputs=[
305
  prompt,
 
306
  negative_prompt,
307
  width,
308
  height,
@@ -319,9 +349,8 @@ Generate images using the Pixelship 2 LoRA.
319
  concurrency_limit=1,
320
  )
321
 
322
-
323
  # ============================================================
324
- # QUEUE / LAUNCH
325
  # ============================================================
326
 
327
  demo.queue(
@@ -329,6 +358,10 @@ demo.queue(
329
  default_concurrency_limit=1,
330
  )
331
 
 
 
 
 
332
  if __name__ == "__main__":
333
  demo.launch(
334
  server_name="0.0.0.0",
 
 
1
  import gc
2
  import random
3
  import threading
4
  import traceback
5
 
6
  import gradio as gr
 
7
  import spaces
8
+ import torch
9
 
10
  from diffusers import QwenImage21Pipeline
11
 
12
  # ============================================================
13
+ # CONFIG
14
  # ============================================================
15
 
16
  BASE_MODEL = "Qwen/Qwen-Image-2.1"
 
24
  generation_lock = threading.Lock()
25
 
26
  # ============================================================
27
+ # LOAD PIPELINE
28
  # ============================================================
29
 
30
  def load_pipeline():
 
33
  if pipe is not None:
34
  return pipe
35
 
36
+ print("Loading Qwen-Image-2.1...", flush=True)
37
 
38
  pipeline = QwenImage21Pipeline.from_pretrained(
39
  BASE_MODEL,
 
41
  low_cpu_mem_usage=True,
42
  )
43
 
44
+ print("Loading Pixelship 2.0 LoRA...", flush=True)
45
 
46
  pipeline.load_lora_weights(
47
  LORA_REPO,
 
57
 
58
  pipe = pipeline
59
 
60
+ print("Pipeline ready.", flush=True)
61
 
62
  return pipe
63
 
64
 
65
  # ============================================================
66
+ # GENERATE / EDIT
67
  # ============================================================
68
 
69
  @spaces.GPU(duration=120)
70
  def generate(
71
  prompt,
72
+ input_image,
73
  negative_prompt,
74
  width,
75
  height,
 
80
  random_seed,
81
  progress=gr.Progress(),
82
  ):
83
+ if not prompt.strip():
84
+ raise gr.Error("Prompt is required.")
85
 
86
  with generation_lock:
87
 
88
  try:
89
+ progress(0.0, desc="Loading model")
90
 
91
  pipeline = load_pipeline()
92
 
 
106
 
107
  kwargs = {
108
  "prompt": prompt,
 
 
109
  "num_inference_steps": int(steps),
110
  "true_cfg_scale": float(true_cfg),
111
  "generator": generator,
112
  }
113
 
114
+ if input_image is not None:
115
+ kwargs["image"] = input_image
116
+ else:
117
+ kwargs["width"] = int(width)
118
+ kwargs["height"] = int(height)
119
+
120
  if float(true_cfg) > 1.0:
121
+ kwargs["negative_prompt"] = (
122
+ negative_prompt or ""
123
+ )
124
 
125
+ progress(0.15, desc="Generating")
126
 
127
  with torch.no_grad():
128
  result = pipeline(**kwargs)
129
 
130
  image = result.images[0]
131
 
132
+ mode = (
133
+ "Image Editing"
134
+ if input_image is not None
135
+ else "Text Generation"
136
+ )
137
+
138
+ progress(1.0, desc="Complete")
139
 
140
  return (
141
  image,
142
+ f"{mode} | Seed={seed} | "
143
+ f"Steps={steps} | "
144
+ f"CFG={true_cfg} | "
145
+ f"LoRA={lora_strength}"
146
  )
147
 
148
  except torch.cuda.OutOfMemoryError:
149
+
150
  gc.collect()
151
 
152
  if torch.cuda.is_available():
153
  torch.cuda.empty_cache()
154
 
155
  raise gr.Error(
156
+ "Out of VRAM. Try a smaller image."
 
157
  )
158
 
159
  except Exception as e:
160
+
161
  traceback.print_exc()
162
+
163
  raise gr.Error(
164
+ f"Generation failed:\n{e}"
165
  )
166
 
167
 
168
  # ============================================================
169
+ # UI
170
  # ============================================================
171
 
172
  CSS = """
173
  .gradio-container {
174
+ max-width: 1600px !important;
175
  margin: auto !important;
176
  }
177
 
178
  #prompt-box textarea {
179
+ min-height: 240px !important;
180
  font-family: monospace !important;
 
181
  }
182
 
183
  #generate-button {
184
  font-size: 18px !important;
185
  font-weight: 700 !important;
186
  }
 
 
 
 
187
  """
188
 
189
  with gr.Blocks(
 
196
  """
197
  # 🎨 Pixelship 2
198
 
199
+ ### Qwen Image 2.1 + Pixelship 2.0
200
+
201
+ Supports:
202
 
203
+ βœ… Text β†’ Image
204
 
205
+ βœ… Image β†’ Image Editing
206
+
207
+ βœ… Adjustable LoRA Strength
208
+
209
+ βœ… ZeroGPU Compatible
210
  """
211
  )
212
 
213
  with gr.Row():
214
 
215
+ # ========================================================
216
+ # LEFT
217
+ # ========================================================
218
+
219
  with gr.Column(scale=5):
220
 
221
  prompt = gr.Textbox(
222
  label="Prompt",
 
223
  lines=12,
224
  max_lines=40,
225
  max_length=None,
226
  elem_id="prompt-box",
227
+ placeholder=(
228
+ "Describe what you want..."
229
+ ),
230
+ )
231
+
232
+ input_image = gr.Image(
233
+ label="Image To Edit (Optional)",
234
+ type="pil",
235
  )
236
 
237
  negative_prompt = gr.Textbox(
238
  label="Negative Prompt",
 
239
  lines=3,
240
  max_length=None,
241
+ placeholder="Optional",
242
  )
243
 
244
  with gr.Accordion(
 
249
  with gr.Row():
250
 
251
  width = gr.Slider(
252
+ 256,
253
+ 2048,
254
  value=1024,
255
  step=64,
256
  label="Width",
257
  )
258
 
259
  height = gr.Slider(
260
+ 256,
261
+ 2048,
262
  value=1024,
263
  step=64,
264
  label="Height",
 
267
  with gr.Row():
268
 
269
  steps = gr.Slider(
270
+ 1,
271
+ 100,
272
  value=30,
273
  step=1,
274
+ label="Steps",
275
  )
276
 
277
  true_cfg = gr.Slider(
278
+ 1.0,
279
+ 10.0,
280
  value=1.0,
281
  step=0.1,
282
+ label="True CFG",
283
  )
284
 
285
  lora_strength = gr.Slider(
286
+ 0.0,
287
+ 2.0,
288
  value=0.75,
289
  step=0.05,
290
  label="LoRA Strength",
 
304
  )
305
 
306
  generate_button = gr.Button(
307
+ "Generate",
308
  variant="primary",
309
  size="lg",
310
  elem_id="generate-button",
311
  )
312
 
313
+ # ========================================================
314
+ # RIGHT
315
+ # ========================================================
316
+
317
  with gr.Column(scale=5):
318
 
319
  output_image = gr.Image(
320
+ label="Output",
321
  type="pil",
322
  format="png",
323
+ height=700,
 
 
324
  )
325
 
326
  status = gr.Textbox(
327
+ label="Status",
328
  interactive=False,
329
  )
330
 
 
332
  fn=generate,
333
  inputs=[
334
  prompt,
335
+ input_image,
336
  negative_prompt,
337
  width,
338
  height,
 
349
  concurrency_limit=1,
350
  )
351
 
 
352
  # ============================================================
353
+ # QUEUE
354
  # ============================================================
355
 
356
  demo.queue(
 
358
  default_concurrency_limit=1,
359
  )
360
 
361
+ # ============================================================
362
+ # LAUNCH
363
+ # ============================================================
364
+
365
  if __name__ == "__main__":
366
  demo.launch(
367
  server_name="0.0.0.0",