prithivMLmods commited on
Commit
767a6fa
·
verified ·
1 Parent(s): c3dd14a

update app

Browse files
Files changed (1) hide show
  1. app.py +257 -278
app.py CHANGED
@@ -1,325 +1,304 @@
1
- import spaces
2
  import gradio as gr
3
- import torch
4
- from PIL import Image
5
- from diffusers import DiffusionPipeline
6
- import random
7
- import uuid
8
  import numpy as np
9
- import time
 
 
 
10
  import os
 
 
 
 
 
 
 
11
 
12
- # --- Constants & Configuration ---
13
- MAX_SEED = np.iinfo(np.int32).max
14
 
15
- # Specific Adapter Configuration
16
- ADAPTER_SPECS = {
17
- "Qwen-Image-2512-Turbo-LoRA": {
18
- "repo": "Wuli-art/Qwen-Image-2512-Turbo-LoRA",
19
- "weights": "Wuli-Qwen-Image-2512-Turbo-LoRA-4steps-V1.0-bf16.safetensors",
20
- "adapter_name": "turbo-fast"
21
- },
22
- }
23
 
24
- # Track loaded adapters to prevent re-loading
25
- LOADED_ADAPTERS = set()
 
26
 
27
- dtype = torch.bfloat16
28
- device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
- # --- Model Loading ---
31
- print(f"Loading Qwen-Image pipeline on {device}...")
32
- pipe_qwen = DiffusionPipeline.from_pretrained("Qwen/Qwen-Image-2512", torch_dtype=dtype).to(device)
33
 
34
- # Aspect ratios
35
- aspect_ratios = {
36
- "1:1": (1328, 1328),
37
- "16:9": (1664, 928),
38
- "9:16": (928, 1664),
39
- "4:3": (1472, 1140),
40
- "3:4": (1140, 1472)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
- def save_image(img):
44
- unique_name = str(uuid.uuid4()) + ".png"
45
- img.save(unique_name)
46
- return unique_name
 
47
 
48
- # --- Generation Logic ---
49
- @spaces.GPU
50
- def generate_qwen(
51
- prompt: str,
52
- negative_prompt: str = "",
53
- seed: int = 0,
54
- width: int = 1024,
55
- height: int = 1024,
56
- guidance_scale: float = 4.0,
57
- randomize_seed: bool = False,
58
- num_inference_steps: int = 8, # Default changed to 8
59
- num_images: int = 1,
60
- adapter_choice: str = None,
61
- lora_scale: float = 1.0,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  progress=gr.Progress(track_tqdm=True),
63
  ):
 
 
 
 
 
 
64
  if randomize_seed:
65
  seed = random.randint(0, MAX_SEED)
66
- generator = torch.Generator(device).manual_seed(seed)
67
-
68
- start_time = time.time()
69
 
70
- # --- Adapter Logic ---
71
- # 1. Disable existing adapters first
72
- pipe_qwen.disable_lora()
73
-
74
- # 2. Check if a specific adapter is requested
75
- if adapter_choice in ADAPTER_SPECS:
76
- spec = ADAPTER_SPECS[adapter_choice]
77
- adapter_name = spec["adapter_name"]
78
-
79
- # 3. Load if not already loaded
80
- if adapter_name not in LOADED_ADAPTERS:
81
- print(f"--- Downloading and Loading Adapter: {adapter_choice} ---")
82
- try:
83
- pipe_qwen.load_lora_weights(
84
- spec["repo"],
85
- weight_name=spec["weights"],
86
- adapter_name=adapter_name
87
- )
88
- LOADED_ADAPTERS.add(adapter_name)
89
- except Exception as e:
90
- raise gr.Error(f"Failed to load adapter {adapter_choice}: {e}")
91
-
92
- # 4. Activate the adapter
93
- pipe_qwen.set_adapters([adapter_name], adapter_weights=[lora_scale])
94
- print(f"Active Adapter: {adapter_name} with scale {lora_scale}")
95
-
96
- # --- Inference ---
97
- images = pipe_qwen(
98
- prompt=prompt,
99
- negative_prompt=negative_prompt if negative_prompt else "",
100
- height=height,
101
- width=width,
102
- guidance_scale=guidance_scale,
103
- num_inference_steps=num_inference_steps,
104
- num_images_per_prompt=num_images,
105
- generator=generator,
106
- output_type="pil",
107
- ).images
108
-
109
- end_time = time.time()
110
- duration = end_time - start_time
111
 
112
- image_paths = [save_image(img) for img in images]
113
 
114
- # Clean up (Optional: disable lora after run to ensure clean state next time)
115
- pipe_qwen.disable_lora()
116
-
117
- return image_paths, seed, f"{duration:.2f}"
118
 
119
- # Wrapper function to handle UI logic
120
- @spaces.GPU
121
- def generate(
122
- prompt: str,
123
- negative_prompt: str,
124
- use_negative_prompt: bool,
125
- seed: int,
126
- width: int,
127
- height: int,
128
- guidance_scale: float,
129
- randomize_seed: bool,
130
- num_inference_steps: int,
131
- num_images: int,
132
- adapter_choice: str,
133
- lora_scale: float,
134
- progress=gr.Progress(track_tqdm=True),
135
- ):
136
- final_negative_prompt = negative_prompt if use_negative_prompt else ""
137
- return generate_qwen(
138
  prompt=prompt,
139
- negative_prompt=final_negative_prompt,
140
- seed=seed,
141
  width=width,
142
  height=height,
143
- guidance_scale=guidance_scale,
144
- randomize_seed=randomize_seed,
145
  num_inference_steps=num_inference_steps,
146
- num_images=num_images,
147
- adapter_choice=adapter_choice,
148
- lora_scale=lora_scale,
149
- progress=progress,
150
- )
 
 
 
 
 
151
 
152
- # Examples
153
  examples = [
154
- "A decadent slice of layered chocolate cake on a ceramic plate with a drizzle of chocolate syrup and powdered sugar dusted on top. photographed from a slightly low angle with high resolution, natural soft lighting, rich contrast, shallow depth of field, and professional color grading to highlight the dessert’s textures --ar 85:128 --v 6.0 --style raw",
155
- "A beautifully decorated round chocolate birthday cake with rich chocolate frosting and elegant piping, topped with the name 'Qwen' written in white icing. placed on a wooden cake stand with scattered chocolate shavings around, softly lit with natural light, high resolution, professional food photography, clean background, no branding --ar 85:128 --v 6.0 --style raw",
156
- "Realistic still life photography style: A single, fresh apple, resting on a clean, soft-textured surface. The apple is slightly off-center, softly backlit to highlight its natural gloss and subtle color gradients—deep crimson red blending into light golden hues. Fine details such as small blemishes, dew drops, and a few light highlights enhance its lifelike appearance. A shallow depth of field gently blurs the neutral background, drawing full attention to the apple. Hyper-detailed 8K resolution, studio lighting, photorealistic render, emphasizing texture and form.",
157
- "A young girl wearing school uniform stands in a classroom, writing on a chalkboard. The text Introducing Qwen-Image, a foundational image generation model that excels in complex text rendering and precise image editing appears in neat white chalk at the center of the blackboard. Soft natural light filters through windows, casting gentle shadows. The scene is rendered in a realistic photography style with fine details, shallow depth of field, and warm tones. The girl's focused expression and chalk dust in the air add dynamism. Background elements include desks and educational posters, subtly blurred to emphasize the central action. Ultra-detailed 32K resolution, DSLR-quality, soft bokeh effect, documentary-style composition"
 
 
 
 
 
158
  ]
159
 
160
- css = '''
161
- .gradio-container {
162
- max-width: 800px !important;
163
- margin: 0 auto !important;
164
  }
165
- #main-title h1 { font-size: 2.3em !important; }
166
- '''
167
 
168
  with gr.Blocks() as demo:
169
- gr.Markdown("# **Qwen-Image-Diffusion-Turbo**", elem_id="main-title")
170
-
171
- with gr.Row():
172
- with gr.Column(scale=1):
173
- prompt = gr.Text(
174
- label="Prompt",
175
- show_label=False,
176
- max_lines=3,
177
- placeholder="Enter your prompt..",
178
- container=False,
179
- )
180
- run_button = gr.Button("Generate", variant="primary", scale=0)
181
-
182
- with gr.Group():
183
- with gr.Row():
184
- aspect_ratio = gr.Dropdown(
185
- label="Aspect Ratio",
186
- choices=list(aspect_ratios.keys()),
187
- value="1:1",
188
- )
189
- adapter_choice = gr.Dropdown(
190
- label="LoRA Adapter",
191
- choices=["None"] + list(ADAPTER_SPECS.keys()),
192
- value="Qwen-Image-2512-Turbo-LoRA",
193
- )
194
-
195
- with gr.Accordion("Advanced Settings", open=False):
196
- use_negative_prompt = gr.Checkbox(
197
- label="Use negative prompt",
198
- value=True,
199
- visible=True
200
- )
201
- negative_prompt = gr.Text(
202
- label="Negative prompt",
203
- max_lines=1,
204
- placeholder="Enter a negative prompt",
205
- value="text, watermark, copyright, blurry, low resolution",
206
- visible=True,
207
- )
208
- seed = gr.Slider(
209
- label="Seed",
210
- minimum=0,
211
- maximum=MAX_SEED,
212
- step=1,
213
- value=0,
214
  )
215
- randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
216
-
217
- with gr.Row():
218
- width = gr.Slider(
219
- label="Width",
220
- minimum=512,
221
- maximum=2048,
222
- step=64,
223
- value=1024,
224
- )
225
- height = gr.Slider(
226
- label="Height",
227
- minimum=512,
228
- maximum=2048,
229
- step=64,
230
- value=1024,
231
- )
232
 
233
- with gr.Row():
234
- guidance_scale = gr.Slider(
235
- label="Guidance Scale",
236
- minimum=0.0,
237
- maximum=20.0,
238
- step=0.1,
239
- value=3.5,
240
- )
241
- num_inference_steps = gr.Slider(
242
- label="Steps",
243
- minimum=1,
244
- maximum=50,
245
- step=1,
246
- value=8,
247
- )
248
-
249
- with gr.Row():
250
- num_images = gr.Slider(
251
- label="Batch Size",
252
- minimum=1,
253
- maximum=4,
254
- step=1,
255
- value=1,
256
- )
257
- lora_scale = gr.Slider(
258
- label="LoRA Scale",
259
  minimum=0,
260
- maximum=2,
261
- step=0.01,
262
- value=1.0,
263
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
264
 
265
- with gr.Column(scale=2):
266
- result = gr.Gallery(label="Result", columns=1, show_label=False, preview=True, height=600)
267
- with gr.Row():
268
- seed_display = gr.Textbox(label="Seed used", interactive=False)
269
- generation_time = gr.Textbox(label="Time (s)", interactive=False)
270
-
271
- # Update aspect ratio
272
- def set_dimensions(ar):
273
- w, h = aspect_ratios[ar]
274
- return gr.update(value=w), gr.update(value=h)
275
-
276
- aspect_ratio.change(
277
- fn=set_dimensions,
278
- inputs=aspect_ratio,
279
- outputs=[width, height]
280
- )
281
-
282
- # Negative prompt visibility
283
- use_negative_prompt.change(
284
- fn=lambda x: gr.update(visible=x),
285
- inputs=use_negative_prompt,
286
- outputs=negative_prompt
287
- )
288
 
289
- # Run button and prompt submit
290
  gr.on(
291
- triggers=[prompt.submit, run_button.click],
292
- fn=generate,
293
  inputs=[
294
  prompt,
295
- negative_prompt,
296
- use_negative_prompt,
297
  seed,
298
- width,
299
- height,
300
- guidance_scale,
301
  randomize_seed,
 
 
302
  num_inference_steps,
303
- num_images,
304
- adapter_choice,
305
- lora_scale,
306
  ],
307
- outputs=[result, seed_display, generation_time],
308
- api_name="run",
309
- )
310
-
311
- # Examples
312
- gr.Examples(
313
- examples=examples,
314
- inputs=prompt,
315
- outputs=[result, seed_display, generation_time],
316
- fn=generate,
317
- cache_examples=False,
318
  )
319
 
320
  if __name__ == "__main__":
321
- demo.queue(max_size=30).launch(css=css, theme=gr.themes.Soft(
322
- primary_hue="blue",
323
- secondary_hue="indigo",
324
- neutral_hue="slate",
325
- ), mcp_server=True, ssr_mode=False, show_error=True)
 
 
1
  import gradio as gr
 
 
 
 
 
2
  import numpy as np
3
+ import random
4
+ import torch
5
+ import spaces
6
+ import math
7
  import os
8
+ from PIL import Image
9
+ from diffusers import QwenImagePipeline, FlowMatchEulerDiscreteScheduler
10
+ from qwenimage.qwen_fa3_processor import QwenDoubleStreamAttnProcessorFA3
11
+ from optimization import optimize_pipeline_
12
+ from gradio.themes import Soft
13
+ from gradio.themes.utils import colors, fonts, sizes
14
+ from typing import Iterable
15
 
16
+ from huggingface_hub import login
 
17
 
18
+ # Optional: Login if you have set the HF token in environment variables
19
+ if os.environ.get('hf'):
20
+ login(token=os.environ.get('hf'))
 
 
 
 
 
21
 
22
+ # -----------------------------------------------------------------------------
23
+ # Theme Configuration
24
+ # -----------------------------------------------------------------------------
25
 
26
+ colors.orange_red = colors.Color(
27
+ name="orange_red",
28
+ c50="#FFF0E5",
29
+ c100="#FFE0CC",
30
+ c200="#FFC299",
31
+ c300="#FFA366",
32
+ c400="#FF8533",
33
+ c500="#FF4500",
34
+ c600="#E63E00",
35
+ c700="#CC3700",
36
+ c800="#B33000",
37
+ c900="#992900",
38
+ c950="#802200",
39
+ )
40
+
41
+ class OrangeRedTheme(Soft):
42
+ def __init__(
43
+ self,
44
+ *,
45
+ primary_hue: colors.Color | str = colors.gray,
46
+ secondary_hue: colors.Color | str = colors.orange_red,
47
+ neutral_hue: colors.Color | str = colors.slate,
48
+ text_size: sizes.Size | str = sizes.text_lg,
49
+ font: fonts.Font | str | Iterable[fonts.Font | str] = (
50
+ fonts.GoogleFont("Outfit"), "Arial", "sans-serif",
51
+ ),
52
+ font_mono: fonts.Font | str | Iterable[fonts.Font | str] = (
53
+ fonts.GoogleFont("IBM Plex Mono"), "ui-monospace", "monospace",
54
+ ),
55
+ ):
56
+ super().__init__(
57
+ primary_hue=primary_hue,
58
+ secondary_hue=secondary_hue,
59
+ neutral_hue=neutral_hue,
60
+ text_size=text_size,
61
+ font=font,
62
+ font_mono=font_mono,
63
+ )
64
+ super().set(
65
+ background_fill_primary="*primary_50",
66
+ background_fill_primary_dark="*primary_900",
67
+ body_background_fill="linear-gradient(135deg, *primary_200, *primary_100)",
68
+ body_background_fill_dark="linear-gradient(135deg, *primary_900, *primary_800)",
69
+ button_primary_text_color="white",
70
+ button_primary_text_color_hover="white",
71
+ button_primary_background_fill="linear-gradient(90deg, *secondary_500, *secondary_600)",
72
+ button_primary_background_fill_hover="linear-gradient(90deg, *secondary_600, *secondary_700)",
73
+ button_primary_background_fill_dark="linear-gradient(90deg, *secondary_600, *secondary_700)",
74
+ button_primary_background_fill_hover_dark="linear-gradient(90deg, *secondary_500, *secondary_600)",
75
+ button_secondary_text_color="black",
76
+ button_secondary_text_color_hover="white",
77
+ button_secondary_background_fill="linear-gradient(90deg, *primary_300, *primary_300)",
78
+ button_secondary_background_fill_hover="linear-gradient(90deg, *primary_400, *primary_400)",
79
+ button_secondary_background_fill_dark="linear-gradient(90deg, *primary_500, *primary_600)",
80
+ button_secondary_background_fill_hover_dark="linear-gradient(90deg, *primary_500, *primary_500)",
81
+ slider_color="*secondary_500",
82
+ slider_color_dark="*secondary_600",
83
+ block_title_text_weight="600",
84
+ block_border_width="3px",
85
+ block_shadow="*shadow_drop_lg",
86
+ button_primary_shadow="*shadow_drop_lg",
87
+ button_large_padding="11px",
88
+ color_accent_soft="*primary_100",
89
+ block_label_background_fill="*primary_200",
90
+ )
91
 
92
+ orange_red_theme = OrangeRedTheme()
 
 
93
 
94
+ # -----------------------------------------------------------------------------
95
+ # Model & Scheduler Setup
96
+ # -----------------------------------------------------------------------------
97
+
98
+ dtype = torch.bfloat16
99
+ device = "cuda" if torch.cuda.is_available() else "cpu"
100
+
101
+ scheduler_config = {
102
+ "base_image_seq_len": 256,
103
+ "base_shift": math.log(3), # We use shift=3 in distillation
104
+ "invert_sigmas": False,
105
+ "max_image_seq_len": 8192,
106
+ "max_shift": math.log(3), # We use shift=3 in distillation
107
+ "num_train_timesteps": 1000,
108
+ "shift": 1.0,
109
+ "shift_terminal": None,
110
+ "stochastic_sampling": False,
111
+ "time_shift_type": "exponential",
112
+ "use_beta_sigmas": False,
113
+ "use_dynamic_shifting": True,
114
+ "use_exponential_sigmas": False,
115
+ "use_karras_sigmas": False,
116
  }
117
+ scheduler = FlowMatchEulerDiscreteScheduler.from_config(scheduler_config)
118
+
119
+ # Load the model pipeline
120
+ pipe = QwenImagePipeline.from_pretrained(
121
+ "Qwen/Qwen-Image-2512",
122
+ torch_dtype=dtype
123
+ ).to(device)
124
+
125
+ # Load Lightning LoRA
126
+ pipe.load_lora_weights(
127
+ "Wuli-art/Qwen-Image-2512-Turbo-LoRA",
128
+ weight_name="Wuli-Qwen-Image-2512-Turbo-LoRA-4steps-V1.0-bf16.safetensors"
129
+ )
130
+ pipe.fuse_lora()
131
+
132
+ # Enable Flash Attention 3 if available
133
+ try:
134
+ pipe.transformer.set_attn_processor(QwenDoubleStreamAttnProcessorFA3())
135
+ except Exception as e:
136
+ print(f"Warning: Could not set FA3 processor: {e}")
137
 
138
+ # --- Ahead-of-time compilation ---
139
+ try:
140
+ optimize_pipeline_(pipe, prompt="prompt")
141
+ except Exception as e:
142
+ print(f"Warning: Optimization failed: {e}")
143
 
144
+ # -----------------------------------------------------------------------------
145
+ # Inference Logic
146
+ # -----------------------------------------------------------------------------
147
+
148
+ MAX_SEED = np.iinfo(np.int32).max
149
+
150
+ def get_image_size(aspect_ratio):
151
+ """Converts aspect ratio string to width, height tuple."""
152
+ if aspect_ratio == "1:1":
153
+ return 1328, 1328
154
+ elif aspect_ratio == "16:9":
155
+ return 1664, 928
156
+ elif aspect_ratio == "9:16":
157
+ return 928, 1664
158
+ elif aspect_ratio == "4:3":
159
+ return 1472, 1104
160
+ elif aspect_ratio == "3:4":
161
+ return 1104, 1472
162
+ elif aspect_ratio == "3:2":
163
+ return 1584, 1056
164
+ elif aspect_ratio == "2:3":
165
+ return 1056, 1584
166
+ else:
167
+ return 1328, 1328
168
+
169
+ @spaces.GPU(duration=120)
170
+ def infer(
171
+ prompt,
172
+ seed=42,
173
+ randomize_seed=False,
174
+ aspect_ratio="16:9",
175
+ guidance_scale=1.0,
176
+ num_inference_steps=4,
177
  progress=gr.Progress(track_tqdm=True),
178
  ):
179
+ """
180
+ Generates an image using the local Qwen-Image diffusers pipeline.
181
+ """
182
+ # Hardcode the negative prompt
183
+ negative_prompt = "低分辨率,低画质,肢体畸形,手指畸形,画面过饱和,蜡像感,人脸无细节,过度光滑,画面具有AI感。构图混乱。文字模糊,扭曲。"
184
+
185
  if randomize_seed:
186
  seed = random.randint(0, MAX_SEED)
 
 
 
187
 
188
+ # Convert aspect ratio to width and height
189
+ width, height = get_image_size(aspect_ratio)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
+ generator = torch.Generator(device=device).manual_seed(seed)
192
 
193
+ print(f"Generating with Prompt: '{prompt}'")
194
+ print(f"Size: {width}x{height}, Steps: {num_inference_steps}, Guidance: {guidance_scale}")
 
 
195
 
196
+ # Generate the image
197
+ image = pipe(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  prompt=prompt,
199
+ negative_prompt=negative_prompt,
 
200
  width=width,
201
  height=height,
 
 
202
  num_inference_steps=num_inference_steps,
203
+ generator=generator,
204
+ true_cfg_scale=guidance_scale,
205
+ guidance_scale=1.0 # Use a fixed default for distilled guidance
206
+ ).images[0]
207
+
208
+ return image, seed
209
+
210
+ # -----------------------------------------------------------------------------
211
+ # UI Layout
212
+ # -----------------------------------------------------------------------------
213
 
 
214
  examples = [
215
+ '一位身着淡雅水粉色交领襦裙的年轻女子背对镜头而坐,俯身专注地手持毛笔在素白宣纸上书写"通義千問"四个遒劲汉字。古色古香的室内陈设典雅考究,案头错落摆放着青瓷茶盏与鎏金香炉,一缕熏香轻盈升腾;柔和光线洒落肩头,勾勒出她衣裙的柔美质感与专注神情,仿佛凝固了一段宁静温润的旧时光。',
216
+ "Realistic still life photography style: A single, fresh apple resting on a clean, soft-textured surface. The apple is slightly off-center, softly backlit to highlight its natural gloss and subtle color gradients—deep crimson red blending into light golden hues. Fine details such as small blemishes, dew drops, and a few light highlights enhance its lifelike appearance. A shallow depth of field gently blurs the neutral background, drawing full attention to the apple. Hyper-detailed 8K resolution, studio lighting, photorealistic render, emphasizing texture and form.",
217
+ "一位东亚女性,约20-30岁,身材娇小,皮肤白皙如瓷,呈现冷白皮质感,水润光滑,面部轮廓柔和,眼神清澈灵动,眼妆自然清透,睫毛纤长卷翘,唇色为浅粉色,微微上扬的嘴角带着俏皮可爱的笑意。她拥有一头深黑色长发,发丝蓬松柔顺,自然垂落肩头,碎发轻拂脸颊,增添灵动感,发尾���卷,随性散落。身着浅色高质感休闲连衣裙,材质似丝绸或雪纺,搭配一顶贝雷帽,帽檐微微压低,凸显偶像气质。手腕佩戴多条精致手链,金属与珍珠元素交织,正自然展示于镜头前。背景为少女心爆棚的饰品店,店内装修精致,陈列琳琅满目,暖光灯与柔和自然光交织,角落一棵圣诞树点缀着彩灯与装饰物,整体氛围温馨浪漫,画面呈日常快照风格,构图随意却充满生活美感,8K高清摄影。",
218
+ '一位东亚女性,约20岁,身着白色高定蕾丝连衣裙,裙摆轻盈飘动,露出修长双腿与黑色细跟高跟鞋,发色乌黑,长发自然披肩,肌肤白皙如凝脂,唇色为水润朱红,眼神温柔含光,略带腼腆地望向镜头。她坐在咖啡馆窗边,右手轻扶杯沿,杯中是一杯带有爱心拉花的深棕色咖啡,桌旁放一本翻开的纸质书与一束淡粉色康乃馨。窗外阳光斜洒,照亮她半边脸庞,营造出温暖柔和的氛围。背景为暖色调木质窗框与浅米色窗帘,左侧贴有"圣诞快乐"字样贴纸,窗外可见一棵装饰精美的圣诞树,枝头挂满彩灯与小饰品,整体画面采用超广角拍摄,无畸变,32K高清摄影,呈现出静谧而浪漫的午后时光。图像中未出现其他文字。',
219
+ "一位年轻的东亚女性,约20-25岁,开怀大笑,双眼弯如月牙,神情明媚愉悦。她肤色白皙,面部轮廓柔和,妆容清新自然,唇色鲜亮。深棕色大波浪卷发蓬松丰盈,随意披散于肩头。上身穿着明黄色细肩带背心,下搭浅蓝色牛仔短裤,整体穿搭休闲活力。背景是一面色彩斑斓的大型街头涂鸦墙,图案鲜明、笔触奔放,阳光从前方斜照,光线充足明亮,营造出自由、热烈而充满街头艺术气息的氛围。",
220
+ "一位东亚女性,约19岁,身形纤瘦,高鼻梁,黑色长发自然垂落。她身处温馨的咖啡馆内,木质桌面上摆放着一杯拉花咖啡、一块抹茶蛋糕和几张照片卡片。她身穿质感软糯的彩色条纹针织毛衣,纹理细腻,色彩柔和,凸显温暖氛围。她以手肘轻撑桌面,一手托着脸颊,姿态放松自然,脸上带着清甜微笑,眼神灵动而平静,目光或看向镜头或微微偏移,神情慵懒随性。阳光透过发丝洒在面部,肌肤呈现自然状态,无明显妆感。画面为俯视视角,整体光线柔和但略不均匀,存在轻微过曝与运动模糊,保留写实摄影风格的细微噪点,高光不过度溢出,阴影保留细节,构图随意,如iPhone随手抓拍,呈现出真实、松弛又治愈的少女日常瞬间。",
221
+ "一只美洲豹潜伏在热带雨林的河岸边,压低健壮的身躯,深黄色皮毛上布满比普通豹子更大更黑的斑点,下颌线条强健有力。它目光专注地锁定水中动静,墨绿色河面清晰倒映出它的轮廓。背景是茂密潮湿的蕨类植物与交错缠绕的藤蔓,整体光线昏暗,氛围紧张而原始。图像中无任何文字、人像或人工标识。",
222
+ "一头雄性盘羊伫立在崎岖裸露的岩石山坡上,灰褐色皮毛粗硬浓密,身躯魁梧结实,肌肉线条分明。它最引人注目的是那对巨大、厚重且向外螺旋盘旋的角,彰显其野性力量。盘羊眼神警觉,目光锐利地扫视四周环境。背景为陡峭险峻的高山地貌,山体嶙峋,植被稀疏低矮,阳光充沛,整体画面凸显高山荒野的苍劲氛围与盘羊顽强的生命力。",
223
+ "夜空下,璀璨银河如一条发光的河流横贯天际,无数繁星闪烁其间。下方是广袤无垠的沙漠,几座巨大的沙丘在星光映照下轮廓分明,线条柔和流畅。前景中一棵枯死的胡杨树挺立,枝干伸展成极具张力的剪影。整体画面色调深邃,光影对比鲜明,氛围辽阔、静谧,透出宇宙的浩瀚与苍凉。"
224
  ]
225
 
226
+ css = """
227
+ #col-container {
228
+ margin: 0 auto;
229
+ max-width: 1024px;
230
  }
231
+ """
 
232
 
233
  with gr.Blocks() as demo:
234
+ with gr.Column(elem_id="col-container"):
235
+ gr.HTML("""
236
+ <div id="logo-title">
237
+ <img src="https://qianwen-res.oss-cn-beijing.aliyuncs.com/Qwen-Image/qwen_image_logo.png" alt="Qwen-Image Logo" width="400" style="display: block; margin: 0 auto;">
238
+ <h2 style="font-style: italic;color: #5b47d1;margin-top: -33px !important;text-align: center;">Fast, 4-steps with Lightx2v Lightning LoRA</h2>
239
+ </div>
240
+ """)
241
+ gr.Markdown("[Learn more](https://github.com/QwenLM/Qwen-Image) about the Qwen-Image series. Try on [Qwen Chat](https://chat.qwen.ai/), or [download model](https://huggingface.co/Qwen/Qwen-Image) to run locally with ComfyUI or diffusers.")
242
+
243
+ with gr.Row():
244
+ with gr.Column(scale=1):
245
+ prompt = gr.Text(
246
+ label="Prompt",
247
+ show_label=False,
248
+ placeholder="Enter your prompt",
249
+ container=False,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  )
251
+ run_button = gr.Button("Run", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
252
 
253
+ with gr.Accordion("Advanced Settings", open=False):
254
+ seed = gr.Slider(
255
+ label="Seed",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  minimum=0,
257
+ maximum=MAX_SEED,
258
+ step=1,
259
+ value=0,
260
  )
261
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
262
+ with gr.Row():
263
+ aspect_ratio = gr.Radio(
264
+ label="Aspect ratio (width:height)",
265
+ choices=["1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3"],
266
+ value="16:9",
267
+ )
268
+ with gr.Row():
269
+ guidance_scale = gr.Slider(
270
+ label="Guidance scale",
271
+ minimum=0.0,
272
+ maximum=10.0,
273
+ step=0.1,
274
+ value=1.0,
275
+ )
276
+ num_inference_steps = gr.Slider(
277
+ label="Number of inference steps",
278
+ minimum=1,
279
+ maximum=20,
280
+ step=1,
281
+ value=4,
282
+ )
283
+
284
+ with gr.Column(scale=1):
285
+ result = gr.Image(label="Result", show_label=False, type="pil")
286
 
287
+ gr.Examples(examples=examples, inputs=[prompt], outputs=[result, seed], fn=infer, cache_examples=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
 
 
289
  gr.on(
290
+ triggers=[run_button.click, prompt.submit],
291
+ fn=infer,
292
  inputs=[
293
  prompt,
 
 
294
  seed,
 
 
 
295
  randomize_seed,
296
+ aspect_ratio,
297
+ guidance_scale,
298
  num_inference_steps,
 
 
 
299
  ],
300
+ outputs=[result, seed],
 
 
 
 
 
 
 
 
 
 
301
  )
302
 
303
  if __name__ == "__main__":
304
+ demo.launch(css=css, theme=orange_red_theme, mcp_server=True)