File size: 5,394 Bytes
8a62807
 
 
 
 
 
 
 
 
f7a3995
 
 
0145321
8a62807
 
 
 
 
f7a3995
 
8a62807
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0145321
8a62807
0145321
 
8a62807
0145321
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8a62807
 
 
 
0145321
 
 
 
 
 
 
 
 
 
8a62807
0145321
 
 
 
 
 
 
 
 
 
8a62807
0145321
8a62807
0145321
 
 
 
 
09146d4
8a62807
 
 
 
0145321
8a62807
0145321
 
 
8a62807
 
 
 
 
 
 
 
 
 
 
0145321
8a62807
 
0145321
8a62807
7637b97
8a62807
57213ba
8a62807
 
 
 
0145321
 
 
 
 
 
8a62807
 
 
 
 
 
 
 
 
 
 
 
0145321
8a62807
 
 
 
 
 
 
0145321
8a62807
 
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
import math
import os
import random

import gradio as gr
import numpy as np
import spaces
import torch

torch.backends.cuda.matmul.allow_tf32 = True
torch.backends.cudnn.allow_tf32 = True

from diffusers import Flux2KleinPipeline
from lakonlab.models.architectures import OklabColorEncoder
from lakonlab.models.diffusions.schedulers import FlowAdapterScheduler
from lakonlab.pipelines.pipeline_pixelflux2_klein import PixelFlux2KleinPipeline
from lakonlab.ui.gradio.create_text_to_img import create_interface_text_to_img

from huggingface_hub import login
login(token=os.getenv('HF_TOKEN'))


DEFAULT_PROMPT = (
    'Restored color photo from the 1900s. A middle-aged man with cybernetic metal hands is sitting on an old wooden '
    'chair and reading the newspaper. The newspaper has the prominent headline "AsymFLOW RELEASED" in large bold font. '
    'Close-up shot focusing on the newspaper.'
)
DEFAULT_NEG_PROMPT = 'Low quality, worst quality, blurry, deformed, bad anatomy, unclear text'


def set_random_seed(seed: int, deterministic: bool = True) -> None:
    random.seed(seed)
    np.random.seed(seed)
    torch.manual_seed(seed)
    torch.cuda.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)
    os.environ['PYTHONHASHSEED'] = str(seed)
    if deterministic:
        torch.backends.cudnn.deterministic = True
        torch.backends.cudnn.benchmark = False


base_pipe = Flux2KleinPipeline.from_pretrained(
    'black-forest-labs/FLUX.2-klein-base-9B',
    vae=None,
    scheduler=None,
    torch_dtype=torch.bfloat16)
base_pipe = base_pipe.to('cuda')
scheduler = FlowAdapterScheduler(
    shift=17.0,
    use_dynamic_shifting=True,
    base_seq_len=1024 ** 2,
    max_seq_len=2048 ** 2,
    base_logshift=math.log(17.0),
    max_logshift=math.log(34.0),
    dynamic_shifting_type='sqrt',
    base_scheduler='UniPCMultistep')
color_encoder = OklabColorEncoder(
    use_affine_norm=True,
    mean=(0.56, 0.0, 0.01),
    std=0.16).to('cuda')

pipe = PixelFlux2KleinPipeline(
    scheduler=scheduler,
    vae=color_encoder,
    text_encoder=base_pipe.text_encoder,
    tokenizer=base_pipe.tokenizer,
    transformer=base_pipe.transformer)
pipe.load_lakonlab_adapter(
    'Lakonik/AsymFLUX.2-klein-9B',
    target_module_name='transformer')

pipe_sft_zimage_turbo = PixelFlux2KleinPipeline(
    scheduler=scheduler,
    vae=color_encoder,
    text_encoder=base_pipe.text_encoder,
    tokenizer=base_pipe.tokenizer,
    transformer=base_pipe.transformer)
pipe_sft_zimage_turbo.load_lakonlab_adapter(
    'Lakonik/AsymFLUX.2-klein-9B-collection',
    subfolder='asymflux2_klein_9b_sft_zimage_turbo',
    target_module_name='transformer')

pipe_sft_flux2_klein = PixelFlux2KleinPipeline(
    scheduler=scheduler,
    vae=color_encoder,
    text_encoder=base_pipe.text_encoder,
    tokenizer=base_pipe.tokenizer,
    transformer=base_pipe.transformer)
pipe_sft_flux2_klein.load_lakonlab_adapter(
    'Lakonik/AsymFLUX.2-klein-9B-collection',
    subfolder='asymflux2_klein_9b_sft_flux2_klein',
    target_module_name='transformer')

del base_pipe

model_pipes = {
    'AsymFLUX.2 klein 9B (base)': pipe,
    'AsymFLUX.2 klein 9B SFT Z-Image Turbo (finetuned on synthetic data generated by Z-Image Turbo)': pipe_sft_zimage_turbo,
    'AsymFLUX.2 klein 9B SFT FLUX.2 klein (finetuned on synthetic data generated by FLUX.2 klein Distilled 9B)': pipe_sft_flux2_klein,
}
default_model = list(model_pipes.keys())[1]


@spaces.GPU
def generate(
        model_name, seed, prompt, negative_prompt, width, height, steps, guidance_scale,
        progress=gr.Progress(track_tqdm=True)):
    selected_pipe = model_pipes[model_name]
    return selected_pipe(
        prompt=prompt,
        negative_prompt=negative_prompt,
        width=width,
        height=height,
        num_inference_steps=steps,
        guidance_scale=guidance_scale,
        generator=torch.Generator().manual_seed(seed),
    ).images[0]


with gr.Blocks(
        analytics_enabled=False,
        title='AsymFLUX.2 klein Demo',
        css_paths='lakonlab/ui/gradio/style.css') as demo:
    gr.Markdown(
        '# AsymFLUX.2 klein Demo\n\n'
        'Pixel-space text-to-image generation demo of the paper '
        '[Asymmetric Flow Models](https://arxiv.org/abs/2605.12964). '
        '**Base model:** [FLUX.2 klein Base 9B](https://huggingface.co/black-forest-labs/FLUX.2-klein-base-9B). '
        '**Code:** [https://github.com/Lakonik/LakonLab](https://github.com/Lakonik/LakonLab).\n'
        '<br> Use and distribution of this app are governed by the '
        '[FLUX Non-Commercial License](https://huggingface.co/black-forest-labs/FLUX.2-klein-base-9B/blob/main/LICENSE.md).'
    )

    model_dropdown = gr.Dropdown(
        choices=list(model_pipes.keys()),
        value=default_model,
        label='Select model variant',
        elem_classes=['force-hide-container'])

    create_interface_text_to_img(
        generate,
        prompt=DEFAULT_PROMPT,
        negative_prompt=DEFAULT_NEG_PROMPT,
        steps=38,
        min_steps=4,
        max_steps=50,
        guidance_scale=4.0,
        height=1280,
        width=960,
        create_negative_prompt=True,
        args=[
            model_dropdown,
            'last_seed',
            'prompt',
            'negative_prompt',
            'width',
            'height',
            'steps',
            'guidance_scale',
        ])

demo.queue().launch()