File size: 10,583 Bytes
fe6327d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import gradio as gr
from easygui import msgbox
import subprocess
import os
import shutil
from .common_gui import get_folder_path, get_file_path

from library.custom_logging import setup_logging

# Set up logging
log = setup_logging()

folder_symbol = '\U0001f4c2'  # 📂
refresh_symbol = '\U0001f504'  # 🔄
save_style_symbol = '\U0001f4be'  # 💾
document_symbol = '\U0001F4C4'   # 📄
PYTHON = 'python3' if os.name == 'posix' else './venv/Scripts/python.exe'


def convert_model(
    source_model_input,
    source_model_type,
    target_model_folder_input,
    target_model_name_input,
    target_model_type,
    target_save_precision_type,
    unet_use_linear_projection,
):
    # Check for caption_text_input
    if source_model_type == '':
        msgbox('Invalid source model type')
        return

    # Check if source model exist
    if os.path.isfile(source_model_input):
        log.info('The provided source model is a file')
    elif os.path.isdir(source_model_input):
        log.info('The provided model is a folder')
    else:
        msgbox('The provided source model is neither a file nor a folder')
        return

    # Check if source model exist
    if os.path.isdir(target_model_folder_input):
        log.info('The provided model folder exist')
    else:
        msgbox('The provided target folder does not exist')
        return

    run_cmd = f'{PYTHON} "tools/convert_diffusers20_original_sd.py"'

    v1_models = [
        'runwayml/stable-diffusion-v1-5',
        'CompVis/stable-diffusion-v1-4',
    ]

    # check if v1 models
    if str(source_model_type) in v1_models:
        log.info('SD v1 model specified. Setting --v1 parameter')
        run_cmd += ' --v1'
    else:
        log.info('SD v2 model specified. Setting --v2 parameter')
        run_cmd += ' --v2'

    if not target_save_precision_type == 'unspecified':
        run_cmd += f' --{target_save_precision_type}'

    if (
        target_model_type == 'diffuser'
        or target_model_type == 'diffuser_safetensors'
    ):
        run_cmd += f' --reference_model="{source_model_type}"'

    if target_model_type == 'diffuser_safetensors':
        run_cmd += ' --use_safetensors'

    # Fix for stabilityAI diffusers format. When saving v2 models in Diffusers format in training scripts and conversion scripts,
    # it was found that the U-Net configuration is different from those of Hugging Face's stabilityai models (this repository is
    # "use_linear_projection": false, stabilityai is true). Please note that the weight shapes are different, so please be careful
    # when using the weight files directly.

    if unet_use_linear_projection:
        run_cmd += ' --unet_use_linear_projection'

    run_cmd += f' "{source_model_input}"'

    if (
        target_model_type == 'diffuser'
        or target_model_type == 'diffuser_safetensors'
    ):
        target_model_path = os.path.join(
            target_model_folder_input, target_model_name_input
        )
        run_cmd += f' "{target_model_path}"'
    else:
        target_model_path = os.path.join(
            target_model_folder_input,
            f'{target_model_name_input}.{target_model_type}',
        )
        run_cmd += f' "{target_model_path}"'

    log.info(run_cmd)

    # Run the command
    if os.name == 'posix':
        os.system(run_cmd)
    else:
        subprocess.run(run_cmd)

    if (
        not target_model_type == 'diffuser'
        or target_model_type == 'diffuser_safetensors'
    ):

        v2_models = [
            'stabilityai/stable-diffusion-2-1-base',
            'stabilityai/stable-diffusion-2-base',
        ]
        v_parameterization = [
            'stabilityai/stable-diffusion-2-1',
            'stabilityai/stable-diffusion-2',
        ]

        if str(source_model_type) in v2_models:
            inference_file = os.path.join(
                target_model_folder_input, f'{target_model_name_input}.yaml'
            )
            log.info(f'Saving v2-inference.yaml as {inference_file}')
            shutil.copy(
                f'./v2_inference/v2-inference.yaml',
                f'{inference_file}',
            )

        if str(source_model_type) in v_parameterization:
            inference_file = os.path.join(
                target_model_folder_input, f'{target_model_name_input}.yaml'
            )
            log.info(f'Saving v2-inference-v.yaml as {inference_file}')
            shutil.copy(
                f'./v2_inference/v2-inference-v.yaml',
                f'{inference_file}',
            )


#   parser = argparse.ArgumentParser()
#   parser.add_argument("--v1", action='store_true',
#                       help='load v1.x model (v1 or v2 is required to load checkpoint) / 1.xのモデルを読み込む')
#   parser.add_argument("--v2", action='store_true',
#                       help='load v2.0 model (v1 or v2 is required to load checkpoint) / 2.0のモデルを読み込む')
#   parser.add_argument("--fp16", action='store_true',
#                       help='load as fp16 (Diffusers only) and save as fp16 (checkpoint only) / fp16形式で読み込み(Diffusers形式のみ対応)、保存する(checkpointのみ対応)')
#   parser.add_argument("--bf16", action='store_true', help='save as bf16 (checkpoint only) / bf16形式で保存する(checkpointのみ対応)')
#   parser.add_argument("--float", action='store_true',
#                       help='save as float (checkpoint only) / float(float32)形式で保存する(checkpointのみ対応)')
#   parser.add_argument("--epoch", type=int, default=0, help='epoch to write to checkpoint / checkpointに記録するepoch数の値')
#   parser.add_argument("--global_step", type=int, default=0,
#                       help='global_step to write to checkpoint / checkpointに記録するglobal_stepの値')
#   parser.add_argument("--reference_model", type=str, default=None,
#                       help="reference model for schduler/tokenizer, required in saving Diffusers, copy schduler/tokenizer from this / scheduler/tokenizerのコピー元のDiffusersモデル、Diffusers形式で保存するときに必要")

#   parser.add_argument("model_to_load", type=str, default=None,
#                       help="model to load: checkpoint file or Diffusers model's directory / 読み込むモデル、checkpointかDiffusers形式モデルのディレクトリ")
#   parser.add_argument("model_to_save", type=str, default=None,
#                       help="model to save: checkpoint (with extension) or Diffusers model's directory (without extension) / 変換後のモデル、拡張子がある場合はcheckpoint、ない場合はDiffusesモデルとして保存")


###
# Gradio UI
###


def gradio_convert_model_tab(headless=False):
    with gr.Tab('Convert model'):
        gr.Markdown(
            'This utility can be used to convert from one stable diffusion model format to another.'
        )
        
        model_ext = gr.Textbox(value='*.safetensors *.ckpt', visible=False)
        model_ext_name = gr.Textbox(value='Model types', visible=False)
        
        with gr.Row():
            source_model_input = gr.Textbox(
                label='Source model',
                placeholder='path to source model folder of file to convert...',
                interactive=True,
            )
            button_source_model_dir = gr.Button(
                folder_symbol,
                elem_id='open_folder_small',
                visible=(not headless),
            )
            button_source_model_dir.click(
                get_folder_path,
                outputs=source_model_input,
                show_progress=False,
            )

            button_source_model_file = gr.Button(
                document_symbol,
                elem_id='open_folder_small',
                visible=(not headless),
            )
            button_source_model_file.click(
                get_file_path,
                inputs=[source_model_input, model_ext, model_ext_name],
                outputs=source_model_input,
                show_progress=False,
            )

            source_model_type = gr.Dropdown(
                label='Source model type',
                choices=[
                    'stabilityai/stable-diffusion-2-1-base',
                    'stabilityai/stable-diffusion-2-base',
                    'stabilityai/stable-diffusion-2-1',
                    'stabilityai/stable-diffusion-2',
                    'runwayml/stable-diffusion-v1-5',
                    'CompVis/stable-diffusion-v1-4',
                ],
            )
        with gr.Row():
            target_model_folder_input = gr.Textbox(
                label='Target model folder',
                placeholder='path to target model folder of file name to create...',
                interactive=True,
            )
            button_target_model_folder = gr.Button(
                folder_symbol,
                elem_id='open_folder_small',
                visible=(not headless),
            )
            button_target_model_folder.click(
                get_folder_path,
                outputs=target_model_folder_input,
                show_progress=False,
            )

            target_model_name_input = gr.Textbox(
                label='Target model name',
                placeholder='target model name...',
                interactive=True,
            )
            target_model_type = gr.Dropdown(
                label='Target model type',
                choices=[
                    'diffuser',
                    'diffuser_safetensors',
                    'ckpt',
                    'safetensors',
                ],
            )
            target_save_precision_type = gr.Dropdown(
                label='Target model precision',
                choices=['unspecified', 'fp16', 'bf16', 'float'],
                value='unspecified',
            )
            unet_use_linear_projection = gr.Checkbox(
                label='UNet linear projection',
                value=False,
                info="Enable for Hugging Face's stabilityai models",
            )

        convert_button = gr.Button('Convert model')

        convert_button.click(
            convert_model,
            inputs=[
                source_model_input,
                source_model_type,
                target_model_folder_input,
                target_model_name_input,
                target_model_type,
                target_save_precision_type,
                unet_use_linear_projection,
            ],
            show_progress=False,
        )