Spaces:
Running on Zero
Running on Zero
File size: 5,639 Bytes
d58fd10 ca5f734 d58fd10 14aedbe d58fd10 14aedbe d58fd10 14aedbe d58fd10 14aedbe | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | import os
os.environ.setdefault("VF_HF_ATTN_IMPL", "sdpa")
import spaces
import torch
import gradio as gr
import random
from mage_flow import MageFlowPipeline
from mage_flow.models.modules._attn_backend import set_attn_backend
MODEL_ID = "microsoft/Mage-Flow-Base"
pipe = MageFlowPipeline.from_pretrained(MODEL_ID, device="cuda")
# Override the attention backend to SDPA after model load — the model's
# __init__ resets it to "flash2" (the default attn_type), but flash_attn
# is not available on ZeroGPU. SDPA is torch-native and works everywhere.
set_attn_backend("sdpa")
def _estimate_duration(prompt, negative_prompt, height, width, steps, cfg, seed, *args, **kwargs):
"""Estimate GPU time needed based on steps and resolution.
Measured: ~15s for 30 steps at 1024x1024 with SDPA backend + content screening.
"""
pixels = height * width
base = 20 # content screening + text encoding overhead
step_time = 0.5 if pixels <= 1024 * 1024 else 1.0
return min(300, base + int(steps * step_time))
@spaces.GPU(duration=_estimate_duration)
def generate(
prompt: str,
negative_prompt: str = "",
height: int = 1024,
width: int = 1024,
steps: int = 30,
cfg: float = 5.0,
seed: int = 42,
randomize_seed: bool = False,
):
"""Generate an image from a text prompt using Mage-Flow-Base.
Args:
prompt: Text description of the image to generate.
negative_prompt: What to avoid in the generated image.
height: Output image height (512-2048, multiple of 16).
width: Output image width (512-2048, multiple of 16).
steps: Number of denoising steps (more = higher quality, slower).
cfg: Classifier-free guidance scale (higher = more prompt adherence).
seed: Random seed for reproducibility.
randomize_seed: If True, use a random seed each time.
"""
if randomize_seed:
seed = random.randint(0, 2**32 - 1)
seed = int(seed)
height = max(512, min(2048, int(height) // 16 * 16))
width = max(512, min(2048, int(width) // 16 * 16))
neg = negative_prompt.strip() if negative_prompt else " "
result = pipe.generate(
[prompt],
neg_prompts=[neg],
seeds=[seed],
steps=int(steps),
cfg=float(cfg),
heights=[height],
widths=[width],
)
return result[0], seed
CSS = """
#col-container { max-width: 1100px; margin: 0 auto; }
.dark .gradio-container { color: var(--body-text-color); }
"""
with gr.Blocks() as demo:
gr.Markdown("# 🎨 Mage-Flow-Base Text-to-Image")
gr.Markdown(
"Generate images with [microsoft/Mage-Flow-Base](https://huggingface.co/microsoft/Mage-Flow-Base), "
"a 4.1B parameter native-resolution MMDiT model. Supports any resolution from 512 to 2048."
)
with gr.Column(elem_id="col-container"):
with gr.Row():
prompt = gr.Textbox(
label="Prompt",
placeholder="Describe the image you want to generate...",
show_label=False,
container=False,
scale=4,
)
run_btn = gr.Button("Generate", variant="primary", scale=1)
output = gr.Image(label="Generated Image", show_label=False, height=512)
with gr.Accordion("Advanced settings", open=False):
negative_prompt = gr.Textbox(
label="Negative prompt",
placeholder="What to avoid...",
value="",
)
with gr.Row():
height = gr.Slider(
label="Height", minimum=512, maximum=2048, step=16, value=1024
)
width = gr.Slider(
label="Width", minimum=512, maximum=2048, step=16, value=1024
)
with gr.Row():
steps = gr.Slider(
label="Steps", minimum=1, maximum=100, step=1, value=30
)
cfg = gr.Slider(
label="CFG scale", minimum=1.0, maximum=20.0, step=0.1, value=5.0
)
with gr.Row():
seed = gr.Number(label="Seed", value=42, precision=0)
randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
gr.Examples(
examples=[
["A close-up portrait of an elderly African man with deep wrinkles, wearing a traditional hat, soft natural lighting, ultra realistic."],
["An immersive close-up of a steaming bowl of Sichuan mapo tofu over jasmine rice served on a hand-thrown ceramic plate, finished with a wedge of citrus. Surface oils catch a tiny specular highlight. Shot with a Hasselblad H6D-100c, ambient window light, the kind of image that makes the viewer hungry."],
["the Salar de Uyuni mirror surface captured at high noon, with intimate stillness permeating the air. dew beads on every blade of grass. National Geographic editorial, cinematic depth, fine-grained natural texture."],
["A serene Japanese garden with a red wooden bridge over a koi pond, cherry blossoms floating on still water, morning mist, photorealistic."],
],
inputs=[prompt],
outputs=[output, seed],
fn=generate,
cache_examples=True,
cache_mode="lazy",
)
run_btn.click(
fn=generate,
inputs=[prompt, negative_prompt, height, width, steps, cfg, seed, randomize_seed],
outputs=[output, seed],
api_name="generate",
)
demo.launch(mcp_server=True, theme=gr.themes.Citrus(), css=CSS) |