Important: Please merge models of similar type. For e.g. SD 1.4 models with only SD 1.4/1.5 models, SD 2.0 with SD 2.0-type, and SD 2.1 with SD 2.1-type models.
+
+
+
+
+
Base name of the output file. Mix ratio and file suffix will be appended to this.
+
+
+
+
+ Image generation uses fp16, so it's a good choice. Use fp32 if you want to use the result models for more mixes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Make a single file
+
+
+ Make multiple variations
+
+
+
+
+
+ Saves a single merged model file, at the specified merge ratio.
+
+
+ %
+ Model A's contribution to the mix. The rest will be from Model B.
+
+
+
+
+ Saves multiple variations of the model, at different merge ratios. Each variation will be saved as a separate file.
+
+
+
+
Number of models to create
+
+
%
+
Smallest share of model A in the mix
+
+
%
+
Share of model A added into the mix per step
+
+
+
Sigmoid function to be applied to the model share before mixing
+
+
+ Preview of variation ratios:
+
+
+
+
+
+
+
+
+
`
+
+
+ let loraUI=`
+
+
+
+
+
+
+
Thumbnail:
+
+
+
+
+
+
+
+
+
+
+
Keywords:
+
+
+
+ LORA model keywords can be used via the + Embeddings button. They get added to the embedding
+ keyword menu when the LORA has been selected in the image settings.
+
Important: Please merge models of similar type. For e.g. SD 1.4 models with only SD 1.4/1.5 models, SD 2.0 with SD 2.0-type, and SD 2.1 with SD 2.1-type models.
-
-
-
-
-
Base name of the output file. Mix ratio and file suffix will be appended to this.
-
-
-
-
- Image generation uses fp16, so it's a good choice. Use fp32 if you want to use the result models for more mixes
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Make a single file
-
-
- Make multiple variations
-
-
-
-
-
- Saves a single merged model file, at the specified merge ratio.
-
-
- %
- Model A's contribution to the mix. The rest will be from Model B.
-
-
-
-
- Saves multiple variations of the model, at different merge ratios. Each variation will be saved as a separate file.
-
-
-
-
Number of models to create
-
-
%
-
Smallest share of model A in the mix
-
-
%
-
Share of model A added into the mix per step
-
-
-
Sigmoid function to be applied to the model share before mixing
-
-
- Preview of variation ratios:
-
-
-
-
-
-
-
-
-
`,
+ }
+
+ createTab({
+ id: "merge",
+ icon: "fa-toolbox",
+ label: "Model tools",
+ css: mergeCSS,
+ content: tabHTML,
onOpen: ({ firstOpen }) => {
if (!firstOpen) {
return
}
-
- const tabSettingsSingle = document.querySelector("#tab-merge-opts-single")
- const tabSettingsBatch = document.querySelector("#tab-merge-opts-batch")
- linkTabContents(tabSettingsSingle)
- linkTabContents(tabSettingsBatch)
-
- console.log("Activate")
- let mergeModelAField = new ModelDropdown(document.querySelector("#mergeModelA"), "stable-diffusion")
- let mergeModelBField = new ModelDropdown(document.querySelector("#mergeModelB"), "stable-diffusion")
- updateChart()
-
- // slider
- const singleMergeRatioField = document.querySelector("#single-merge-ratio")
- const singleMergeRatioSlider = document.querySelector("#single-merge-ratio-slider")
-
- function updateSingleMergeRatio() {
- singleMergeRatioField.value = singleMergeRatioSlider.value / 10
- singleMergeRatioField.dispatchEvent(new Event("change"))
- }
-
- function updateSingleMergeRatioSlider() {
- if (singleMergeRatioField.value < 0) {
- singleMergeRatioField.value = 0
- } else if (singleMergeRatioField.value > 100) {
- singleMergeRatioField.value = 100
- }
-
- singleMergeRatioSlider.value = singleMergeRatioField.value * 10
- singleMergeRatioSlider.dispatchEvent(new Event("change"))
- }
-
- singleMergeRatioSlider.addEventListener("input", updateSingleMergeRatio)
- singleMergeRatioField.addEventListener("input", updateSingleMergeRatioSlider)
- updateSingleMergeRatio()
-
- document.querySelector(".merge-config").addEventListener("change", updateChart)
-
- document.querySelector("#merge-button").addEventListener("click", async function(e) {
- // Build request template
- let model0 = mergeModelAField.value
- let model1 = mergeModelBField.value
- let request = { model0: model0, model1: model1 }
- request["use_fp16"] = document.querySelector("#merge-fp").value == "fp16"
- let iterations = document.querySelector("#merge-count").value >> 0
- let start = parseFloat(document.querySelector("#merge-start").value)
- let step = parseFloat(document.querySelector("#merge-step").value)
-
- if (isTabActive(tabSettingsSingle)) {
- start = parseFloat(singleMergeRatioField.value)
- step = 0
- iterations = 1
- addLogMessage(`merge ratio = ${start}%`)
- } else {
- addLogMessage(`start = ${start}%`)
- addLogMessage(`step = ${step}%`)
- }
-
- if (start + (iterations - 1) * step >= 100) {
- addLogMessage("Aborting: maximum ratio is ≥ 100%")
- addLogMessage("Reduce the number of variations or the step size")
- addLogSeparator()
- document.querySelector("#merge-count").focus()
- return
- }
-
- if (document.querySelector("#merge-filename").value == "") {
- addLogMessage("Aborting: No output file name specified")
- addLogSeparator()
- document.querySelector("#merge-filename").focus()
- return
- }
-
- // Disable merge button
- e.target.disabled = true
- e.target.classList.add("disabled")
- let cursor = $("body").css("cursor")
- let label = document.querySelector("#merge-button").innerHTML
- $("body").css("cursor", "progress")
- document.querySelector("#merge-button").innerHTML = "Merging models ..."
-
- addLogMessage("Merging models")
- addLogMessage("Model A: " + model0)
- addLogMessage("Model B: " + model1)
-
- // Batch main loop
- for (let i = 0; i < iterations; i++) {
- let alpha = (start + i * step) / 100
-
- if (isTabActive(tabSettingsBatch)) {
- switch (document.querySelector("#merge-interpolation").value) {
- case "SmoothStep":
- alpha = smoothstep(alpha)
- break
- case "SmootherStep":
- alpha = smootherstep(alpha)
- break
- case "SmoothestStep":
- alpha = smootheststep(alpha)
- break
- }
- }
- addLogMessage(`merging batch job ${i + 1}/${iterations}, alpha = ${alpha.toFixed(5)}...`)
-
- request["out_path"] = document.querySelector("#merge-filename").value
- request["out_path"] += "-" + alpha.toFixed(5) + "." + document.querySelector("#merge-format").value
- addLogMessage(` filename: ${request["out_path"]}`)
-
- // sdkit documentation: "ratio - the ratio of the second model. 1 means only the second model will be used."
- request["ratio"] = 1-alpha
- let res = await fetch("/model/merge", {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(request),
- })
- const data = await res.json()
- addLogMessage(JSON.stringify(data))
- }
- addLogMessage(
- "Done. The models have been saved to your models/stable-diffusion folder."
- )
- addLogSeparator()
- // Re-enable merge button
- $("body").css("cursor", cursor)
- document.querySelector("#merge-button").innerHTML = label
- e.target.disabled = false
- e.target.classList.remove("disabled")
-
- // Update model list
- stableDiffusionModelField.innerHTML = ""
- vaeModelField.innerHTML = ""
- hypernetworkModelField.innerHTML = ""
- await getModels()
- })
+ initMergeUI()
+ LoraUI.init()
+ const tabMergeUI = document.querySelector("#tab-model-mergeUI")
+ const tabLoraUI = document.querySelector("#tab-model-loraUI")
+ linkTabContents(tabMergeUI)
+ linkTabContents(tabLoraUI)
},
})
})()
+async function getLoraKeywords(model) {
+ return Bucket.retrieve(`modelinfo/lora/${model}`)
+ .then((info) => info.keywords)
+}