File size: 22,323 Bytes
9afe4d4
2af0814
f2ec08f
5634ca3
 
81b8422
c17074c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2af0814
f2ec08f
9afe4d4
2fc2e78
9afe4d4
2fc2e78
9afe4d4
 
 
75d9493
399083d
424c702
 
149beb8
c1dd3c2
424c702
9afe4d4
 
2c8433f
c1dd3c2
2fc2e78
 
 
 
 
 
 
 
2c8433f
424c702
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2fc2e78
5191e9f
2fc2e78
9afe4d4
 
 
75d9493
9afe4d4
 
 
 
424c702
 
d3e7307
 
424c702
 
d3e7307
 
424c702
 
 
9afe4d4
5191e9f
9afe4d4
75d9493
9afe4d4
619344d
2fc2e78
 
9afe4d4
 
2fc2e78
7bd2485
 
2fc2e78
 
9afe4d4
 
 
 
 
 
2fc2e78
9afe4d4
 
2fc2e78
9afe4d4
2fc2e78
 
9afe4d4
2fc2e78
9afe4d4
2fc2e78
 
149beb8
7bd2485
9afe4d4
2fc2e78
 
 
 
9afe4d4
2fc2e78
149beb8
2fc2e78
9afe4d4
 
2fc2e78
 
 
 
 
9afe4d4
 
2fc2e78
9afe4d4
2fc2e78
 
619344d
 
 
 
 
 
 
 
 
2fc2e78
 
5191e9f
9afe4d4
2fc2e78
fbab7ec
2fc2e78
8e371aa
9afe4d4
 
 
 
 
 
 
 
 
 
 
 
 
424c702
2fc2e78
 
424c702
2fc2e78
 
424c702
 
 
 
149beb8
2fc2e78
 
424c702
2fc2e78
 
9afe4d4
 
2fc2e78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9fec53c
2fc2e78
 
 
 
 
 
 
619344d
2fc2e78
 
 
 
44feeef
 
 
 
810bdf5
2fc2e78
 
 
9fec53c
 
 
 
75d9493
 
149beb8
2fc2e78
 
424c702
 
 
 
 
 
 
 
 
87e43f5
424c702
 
87e43f5
 
424c702
149beb8
424c702
 
 
 
149beb8
424c702
 
 
 
 
 
 
 
 
 
 
 
9afe4d4
424c702
 
 
9afe4d4
2fc2e78
 
 
 
 
 
424c702
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149beb8
424c702
 
 
149beb8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9afe4d4
 
424c702
0a25da6
424c702
 
e50c124
 
 
 
424c702
e50c124
0a25da6
9afe4d4
0a25da6
2fc2e78
 
 
424c702
 
 
 
 
 
 
 
 
9afe4d4
2fc2e78
9afe4d4
 
7bd2485
9afe4d4
 
2c8433f
 
6b6f61f
424c702
 
 
 
 
 
 
 
 
471c9b2
424c702
 
9afe4d4
424c702
 
 
 
 
 
 
9afe4d4
2fc2e78
9afe4d4
2fc2e78
 
 
 
7bd2485
2fc2e78
424c702
2c8433f
424c702
 
7bd2485
 
 
 
 
 
 
 
424c702
0175cc4
424c702
0175cc4
7bd2485
424c702
 
149beb8
424c702
 
2c8433f
2fc2e78
424c702
2fc2e78
424c702
149beb8
2c8433f
 
424c702
2fc2e78
 
 
 
9afe4d4
2fc2e78
 
9afe4d4
424c702
 
 
 
 
149beb8
424c702
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149beb8
424c702
 
 
 
149beb8
424c702
2c8433f
c1dd3c2
44feeef
424c702
 
 
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
print("Starting CoTyle app...")
import os
import subprocess
from pathlib import Path

print(Path(__file__).absolute())
os.chmod("./install.sh", 0o755)
try:
    result = subprocess.run(
        ["./install.sh"],  # 绝对路径更稳妥
        shell=True,
        check=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        encoding="utf-8"
    )
    print("脚本执行成功!stdout:", result.stdout)
except subprocess.CalledProcessError as e:
    # 打印详细错误信息(重点看 stderr)
    print(f"脚本执行失败,状态码:{e.returncode}")
    print(f"脚本输出(stdout):{e.stdout}")
    print(f"脚本错误(stderr):{e.stderr}")  # 这里会显示 Shell 执行脚本时的具体报错


import sys
import json
import torch
import gradio as gr
import spaces
from PIL import Image
from huggingface_hub import snapshot_download
import gc
import psutil
from functools import partial



REPO_ID = "Kwai-Kolors/Kolors-CoTyle"
HF_TOKEN = os.getenv("HF_TOKEN")

device = "cuda" if torch.cuda.is_available() else "cpu"
weight_type = torch.bfloat16 if device == "cuda" else torch.float32

SUGGESTED_PROMPTS = [
    "An artist sits outdoors, engrossed in their work, brush in hand, capturing the scene with focused intensity. On the canvas, trees and buildings blend seamlessly with the real-world surroundings. Symbols from different cultures, along with animals, plants, and abstract lines, float around them. As the brush touches the canvas, the paint transforms into points of light that scatter, while sheets of paper and flower petals flutter in the air, creating a sense of movement. The atmosphere is a high-detail fusion of art and reality.",
    "Seagulls soar along the seaside under the setting sun, as a couple in wedding attire holds hands.",
    "A cute, chubby werewolf holds a balloon and candy, looking adorably mischievous. The background features a full moon on a night sky.",
    "A classical beauty, dressed in a dreamy, light pink flowing gown with wide sleeves, adorned with countless tiny wind crystals.",
    "The train sped swiftly across a large bridge.",
    "In front of the door stands an apple tree with two apples glistening with dewdrops. A beautiful little bird with vibrant feathers perches on a branch, displaying intricate textures and clear details.",
]

# 预设模板配置
PRESET_TEMPLATES = [
    {
        "name": "--sref 1234567",
        "image_path": "assets/1234567.jpg",
        "style_code": 1234567,
        "seed": 42,
        "prompts": [
            "An artist sits outdoors, engrossed in their work, brush in hand, capturing the scene with focused intensity. On the canvas, trees and buildings blend seamlessly with the real-world surroundings. Symbols from different cultures, along with animals, plants, and abstract lines, float around them. As the brush touches the canvas, the paint transforms into points of light that scatter, while sheets of paper and flower petals flutter in the air, creating a sense of movement. The atmosphere is a high-detail fusion of art and reality.",
            "Seagulls soar along the seaside under the setting sun, as a couple in wedding attire holds hands.",
            "A cute, chubby werewolf holds a balloon and candy, looking adorably mischievous. The background features a full moon on a night sky.",
            "A classical beauty, dressed in a dreamy, light pink flowing gown with wide sleeves, adorned with countless tiny wind crystals.",
        ]
    },
    {
        "name": "--sref 666666666",
        "image_path": "assets/666666666.jpg",
        "style_code": 666666666,
        "seed": 42,
        "prompts": [
            "A chubby, white, curly-furred baby lamb in anime style, with a pink nose and short mouth, stands on grass looking directly at the camera.",
            "A boy with a backpack stands on a mountain peak, bathed in sunlight, with continuous mountain ranges in the background.",
            "Aerial view: distant wind turbines, mountains, a river, heavy snowfall, and four or five people in orange work uniforms and white safety helmets marching in a line through the snow.",
            "A beautiful Chinese woman in ancient red silk attire rides a white horse, holding a red tassel spear, facing an enemy army of thousands; ethereal clouds swirl around her, and behind her stand countless celestial soldiers clad in white armor; documentary photography style."
        ]
    },
    {
        "name": "--sref 886",
        "image_path": "assets/886.jpg",
        "style_code": 886,
        "seed": 42,
        "prompts": [
            "A lovely crystal snake spirit, slender and nimble, wears an exquisite crystal crown atop its head. Its scales are translucent, shimmering like crystal, its eyes are bright and round, and its expression is lively. Its body coils naturally, its tail gracefully curved, its overall posture harmonious and beautiful.",
            "Seagulls soar along the seaside under the setting sun, as a couple in wedding attire holds hands.",
            "A cute, chubby werewolf holds a balloon and candy, looking adorably mischievous. The background features a full moon on a night sky.",
            "The train sped swiftly across a large bridge."
        ]
    },
    {
        "name": "--sref 10241024",
        "image_path": "assets/10241024.jpg",
        "style_code": 10241024,
        "seed": 42,
        "prompts": [
            "An elegant tabby cat steps gracefully through the doorway, its soft paws landing silently on the floor. Its amber eyes scan the surroundings with keen alertness, taking in every detail of the room.",
            "Mickey Mouse appears in the 1920s gangster world, dressed in a long trench coat and a fedora, holding an old-fashioned revolver. The backdrop is a dimly lit Chicago alleyway, where shadows stretch across the cobblestones and the air is thick with the intrigue of the era.",
            "A motorcycle speeds down the highway, the rider clad in black leather, with a biker girl seated behind him. The setting sun glints off the metallic fuel tank, while the rear wheel kicks up a trail of dust. In the background, the desolate road stretches endlessly towards the horizon, framed by the vast wilderness.",
            "A classical beauty, dressed in a dreamy, light pink flowing gown with wide sleeves, adorned with countless tiny wind crystals."
        ]
    },
    {
        "name": "--sref 4396",
        "image_path": "assets/4396.jpg",
        "style_code": 4396,
        "seed": 42,
        "prompts": [
            "A boy and a girl are walking along the lakeside, surrounded by vibrant flowers, lush grass, and verdant trees.",
            "A hazy full moon hangs high in the night sky, with the bustling streets of an ancient town below, adorned with a variety of lanterns that are vibrant and bright.",
            "A cartoon bear with a wide, round mouth and neatly arranged teeth, illustration, mascot, chubby.",
            "A real-life depiction of a warrior goddess is strikingly beautiful, adorned in metallic armor. She has long legs and sports enormous wings, adding to her majestic presence. A crown sits atop her head, and she wields a weapon, poised in a dynamic battle stance."
        ]
    },
]



def load_models():
    global pipeline, style_generator, unitok, processor, code_freq, local_repo_dir
    if "pipeline" in globals():
        return
    print('='*10, 'before download')
    local_repo_dir = snapshot_download(
        repo_id=REPO_ID,
        token=HF_TOKEN,
        allow_patterns=[
            "prior/**",
            "codebook/**",
            "tokenizer/**",
            "processor/**",
            "text_encoder/**",
            "freq.json",
            "transformer/**",
            "vae/**",
            "*.json",
            "*.pth",
            "*.safetensors",
        ],
        resume_download=True,
    )
    print('='*10, 'after download')
    sys.path.append(".")
    from models.pipe import CoTylePipeline, PiCoTylePipeline
    from models.vlm_unitok import UniTok
    from models.model import StyleGenerator, Qwen2_5_VLForConditionalGeneration_Quant, Qwen2_5_VL_Quant
    from models.utils import patched_from_model_config
    from transformers import Qwen2VLProcessor, AutoConfig
    from transformers.generation.configuration_utils import GenerationConfig
    from diffusers.schedulers import FlowMatchEulerDiscreteScheduler

    GenerationConfig.from_model_config = classmethod(patched_from_model_config)
    unitok_config = {
        "unitok_embed_dim": 3584,
        "unitok_vocab_width": 64,
        "unitok_vocab_size": 1024,
        "unitok_e_temp": 0.01,
        "unitok_num_codebooks": 1,
        "unitok_le": 0.0,
    }
    style_generator_path = os.path.join(local_repo_dir, "prior")
    config = AutoConfig.from_pretrained(style_generator_path)
    style_generator = StyleGenerator._from_config(config)
    state_dict = torch.load(os.path.join(style_generator_path, "prior.pth"), map_location="cpu")
    style_generator.load_state_dict(state_dict)
    style_generator.to(device, dtype=weight_type)
    codebook_path = os.path.join(local_repo_dir, "codebook")
    unitok = UniTok(unitok_config)
    unitok_state_dict = torch.load(os.path.join(codebook_path, "model.pth"), map_location="cpu")
    unitok.load_state_dict(unitok_state_dict)
    unitok.to(device, dtype=weight_type)

    pipeline = PiCoTylePipeline.from_pretrained(
        local_repo_dir,
        torch_dtype=weight_type,
        text_encoder=None,
        processor=None,
        safety_checker=None,
        requires_safety_checker=False,
    )

    qwen_text_visual_encoder = Qwen2_5_VLForConditionalGeneration_Quant.from_pretrained(
        local_repo_dir,
        subfolder="text_encoder",
    ).to(device, dtype=weight_type)
    qwen_text_visual_encoder = Qwen2_5_VL_Quant(unitok, qwen_text_visual_encoder)
    qwen_text_visual_encoder.to(device, dtype=weight_type)
    pipeline.text_encoder = qwen_text_visual_encoder
    processor = Qwen2VLProcessor.from_pretrained(
        local_repo_dir,
        subfolder="processor",
        min_pixels=64 * 28 * 28,
        max_pixels=256 * 28 * 28,
    )
    pipeline.processor = processor
    adapter_name = pipeline.load_piflow_adapter(  # you may later call `pipe.set_adapters([adapter_name, ...])` to combine other adapters (e.g., style LoRAs)
        'pretrained_models/pi-Qwen-Image',
        subfolder='gmqwen_k8_piid_4step',
        target_module_name='transformer')
    pipeline.scheduler = FlowMatchEulerDiscreteScheduler.from_config(  # use fixed shift=3.2
        pipeline.scheduler.config, shift=3.2, shift_terminal=None, use_dynamic_shifting=False)



    pipeline.to(device, dtype=weight_type)
    pipeline.set_progress_bar_config(disable=True)
    
    with open(os.path.join(local_repo_dir, "freq.json"), "r") as f:
        code_freq = json.load(f)
    print('='*10, " All models loaded successfully!")

@spaces.GPU
def generate_images(style_code, seed, num_prompts, *args):
    try:
        style_code = int(style_code)
    except Exception:
        style_code = 0
    try:
        seed = int(seed)
    except Exception:
        seed = 42
    try:
        num_prompts = int(num_prompts)
    except Exception:
        num_prompts = 1
    
    load_models()
    from models.utils import set_seed
    
    prompts = []
    for i in range(num_prompts):
        if i < len(args):
            prompt_text = (args[i] or "").strip()
            if prompt_text:
                prompts.append(prompt_text)
        
    if not prompts:
        raise gr.Error("Please enter at least one valid prompt!")
    
    set_seed(style_code)
    style_generator_inputs = {
        "input_ids": torch.randint(low=0, high=1024, size=(1, 1)).to(device),
        "attention_mask": torch.ones((1, 1)).to(device),
    }
    with torch.no_grad():
        generated_ids = style_generator.generate(
            **style_generator_inputs,
            max_new_tokens=195,
            temperature=1.0,
            top_k=200,
            top_p=0.95,
            do_sample=True,
            repetition_penalty=50.0,
            code_freq=code_freq,
            code_freq_threshold=90000,
            k=0.0001,
        )
    placeholder_image = Image.new("RGB", (392, 392), (0, 0, 0))
    results = []
    for i, prompt in enumerate(prompts):
        
        set_seed(seed)
        inputs = {
            "image": [placeholder_image],
            "prompt": prompt,
            "generator": torch.Generator(device=device).manual_seed(seed),
            "true_cfg_scale": 6.0,
            "negative_prompt": "ugly, monster, grotesque, deformed, mutated, anatomically incorrect, distorted face, disfigured limbs, unnatural posture, blurry, low quality",
            "num_inference_steps": 4,
            "guidance_scale": 1.0,
            "num_images_per_prompt": 1,
            "codebook_id": generated_ids,
        }
        if torch.cuda.is_available():
            torch.cuda.empty_cache()
        gc.collect()

        print(f"generating {i+1}/{len(prompts)}")
        with torch.inference_mode():
            output = pipeline(**inputs)
        results.append(output.images[0])
        print(f"Successfully generate {i+1}/{len(prompts)} images")
        if torch.cuda.is_available():
            torch.cuda.empty_cache()
        gc.collect()
    del output

    print(f"Successfully generate {len(results)} images")
    return results

def load_preset_template(template_idx):
    template = PRESET_TEMPLATES[template_idx]
    
    outputs = [
        template["style_code"],
        template["seed"],
        4,
    ]
    
    for i in range(4):
        outputs.append(template["prompts"][i])
    
    for i in range(2):
        outputs.append(SUGGESTED_PROMPTS[4+i])
    
    return tuple(outputs) 

def create_placeholder_image(text):
    return Image.new('RGB', (300, 200), color=(240, 240, 240))


custom_js = """
function() {
    // 优化 Gradio 的更新性能
    const style = document.createElement('style');
    style.textContent = `
        .gradio-container { transition: none !important; }
        .gr-box { transition: none !important; }
    `;
    document.head.appendChild(style);
}
"""

with gr.Blocks(
    # theme=gr.themes.midnight(),
    theme = 'Taithrah/Minimal',
    js=custom_js,  # 添加自定义 JS 来禁用不必要的动画
    css="""
    .prompt-hint {
        font-size: 0.9em;
        color: #666;
        margin-top: -8px;
        margin-bottom: 12px;
    }
    .preset-container {
        border: 2px solid #e0e0e0;
        border-radius: 12px;
        padding: 12px;
        cursor: pointer;
        transition: all 0.3s ease;
        background: white;
        height: 100%;
        display: flex;
        flex-direction: column;
        max-width: 280px;
        margin: 0 auto;
    }
    .preset-container:hover {
        border-color: #2196F3;
        box-shadow: 0 4px 12px rgba(33, 150, 243, 0.2);
        transform: translateY(-2px);
    }
    .preset-image-container {
        width: 100%;
        height: 240px;
        overflow: hidden;
        border-radius: 8px;
        margin-bottom: 1px;
        background: white;
        display: flex;
        align-items: center;
        justify-content: center;
    }
    .preset-image-container img {
        width: 100%;
        height: 100%;
        object-fit: cover;
    }
    .preset-text {
        text-align: center;
        font-weight: bold;
        font-size: 1.0em;
        color: #333;
        padding: 3px 0;
    }
    .preset-row {
        margin-bottom: 10px;
        justify-content: center;
        gap: 15px;
    }
    .preset-section {
        max-width: 1900px;
        margin: 0 auto;
        padding: 0 20px;
    }

    .gr-box, .gr-form, .gr-input {
        transition: none !important;
    }


    .gradio-gallery {
        width: 100% !important;
        max-width: none !important;
        margin: 0 !important;
        padding: 0 !important;
    }
    .gradio-gallery .grid-container {
        grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)) !important;
        gap: 12px !important;
    }


    .form-label {
        color: #2d3748 !important;  
        font-weight: 600;
    }
"""
) as demo:
    gr.HTML(
        """
    <div align="center" style="font-size: 40px;">
    🎨 CoTyle: Unlocking Code-to-Style Image Generation with Discrete Style Space
    <div style="display: flex; justify-content: center; gap: 10px; flex-wrap: wrap; margin: 15px 0;">
        <a href="xxx"><img alt="Project Page" src="https://img.shields.io/badge/Project%20Page-Homepage-yellow"></a>
        <a href="xxx"><img alt="GitHub" src="https://img.shields.io/badge/GitHub-Code-f8f0f0.svg"></a>
        <a href="xxx"><img alt="arXiv" src="https://img.shields.io/badge/arXiv-Paper-da282a.svg"></a>
        <a href="https://huggingface.co/spaces/Kwai-Kolors/CoTyle"><img alt="Hugging Face Demo" src="https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Demo-fd8b02"></a>
    </div>
    </div>
        """
    )

    with gr.Row():
        with gr.Column():
            # style_code = gr.Number(label="Style Code", value=1234567, step=1)
            style_code = gr.Slider(
                minimum=1,
                maximum=4294967296,
                value=1234567,
                step=1,
                label="Style Code",
            )


            num_prompts = gr.Slider(
                minimum=1,
                maximum=6,
                value=4,
                step=1,
                label="Number of Prompts (You can choose how many prompt images to generate at once)",
            )


            text_inputs = []
            for i in range(6):
                default_prompt = SUGGESTED_PROMPTS[i] if i < len(SUGGESTED_PROMPTS) else ""
                textbox = gr.Textbox(
                    value=default_prompt,
                    label=f"Prompt {i+1}",
                    lines=3,
                    max_lines=10,
                    placeholder="Enter your prompt here...",
                    visible=(i < 2),
                )
                text_inputs.append(textbox)

            seed = gr.Slider(
                minimum=1,
                maximum=4294967296,
                value=42,
                step=1,
                label="Seed",
            )

            run_btn = gr.Button("✨ Generate All Images", variant="primary", size="lg")

        with gr.Column():
            gallery = gr.Gallery(
                label="Generated Results",
                show_label=True,
                columns=4,
                object_fit="contain",
                height="100%",
            )
            gr.Markdown(
                """
                > ❗️ <strong>Note</strong>: 
                > The Gradio apps use an accelerated version, which may result in a slight reduction in image generation quality.
                """
                )

            gr.Markdown(
                """
            > ✅ <strong>Tips</strong>:
            > - Adjust the <strong>Number of Prompts</strong> slider to add or remove input rows.
            > - Type your own prompts directly in the text boxes .
            > - You can click any template below to quickly load preset style code and prompts.
            > - This model is the open-source version, utilizing [Qwen-Image](https://github.com/QwenLM/Qwen-Image) as the pre-trained model, while the more powerful closed-source version employs Kolors 2.1 as the pre-trained model and will soon be launched on the [KlingAI](https://app.klingai.com/global/?gad_source=1&gad_campaignid=22803840655&gbraid=0AAAAA_AcKMnNNjEHRRI1l9_5z1qK881dO).

            """
            )

    def update_textboxes_visibility(n):
        return [gr.update(visible=(i < n)) for i in range(6)]

    num_prompts.change(
        fn=update_textboxes_visibility,
        inputs=num_prompts,
        outputs=text_inputs,
        queue=False, 
    )

    input_components = [style_code, seed, num_prompts] + text_inputs

    run_btn.click(
        fn=generate_images,
        inputs=input_components,
        outputs=gallery,
    )


    output_components = [style_code, seed, num_prompts] + text_inputs
    with gr.Column(elem_classes="preset-section"):
        gr.Markdown("## 🎯 Examples")
        gr.Markdown("Click any example below to quickly load preset style code, seed, and prompts")
        
    
        with gr.Row(elem_classes="preset-row"):
            for i in range(5):
                with gr.Column(scale=1, min_width=250):
                    template = PRESET_TEMPLATES[i]
                    with gr.Column(elem_classes="preset-container"):
                        if os.path.exists(template["image_path"]):
                            preset_img = gr.Image(
                                value=template["image_path"],
                                show_label=False,
                                interactive=False,
                                container=False,
                                height=280,
                                elem_classes="preset-image-container"
                            )
                        else:
                            placeholder = create_placeholder_image(template["name"])
                            preset_img = gr.Image(
                                value=placeholder,
                                show_label=False,
                                interactive=False,
                                container=False,
                                height=280,
                                elem_classes="preset-image-container"
                            )
                        
                        preset_btn = gr.Button(
                            value=template["name"],
                            variant="secondary",
                            size="lg"
                        )
                        
                
                        preset_btn.click(
                            fn=partial(load_preset_template, i),
                            inputs=None,
                            outputs=output_components,
                            queue=False, 
                        )
if __name__ == "__main__":
    load_models()
    demo.queue(max_size=1).launch(
        max_threads=1,
        share=True
    )