Spaces:
Running on Zero
Running on Zero
Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,273 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import spaces
|
| 3 |
+
import gradio as gr
|
| 4 |
+
from diffusers import ZImagePipeline
|
| 5 |
+
|
| 6 |
+
# Load the pipeline once at startup
|
| 7 |
+
print("Loading Z-Image pipeline...")
|
| 8 |
+
pipe = ZImagePipeline.from_pretrained(
|
| 9 |
+
"Tongyi-MAI/Z-Image",
|
| 10 |
+
torch_dtype=torch.bfloat16,
|
| 11 |
+
low_cpu_mem_usage=False,
|
| 12 |
+
)
|
| 13 |
+
pipe.to("cuda")
|
| 14 |
+
|
| 15 |
+
print("Pipeline loaded!")
|
| 16 |
+
|
| 17 |
+
@spaces.GPU
|
| 18 |
+
def generate_image(prompt, negative_prompt, height, width, num_inference_steps, guidance_scale, seed, randomize_seed, progress=gr.Progress(track_tqdm=True)):
|
| 19 |
+
"""Generate an image from the given prompt."""
|
| 20 |
+
if randomize_seed:
|
| 21 |
+
seed = torch.randint(0, 2**32 - 1, (1,)).item()
|
| 22 |
+
|
| 23 |
+
generator = torch.Generator("cuda").manual_seed(int(seed))
|
| 24 |
+
image = pipe(
|
| 25 |
+
prompt=prompt,
|
| 26 |
+
negative_prompt=negative_prompt if negative_prompt.strip() else None,
|
| 27 |
+
height=int(height),
|
| 28 |
+
width=int(width),
|
| 29 |
+
num_inference_steps=int(num_inference_steps),
|
| 30 |
+
guidance_scale=float(guidance_scale),
|
| 31 |
+
cfg_normalization=False,
|
| 32 |
+
generator=generator,
|
| 33 |
+
).images[0]
|
| 34 |
+
|
| 35 |
+
return image, seed
|
| 36 |
+
|
| 37 |
+
# Example prompts
|
| 38 |
+
examples = [
|
| 39 |
+
["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."],
|
| 40 |
+
["A majestic dragon soaring through clouds at sunset, scales shimmering with iridescent colors, detailed fantasy art style"],
|
| 41 |
+
["Cozy coffee shop interior, warm lighting, rain on windows, plants on shelves, vintage aesthetic, photorealistic"],
|
| 42 |
+
["Astronaut riding a horse on Mars, cinematic lighting, sci-fi concept art, highly detailed"],
|
| 43 |
+
["Portrait of a wise old wizard with a long white beard, holding a glowing crystal staff, magical forest background"],
|
| 44 |
+
]
|
| 45 |
+
|
| 46 |
+
# Custom theme with modern aesthetics (Gradio 6)
|
| 47 |
+
custom_theme = gr.themes.Soft(
|
| 48 |
+
primary_hue="yellow",
|
| 49 |
+
secondary_hue="amber",
|
| 50 |
+
neutral_hue="slate",
|
| 51 |
+
font=gr.themes.GoogleFont("Inter"),
|
| 52 |
+
text_size="lg",
|
| 53 |
+
spacing_size="md",
|
| 54 |
+
radius_size="lg"
|
| 55 |
+
).set(
|
| 56 |
+
button_primary_background_fill="*primary_500",
|
| 57 |
+
button_primary_background_fill_hover="*primary_600",
|
| 58 |
+
block_title_text_weight="600",
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
+
# Build the Gradio interface
|
| 62 |
+
with gr.Blocks(fill_height=True) as demo:
|
| 63 |
+
# Header
|
| 64 |
+
gr.Markdown(
|
| 65 |
+
"""
|
| 66 |
+
# 🎨 Z-Image
|
| 67 |
+
**Foundation Image Generation Model** • Full CFG support with high diversity and aesthetic versatility
|
| 68 |
+
""",
|
| 69 |
+
elem_classes="header-text"
|
| 70 |
+
)
|
| 71 |
+
|
| 72 |
+
with gr.Row(equal_height=False):
|
| 73 |
+
# Left column - Input controls
|
| 74 |
+
with gr.Column(scale=1, min_width=320):
|
| 75 |
+
prompt = gr.Textbox(
|
| 76 |
+
label="✨ Your Prompt",
|
| 77 |
+
placeholder="Describe the image you want to create...",
|
| 78 |
+
lines=5,
|
| 79 |
+
max_lines=10,
|
| 80 |
+
autofocus=True,
|
| 81 |
+
)
|
| 82 |
+
|
| 83 |
+
negative_prompt = gr.Textbox(
|
| 84 |
+
label="🚫 Negative Prompt (Optional)",
|
| 85 |
+
placeholder="Describe what you want to avoid in the image...",
|
| 86 |
+
lines=2,
|
| 87 |
+
max_lines=5,
|
| 88 |
+
)
|
| 89 |
+
|
| 90 |
+
with gr.Accordion("⚙️ Advanced Settings", open=False):
|
| 91 |
+
with gr.Row():
|
| 92 |
+
height = gr.Slider(
|
| 93 |
+
minimum=512,
|
| 94 |
+
maximum=2048,
|
| 95 |
+
value=1024,
|
| 96 |
+
step=64,
|
| 97 |
+
label="Height",
|
| 98 |
+
info="Image height in pixels"
|
| 99 |
+
)
|
| 100 |
+
width = gr.Slider(
|
| 101 |
+
minimum=512,
|
| 102 |
+
maximum=2048,
|
| 103 |
+
value=1024,
|
| 104 |
+
step=64,
|
| 105 |
+
label="Width",
|
| 106 |
+
info="Image width in pixels"
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
num_inference_steps = gr.Slider(
|
| 110 |
+
minimum=20,
|
| 111 |
+
maximum=50,
|
| 112 |
+
value=28,
|
| 113 |
+
step=1,
|
| 114 |
+
label="Inference Steps",
|
| 115 |
+
info="28-50 steps recommended for best quality"
|
| 116 |
+
)
|
| 117 |
+
|
| 118 |
+
guidance_scale = gr.Slider(
|
| 119 |
+
minimum=1.0,
|
| 120 |
+
maximum=10.0,
|
| 121 |
+
value=4.0,
|
| 122 |
+
step=0.5,
|
| 123 |
+
label="Guidance Scale (CFG)",
|
| 124 |
+
info="3.0-5.0 recommended"
|
| 125 |
+
)
|
| 126 |
+
|
| 127 |
+
with gr.Row():
|
| 128 |
+
randomize_seed = gr.Checkbox(
|
| 129 |
+
label="🎲 Random Seed",
|
| 130 |
+
value=True,
|
| 131 |
+
)
|
| 132 |
+
seed = gr.Number(
|
| 133 |
+
label="Seed",
|
| 134 |
+
value=42,
|
| 135 |
+
precision=0,
|
| 136 |
+
visible=False,
|
| 137 |
+
)
|
| 138 |
+
|
| 139 |
+
def toggle_seed(randomize):
|
| 140 |
+
return gr.Number(visible=not randomize)
|
| 141 |
+
|
| 142 |
+
randomize_seed.change(
|
| 143 |
+
toggle_seed,
|
| 144 |
+
inputs=[randomize_seed],
|
| 145 |
+
outputs=[seed]
|
| 146 |
+
)
|
| 147 |
+
|
| 148 |
+
generate_btn = gr.Button(
|
| 149 |
+
"🚀 Generate Image",
|
| 150 |
+
variant="primary",
|
| 151 |
+
size="lg",
|
| 152 |
+
scale=1
|
| 153 |
+
)
|
| 154 |
+
|
| 155 |
+
# Example prompts
|
| 156 |
+
gr.Examples(
|
| 157 |
+
examples=examples,
|
| 158 |
+
inputs=[prompt],
|
| 159 |
+
label="💡 Try these prompts",
|
| 160 |
+
examples_per_page=5,
|
| 161 |
+
)
|
| 162 |
+
|
| 163 |
+
# Right column - Output
|
| 164 |
+
with gr.Column(scale=1, min_width=320):
|
| 165 |
+
output_image = gr.Image(
|
| 166 |
+
label="Generated Image",
|
| 167 |
+
type="pil",
|
| 168 |
+
show_label=False,
|
| 169 |
+
height=600,
|
| 170 |
+
buttons=["download", "share"],
|
| 171 |
+
)
|
| 172 |
+
|
| 173 |
+
used_seed = gr.Number(
|
| 174 |
+
label="🎲 Seed Used",
|
| 175 |
+
interactive=False,
|
| 176 |
+
container=True,
|
| 177 |
+
)
|
| 178 |
+
|
| 179 |
+
# Footer credits
|
| 180 |
+
gr.Markdown(
|
| 181 |
+
"""
|
| 182 |
+
---
|
| 183 |
+
<div style="text-align: center; opacity: 0.7; font-size: 0.9em; margin-top: 1rem;">
|
| 184 |
+
<strong>Model:</strong> <a href="https://huggingface.co/Tongyi-MAI/Z-Image" target="_blank">Tongyi-MAI/Z-Image</a> (Apache 2.0 License) •
|
| 185 |
+
<strong>Demo by:</strong> <a href="https://x.com/realmrfakename" target="_blank">@mrfakename</a> •
|
| 186 |
+
<strong>Redesign by:</strong> AnyCoder •
|
| 187 |
+
<strong>Optimizations:</strong> <a href="https://huggingface.co/multimodalart" target="_blank">@multimodalart</a> (FA3 + AoTI)
|
| 188 |
+
</div>
|
| 189 |
+
""",
|
| 190 |
+
elem_classes="footer-text"
|
| 191 |
+
)
|
| 192 |
+
|
| 193 |
+
# Connect the generate button
|
| 194 |
+
generate_btn.click(
|
| 195 |
+
fn=generate_image,
|
| 196 |
+
inputs=[prompt, negative_prompt, height, width, num_inference_steps, guidance_scale, seed, randomize_seed],
|
| 197 |
+
outputs=[output_image, used_seed],
|
| 198 |
+
)
|
| 199 |
+
|
| 200 |
+
# Also allow generating by pressing Enter in the prompt box
|
| 201 |
+
prompt.submit(
|
| 202 |
+
fn=generate_image,
|
| 203 |
+
inputs=[prompt, negative_prompt, height, width, num_inference_steps, guidance_scale, seed, randomize_seed],
|
| 204 |
+
outputs=[output_image, used_seed],
|
| 205 |
+
)
|
| 206 |
+
|
| 207 |
+
if __name__ == "__main__":
|
| 208 |
+
demo.launch(
|
| 209 |
+
theme=custom_theme,
|
| 210 |
+
css="""
|
| 211 |
+
.header-text h1 {
|
| 212 |
+
font-size: 2.5rem !important;
|
| 213 |
+
font-weight: 700 !important;
|
| 214 |
+
margin-bottom: 0.5rem !important;
|
| 215 |
+
background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);
|
| 216 |
+
-webkit-background-clip: text;
|
| 217 |
+
-webkit-text-fill-color: transparent;
|
| 218 |
+
background-clip: text;
|
| 219 |
+
}
|
| 220 |
+
|
| 221 |
+
.header-text p {
|
| 222 |
+
font-size: 1.1rem !important;
|
| 223 |
+
color: #64748b !important;
|
| 224 |
+
margin-top: 0 !important;
|
| 225 |
+
}
|
| 226 |
+
|
| 227 |
+
.footer-text {
|
| 228 |
+
padding: 1rem 0;
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
.footer-text a {
|
| 232 |
+
color: #f59e0b !important;
|
| 233 |
+
text-decoration: none !important;
|
| 234 |
+
font-weight: 500;
|
| 235 |
+
}
|
| 236 |
+
|
| 237 |
+
.footer-text a:hover {
|
| 238 |
+
text-decoration: underline !important;
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
/* Mobile optimizations */
|
| 242 |
+
@media (max-width: 768px) {
|
| 243 |
+
.header-text h1 {
|
| 244 |
+
font-size: 1.8rem !important;
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
.header-text p {
|
| 248 |
+
font-size: 1rem !important;
|
| 249 |
+
}
|
| 250 |
+
}
|
| 251 |
+
|
| 252 |
+
/* Smooth transitions */
|
| 253 |
+
button, .gr-button {
|
| 254 |
+
transition: all 0.2s ease !important;
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
button:hover, .gr-button:hover {
|
| 258 |
+
transform: translateY(-1px);
|
| 259 |
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important;
|
| 260 |
+
}
|
| 261 |
+
|
| 262 |
+
/* Better spacing */
|
| 263 |
+
.gradio-container {
|
| 264 |
+
max-width: 1400px !important;
|
| 265 |
+
margin: 0 auto !important;
|
| 266 |
+
}
|
| 267 |
+
""",
|
| 268 |
+
footer_links=[
|
| 269 |
+
"api",
|
| 270 |
+
"gradio"
|
| 271 |
+
],
|
| 272 |
+
mcp_server=True
|
| 273 |
+
)
|