Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save diegocr/cc04c2eee335a60e8fc4e2e9d987d4d9 to your computer and use it in GitHub Desktop.
Save diegocr/cc04c2eee335a60e8fc4e2e9d987d4d9 to your computer and use it in GitHub Desktop.
A script help you convert diffusers lora to sd webui format
from pathlib import Path
from diffusers import StableDiffusionXLPipeline
import torch
from safetensors.torch import save_file
# text_encoder.text_model.encoder.layers.0.self_attn.k_proj.lora_linear_layer.down.weight
# lora_te_text_model_encoder_layers_0_self_attn_k_proj.lora_down.weight
# 1. text_encoder -> lora_te, text_encoder_2 -> lora_te2
# 2. map
# 3. .weight -> 2 .alpha -> 1 and replace . -> _
# test:
# 1. lora_te.text_model.encoder.layers.0.self_attn.k_proj.lora_linear_layer.down.weight
# 2. lora_te.text_model.encoder.layers.0.self_attn.k_proj.lora_down.weight
# 2. lora_te_text_model_encoder_layers_0_self_attn_k_proj.lora_down.weight
# unet.down_blocks.1.attentions.0.transformer_blocks.0.attn1.processor.to_k_lora.down.weight
# lora_unet_down_blocks_1_attentions_0_transformer_blocks_0_attn1_to_k.lora_down.weight
# 1. unet -> lora_unet
# 2. map
# 4. .weight -> 2 .alpha -> 1 and replace . -> _
# test:
# 1. lora_unet.down_blocks.1.attentions.0.transformer_blocks.0.attn1.processor.to_k_lora.down.weight
# 2. lora_unet.down_blocks_1_attentions_0_transformer_blocks_0_attn1.to_k.lora_down.weight
# 4. lora_unet_down_blocks_1_attentions_0_transformer_blocks_0_attn1_to_k.lora_down.weight
pipe = StableDiffusionXLPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-base-1.0", torch_dtype=torch.float32, local_files_only=True
)
state_dict, network_alphas = pipe.lora_state_dict(
Path("<your_lora.safetensors>"), local_files_only=True
)
LORA_CLIP_MAP = {
"mlp.fc1": "mlp_fc1",
"mlp.fc2": "mlp_fc2",
"self_attn.k_proj": "self_attn_k_proj",
"self_attn.q_proj": "self_attn_q_proj",
"self_attn.v_proj": "self_attn_v_proj",
"self_attn.out_proj": "self_attn_out_proj",
"lora_linear_layer.down": "lora_down",
"lora_linear_layer.up": "lora_up",
}
LORA_UNET_MAP = {
"processor.to_q_lora.down": "to_q.lora_down",
"processor.to_q_lora.up": "to_q.lora_up",
"processor.to_k_lora.down": "to_k.lora_down",
"processor.to_k_lora.up": "to_k.lora_up",
"processor.to_v_lora.down": "to_v.lora_down",
"processor.to_v_lora.up": "to_v.lora_up",
"processor.to_out_lora.down": "to_out_0.lora_down",
"processor.to_out_lora.up": "to_out_0.lora_up",
"processor.to_q.alpha": "to_q.alpha",
"processor.to_k.alpha": "to_k.alpha",
"processor.to_v.alpha": "to_v.alpha",
}
webui_lora_state_dict = {}
for k, v in state_dict.items():
is_text_encoder = False
prefix = k.split(".")[0]
if prefix == "text_encoder":
k = k.replace("text_encoder", "lora_te1")
is_text_encoder = True
elif prefix == "text_encoder_2":
k = k.replace("text_encoder_2", "lora_te2")
is_text_encoder = True
elif prefix == "unet":
k = k.replace("unet", "lora_unet")
if is_text_encoder:
for map_k, map_v in LORA_CLIP_MAP.items():
k = k.replace(map_k, map_v)
else:
for map_k, map_v in LORA_UNET_MAP.items():
k = k.replace(map_k, map_v)
keep_dots = 0
if k.endswith(".alpha"):
keep_dots = 1
elif k.endswith(".weight"):
keep_dots = 2
parts = k.split(".")
k = "_".join(parts[:-keep_dots]) + "." + ".".join(parts[-keep_dots:])
webui_lora_state_dict[k] = v
save_file(webui_lora_state_dict, "<your_lora_for_webui.safetensors>")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment