mage-flow-base / app.py
multimodalart's picture
multimodalart HF Staff
Upload app.py with huggingface_hub
14aedbe verified
Raw
History Blame Contribute Delete
5.64 kB
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)