import gc
import os
import os.path
import re
import json
import shutil
from tqdm import tqdm
import torch
from statistics import mean
import csv
import torch.nn as nn
import torch.nn.functional as F
from importlib import reload
from pprint import pprint
import gradio as gr
from modules import (script_callbacks, sd_models,sd_vae, shared)
from modules.scripts import basedir
from modules.sd_models import checkpoints_loaded, load_model,unload_model_weights
from modules.shared import opts
from modules.sd_samplers import samplers
from modules.ui import create_output_panel, create_refresh_button
import scripts.mergers.mergers
import scripts.mergers.pluslora
import scripts.mergers.xyplot
import scripts.mergers.components as components
from importlib import reload
reload(scripts.mergers.mergers)
reload(scripts.mergers.xyplot)
reload(scripts.mergers.pluslora)
import csv
import scripts.mergers.pluslora as pluslora
from scripts.mergers.mergers import (TYPESEG,EXCLUDE_CHOICES, freezemtime, rwmergelog, blockfromkey, clearcache, getcachelist)
from scripts.mergers.xyplot import freezetime, nulister
from scripts.mergers.model_util import filenamecutter, savemodel
path_root = basedir()
xyzpath = os.path.join(path_root,"xyzpresets.json")
CALCMODES = ["normal", "cosineA", "cosineB","trainDifference","smoothAdd","smoothAdd MT","extract","tensor","tensor2","self","plus random"]
class ResizeHandleRow(gr.Row):
"""Same as gr.Row but fits inside gradio forms"""
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.elem_classes.append("resize-handle-row")
def get_block_name(self):
return "row"
from typing import Union
def network_reset_cached_weight(self: Union[torch.nn.Conv2d, torch.nn.Linear]):
self.network_current_names = ()
self.network_weights_backup = None
self.network_bias_backup = None
def fix_network_reset_cached_weight():
try:
import networks as net
net.network_reset_cached_weight = network_reset_cached_weight
except:
pass
def on_ui_tabs():
fix_network_reset_cached_weight()
weights_presets=""
userfilepath = os.path.join(path_root, "scripts","mbwpresets.txt")
if os.path.isfile(userfilepath):
try:
with open(userfilepath) as f:
weights_presets = f.read()
filepath = userfilepath
except OSError as e:
pass
else:
filepath = os.path.join(path_root, "scripts","mbwpresets_master.txt")
try:
with open(filepath) as f:
weights_presets = f.read()
shutil.copyfile(filepath, userfilepath)
except OSError as e:
pass
if "ALLR" not in weights_presets: weights_presets += ADDRAND
with gr.Blocks() as supermergerui:
with gr.Tab("Merge"):
with ResizeHandleRow(equal_height=False):
with gr.Column(variant="compact"):
gr.HTML(value="
Merge models and load it for generation
")
with gr.Row():
s_reverse= gr.Button(value="Load settings from:",elem_classes=["compact_button"],variant='primary')
mergeid = gr.Textbox(label="merged model ID (-1 for last)", elem_id="model_converter_custom_name",value = "-1")
mclearcache= gr.Button(value="Clear Cache",elem_classes=["compact_button"],variant='primary')
with gr.Row(variant="compact"):
model_a = gr.Dropdown(sd_models.checkpoint_tiles(),elem_id="model_converter_model_name",label="Model A",interactive=True)
create_refresh_button(model_a, sd_models.list_models,lambda: {"choices": sd_models.checkpoint_tiles()},"refresh_checkpoint_Z")
model_b = gr.Dropdown(sd_models.checkpoint_tiles(),elem_id="model_converter_model_name",label="Model B",interactive=True)
create_refresh_button(model_b, sd_models.list_models,lambda: {"choices": sd_models.checkpoint_tiles()},"refresh_checkpoint_Z")
model_c = gr.Dropdown(sd_models.checkpoint_tiles(),elem_id="model_converter_model_name",label="Model C",interactive=True)
create_refresh_button(model_c, sd_models.list_models,lambda: {"choices": sd_models.checkpoint_tiles()},"refresh_checkpoint_Z")
mode = gr.Radio(label = "Merge Mode",choices = ["Weight sum", "Add difference", "Triple sum", "sum Twice"], value="Weight sum", info="A*(1-alpha)+B*alpha")
calcmode = gr.Radio(label = "Calculation Mode",choices = CALCMODES, value = "normal")
with gr.Row(variant="compact"):
with gr.Column(scale = 1):
useblocks = gr.Checkbox(label="use MBW", info="use Merge Block Weights")
with gr.Column(scale = 3), gr.Group() as alpha_group:
with gr.Row():
base_alpha = gr.Slider(label="alpha", minimum=-1.0, maximum=2, step=0.001, value=0.5)
base_beta = gr.Slider(label="beta", minimum=-1.0, maximum=2, step=0.001, value=0.25, interactive=False)
#weights = gr.Textbox(label="weights,base alpha,IN00,IN02,...IN11,M00,OUT00,...,OUT11",lines=2,value="0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5")
with gr.Accordion("Options", open=False):
with gr.Row(variant="compact"):
save_sets = gr.CheckboxGroup(["use cuda","save model", "overwrite","safetensors","fp16","save metadata","copy config","prune","Reset CLIP ids","use old calc method","debug"], value=["safetensors"], show_label=False, label="save settings")
with gr.Row():
components.id_sets = gr.CheckboxGroup(["image", "PNG info"], label="save merged model ID to")
opt_value = gr.Slider(label="option(gamma) ", minimum=-1.0, maximum=20, step=0.1, value=0.3, interactive=True)
with gr.Row(variant="compact"):
with gr.Column(min_width = 50):
with gr.Row():
custom_name = gr.Textbox(label="Custom Name (Optional)", elem_id="model_converter_custom_name")
with gr.Column():
with gr.Row():
bake_in_vae = gr.Dropdown(choices=["None"] + list(sd_vae.vae_dict), value="None", label="Bake in VAE", elem_id="modelmerger_bake_in_vae")
create_refresh_button(bake_in_vae, sd_vae.refresh_vae_list, lambda: {"choices": ["None"] + list(sd_vae.vae_dict)}, "modelmerger_refresh_bake_in_vae")
with gr.Row(variant="compact"):
savecurrent = gr.Button(elem_id="savecurrent", elem_classes=["compact_button"], value="Save current merge(fp16 only)")
with gr.Row():
components.merge = gr.Button(elem_id="model_merger_merge", elem_classes=["compact_button"], value="Merge!",variant='primary')
components.mergeandgen = gr.Button(elem_id="model_merger_merge", elem_classes=["compact_button"], value="Merge&Gen",variant='primary')
components.gen = gr.Button(elem_id="model_merger_merge", elem_classes=["compact_button"], value="Gen",variant='primary')
stopmerge = gr.Button(elem_id="stopmerge", elem_classes=["compact_button"], value="Stop")
with gr.Accordion("Merging Block Weights", open=False):
with gr.Row():
isxl = gr.Radio(label = "Block Type",choices = ["1.X or 2.X", "XL"], value = "1.X or 2.X", type="index")
with gr.Tab("Weights Setting"):
with gr.Group(), gr.Tabs():
with gr.Tab("Weights for alpha"):
with gr.Row(variant="compact"):
weights_a = gr.Textbox(label="BASE,IN00,IN02,...IN11,M00,OUT00,...,OUT11",value = "0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5", show_copy_button=True)
with gr.Row(scale=2):
setalpha = gr.Button(elem_id="copytogen", value="↑ Set alpha",variant='primary', scale=3)
readalpha = gr.Button(elem_id="copytogen", value="↓ Read alpha",variant='primary', scale=3)
setx = gr.Button(elem_id="copytogen", value="↑ Set X", min_width="80px", scale=1)
with gr.Tab("beta"):
with gr.Row(variant="compact"):
weights_b = gr.Textbox(label="BASE,IN00,IN02,...IN11,M00,OUT00,...,OUT11",value = "0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2", show_copy_button=True)
with gr.Row(scale=2):
setbeta = gr.Button(elem_id="copytogen", value="↑ Set beta",variant='primary', scale=3)
readbeta = gr.Button(elem_id="copytogen", value="↓ Read beta",variant='primary', scale=3)
sety = gr.Button(elem_id="copytogen", value="↑ Set Y", min_width="80px", scale=1)
with gr.Group(), gr.Tabs():
with gr.Tab("Preset"):
with gr.Row():
dd_preset_weight = gr.Dropdown(label="Select preset", choices=preset_name_list(weights_presets), interactive=True, elem_id="refresh_presets")
preset_refresh = gr.Button(value='\U0001f504', elem_classes=["tool"])
with gr.Tab("Random Preset"):
with gr.Row():
dd_preset_weight_r = gr.Dropdown(label="Load Romdom preset", choices=preset_name_list(weights_presets,True), interactive=True, elem_id="refresh_presets")
preset_refresh_r = gr.Button(value='\U0001f504', elem_classes=["tool"])
luckab = gr.Radio(label = "for",choices = ["none", "alpha", "beta"], value = "none", type="value")
with gr.Tab("Helper"):
with gr.Column():
resetval = gr.Slider(label="Value", show_label=False, info="Value to set/add/mul", minimum=0, maximum=2, step=0.0001, value=0)
resetopt = gr.Radio(label="Pre defined", show_label=False, choices = ["0", "0.25", "0.5", "0.75", "1"], value = "0", type="value")
with gr.Column():
resetblockopt = gr.CheckboxGroup(["BASE","INP*","MID","OUT*"], value=["INP*","OUT*"], label="Blocks", show_label=False, info="Select blocks to change")
with gr.Column():
with gr.Row():
resetweight = gr.Button(elem_classes=["reset"], value="Set")
addweight = gr.Button(elem_classes=["reset"], value="Add")
mulweight = gr.Button(elem_classes=["reset"], value="Mul")
with gr.Row():
lower = gr.Slider(label="Slider Lower Limit", minimum=-2, maximum=3, step=0.1, value=0)
upper = gr.Slider(label="Slider Upper Limit", minimum=-2, maximum=3, step=0.1, value=1)
with gr.Row():
with gr.Column(scale=1, min_width=100):
gr.Slider(visible=False)
with gr.Column(scale=2, min_width=200):
base = gr.Slider(label="Base", minimum=0, maximum=1, step=0.0001, value=0.5)
with gr.Column(scale=1, min_width=100):
gr.Slider(visible=False)
with gr.Row():
with gr.Column(scale=2, min_width=200):
in00 = gr.Slider(label="IN00", minimum=0, maximum=1, step=0.0001, value=0.5)
in01 = gr.Slider(label="IN01", minimum=0, maximum=1, step=0.0001, value=0.5)
in02 = gr.Slider(label="IN02", minimum=0, maximum=1, step=0.0001, value=0.5)
in03 = gr.Slider(label="IN03", minimum=0, maximum=1, step=0.0001, value=0.5)
in04 = gr.Slider(label="IN04", minimum=0, maximum=1, step=0.0001, value=0.5)
in05 = gr.Slider(label="IN05", minimum=0, maximum=1, step=0.0001, value=0.5)
in06 = gr.Slider(label="IN06", minimum=0, maximum=1, step=0.0001, value=0.5)
in07 = gr.Slider(label="IN07", minimum=0, maximum=1, step=0.0001, value=0.5)
in08 = gr.Slider(label="IN08", minimum=0, maximum=1, step=0.0001, value=0.5)
in09 = gr.Slider(label="IN09", minimum=0, maximum=1, step=0.0001, value=0.5)
in10 = gr.Slider(label="IN10", minimum=0, maximum=1, step=0.0001, value=0.5)
in11 = gr.Slider(label="IN11", minimum=0, maximum=1, step=0.0001, value=0.5)
with gr.Column(scale=2, min_width=200):
ou11 = gr.Slider(label="OUT11", minimum=0, maximum=1, step=0.0001, value=0.5)
ou10 = gr.Slider(label="OUT10", minimum=0, maximum=1, step=0.0001, value=0.5)
ou09 = gr.Slider(label="OUT09", minimum=0, maximum=1, step=0.0001, value=0.5)
ou08 = gr.Slider(label="OUT08", minimum=0, maximum=1, step=0.0001, value=0.5)
ou07 = gr.Slider(label="OUT07", minimum=0, maximum=1, step=0.0001, value=0.5)
ou06 = gr.Slider(label="OUT06", minimum=0, maximum=1, step=0.0001, value=0.5)
ou05 = gr.Slider(label="OUT05", minimum=0, maximum=1, step=0.0001, value=0.5)
ou04 = gr.Slider(label="OUT04", minimum=0, maximum=1, step=0.0001, value=0.5)
ou03 = gr.Slider(label="OUT03", minimum=0, maximum=1, step=0.0001, value=0.5)
ou02 = gr.Slider(label="OUT02", minimum=0, maximum=1, step=0.0001, value=0.5)
ou01 = gr.Slider(label="OUT01", minimum=0, maximum=1, step=0.0001, value=0.5)
ou00 = gr.Slider(label="OUT00", minimum=0, maximum=1, step=0.0001, value=0.5)
with gr.Row():
with gr.Column(scale=1, min_width=100):
gr.Slider(visible=False)
with gr.Column(scale=2, min_width=200):
mi00 = gr.Slider(label="M00", minimum=0, maximum=1, step=0.0001, value=0.5)
with gr.Column(scale=1, min_width=100):
gr.Slider(visible=False)
with gr.Tab("Weights Presets"):
with gr.Row():
s_reloadtext = gr.Button(value="Reload Presets",variant='primary')
s_reloadtags = gr.Button(value="Reload Tags",variant='primary')
s_savetext = gr.Button(value="Save Presets",variant='primary')
s_openeditor = gr.Button(value="Open TextEditor",variant='primary')
weightstags= gr.Textbox(label="available",lines = 2,value=tagdicter(weights_presets),visible =True,interactive =True)
wpresets= gr.TextArea(label="",value=(weights_presets+ADDRAND),visible =True,interactive = True)
with gr.Accordion("XYZ Plot", open=False):
with gr.Row():
x_type = gr.Dropdown(label="X type", choices=[x for x in TYPESEG], value="alpha", type="index")
x_randseednum = gr.Number(value=3, label="number of -1", interactive=True, visible = True)
xgrid = gr.Textbox(label="X Values",lines=3,value="0.25,0.5,0.75")
y_type = gr.Dropdown(label="Y type", choices=[y for y in TYPESEG], value="none", type="index")
ygrid = gr.Textbox(label="Y Values (Disabled if blank)",lines=3,value="",visible =False)
z_type = gr.Dropdown(label="Z type", choices=[y for y in TYPESEG], value="none", type="index")
zgrid = gr.Textbox(label="Z Values (Disabled if blank)",lines=3,value="",visible =False)
esettings = gr.CheckboxGroup(label = "XYZ plot settings",choices=["swap XY","save model","save csv","save anime gif","not save grid","print change","0 stock"],type="value",interactive=True)
with gr.Row():
components.gengrid = gr.Button(elem_id="model_merger_merge", value="Run XYZ Plot",variant='primary')
stopgrid = gr.Button(elem_id="model_merger_merge", value="Stop XYZ Plot")
components.s_reserve1 = gr.Button(value="Reserve XYZ Plot",variant='primary')
with gr.Accordion("XYZ presets",open = True):
with gr.Row():
xyzpresets = gr.Dropdown(label="Preset name",allow_custom_value=True,choices=get_xyzpreset_keylist(),scale=10)
refreshxyzpresets_b = gr.Button(value='\U0001f504', elem_classes=["tool"],scale=1)
savexyzpreset_overwrite = gr.CheckboxGroup(label = " ",choices=["Overwrite"],type="index",interactive=True,scale=1)
with gr.Row():
loadxyzpreset_b = gr.Button(value="Load preset",variant='primary')
savexyzpreset_b = gr.Button(value="Save current plot as preset",variant='primary')
deletexyzpreset_b = gr.Button(value="Delete preset",variant='primary')
openxyzpreset = gr.Button(value="Open XYZ Preset file")
openxyzpreset.click(fn=lambda:subprocess.Popen(['start', xyzpath], shell=True))
with gr.Column(visible = False, variant="compact") as row_inputers:
with gr.Row(variant="compact"):
inputer = gr.Textbox(label="Selected", lines=1, value="", show_copy_button=True)
with gr.Row(variant="compact"):
addtox = gr.Button(value="↑ Add to X Values")
addtoy = gr.Button(value="↑ Add to Y Values")
addtoz = gr.Button(value="↑ Add to Z Values")
with gr.Row(visible = False) as row_blockids:
blockids = gr.CheckboxGroup(label = "block IDs",choices=BLOCKID[:-1],type="value",interactive=True)
with gr.Row(visible = False) as row_calcmode:
calcmodes = gr.CheckboxGroup(label = "calcmode",choices=CALCMODES,type="value",interactive=True)
with gr.Row(visible = False) as row_checkpoints:
checkpoints = gr.CheckboxGroup(label = "checkpoints",choices=[x.model_name for x in sd_models.checkpoints_list.values()],type="value",interactive=True)
create_refresh_button(checkpoints, sd_models.list_models, lambda: {"choices": [x.model_name for x in sd_models.checkpoints_list.values()]}, "refresh_checkpoint_xyz")
with gr.Row(visible = False) as row_blocks:
gr.HTML(value="BASE,IN00,IN01,IN02,IN03,IN04,IN05,IN06,IN07,IN08,IN09,IN10,IN11
,M00,OUT00,OUT01,OUT02,OUT03,OUT04,OUT05,OUT06,OUT07,OUT08,OUT09,OUT10,OUT11,Adjust,VAE,print
")
with gr.Accordion("Reservation", open=False):
with gr.Row():
components.s_reserve = gr.Button(value="Reserve XY Plot",variant='primary')
s_reloadreserve = gr.Button(value="Reloat List",variant='primary')
components.s_startreserve = gr.Button(value="Start XY plot",variant='primary')
s_delreserve = gr.Button(value="Delete list(-1 for all)",variant='primary')
s_delnum = gr.Number(value=1, label="Delete num : ", interactive=True, visible = True,precision =0)
with gr.Row():
components.numaframe = gr.Dataframe(
headers=["No.","status","xtype","xmenber","ytype","ymenber","ztype","zmenber","model A","model B","model C","alpha","beta","mode","use MBW","weights alpha","weights beta"],
row_count=5,)
components.dtrue = gr.Checkbox(value = True, visible = False)
components.dfalse = gr.Checkbox(value = False,visible = False)
dummy_t = gr.Textbox(value = "",visible = False)
with gr.Accordion("Elemental Merge",open = False):
with gr.Row():
components.esettings1 = gr.CheckboxGroup(label = "settings",choices=["print change"],type="value",interactive=True)
with gr.Row():
deep = gr.Textbox(label="Blocks:Element:Ratio,Blocks:Element:Ratio,...",lines=2,value="")
with gr.Accordion("Adjust", open=False) as acc_ad:
with gr.Row(variant="compact"):
finetune = gr.Textbox(label="Adjust", show_label=False, info="Adjust IN,OUT,OUT2,Contrast,Brightness,COL1,COL2,COL3", visible=True, value="", lines=1)
finetune_write = gr.Button(value="↑", elem_classes=["tool"])
finetune_read = gr.Button(value="↓", elem_classes=["tool"])
finetune_reset = gr.Button(value="\U0001f5d1\ufe0f", elem_classes=["tool"])
with gr.Row(variant="compact"):
with gr.Column(scale=1, min_width=100):
detail1 = gr.Slider(label="IN", minimum=-6, maximum=6, step=0.01, value=0, info="Detail/Noise")
with gr.Column(scale=1, min_width=100):
detail2 = gr.Slider(label="OUT", minimum=-6, maximum=6, step=0.01, value=0, info="Detail/Noise")
with gr.Column(scale=1, min_width=100):
detail3 = gr.Slider(label="OUT2", minimum=-6, maximum=6, step=0.01, value=0, info="Detail/Noise")
with gr.Row(variant="compact"):
with gr.Column(scale=1, min_width=100):
contrast = gr.Slider(label="Contrast", minimum=-10, maximum=10, step=0.01, value=0, info="Contrast/Detail")
with gr.Column(scale=1, min_width=100):
bri = gr.Slider(label="Brightness", minimum=-10, maximum=10, step=0.01, value=0, info="Dark(Minius)-Bright(Plus)")
with gr.Row(variant="compact"):
with gr.Column(scale=1, min_width=100):
col1 = gr.Slider(label="Cyan-Red", minimum=-10, maximum=10, step=0.01, value=0, info="Cyan(Minius)-Red(Plus)")
with gr.Column(scale=1, min_width=100):
col2 = gr.Slider(label="Magenta-Green", minimum=-10, maximum=10, step=0.01, value=0, info="Magenta(Minius)-Green(Plus)")
with gr.Column(scale=1, min_width=100):
col3 = gr.Slider(label="Yellow-Blue", minimum=-10, maximum=10, step=0.01, value=0, info="Yellow(Minius)-Blue(Plus)")
finetune.change(fn=lambda x:gr.update(label = f"Adjust : {x}"if x != "" and x !="0,0,0,0,0,0,0,0" else "Adjust"),inputs=[finetune],outputs = [acc_ad])
with gr.Accordion("Let the Dice roll",open = False,visible=True):
with gr.Row():
gr.HTML(value="R:0~1, U: -0.5~1.5
")
with gr.Row():
luckmode = gr.Radio(label = "Random Mode",choices = ["off", "R", "U", "X", "ER", "EU", "EX","custom"], value = "off")
with gr.Row():
lucksets = gr.CheckboxGroup(label = "Settings",choices=["alpha","beta","save E-list"],value=["alpha"],type="value",interactive=True)
with gr.Row():
luckseed = gr.Number(minimum=-1, maximum=4294967295, step=1, label='Seed for Random Ratio', value=-1, elem_id="luckseed")
luckround = gr.Number(minimum=1, maximum=4294967295, step=1, label='Round', value=3, elem_id="luckround")
luckserial = gr.Number(minimum=1, maximum=4294967295, step=1, label='Num of challenge', value=1, elem_id="luckchallenge")
with gr.Row():
luckcustom = gr.Textbox(label="custom",value = "U,0,0,0,0,0,0,0,0,0,0,0,0,R,R,R,R,R,R,R,R,R,R,R,R,R")
with gr.Row():
lucklimits_u = gr.Textbox(label="Upper limit for X",value = "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1")
with gr.Row():
lucklimits_l = gr.Textbox(label="Lower limit for X",value = "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
components.rand_merge = gr.Button(elem_id="runrandmerge", value="Run Rand",variant='primary')
with gr.Accordion("Generation Parameters",open = False):
gr.HTML(value='If blank or set to 0, parameters in the "txt2img" tab are used.
batch size, restore face, hires fix settigns must be set here')
prompt = gr.Textbox(label="prompt",lines=1,value="")
neg_prompt = gr.Textbox(label="neg_prompt",lines=1,value="")
with gr.Row():
sampler = gr.Dropdown(label='Sampling method', elem_id=f"sampling", choices=[" ",*[x.name for x in samplers]], value=" ", type="index")
steps = gr.Slider(minimum=0.0, maximum=150, step=1, label='Steps',value=0, elem_id="Steps")
cfg = gr.Slider(minimum=0.0, maximum=30, step=0.5, label='CFG scale', value=0, elem_id="cfg")
with gr.Row():
width = gr.Slider(minimum=0, maximum=2048, step=8, label="Width", value=0, elem_id="txt2img_width")
height = gr.Slider(minimum=0, maximum=2048, step=8, label="Height", value=0, elem_id="txt2img_height")
seed = gr.Number(minimum=-1, maximum=4294967295, step=1, label='Seed', value=0, elem_id="seed")
batch_size = denois_str = gr.Slider(minimum=0, maximum=8, step=1, label='Batch size', value=1, elem_id="sm_txt2img_batch_size")
genoptions = gr.CheckboxGroup(label = "Gen Options",choices=["Restore faces", "Tiling", "Hires. fix"], visible = True,interactive=True,type="value")
with gr.Row(elem_id="txt2img_hires_fix_row1", variant="compact"):
hrupscaler = gr.Dropdown(label="Upscaler", elem_id="txt2img_hr_upscaler", choices=[*shared.latent_upscale_modes, *[x.name for x in shared.sd_upscalers]], value=shared.latent_upscale_default_mode)
hr2ndsteps = gr.Slider(minimum=0, maximum=150, step=1, label='Hires steps', value=0, elem_id="txt2img_hires_steps")
denois_str = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising strength', value=0.7, elem_id="txt2img_denoising_strength")
hr_scale = gr.Slider(minimum=1.0, maximum=4.0, step=0.05, label="Upscale by", value=2.0, elem_id="txt2img_hr_scale")
with gr.Row():
setdefault = gr.Button(elem_id="setdefault", value="set to default",variant='primary')
resetdefault = gr.Button(elem_id="resetdefault", value="reset default",variant='primary')
resetcurrent = gr.Button(elem_id="resetcurrent", value="reset current",variant='primary')
with gr.Accordion("Include/Exclude", open=False) as acc_ex:
with gr.Row():
inex = gr.Radio(label="Mode", choices=["Off","Include","Exclude"], value="Off")
with gr.Row():
ex_blocks = gr.CheckboxGroup(choices=EXCLUDE_CHOICES + ["print"], visible = True,interactive=True,type="value")
with gr.Row():
ex_elems = gr.Textbox(label="Elements")
inex.change(fn=lambda i, x,y: gr.update(label =f"{i} : " + ",".join(x) +","+ y if x != [] or y != "" else "Include/Exclude"), inputs = [inex,ex_blocks,ex_elems],outputs = [acc_ex])
ex_blocks.change(fn=lambda i, x,y: gr.update(label =f"{i} : " + ",".join(x) +","+ y if x != [] or y != "" else "Include/Exclude"), inputs = [inex,ex_blocks,ex_elems],outputs = [acc_ex])
ex_elems.change(fn=lambda i, x,y: gr.update(label =f"{i} : " + ",".join(x) +","+ y if x != [] or y != "" else "Include/Exclude"),inputs=[inex,ex_blocks,ex_elems],outputs = [acc_ex])
with gr.Accordion("Advanced", open=False):
with gr.Row():
currentcache = gr.Textbox(label="Current Cache")
loadcachelist = gr.Button(elem_id="model_merger_merge", value="Reload Cache List",variant='primary')
unloadmodel = gr.Button(value="unload model",variant='primary')
with gr.Column(variant="compact"):
components.currentmodel = gr.Textbox(label="Current Model",lines=1,value="")
components.submit_result = gr.Textbox(label="Message")
output_panel = create_output_panel("txt2img", opts.outdir_txt2img_samples)
mgallery = output_panel[0] if isinstance(output_panel, tuple) else output_panel.gallery
mgeninfo = output_panel[1] if isinstance(output_panel, tuple) else output_panel.generation_info
mhtmlinfo = output_panel[2] if isinstance(output_panel, tuple) else output_panel.infotext
mhtmllog = output_panel[3] if isinstance(output_panel, tuple) else output_panel.html_log
# main ui end
with gr.Tab("LoRA", elem_id="tab_lora"):
pluslora.on_ui_tabs()
with gr.Tab("Analysis", elem_id="tab_analysis"):
with gr.Tab("Models"):
with gr.Row():
an_model_a = gr.Dropdown(sd_models.checkpoint_tiles(),elem_id="model_converter_model_name",label="Checkpoint A",interactive=True)
create_refresh_button(an_model_a, sd_models.list_models,lambda: {"choices": sd_models.checkpoint_tiles()},"refresh_checkpoint_Z")
an_model_b = gr.Dropdown(sd_models.checkpoint_tiles(),elem_id="model_converter_model_name",label="Checkpoint B",interactive=True)
create_refresh_button(an_model_b, sd_models.list_models,lambda: {"choices": sd_models.checkpoint_tiles()},"refresh_checkpoint_Z")
with gr.Row():
an_mode = gr.Radio(label = "Analysis Mode",choices = ["ASimilarity","Block","Element","Both"], value = "ASimilarity",type = "value")
an_calc = gr.Radio(label = "Block method",choices = ["Mean","Min","attn2"], value = "Mean",type = "value")
an_include = gr.CheckboxGroup(label = "Include",choices = ["Textencoder(BASE)","U-Net","VAE"], value = ["Textencoder(BASE)","U-Net"],type = "value")
an_settings = gr.CheckboxGroup(label = "Settings",choices=["save as txt", "save as csv"],type="value",interactive=True)
with gr.Row():
run_analysis = gr.Button(value="Run Analysis",variant='primary')
with gr.Row():
analysis_cosdif = gr.Dataframe(headers=["block","key","similarity[%]"],)
with gr.Tab("Text Encoder"):
with gr.Row():
te_smd_loadkeys = gr.Button(value="Calculate Textencoer",variant='primary')
te_smd_searchkeys = gr.Button(value="Search Word(red,blue,girl,...)",variant='primary')
exclude = gr.Checkbox(label="exclude non numeric,alphabet,symbol word")
pickupword = gr.TextArea()
encoded = gr.Dataframe()
run_analysis.click(fn=calccosinedif,inputs=[an_model_a,an_model_b,an_mode,an_settings,an_include,an_calc],outputs=[analysis_cosdif])
with gr.Tab("History", elem_id="tab_history"):
with gr.Row():
with gr.Column(scale = 2):
with gr.Row():
count = gr.Dropdown(choices=["20", "30", "40", "50", "100"], value="20", label="Load count")
load_history = gr.Button(value="Load history",variant='primary', elem_classes=["reset"])
reload_history = gr.Button(value="Reload history", elem_classes=["reset"])
with gr.Column(scale = 2):
with gr.Row():
searchwrods = gr.Textbox(label="",lines=1,value="")
search = gr.Button(value="search", elem_classes=["reset"])
searchmode = gr.Radio(label = "Search Mode",choices = ["or","and"], value = "or",type = "value")
with gr.Row():
history = gr.Dataframe(
headers=["ID","Time","Name","Weights alpha","Weights beta","Model A","Model B","Model C","alpha","beta","Mode","use MBW","custum name","save setting","use ID"],
)
import lora
with gr.Tab("Elements", elem_id="tab_deep"):
with gr.Row():
smd_model_a = gr.Dropdown(sd_models.checkpoint_tiles(),elem_id="model_converter_model_name",label="Checkpoint",interactive=True)
create_refresh_button(smd_model_a, sd_models.list_models,lambda: {"choices": sd_models.checkpoint_tiles()},"refresh_checkpoint_Z")
smd_loadkeys = gr.Button(value="load keys",variant='primary')
with gr.Row():
smd_lora = gr.Dropdown(list(lora.available_loras.keys()),elem_id="model_converter_model_name",label="LoRA",interactive=True)
create_refresh_button(smd_lora, lora.list_available_loras, lambda: {"choices": list(lora.available_loras.keys())},"refresh_checkpoint_Z")
smd_loadkeys_l = gr.Button(value="load keys",variant='primary')
with gr.Row():
keys = gr.Dataframe(headers=["No.","block","key"],)
with gr.Tab("Metadeta", elem_id="tab_metadata"):
with gr.Row():
meta_model_a = gr.Dropdown(sd_models.checkpoint_tiles(),elem_id="model_converter_model_name",label="read metadata",interactive=True)
create_refresh_button(meta_model_a, sd_models.list_models,lambda: {"choices": sd_models.checkpoint_tiles()},"refresh_checkpoint_Z")
smd_loadmetadata = gr.Button(value="load keys",variant='primary')
with gr.Row():
metadata = gr.TextArea()
smd_loadmetadata.click(
fn=loadmetadata,
inputs=[meta_model_a],
outputs=[metadata]
)
mclearcache.click(fn=clearcache)
smd_loadkeys.click(fn=loadkeys,inputs=[smd_model_a,components.dfalse],outputs=[keys])
smd_loadkeys_l.click(fn=loadkeys,inputs=[smd_lora,components.dtrue],outputs=[keys])
te_smd_loadkeys.click(fn=encodetexts,inputs=[exclude],outputs=[encoded])
te_smd_searchkeys.click(fn=pickupencode,inputs=[pickupword],outputs=[encoded])
def unload():
if shared.sd_model == None: return "already unloaded"
load_model,unload_model_weights()
return "model unloaded"
unloadmodel.click(fn=unload,outputs=[components.submit_result])
load_history.click(fn=load_historyf,inputs=[history,count],outputs=[history])
reload_history.click(fn=load_historyf,inputs=[history,count,components.dtrue],outputs=[history])
components.msettings=[weights_a,weights_b,model_a,model_b,model_c,base_alpha,base_beta,mode,calcmode,useblocks,custom_name,save_sets,components.id_sets,wpresets,deep,finetune,bake_in_vae,opt_value,inex,ex_blocks,ex_elems]
components.imagegal = [mgallery,mgeninfo,mhtmlinfo,mhtmllog]
components.xysettings=[x_type,xgrid,y_type,ygrid,z_type,zgrid,esettings]
components.genparams=[prompt,neg_prompt,steps,sampler,cfg,seed,width,height,batch_size]
components.hiresfix = [genoptions,hrupscaler,hr2ndsteps,denois_str,hr_scale]
components.lucks = [luckmode,lucksets,lucklimits_u,lucklimits_l,luckseed,luckserial,luckcustom,luckround]
setdefault.click(fn = configdealer,
inputs =[*components.genparams,*components.hiresfix[1:],components.dfalse],
)
resetdefault.click(fn = configdealer,
inputs =[*components.genparams,*components.hiresfix[1:],components.dtrue],
)
resetcurrent.click(fn = lambda x : [gr.update(value = x) for x in RESETVALS] ,outputs =[*components.genparams,*components.hiresfix[1:]],)
s_reverse.click(fn = reversparams,
inputs =mergeid,
outputs = [components.submit_result,*components.msettings[0:8],*components.msettings[9:13],deep,calcmode,luckseed,finetune,opt_value,inex,ex_blocks,ex_elems]
)
search.click(fn = searchhistory,inputs=[searchwrods,searchmode],outputs=[history])
s_reloadreserve.click(fn=nulister,inputs=[components.dfalse],outputs=[components.numaframe])
s_delreserve.click(fn=nulister,inputs=[s_delnum],outputs=[components.numaframe])
loadcachelist.click(fn=getcachelist,inputs=[],outputs=[currentcache])
addtox.click(fn=lambda x:gr.Textbox.update(value = x),inputs=[inputer],outputs=[xgrid])
addtoy.click(fn=lambda x:gr.Textbox.update(value = x),inputs=[inputer],outputs=[ygrid])
addtoz.click(fn=lambda x:gr.Textbox.update(value = x),inputs=[inputer],outputs=[zgrid])
stopgrid.click(fn=freezetime)
stopmerge.click(fn=freezemtime)
checkpoints.change(fn=lambda x:",".join(x),inputs=[checkpoints],outputs=[inputer])
blockids.change(fn=lambda x:" ".join(x),inputs=[blockids],outputs=[inputer])
calcmodes.change(fn=lambda x:",".join(x),inputs=[calcmodes],outputs=[inputer])
menbers = [base,in00,in01,in02,in03,in04,in05,in06,in07,in08,in09,in10,in11,mi00,ou00,ou01,ou02,ou03,ou04,ou05,ou06,ou07,ou08,ou09,ou10,ou11]
menbers_plus = menbers + [resetval]
lower.change(fn = lambda x: [gr.update(minimum = x) for i in range(len(menbers_plus))],inputs = [lower],outputs = menbers_plus)
upper.change(fn = lambda x: [gr.update(maximum = x) for i in range(len(menbers_plus))],inputs = [upper],outputs = menbers_plus)
setalpha.click(fn=slider2text,inputs=[*menbers,wpresets, dd_preset_weight,isxl],outputs=[weights_a])
setbeta.click(fn=slider2text,inputs=[*menbers,wpresets, dd_preset_weight,isxl],outputs=[weights_b])
setx.click(fn=add_to_seq,inputs=[xgrid,weights_a],outputs=[xgrid])
sety.click(fn=add_to_seq,inputs=[ygrid,weights_b],outputs=[ygrid])
mode_info = {
"Weight sum": "A*(1-alpha)+B*alpha",
"Add difference": "A+(B-C)*alpha",
"Triple sum": "A*(1-alpha-beta)+B*alpha+C*beta",
"sum Twice": "(A*(1-alpha)+B*alpha)*(1-beta)+C*beta"
}
mode.change(fn=lambda mode,calcmode: [gr.update(info=mode_info[mode]), gr.update(interactive=True if mode in ["Triple sum", "sum Twice"] or calcmode in ["tensor", "tensor2"] else False)], inputs=[mode,calcmode], outputs=[mode, base_beta], show_progress=False)
calcmode.change(fn=lambda calcmode: gr.update(interactive=True) if calcmode in ["tensor", "tensor2","extract"] else gr.update(), inputs=[calcmode], outputs=base_beta, show_progress=False)
useblocks.change(fn=lambda mbw: gr.update(visible=False if mbw else True), inputs=[useblocks], outputs=[alpha_group])
def save_current_merge(custom_name, save_settings):
msg = savemodel(None,None,custom_name,save_settings)
return gr.update(value=msg)
def addblockweights(val, blockopt, *blocks):
if val == "none":
val = 0
value = float(val)
if "BASE" in blockopt:
vals = [blocks[0] + value]
else:
vals = [blocks[0]]
if "INP*" in blockopt:
inp = [blocks[i + 1] + value for i in range(12)]
else:
inp = [blocks[i + 1] for i in range(12)]
vals = vals + inp
if "MID" in blockopt:
mid = [blocks[13] + value]
else:
mid = [blocks[13]]
vals = vals + mid
if "OUT*" in blockopt:
out = [blocks[i + 14] + value for i in range(12)]
else:
out = [blocks[i + 14] for i in range(12)]
vals = vals + out
return setblockweights(vals, blockopt)
def mulblockweights(val, blockopt, *blocks):
if val == "none":
val = 0
value = float(val)
if "BASE" in blockopt:
vals = [blocks[0] * value]
else:
vals = [blocks[0]]
if "INP*" in blockopt:
inp = [blocks[i + 1] * value for i in range(12)]
else:
inp = [blocks[i + 1] for i in range(12)]
vals = vals + inp
if "MID" in blockopt:
mid = [blocks[13] * value]
else:
mid = [blocks[13]]
vals = vals + mid
if "OUT*" in blockopt:
out = [blocks[i + 14] * value for i in range(12)]
else:
out = [blocks[i + 14] for i in range(12)]
vals = vals + out
return setblockweights(vals, blockopt)
def resetblockweights(val, blockopt):
if val == "none":
val = 0
vals = [float(val)] * 26
return setblockweights(vals, blockopt)
def setblockweights(vals, blockopt):
if "BASE" in blockopt:
ret = [gr.update(value = vals[0])]
else:
ret = [gr.update()]
if "INP*" in blockopt:
inp = [gr.update(value = vals[i + 1]) for i in range(12)]
else:
inp = [gr.update() for _ in range(12)]
ret = ret + inp
if "MID" in blockopt:
mid = [gr.update(value = vals[13])]
else:
mid = [gr.update()]
ret = ret + mid
if "OUT*" in blockopt:
out = [gr.update(value = vals[i + 14]) for i in range(12)]
else:
out = [gr.update() for _ in range(12)]
ret = ret + out
return ret
def resetvalopt(opt):
if opt == "none":
value = 0.0
else:
value = float(opt)
return gr.update(value = value)
def finetune_update(finetune, detail1, detail2, detail3, contrast, bri, col1, col2, col3):
arr = [detail1, detail2, detail3, contrast, bri, col1, col2, col3]
tmp = ",".join(map(lambda x: str(int(x)) if x == 0.0 else str(x), arr))
if finetune != tmp:
return gr.update(value=tmp)
return gr.update()
def finetune_reader(finetune):
tmp = [t.strip() for t in finetune.split(",")]
ret = [gr.update()]*7
for i, f in enumerate(tmp[0:7]):
try:
f = float(f)
ret[i] = gr.update(value=f)
except:
pass
return ret
# update finetune
finetunes = [detail1, detail2, detail3, contrast, bri, col1, col2, col3]
finetune_reset.click(fn=lambda: [gr.update(value="")]+[gr.update(value=0.0)]*8, inputs=[], outputs=[finetune, *finetunes])
finetune_read.click(fn=finetune_reader, inputs=[finetune], outputs=[*finetunes])
finetune_write.click(fn=finetune_update, inputs=[finetune, *finetunes], outputs=[finetune])
detail1.release(fn=finetune_update, inputs=[finetune, *finetunes], outputs=finetune, show_progress=False)
detail2.release(fn=finetune_update, inputs=[finetune, *finetunes], outputs=finetune, show_progress=False)
detail3.release(fn=finetune_update, inputs=[finetune, *finetunes], outputs=finetune, show_progress=False)
contrast.release(fn=finetune_update, inputs=[finetune, *finetunes], outputs=finetune, show_progress=False)
bri.release(fn=finetune_update, inputs=[finetune, *finetunes], outputs=finetune, show_progress=False)
col1.release(fn=finetune_update, inputs=[finetune, *finetunes], outputs=finetune, show_progress=False)
col2.release(fn=finetune_update, inputs=[finetune, *finetunes], outputs=finetune, show_progress=False)
col3.release(fn=finetune_update, inputs=[finetune, *finetunes], outputs=finetune, show_progress=False)
savecurrent.click(fn=save_current_merge, inputs=[custom_name, save_sets], outputs=[components.submit_result])
resetopt.change(fn=resetvalopt,inputs=[resetopt],outputs=[resetval])
resetweight.click(fn=resetblockweights,inputs=[resetval,resetblockopt],outputs=menbers)
addweight.click(fn=addblockweights,inputs=[resetval,resetblockopt,*menbers],outputs=menbers)
mulweight.click(fn=mulblockweights,inputs=[resetval,resetblockopt,*menbers],outputs=menbers)
readalpha.click(fn=text2slider,inputs=[weights_a,isxl],outputs=menbers)
readbeta.click(fn=text2slider,inputs=[weights_b,isxl],outputs=menbers)
dd_preset_weight.change(fn=on_change_dd_preset_weight,inputs=[wpresets, dd_preset_weight],outputs=menbers)
dd_preset_weight_r.change(fn=on_change_dd_preset_weight_r,inputs=[wpresets, dd_preset_weight_r,luckab],outputs=[weights_a,weights_b])
def refresh_presets(presets,rand,ab = ""):
choices = preset_name_list(presets,rand)
return gr.update(choices = choices)
preset_refresh.click(fn=refresh_presets,inputs=[wpresets,components.dfalse],outputs=[dd_preset_weight])
preset_refresh_r.click(fn=refresh_presets,inputs=[wpresets,components.dtrue],outputs=[weights_a,weights_b])
def changexl(isxl):
out = [True] * 26
if isxl:
for i,id in enumerate(BLOCKID[:-1]):
if id not in BLOCKIDXLL[:-1]:
out[i] = False
return [gr.update(visible = x) for x in out]
isxl.change(fn=changexl,inputs=[isxl], outputs=menbers)
x_type.change(fn=showxy,inputs=[x_type,y_type,z_type], outputs=[row_blockids,row_checkpoints,row_inputers,ygrid,zgrid,row_blocks,row_calcmode])
y_type.change(fn=showxy,inputs=[x_type,y_type,z_type], outputs=[row_blockids,row_checkpoints,row_inputers,ygrid,zgrid,row_blocks,row_calcmode])
z_type.change(fn=showxy,inputs=[x_type,y_type,z_type], outputs=[row_blockids,row_checkpoints,row_inputers,ygrid,zgrid,row_blocks,row_calcmode])
x_randseednum.change(fn=makerand,inputs=[x_randseednum],outputs=[xgrid])
import subprocess
def openeditors():
subprocess.Popen(['start', filepath], shell=True)
def reloadpresets():
try:
with open(filepath) as f:
weights_presets = f.read()
choices = preset_name_list(weights_presets)
return [weights_presets, gr.update(choices = choices)]
except OSError as e:
pass
def savepresets(text):
with open(filepath,mode = 'w') as f:
f.write(text)
s_reloadtext.click(fn=reloadpresets,inputs=[],outputs=[wpresets, dd_preset_weight])
s_reloadtags.click(fn=tagdicter,inputs=[wpresets],outputs=[weightstags])
s_savetext.click(fn=savepresets,inputs=[wpresets],outputs=[])
s_openeditor.click(fn=openeditors,inputs=[],outputs=[])
def savexyzpreset_f(xtype, xvals, ytype, yvals, ztype, zvals, name, mode_overwrite):
new_data = {"xtype": TYPESEG[xtype], "xvalues": xvals,
"ytype": TYPESEG[ytype], "yvalues": yvals,
"ztype": TYPESEG[ztype], "zvalues": zvals
}
data = get_xyzpreset_data()
if mode_overwrite:
data[name] = new_data
else:
if name in data:
gr.Info(f"Supermerger: Preset {name} already exists.")
else:
data[name] = new_data
with open(xyzpath, 'w') as file:
json.dump(data, file, indent=4)
data_keys = list(data.keys())
return gr.update(choices = sorted(data_keys))
def deletexyzpreset_f(name):
data = get_xyzpreset_data()
try: del data[name]
except KeyError: gr.Info(f"Supermerger: Preset {name} not found.")
with open(xyzpath, 'w') as file:
json.dump(data, file, indent=4)
keys_list = list(data.keys())
return gr.update(choices = sorted(keys_list))
def loadxyzpreset_f(name):
data = get_xyzpreset_data()
preset_data = data.get(name)
if not preset_data:
gr.Info(f"Supermerger: Preset {name} not found.")
return [gr.update(value = x) for x in ["alpha","","none","","none",""]]
sets = [("xtype"),"xvalues","ytype","yvalues","ztype","zvalues"]
return [gr.update(value = preset_data.get(x)) for x in sets]
def refreshxyzpresets_f():
return gr.update(choices = get_xyzpreset_keylist())
savexyzpreset_b.click(fn=savexyzpreset_f,inputs=[x_type, xgrid, y_type, ygrid, z_type, zgrid,xyzpresets,savexyzpreset_overwrite],outputs=[xyzpresets])
loadxyzpreset_b.click(fn=loadxyzpreset_f,inputs=[xyzpresets],outputs=[x_type, xgrid, y_type, ygrid, z_type, zgrid])
deletexyzpreset_b.click(fn=deletexyzpreset_f,inputs=[xyzpresets],outputs=[xyzpresets])
refreshxyzpresets_b.click(fn=refreshxyzpresets_f,outputs=[xyzpresets])
return (supermergerui, "SuperMerger", "supermerger"),
msearch = []
mlist=[]
def loadmetadata(model):
import json
checkpoint_info = sd_models.get_closet_checkpoint_match(model)
if ".safetensors" not in checkpoint_info.filename: return "no metadata(not safetensors)"
sdict = sd_models.read_metadata_from_safetensors(checkpoint_info.filename)
if sdict == {}: return "no metadata"
return json.dumps(sdict,indent=4)
def load_historyf(data, count=20, reload=False):
filepath = os.path.join(path_root,"mergehistory.csv")
global mlist,msearch
try:
with open(filepath, 'r') as f:
reader = csv.reader(f)
next(reader) # skip header
row_count = sum(1 for row in reader)
count = int(count)
nth = None
if not reload and data is not None and len(data) > 1:
old = data.loc[len(data)-1, 'ID']
if old != '':
nth = int(old) - count - 1
if nth is None:
msearch = []
mlist = []
nth = row_count - count
f.seek(0)
next(reader)
nlist = [raw for n,raw in enumerate(reader, start=1) if n > nth and n <= (nth + count)]
nlist.reverse()
for m in nlist:
msearch.append(" ".join(m))
maxlen = len(nlist[-1][0])
for i,m in enumerate(nlist):
nlist[i][0] = nlist[i][0].zfill(maxlen)
mlist += nlist
return mlist
except:
return [["no data","",""],]
def searchhistory(words,searchmode):
outs =[]
ando = "and" in searchmode
words = words.split(" ") if " " in words else [words]
for i, m in enumerate(msearch):
hit = ando
for w in words:
if ando:
if w not in m:hit = False
else:
if w in m:hit = True
if hit :outs.append(mlist[i])
if outs == []:return [["no result","",""],]
return outs
#msettings=[0 weights_a,1 weights_b,2 model_a,3 model_b,4 model_c,5 base_alpha,6 base_beta,7 mode,8 useblocks,9 custom_name,10 save_sets,11 id_sets,12 wpresets]
#13 deep,14 calcmode,15 luckseed 16:opt_value 17 include/exclude 18: exclude_blocks, 19: exclude_elements
MSETSNUM = 20
def reversparams(id):
def selectfromhash(hash):
for model in sd_models.checkpoint_tiles():
if hash in model:
return model
return ""
try:
idsets = rwmergelog(id = id)
except:
return [gr.update(value = "ERROR: history file could not open"),*[gr.update() for x in range(MSETSNUM)]]
if type(idsets) == str:
print("ERROR")
return [gr.update(value = idsets),*[gr.update() for x in range(MSETSNUM)]]
if idsets[0] == "ID":return [gr.update(value ="ERROR: no history"),*[gr.update() for x in range(MSETSNUM)]]
mgs = idsets[3:]
if mgs[0] == "":mgs[0] = "0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5"
if mgs[1] == "":mgs[1] = "0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2"
def cutter(text):
text = text.replace("[","").replace("]","").replace("'", "")
return [x.strip() for x in text.split(",") if x != ""]
mgs[2] = selectfromhash(mgs[2]) if len(mgs[2]) > 5 else ""
mgs[3] = selectfromhash(mgs[3]) if len(mgs[3]) > 5 else ""
mgs[4] = selectfromhash(mgs[4]) if len(mgs[4]) > 5 else ""
mgs[7] = mgs[7].split(":")[0] # get mode name only
mgs[8] = mgs[8] =="True"
mgs[10] = cutter(mgs[10])
mgs[11] = cutter(mgs[11])
while len(mgs) < MSETSNUM:
mgs.append("")
mgs[13] = "normal" if mgs[13] == "" else mgs[13]
mgs[14] = -1 if mgs[14] == "" else mgs[14]
mgs[16] = 0.3 if mgs[16] == "" else float(mgs[16])
mgs[17] = "Off" if mgs[17] == "" else mgs[17]
mgs[18] = cutter(mgs[18])
mgs[18] = [x for x in mgs[18] if x in EXCLUDE_CHOICES + ["print"]]
return [gr.update(value = "setting loaded") ,*[gr.update(value = x) for x in mgs[0:MSETSNUM]]]
def add_to_seq(seq,maker):
return gr.Textbox.update(value = maker if seq=="" else seq+"\r\n"+maker)
def load_cachelist():
text = ""
for x in checkpoints_loaded.keys():
text = text +"\r\n"+ x.model_name
return text.replace("\r\n","",1)
def makerand(num):
text = ""
for x in range(int(num)):
text = text +"-1,"
text = text[:-1]
return text
#0 row_blockids, 1 row_checkpoints, 2 row_inputers,3 ygrid, 4 zgrid, 5 row_blocks, 6 row_calcmode
def showxy(x,y,z):
flags =[False]*7
t = TYPESEG
txy = t[x] + t[y] + t[z]
if "model" in txy : flags[1] = flags[2] = True
if "pinpoint" in txy : flags[0] = flags[2] = True
if "clude" in txy in txy : flags[5] = True
if "calcmode" in txy : flags[6] = True
if not "none" in t[y] : flags[3] = flags[2] = True
if not "none" in t[z] : flags[4] = flags[2] = True
return [gr.update(visible = x) for x in flags]
def get_xyzpreset_data():
try:
with open(xyzpath, 'r') as file:
return json.load(file)
except FileNotFoundError:
with open(xyzpath, 'w') as file:
json.dump({}, file, indent=4)
return {}
def get_xyzpreset_keylist():
keys_list = list(get_xyzpreset_data())
return sorted(keys_list)
def text2slider(text, isxl=False):
vals = [t.strip() for t in text.split(",")]
vals = [0 if v in "RUX" else v for v in vals]
if isxl:
j = 0
ret = []
for i, v in enumerate(ISXLBLOCK):
if v:
ret.append(gr.update(value = float(vals[j])))
j += 1
else:
ret.append(gr.update())
return ret
return [gr.update(value = float(v)) for v in vals]
def slider2text(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,presets, preset, isxl):
az = find_preset_by_name(presets, preset)
if az is not None:
if any(element in az for element in RANCHA):return az
numbers = [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z]
if isxl:
newnums = []
for i,id in enumerate(BLOCKID[:-1]):
if id in BLOCKIDXLL[:-1]:
newnums.append(numbers[i])
numbers = newnums
numbers = [str(x) for x in numbers]
return gr.update(value = ",".join(numbers) )
def on_change_dd_preset_weight(presets, preset):
weights = find_preset_by_name(presets, preset)
if weights is not None:
return text2slider(weights)
def on_change_dd_preset_weight_r(presets, preset, ab):
weights = find_preset_by_name(presets, preset)
if weights is not None:
if "none" in ab : return gr.update(),gr.update()
if "alpha" in ab : return gr.update(value = weights),gr.update()
if "beta" in ab : return gr.update(),gr.update(value = weights)
return gr.update(),gr.update()
RANCHA = ["R","U","X"]
def tagdicter(presets, rand = False):
presets=presets.splitlines()
wdict={}
for l in presets:
w=""
if ":" in l :
key = l.split(":",1)[0]
w = l.split(":",1)[1]
if "\t" in l:
key = l.split("\t",1)[0]
w = l.split("\t",1)[1]
if len([w for w in w.split(",")]) == 26:
if rand and not any(element in w for element in RANCHA) : continue
wdict[key.strip()]=w
return ",".join(list(wdict.keys()))
def preset_name_list(presets, rand = False):
return tagdicter(presets, rand).split(",")
def find_preset_by_name(presets, preset):
presets = presets.splitlines()
for l in presets:
if ":" in l:
key = l.split(":",1)[0]
w = l.split(":",1)[1]
elif "\t" in l:
key = l.split("\t",1)[0]
w = l.split("\t",1)[1]
else:
continue
if key == preset and len([w for w in w.split(",")]) == 26:
return w
return None
BLOCKID=["BASE","IN00","IN01","IN02","IN03","IN04","IN05","IN06","IN07","IN08","IN09","IN10","IN11","M00","OUT00","OUT01","OUT02","OUT03","OUT04","OUT05","OUT06","OUT07","OUT08","OUT09","OUT10","OUT11","Not Merge"]
BLOCKIDXL=['BASE', 'IN0', 'IN1', 'IN2', 'IN3', 'IN4', 'IN5', 'IN6', 'IN7', 'IN8', 'M', 'OUT0', 'OUT1', 'OUT2', 'OUT3', 'OUT4', 'OUT5', 'OUT6', 'OUT7', 'OUT8', 'VAE']
BLOCKIDXLL=['BASE', 'IN00', 'IN01', 'IN02', 'IN03', 'IN04', 'IN05', 'IN06', 'IN07', 'IN08', 'M00', 'OUT00', 'OUT01', 'OUT02', 'OUT03', 'OUT04', 'OUT05', 'OUT06', 'OUT07', 'OUT08', 'VAE']
ISXLBLOCK=[True, True, True, True, True, True, True, True, True, True, False, False, False, True, True, True, True, True, True, True, True, True, True, False, False, False]
def modeltype(sd):
if "conditioner.embedders.1.model.transformer.resblocks.9.mlp.c_proj.weight" in sd.keys():
modeltype = "XL"
else:
modeltype = "1.X or 2.X"
return modeltype
def loadkeys(model_a, lora):
if lora:
import lora
sd = sd_models.read_state_dict(lora.available_loras[model_a].filename,"cpu")
else:
sd = loadmodel(model_a)
keys = []
mtype = modeltype(sd)
if lora:
for i, key in enumerate(sd.keys()):
keys.append([i,"LoRA",key,sd[key].shape])
else:
for i, key in enumerate(sd.keys()):
keys.append([i,blockfromkey(key,mtype),key,sd[key].shape])
return keys
def loadmodel(model):
checkpoint_info = sd_models.get_closet_checkpoint_match(model)
sd = sd_models.read_state_dict(checkpoint_info.filename,"cpu")
return sd
ADDRAND = "\n\
ALL_R R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R,R\n\
ALL_U U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U,U\n\
ALL_X X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X\n\
"
def calccosinedif(model_a,model_b,mode,settings,include,calc):
inc = " ".join(include)
settings = " ".join(settings)
a, b = loadmodel(model_a), loadmodel(model_b)
name = filenamecutter(model_a) + "-" + filenamecutter(model_b)
cosine_similarities = []
blocksim = {}
blockvals = []
attn2 = {}
isxl = "XL" == modeltype(a)
blockids = BLOCKIDXLL if isxl else BLOCKID
for bl in blockids:
blocksim[bl] = []
blocksim["VAE"] = []
if "ASim" in mode:
result = asimilarity(a,b,isxl)
if len(settings) > 1: savecalc(result,name,settings,True,"Asim")
del a ,b
gc.collect()
return result
else:
for key in tqdm(a.keys(), desc="Calculating cosine similarity"):
block = None
if blockfromkey(key,isxl) == "Not Merge": continue
if "model_ema" in key: continue
if "model" not in key:continue
if "first_stage_model" in key and not ("VAE" in inc):
continue
elif "first_stage_model" in key and "VAE" in inc:
block = "VAE"
if "diffusion_model" in key and not ("U-Net" in inc): continue
if "encoder" in key and not ("encoder" in inc): continue
if key in b and a[key].size() == b[key].size():
a_flat = a[key].view(-1).to(torch.float32)
b_flat = b[key].view(-1).to(torch.float32)
simab = torch.nn.functional.cosine_similarity(a_flat.unsqueeze(0), b_flat.unsqueeze(0))
if block is None: block,blocks26 = blockfromkey(key,isxl)
if block =="Not Merge" :continue
cosine_similarities.append([block, key, round(simab.item()*100,3)])
blocksim[blocks26].append(round(simab.item()*100,3))
if "attn2.to_out.0.weight" in key: attn2[block] = round(simab.item()*100,3)
for bl in blockids:
val = None
if bl == "Not Merge": continue
if bl not in blocksim.keys():continue
if blocksim[bl] == []: continue
if "Mean" in calc:
val = mean(blocksim[bl])
elif "Min" in calc:
val = min(blocksim[bl])
else:
if bl in attn2.keys():val = attn2[bl]
if val:blockvals.append([bl,"",round(val,3)])
if mode != "Element": cosine_similarities.insert(0,[bl,"",round(mean(blocksim[bl]),3)])
if mode == "Block":
if len(settings) > 1: savecalc(blockvals,name,settings,True,"Blocks")
del a ,b
gc.collect()
return blockvals
else:
if len(settings) > 1: savecalc(cosine_similarities,name,settings,False,"Elements",)
del a ,b
gc.collect()
return cosine_similarities
def savecalc(data,name,settings,blocks,add):
name = name + "_" + add
csvpath = os.path.join(path_root,f"{name}.csv")
txtpath = os.path.join(path_root,f"{name}.txt")
txt = ""
for row in data:
row = [str(r) for r in row]
txt = txt + ",".join(row)+"\n"
if blocks: txt = txt.replace(",,",",")
if "txt" in settings:
with open(txtpath, 'w+') as f:
f.writelines(txt)
print("file saved to ",txtpath)
if "csv" in settings:
with open(csvpath, 'w+') as f:
f.writelines(txt)
print("file saved to ",csvpath)
#code from https://huggingface.co/JosephusCheung/ASimilarityCalculatior
def cal_cross_attn(to_q, to_k, to_v, rand_input):
hidden_dim, embed_dim = to_q.shape
attn_to_q = nn.Linear(hidden_dim, embed_dim, bias=False)
attn_to_k = nn.Linear(hidden_dim, embed_dim, bias=False)
attn_to_v = nn.Linear(hidden_dim, embed_dim, bias=False)
attn_to_q.load_state_dict({"weight": to_q})
attn_to_k.load_state_dict({"weight": to_k})
attn_to_v.load_state_dict({"weight": to_v})
return torch.einsum(
"ik, jk -> ik",
F.softmax(torch.einsum("ij, kj -> ik", attn_to_q(rand_input), attn_to_k(rand_input)), dim=-1),
attn_to_v(rand_input)
)
def eval(model, n, input, block):
qk = f"model.diffusion_model.{block}_block{n}.1.transformer_blocks.0.attn1.to_q.weight"
uk = f"model.diffusion_model.{block}_block{n}.1.transformer_blocks.0.attn1.to_k.weight"
vk = f"model.diffusion_model.{block}_block{n}.1.transformer_blocks.0.attn1.to_v.weight"
atoq, atok, atov = model[qk], model[uk], model[vk]
attn = cal_cross_attn(atoq, atok, atov, input)
return attn
ATTN1BLOCKS = [[1,"input"],[2,"input"],[4,"input"],[5,"input"],[7,"input"],[8,"input"],["","middle"],
[3,"output"],[4,"output"],[5,"output"],[6,"output"],[7,"output"],[8,"output"],[9,"output"],[10,"output"],[11,"output"]]
def asimilarity(model_a,model_b,mtype):
torch.manual_seed(2244096)
sims = []
for nblock in tqdm(ATTN1BLOCKS, desc="Calculating cosine similarity"):
n,block = nblock[0],nblock[1]
if n != "": n = f"s.{n}"
key = f"model.diffusion_model.{block}_block{n}.1.transformer_blocks.0.attn1.to_q.weight"
hidden_dim, embed_dim = model_a[key].shape
rand_input = torch.randn([embed_dim, hidden_dim])
attn_a = eval(model_a, n, rand_input, block)
attn_b = eval(model_b, n, rand_input, block)
sim = torch.mean(torch.cosine_similarity(attn_a, attn_b))
sims.append([blockfromkey(key,mtype),"",round(sim.item() * 100,3)])
return sims
CONFIGS = ["prompt","neg_prompt","Steps","Sampling method","CFG scale","Seed","Width","Height","Batch size","Upscaler","Hires steps","Denoising strength","Upscale by"]
RESETVALS = ["","",0," ",0,0,0,0,1,"Latent",0,0.7,2]
def configdealer(prompt,neg_prompt,steps,sampler,cfg,seed,width,height,batch_size,
hrupscaler,hr2ndsteps,denois_str,hr_scale,reset):
data = [prompt,neg_prompt,steps,sampler,cfg,seed,width,height,batch_size,
hrupscaler,hr2ndsteps,denois_str,hr_scale]
current_directory = os.getcwd()
jsonpath = os.path.join(current_directory,"ui-config.json")
print(jsonpath)
with open(jsonpath, 'r') as file:
json_data = json.load(file)
for name,men,default in zip(CONFIGS,data,RESETVALS):
key = f"supermerger/{name}/value"
json_data[key] = default if reset else men
with open(jsonpath, 'w') as file:
json.dump(json_data, file, indent=4)
sorted_output = []
def encodetexts(exclude):
isxl = hasattr(shared.sd_model,"conditioner")
model = shared.sd_model.conditioner.embedders[0] if isxl else shared.sd_model.cond_stage_model
encoder = model.encode_with_transformers
tokenizer = model.tokenizer
vocab = tokenizer.get_vocab()
byte_decoder = tokenizer.byte_decoder
batch = 500
b_texts = [list(vocab.items())[i:i + batch] for i in range(0, len(vocab), batch)]
output = []
for texts in tqdm(b_texts):
batch = []
words = []
for word, idx in texts:
tokens = [model.id_start, idx, model.id_end] + [model.id_end] * 74
batch.append(tokens)
words.append((idx, word))
embedding = encoder(torch.IntTensor(batch).to("cuda"))[:,1,:] # (bs,768)
embedding = embedding.to('cuda')
emb_norms = torch.linalg.vector_norm(embedding, dim=-1) # (bs,)
for i, (word, token) in enumerate(texts):
try:
word = bytearray([byte_decoder[x] for x in word]).decode("utf-8")
except UnicodeDecodeError:
pass
if exclude:
if has_alphanumeric(word) : output.append([word,token,emb_norms[i].item()])
else:
output.append([word,token,emb_norms[i].item()])
output = sorted(output, key=lambda x: x[2], reverse=True)
for i in range(len(output)):
output[i].insert(0,i)
global sorted_output
sorted_output = output
return output[:1000]
def pickupencode(texts):
wordlist = [x[1] for x in sorted_output]
texts = texts.split(",")
output = []
for text in texts:
if text in wordlist:
output.append(sorted_output[wordlist.index(text)])
if text+"" in wordlist:
output.append(sorted_output[wordlist.index(text+"")])
return output
def has_alphanumeric(text):
pattern = re.compile(r'[a-zA-Z0-9!@#$%^&*()_+{}\[\]:;"\'<>,.?/\|\\]')
return bool(pattern.search(text.replace("","")))
if __package__ == "supermerger":
script_callbacks.on_ui_tabs(on_ui_tabs)