Add quality model option to unified Space demo

#1
by Xinjie-Q - opened
Files changed (2) hide show
  1. README.md +5 -5
  2. app.py +59 -14
README.md CHANGED
@@ -17,19 +17,19 @@ Efficient Native-Resolution Foundation Model for Image Generation and Editing.
17
 
18
  This Space demonstrates [Mage-Flow](https://huggingface.co/papers/2607.19064) from Microsoft, a 4B-scale image generation and editing foundation model through a single unified interface:
19
 
20
- - **No image** → the prompt generates a new image (routes to [Mage-Flow-Turbo](https://huggingface.co/microsoft/Mage-Flow-Turbo)).
21
- - **With an uploaded image** → the prompt is treated as an edit instruction (routes to [Mage-Flow-Edit-Turbo](https://huggingface.co/microsoft/Mage-Flow-Edit-Turbo)).
22
 
23
- The demo uses the Turbo variants for fast, few-step inference (4 steps, CFG 1.0).
24
 
25
  ## Usage
26
 
27
  1. Enter a prompt.
28
  2. *(Optional)* Upload an image to edit — the prompt becomes an edit instruction.
29
- 3. Click **Run**.
30
 
31
  ## References
32
 
33
  - Paper: [Mage-Flow: An Efficient Native-Resolution Foundation Model for Image Generation and Editing](https://huggingface.co/papers/2607.19064)
34
  - GitHub: [microsoft/Mage](https://github.com/microsoft/Mage)
35
- - Models: [microsoft/Mage-Flow-Turbo](https://huggingface.co/microsoft/Mage-Flow-Turbo), [microsoft/Mage-Flow-Edit-Turbo](https://huggingface.co/microsoft/Mage-Flow-Edit-Turbo)
 
17
 
18
  This Space demonstrates [Mage-Flow](https://huggingface.co/papers/2607.19064) from Microsoft, a 4B-scale image generation and editing foundation model through a single unified interface:
19
 
20
+ - **No image** → text-to-image generation.
21
+ - **With an uploaded image** → instruction-based image editing.
22
 
23
+ Choose **Mage-Flow-Turbo · Fast** (4 steps, CFG 1.0) or **Mage-Flow · Quality**. The quality variant uses 20 steps / CFG 5.0 for generation and 30 steps / CFG 5.0 for editing; uploading or removing an image updates these defaults automatically.
24
 
25
  ## Usage
26
 
27
  1. Enter a prompt.
28
  2. *(Optional)* Upload an image to edit — the prompt becomes an edit instruction.
29
+ 3. Choose Fast or Quality, then click **Run**.
30
 
31
  ## References
32
 
33
  - Paper: [Mage-Flow: An Efficient Native-Resolution Foundation Model for Image Generation and Editing](https://huggingface.co/papers/2607.19064)
34
  - GitHub: [microsoft/Mage](https://github.com/microsoft/Mage)
35
+ - Models: [Mage-Flow](https://huggingface.co/microsoft/Mage-Flow), [Mage-Flow-Turbo](https://huggingface.co/microsoft/Mage-Flow-Turbo), [Mage-Flow-Edit](https://huggingface.co/microsoft/Mage-Flow-Edit), [Mage-Flow-Edit-Turbo](https://huggingface.co/microsoft/Mage-Flow-Edit-Turbo)
app.py CHANGED
@@ -1,10 +1,11 @@
1
  """Mage-Flow: Efficient Native-Resolution Foundation Model for Image Generation and Editing.
2
 
3
- Gradio Space demo with a single unified interface: enter a prompt and optionally
4
- upload an image. If an image is provided, the request is routed to the
5
- Mage-Flow-Edit-Turbo model; otherwise it is routed to the Mage-Flow-Turbo model.
6
  """
 
7
  import os
 
8
 
9
  # Use flash_attention_2 for the HF text encoder (flash_attn is installed via wheel)
10
  os.environ.setdefault("VF_HF_ATTN_IMPL", "flash_attention_2")
@@ -19,11 +20,43 @@ from PIL import Image, ImageDraw, ImageFont
19
  from mage_flow.pipeline import MageFlowPipeline
20
  from mage_flow.models.modules.mage_text import CATEGORY_DISPLAY
21
 
22
- T2I_MODEL = "microsoft/Mage-Flow-Turbo"
23
- EDIT_MODEL = "microsoft/Mage-Flow-Edit-Turbo"
24
-
25
- pipe_t2i = MageFlowPipeline.from_pretrained(T2I_MODEL, device="cuda")
26
- pipe_edit = MageFlowPipeline.from_pretrained(EDIT_MODEL, device="cuda")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
 
29
  def _block_reason_text(verdict) -> str:
@@ -67,7 +100,7 @@ def _blocked_image(reason_text: str, height: int = 1024, width: int = 1024) -> I
67
  return img
68
 
69
 
70
- @spaces.GPU(duration=60)
71
  def generate(
72
  prompt: str,
73
  image=None,
@@ -78,13 +111,13 @@ def generate(
78
  width: int = 1024,
79
  max_size: int = 1024,
80
  seed: int = 42,
 
81
  progress=gr.Progress(track_tqdm=True),
82
  ):
83
  """Generate or edit an image with Mage-Flow.
84
 
85
- If ``image`` is provided, the reference image is edited with
86
- Mage-Flow-Edit-Turbo. Otherwise a new image is generated from the text
87
- prompt with Mage-Flow-Turbo.
88
 
89
  Args:
90
  prompt: Text description (generation) or edit instruction (editing).
@@ -102,6 +135,7 @@ def generate(
102
 
103
  if image is not None:
104
  # Route to the edit model when an image is provided.
 
105
  if isinstance(image, str):
106
  image = Image.open(image)
107
  refs = [image.convert("RGB")]
@@ -129,6 +163,7 @@ def generate(
129
  # No image: route to the text-to-image model.
130
  # Content-safety gate: surface a block to the user instead of failing
131
  # silently (gr.Warning toast + a stamped output image).
 
132
  verdict = pipe_t2i.model.txt_enc.screen_text(prompt)
133
  if verdict.violates:
134
  reason_text = _block_reason_text(verdict)
@@ -160,7 +195,9 @@ with gr.Blocks(css=CSS) as demo:
160
  "# Mage-Flow\n"
161
  "Efficient Native-Resolution Foundation Model for Image Generation and Editing. "
162
  "Enter a prompt to generate an image, or upload an image to edit it.\n\n"
163
- "Models: [Mage-Flow-Turbo](https://huggingface.co/microsoft/Mage-Flow-Turbo) & "
 
 
164
  "[Mage-Flow-Edit-Turbo](https://huggingface.co/microsoft/Mage-Flow-Edit-Turbo) | "
165
  "[Paper](https://huggingface.co/papers/2607.19064) | "
166
  "[GitHub](https://github.com/microsoft/Mage)"
@@ -179,6 +216,11 @@ with gr.Blocks(css=CSS) as demo:
179
  )
180
  run_btn = gr.Button("Run", variant="primary", scale=1)
181
 
 
 
 
 
 
182
  with gr.Accordion("Input image (optional — enables editing)", open=True):
183
  image = gr.Image(
184
  type="pil",
@@ -232,7 +274,10 @@ with gr.Blocks(css=CSS) as demo:
232
  cache_mode="lazy",
233
  )
234
 
235
- inputs = [prompt, image, negative_prompt, steps, cfg, height, width, max_size, seed]
 
 
 
236
  run_btn.click(lambda: None, None, result).then(
237
  generate, inputs, result, api_name="generate",
238
  )
 
1
  """Mage-Flow: Efficient Native-Resolution Foundation Model for Image Generation and Editing.
2
 
3
+ Gradio Space demo with a single unified interface: image presence selects
4
+ editing vs. generation, while the model control selects fast vs. quality.
 
5
  """
6
+ import gc
7
  import os
8
+ import threading
9
 
10
  # Use flash_attention_2 for the HF text encoder (flash_attn is installed via wheel)
11
  os.environ.setdefault("VF_HF_ATTN_IMPL", "flash_attention_2")
 
20
  from mage_flow.pipeline import MageFlowPipeline
21
  from mage_flow.models.modules.mage_text import CATEGORY_DISPLAY
22
 
23
+ MODEL_VARIANTS = {
24
+ "turbo": {
25
+ "t2i": "microsoft/Mage-Flow-Turbo", "edit": "microsoft/Mage-Flow-Edit-Turbo",
26
+ "t2i_steps": 4, "edit_steps": 4, "cfg": 1.0,
27
+ },
28
+ "quality": {
29
+ "t2i": "microsoft/Mage-Flow", "edit": "microsoft/Mage-Flow-Edit",
30
+ "t2i_steps": 20, "edit_steps": 30, "cfg": 5.0,
31
+ },
32
+ }
33
+
34
+ _pipe_slots = {
35
+ "t2i": {"variant": "turbo", "pipe": MageFlowPipeline.from_pretrained(MODEL_VARIANTS["turbo"]["t2i"], device="cuda")},
36
+ "edit": {"variant": "turbo", "pipe": MageFlowPipeline.from_pretrained(MODEL_VARIANTS["turbo"]["edit"], device="cuda")},
37
+ }
38
+ _pipe_lock = threading.Lock()
39
+
40
+
41
+ def _get_pipe(task: str, variant: str):
42
+ """Keep one loaded variant per task, matching the original two-pipeline footprint."""
43
+ with _pipe_lock:
44
+ slot = _pipe_slots.get(task)
45
+ if slot and slot["variant"] == variant:
46
+ return slot["pipe"]
47
+ if slot:
48
+ del _pipe_slots[task]
49
+ del slot
50
+ gc.collect()
51
+ torch.cuda.empty_cache()
52
+ pipe = MageFlowPipeline.from_pretrained(MODEL_VARIANTS[variant][task], device="cuda")
53
+ _pipe_slots[task] = {"variant": variant, "pipe": pipe}
54
+ return pipe
55
+
56
+
57
+ def _recommended(variant: str, image):
58
+ spec = MODEL_VARIANTS[variant]
59
+ return (spec["edit_steps"] if image is not None else spec["t2i_steps"], spec["cfg"])
60
 
61
 
62
  def _block_reason_text(verdict) -> str:
 
100
  return img
101
 
102
 
103
+ @spaces.GPU(duration=120)
104
  def generate(
105
  prompt: str,
106
  image=None,
 
111
  width: int = 1024,
112
  max_size: int = 1024,
113
  seed: int = 42,
114
+ model_variant: str = "turbo",
115
  progress=gr.Progress(track_tqdm=True),
116
  ):
117
  """Generate or edit an image with Mage-Flow.
118
 
119
+ If ``image`` is provided, route to the selected edit model; otherwise route
120
+ to the selected text-to-image model.
 
121
 
122
  Args:
123
  prompt: Text description (generation) or edit instruction (editing).
 
135
 
136
  if image is not None:
137
  # Route to the edit model when an image is provided.
138
+ pipe_edit = _get_pipe("edit", model_variant)
139
  if isinstance(image, str):
140
  image = Image.open(image)
141
  refs = [image.convert("RGB")]
 
163
  # No image: route to the text-to-image model.
164
  # Content-safety gate: surface a block to the user instead of failing
165
  # silently (gr.Warning toast + a stamped output image).
166
+ pipe_t2i = _get_pipe("t2i", model_variant)
167
  verdict = pipe_t2i.model.txt_enc.screen_text(prompt)
168
  if verdict.violates:
169
  reason_text = _block_reason_text(verdict)
 
195
  "# Mage-Flow\n"
196
  "Efficient Native-Resolution Foundation Model for Image Generation and Editing. "
197
  "Enter a prompt to generate an image, or upload an image to edit it.\n\n"
198
+ "Models: [Mage-Flow](https://huggingface.co/microsoft/Mage-Flow), "
199
+ "[Mage-Flow-Turbo](https://huggingface.co/microsoft/Mage-Flow-Turbo), "
200
+ "[Mage-Flow-Edit](https://huggingface.co/microsoft/Mage-Flow-Edit), "
201
  "[Mage-Flow-Edit-Turbo](https://huggingface.co/microsoft/Mage-Flow-Edit-Turbo) | "
202
  "[Paper](https://huggingface.co/papers/2607.19064) | "
203
  "[GitHub](https://github.com/microsoft/Mage)"
 
216
  )
217
  run_btn = gr.Button("Run", variant="primary", scale=1)
218
 
219
+ model_variant = gr.Radio(
220
+ [("Mage-Flow-Turbo · Fast", "turbo"), ("Mage-Flow · Quality", "quality")],
221
+ value="turbo", label="Model",
222
+ )
223
+
224
  with gr.Accordion("Input image (optional — enables editing)", open=True):
225
  image = gr.Image(
226
  type="pil",
 
274
  cache_mode="lazy",
275
  )
276
 
277
+ model_variant.change(_recommended, [model_variant, image], [steps, cfg], api_name=False)
278
+ image.change(_recommended, [model_variant, image], [steps, cfg], api_name=False)
279
+
280
+ inputs = [prompt, image, negative_prompt, steps, cfg, height, width, max_size, seed, model_variant]
281
  run_btn.click(lambda: None, None, result).then(
282
  generate, inputs, result, api_name="generate",
283
  )