appsnprojectsstpl-tech commited on
Commit
0cba1d4
·
1 Parent(s): f545704

Switch to Instruct-Pix2Pix

Browse files
Files changed (1) hide show
  1. app.py +75 -247
app.py CHANGED
@@ -1,299 +1,127 @@
1
  import torch
2
  import spaces
3
  import gradio as gr
4
- from diffusers import DiffusionPipeline, AutoPipelineForImage2Image
5
  from diffusers.utils import load_image
6
- import PIL.Image
7
 
8
- # Load the pipeline once at startup
9
- print("Loading Z-Image-Turbo pipeline...")
10
- pipe = DiffusionPipeline.from_pretrained(
11
- "Tongyi-MAI/Z-Image-Turbo",
12
- torch_dtype=torch.bfloat16,
13
- low_cpu_mem_usage=True,
14
- )
15
- pipe.to("cuda")
16
-
17
- try:
18
- print("Loading Image-to-Image pipeline...")
19
- pipe_i2i = AutoPipelineForImage2Image.from_pipe(pipe)
20
- except Exception as e:
21
- print(f"Warning: Could not load Img2Img pipeline: {e}")
22
- pipe_i2i = None
23
 
24
- # ======== AoTI compilation + FA3 ========
25
- # pipe.transformer.layers._repeated_blocks = ["ZImageTransformerBlock"]
26
- # spaces.aoti_blocks_load(pipe.transformer.layers, "zerogpu-aoti/Z-Image", variant="fa3")
 
 
 
27
 
28
- print("Pipeline loaded!")
29
 
30
  @spaces.GPU
31
- def generate_image(prompt, input_image, strength, height, width, num_inference_steps, seed, randomize_seed, progress=gr.Progress(track_tqdm=True)):
32
- """Generate or edit an image from the given prompt and optional input image."""
33
  if randomize_seed:
34
  seed = torch.randint(0, 2**32 - 1, (1,)).item()
35
-
36
  generator = torch.Generator("cuda").manual_seed(int(seed))
37
 
 
 
 
38
  if input_image is not None:
39
- if pipe_i2i is None:
40
- raise gr.Error("Image-to-Image is not supported by your current diffusers version for Z-Image.")
41
- # Resize input image to match target height/width
42
- input_image = input_image.resize((int(width), int(height)))
43
- image = pipe_i2i(
44
- prompt=prompt,
 
45
  image=input_image,
46
- strength=strength,
47
  num_inference_steps=int(num_inference_steps),
48
- guidance_scale=0.0,
 
49
  generator=generator,
50
  ).images[0]
51
  else:
52
- image = pipe(
53
- prompt=prompt,
54
- height=int(height),
55
- width=int(width),
56
  num_inference_steps=int(num_inference_steps),
57
- guidance_scale=0.0,
58
  generator=generator,
59
  ).images[0]
60
-
61
  return image, seed
62
 
63
- # Example prompts
64
- examples = [
65
- ["Young Chinese woman in red Hanfu, intricate embroidery. Impeccable makeup, red floral forehead pattern. Elaborate high bun, golden phoenix headdress, red flowers, beads. Holds round folding fan with lady, trees, bird. Neon lightning-bolt lamp, bright yellow glow, above extended left palm. Soft-lit outdoor night background, silhouetted tiered pagoda, blurred colorful distant lights."],
66
- ["A majestic dragon soaring through clouds at sunset, scales shimmering with iridescent colors, detailed fantasy art style"],
67
- ["Cozy coffee shop interior, warm lighting, rain on windows, plants on shelves, vintage aesthetic, photorealistic"],
68
- ["Astronaut riding a horse on Mars, cinematic lighting, sci-fi concept art, highly detailed"],
69
- ["Portrait of a wise old wizard with a long white beard, holding a glowing crystal staff, magical forest background"],
70
- ]
71
-
72
- # Custom theme with modern aesthetics (Gradio 6)
73
  custom_theme = gr.themes.Soft(
74
- primary_hue="yellow",
75
- secondary_hue="amber",
76
- neutral_hue="slate",
77
  font=gr.themes.GoogleFont("Inter"),
78
- text_size="lg",
79
- spacing_size="md",
80
- radius_size="lg"
81
- ).set(
82
- button_primary_background_fill="*primary_500",
83
- button_primary_background_fill_hover="*primary_600",
84
- block_title_text_weight="600",
85
  )
86
 
87
- # Build the Gradio interface
88
- with gr.Blocks(fill_height=True) as demo:
89
- # Header
90
  gr.Markdown(
91
  """
92
- # 🎨 Z-Image-Turbo
93
- **Ultra-fast AI image generation** Generate stunning images in just 8 steps
94
- """,
95
- elem_classes="header-text"
96
  )
97
 
98
- with gr.Row(equal_height=False):
99
- # Left column - Input controls
100
- with gr.Column(scale=1, min_width=320):
101
  prompt = gr.Textbox(
102
- label="✨ Your Prompt",
103
- placeholder="Describe the image you want to create or edit...",
104
- lines=5,
105
- max_lines=10,
106
- autofocus=True,
107
  )
108
-
109
  input_image = gr.Image(
110
- label="🖼️ Input Image (Optional, for Image-to-Image Editing)",
111
- type="pil",
112
- height=256,
113
  )
114
 
115
  with gr.Accordion("⚙️ Advanced Settings", open=False):
116
- with gr.Row():
117
- height = gr.Slider(
118
- minimum=512,
119
- maximum=2048,
120
- value=1024,
121
- step=64,
122
- label="Height",
123
- info="Image height in pixels"
124
- )
125
- width = gr.Slider(
126
- minimum=512,
127
- maximum=2048,
128
- value=1024,
129
- step=64,
130
- label="Width",
131
- info="Image width in pixels"
132
- )
133
-
134
- num_inference_steps = gr.Slider(
135
- minimum=1,
136
- maximum=20,
137
- value=9,
138
- step=1,
139
- label="Inference Steps",
140
- info="9 steps = 8 DiT forwards (recommended)"
141
- )
142
-
143
- strength = gr.Slider(
144
- minimum=0.0,
145
- maximum=1.0,
146
- value=0.5,
147
- step=0.05,
148
- label="Denoising Strength (For Image-to-Image)",
149
- info="Higher values = more changes from input image"
150
  )
151
 
152
  with gr.Row():
153
- randomize_seed = gr.Checkbox(
154
- label="🎲 Random Seed",
155
- value=True,
156
- )
157
- seed = gr.Number(
158
- label="Seed",
159
- value=42,
160
- precision=0,
161
- visible=False,
162
- )
163
-
164
- def toggle_seed(randomize):
165
- return gr.Number(visible=not randomize)
166
 
167
  randomize_seed.change(
168
- toggle_seed,
169
- inputs=[randomize_seed],
170
  outputs=[seed]
171
  )
 
 
172
 
173
- generate_btn = gr.Button(
174
- "🚀 Generate Image",
175
- variant="primary",
176
- size="lg",
177
- scale=1
178
- )
179
-
180
- # Example prompts
181
- gr.Examples(
182
- examples=examples,
183
- inputs=[prompt],
184
- label="💡 Try these prompts",
185
- examples_per_page=5,
186
- )
187
-
188
- # Right column - Output
189
- with gr.Column(scale=1, min_width=320):
190
- output_image = gr.Image(
191
- label="Generated Image",
192
- type="pil",
193
- format="png",
194
- show_label=False,
195
- height=600,
196
- buttons=["download", "share"],
197
- )
198
-
199
- used_seed = gr.Number(
200
- label="🎲 Seed Used",
201
- interactive=False,
202
- container=True,
203
- )
204
-
205
- # Footer credits
206
- gr.Markdown(
207
- """
208
- ---
209
- <div style="text-align: center; opacity: 0.7; font-size: 0.9em; margin-top: 1rem;">
210
- <strong>Model:</strong> <a href="https://huggingface.co/Tongyi-MAI/Z-Image-Turbo" target="_blank">Tongyi-MAI/Z-Image-Turbo</a> (Apache 2.0 License) •
211
- <strong>Demo by:</strong> <a href="https://x.com/realmrfakename" target="_blank">@mrfakename</a> •
212
- <strong>Redesign by:</strong> AnyCoder •
213
- <strong>Optimizations:</strong> <a href="https://huggingface.co/multimodalart" target="_blank">@multimodalart</a> (FA3 + AoTI)
214
- </div>
215
- """,
216
- elem_classes="footer-text"
217
- )
218
-
219
- # Connect the generate button
220
  generate_btn.click(
221
- fn=generate_image,
222
- inputs=[prompt, input_image, strength, height, width, num_inference_steps, seed, randomize_seed],
223
- outputs=[output_image, used_seed],
224
  )
225
-
226
- # Also allow generating by pressing Enter in the prompt box
227
  prompt.submit(
228
- fn=generate_image,
229
- inputs=[prompt, input_image, strength, height, width, num_inference_steps, seed, randomize_seed],
230
- outputs=[output_image, used_seed],
231
  )
232
 
233
  if __name__ == "__main__":
234
- demo.launch(
235
- theme=custom_theme,
236
- css="""
237
- .header-text h1 {
238
- font-size: 2.5rem !important;
239
- font-weight: 700 !important;
240
- margin-bottom: 0.5rem !important;
241
- background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);
242
- -webkit-background-clip: text;
243
- -webkit-text-fill-color: transparent;
244
- background-clip: text;
245
- }
246
-
247
- .header-text p {
248
- font-size: 1.1rem !important;
249
- color: #64748b !important;
250
- margin-top: 0 !important;
251
- }
252
-
253
- .footer-text {
254
- padding: 1rem 0;
255
- }
256
-
257
- .footer-text a {
258
- color: #f59e0b !important;
259
- text-decoration: none !important;
260
- font-weight: 500;
261
- }
262
-
263
- .footer-text a:hover {
264
- text-decoration: underline !important;
265
- }
266
-
267
- /* Mobile optimizations */
268
- @media (max-width: 768px) {
269
- .header-text h1 {
270
- font-size: 1.8rem !important;
271
- }
272
-
273
- .header-text p {
274
- font-size: 1rem !important;
275
- }
276
- }
277
-
278
- /* Smooth transitions */
279
- button, .gr-button {
280
- transition: all 0.2s ease !important;
281
- }
282
-
283
- button:hover, .gr-button:hover {
284
- transform: translateY(-1px);
285
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
286
- }
287
-
288
- /* Better spacing */
289
- .gradio-container {
290
- max-width: 1400px !important;
291
- margin: 0 auto !important;
292
- }
293
- """,
294
- footer_links=[
295
- "api",
296
- "gradio"
297
- ],
298
- mcp_server=True
299
- )
 
1
  import torch
2
  import spaces
3
  import gradio as gr
4
+ from diffusers import StableDiffusionInstructPix2PixPipeline, StableDiffusionPipeline
5
  from diffusers.utils import load_image
 
6
 
7
+ print("Loading Models...")
8
+ # 1. Text-to-Image Model (Standard Generation)
9
+ pipe_t2i = StableDiffusionPipeline.from_pretrained(
10
+ "runwayml/stable-diffusion-v1-5",
11
+ torch_dtype=torch.float16,
12
+ safety_checker=None
13
+ ).to("cuda")
 
 
 
 
 
 
 
 
14
 
15
+ # 2. Instruct-Pix2Pix Model (Instruction-Based Editing)
16
+ pipe_edit = StableDiffusionInstructPix2PixPipeline.from_pretrained(
17
+ "timbrooks/instruct-pix2pix",
18
+ torch_dtype=torch.float16,
19
+ safety_checker=None
20
+ ).to("cuda")
21
 
22
+ print("Models loaded successfully!")
23
 
24
  @spaces.GPU
25
+ def generate_or_edit(prompt, input_image, image_guidance_scale, guidance_scale, num_inference_steps, seed, randomize_seed, progress=gr.Progress(track_tqdm=True)):
 
26
  if randomize_seed:
27
  seed = torch.randint(0, 2**32 - 1, (1,)).item()
 
28
  generator = torch.Generator("cuda").manual_seed(int(seed))
29
 
30
+ if not prompt:
31
+ raise gr.Error("Please enter a prompt or instruction!")
32
+
33
  if input_image is not None:
34
+ # Edit mode
35
+ input_image = input_image.convert("RGB")
36
+ # Resize image for SD1.5 (InstructPix2Pix)
37
+ input_image = input_image.resize((512, 512))
38
+
39
+ image = pipe_edit(
40
+ prompt,
41
  image=input_image,
 
42
  num_inference_steps=int(num_inference_steps),
43
+ image_guidance_scale=image_guidance_scale,
44
+ guidance_scale=guidance_scale,
45
  generator=generator,
46
  ).images[0]
47
  else:
48
+ # Generate mode
49
+ image = pipe_t2i(
50
+ prompt,
 
51
  num_inference_steps=int(num_inference_steps),
52
+ guidance_scale=guidance_scale,
53
  generator=generator,
54
  ).images[0]
55
+
56
  return image, seed
57
 
58
+ # Build the Gradio interface
 
 
 
 
 
 
 
 
 
59
  custom_theme = gr.themes.Soft(
60
+ primary_hue="blue",
61
+ secondary_hue="indigo",
 
62
  font=gr.themes.GoogleFont("Inter"),
 
 
 
 
 
 
 
63
  )
64
 
65
+ with gr.Blocks(theme=custom_theme, fill_height=True) as demo:
 
 
66
  gr.Markdown(
67
  """
68
+ # 🎨 AI Image Studio (Generation & Instruction Editing)
69
+ Generate images from scratch, or upload an image and use a prompt like *"Make him wear sunglasses"* to edit it seamlessly.
70
+ """
 
71
  )
72
 
73
+ with gr.Row():
74
+ with gr.Column(scale=1):
 
75
  prompt = gr.Textbox(
76
+ label="✨ Instruction / Prompt",
77
+ lines=3,
78
+ placeholder="e.g. 'A futuristic city at night' (for generation) OR 'Turn the daytime into nighttime' (for editing)",
79
+ autofocus=True
 
80
  )
 
81
  input_image = gr.Image(
82
+ label="🖼️ Input Image (Optional - Leave blank to generate from scratch)",
83
+ type="pil"
 
84
  )
85
 
86
  with gr.Accordion("⚙️ Advanced Settings", open=False):
87
+ num_inference_steps = gr.Slider(minimum=10, maximum=50, value=30, step=1, label="Inference Steps")
88
+ guidance_scale = gr.Slider(minimum=1.0, maximum=15.0, value=7.5, step=0.5, label="Text Guidance Scale")
89
+ image_guidance_scale = gr.Slider(
90
+ minimum=1.0,
91
+ maximum=3.0,
92
+ value=1.5,
93
+ step=0.1,
94
+ label="Image Guidance Scale (Editing Only)",
95
+ info="Lower values = more changes. Higher values = stays closer to original image."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  )
97
 
98
  with gr.Row():
99
+ randomize_seed = gr.Checkbox(label="🎲 Random Seed", value=True)
100
+ seed = gr.Number(label="Seed", value=42, precision=0, visible=False)
 
 
 
 
 
 
 
 
 
 
 
101
 
102
  randomize_seed.change(
103
+ lambda r: gr.Number(visible=not r),
104
+ inputs=[randomize_seed],
105
  outputs=[seed]
106
  )
107
+
108
+ generate_btn = gr.Button("🚀 Generate / Edit Image", variant="primary", size="lg")
109
 
110
+ with gr.Column(scale=1):
111
+ output_image = gr.Image(label="Result", type="pil", interactive=False)
112
+ used_seed = gr.Number(label="Seed Used", interactive=False)
113
+
114
+ # Connections
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  generate_btn.click(
116
+ fn=generate_or_edit,
117
+ inputs=[prompt, input_image, image_guidance_scale, guidance_scale, num_inference_steps, seed, randomize_seed],
118
+ outputs=[output_image, used_seed]
119
  )
 
 
120
  prompt.submit(
121
+ fn=generate_or_edit,
122
+ inputs=[prompt, input_image, image_guidance_scale, guidance_scale, num_inference_steps, seed, randomize_seed],
123
+ outputs=[output_image, used_seed]
124
  )
125
 
126
  if __name__ == "__main__":
127
+ demo.launch()