saik0s's picture
Add files using upload-large-folder tool
f1e06e5 verified
Raw
History Blame Contribute Delete
6.94 kB
import { app } from "../../scripts/app.js";
app.registerExtension({
name: "INT8.PreLoraLoader",
async beforeRegisterNodeDef(nodeType, nodeData, app) {
if (nodeData.name === "INT8PreLoraLoader") {
const parseSavedLoras = (values) => {
const pairs = [];
if (!Array.isArray(values)) {
return pairs;
}
for (let i = 0; i < values.length; i++) {
const name = values[i];
const strength = values[i + 1];
if (name === "Add LoRA" || name === "Remove LoRA") {
continue;
}
if (typeof name === "string" && typeof strength === "number") {
pairs.push({ name, strength });
i++;
}
}
return pairs;
};
const getLoraOptions = (node) => {
for (let i = 0; i < node.widgets.length; i++) {
const w = node.widgets[i];
if (w && w.name && w.name.startsWith("lora_name_")) {
return w.options?.values || [];
}
}
return [];
};
const getStrengthOptions = (node) => {
for (let i = 0; i < node.widgets.length; i++) {
const w = node.widgets[i];
if (w && w.name === "lora_strength_1") {
const options = Object.assign({}, w.options);
options.precision = 2;
return {
options,
callback: w.callback || (() => {}),
};
}
}
return {
options: { min: -10.0, max: 10.0, step: 0.01, precision: 2 },
callback: () => {},
};
};
const countLoraRows = (node) => {
let maxIndex = 0;
for (let i = 0; i < node.widgets.length; i++) {
const match = node.widgets[i]?.name?.match(/^lora_name_(\d+)$/);
if (match) {
maxIndex = Math.max(maxIndex, parseInt(match[1]));
}
}
return maxIndex;
};
const addLoraRow = (node, index, name = null, strength = 1.0) => {
const loraOptions = getLoraOptions(node);
const strengthConfig = getStrengthOptions(node);
const combo = node.addWidget("combo", `lora_name_${index}`, name ?? loraOptions[0] ?? "None", () => {}, { values: loraOptions });
const number = node.addWidget("number", `lora_strength_${index}`, strength, strengthConfig.callback, strengthConfig.options);
return { combo, number };
};
const ensureLoraRows = (node, count) => {
for (let i = countLoraRows(node) + 1; i <= count; i++) {
addLoraRow(node, i);
}
};
const applySavedLoras = (node, pairs) => {
for (let i = 0; i < pairs.length; i++) {
const index = i + 1;
const nameWidget = node.widgets.find((w) => w?.name === `lora_name_${index}`);
const strengthWidget = node.widgets.find((w) => w?.name === `lora_strength_${index}`);
if (nameWidget) {
nameWidget.value = pairs[i].name;
}
if (strengthWidget) {
strengthWidget.value = pairs[i].strength;
}
}
};
const onNodeCreated = nodeType.prototype.onNodeCreated;
nodeType.prototype.onNodeCreated = function () {
const r = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined;
this.updateRemoveBtn = () => {
let maxIndex = 0;
for (let i = 0; i < this.widgets.length; i++) {
const w = this.widgets[i];
if (w && w.name) {
const match = w.name.match(/lora_name_(\d+)/);
if (match) {
maxIndex = Math.max(maxIndex, parseInt(match[1]));
}
}
}
if (maxIndex > 1) {
if (!this.removeBtn) {
this.removeBtn = this.addWidget("button", "Remove LoRA", "Remove LoRA", () => {
let mIdx = 0;
let maxNameWidget = null;
let maxStrengthWidget = null;
for (let i = 0; i < this.widgets.length; i++) {
const w = this.widgets[i];
if (w && w.name) {
const match = w.name.match(/lora_name_(\d+)/);
if (match) {
const idx = parseInt(match[1]);
if (idx > mIdx) {
mIdx = idx;
maxNameWidget = w;
}
}
const matchStr = w.name.match(/lora_strength_(\d+)/);
if (matchStr) {
const idx = parseInt(matchStr[1]);
if (idx === mIdx) {
maxStrengthWidget = w;
}
}
}
}
if (mIdx > 1) { // Never remove the first lora
if (maxNameWidget) {
this.widgets.splice(this.widgets.indexOf(maxNameWidget), 1);
}
if (maxStrengthWidget) {
this.widgets.splice(this.widgets.indexOf(maxStrengthWidget), 1);
}
this.updateRemoveBtn();
const sz = this.computeSize();
this.size[0] = Math.max(this.size[0], sz[0]);
this.size[1] = sz[1];
this.setDirtyCanvas(true, true);
}
});
this.removeBtn.serialize = false;
} else {
// Ensure it's at the bottom
const idx = this.widgets.indexOf(this.removeBtn);
if (idx !== -1) {
this.widgets.splice(idx, 1);
this.widgets.push(this.removeBtn);
}
}
} else {
if (this.removeBtn) {
const idx = this.widgets.indexOf(this.removeBtn);
if (idx !== -1) {
this.widgets.splice(idx, 1);
}
this.removeBtn = null;
}
}
};
const addBtn = this.addWidget("button", "Add LoRA", "Add LoRA", () => {
const nextIndex = countLoraRows(this) + 1;
addLoraRow(this, nextIndex);
this.updateRemoveBtn();
const sz = this.computeSize();
this.size[0] = Math.max(this.size[0], sz[0]);
this.size[1] = Math.max(this.size[1], sz[1]);
this.setDirtyCanvas(true, true);
});
addBtn.serialize = false;
this.addBtn = addBtn;
// Move addBtn to top
this.widgets.splice(this.widgets.indexOf(addBtn), 1);
this.widgets.unshift(addBtn);
// Fix the precision of the initial lora_strength_1 to display 2 decimals
for (let i = 0; i < this.widgets.length; i++) {
if (this.widgets[i] && this.widgets[i].name === "lora_strength_1") {
this.widgets[i].options.precision = 2;
}
}
// Initially call update RemoveBtn to ensure correct state (should be hidden)
this.updateRemoveBtn();
return r;
};
const onConfigure = nodeType.prototype.onConfigure;
nodeType.prototype.onConfigure = function (info) {
const savedLoras = parseSavedLoras(info?.widgets_values);
if (info && info.widgets_values) {
ensureLoraRows(this, savedLoras.length);
if (this.updateRemoveBtn) {
this.updateRemoveBtn();
}
}
const r = onConfigure ? onConfigure.apply(this, arguments) : undefined;
applySavedLoras(this, savedLoras);
if (this.addBtn) {
this.addBtn.value = "Add LoRA";
}
if (this.removeBtn) {
this.removeBtn.value = "Remove LoRA";
}
if (this.updateRemoveBtn) {
this.updateRemoveBtn();
}
const sz = this.computeSize();
this.size[0] = Math.max(this.size[0], sz[0]);
this.size[1] = sz[1];
return r;
};
}
}
});