Add lora stacker support and fix TriggerWord Toggle node

This commit is contained in:
Will Miao
2025-03-11 20:46:40 +08:00
parent ad56cafd62
commit 79ebe25bc2
8 changed files with 21 additions and 26 deletions

View File

@@ -5,8 +5,8 @@ from .py.nodes.lora_stacker import LoraStacker
NODE_CLASS_MAPPINGS = { NODE_CLASS_MAPPINGS = {
LoraManagerLoader.NAME: LoraManagerLoader, LoraManagerLoader.NAME: LoraManagerLoader,
TriggerWordToggle.NAME: TriggerWordToggle TriggerWordToggle.NAME: TriggerWordToggle,
# LoraStacker.NAME: LoraStacker LoraStacker.NAME: LoraStacker
} }
WEB_DIRECTORY = "./web/comfyui" WEB_DIRECTORY = "./web/comfyui"

View File

@@ -23,10 +23,7 @@ class LoraManagerLoader:
"placeholder": "LoRA syntax input: <lora:name:strength>" "placeholder": "LoRA syntax input: <lora:name:strength>"
}), }),
}, },
"optional": { "optional": FlexibleOptionalInputType(any_type),
**FlexibleOptionalInputType(any_type),
"lora_stack": ("LORA_STACK", {"default": None}),
}
} }
RETURN_TYPES = ("MODEL", "CLIP", IO.STRING) RETURN_TYPES = ("MODEL", "CLIP", IO.STRING)
@@ -58,12 +55,12 @@ class LoraManagerLoader:
basename = os.path.basename(lora_path) basename = os.path.basename(lora_path)
return os.path.splitext(basename)[0] return os.path.splitext(basename)[0]
def load_loras(self, model, clip, text, lora_stack=None, **kwargs): def load_loras(self, model, clip, text, **kwargs):
print("load_loras kwargs: ", kwargs)
"""Loads multiple LoRAs based on the kwargs input and lora_stack.""" """Loads multiple LoRAs based on the kwargs input and lora_stack."""
loaded_loras = [] loaded_loras = []
all_trigger_words = [] all_trigger_words = []
lora_stack = kwargs.get('lora_stack', None)
# First process lora_stack if available # First process lora_stack if available
if lora_stack: if lora_stack:
for lora_path, model_strength, clip_strength in lora_stack: for lora_path, model_strength, clip_strength in lora_stack:

View File

@@ -20,10 +20,7 @@ class LoraStacker:
"placeholder": "LoRA syntax input: <lora:name:strength>" "placeholder": "LoRA syntax input: <lora:name:strength>"
}), }),
}, },
"optional": { "optional": FlexibleOptionalInputType(any_type),
**FlexibleOptionalInputType(any_type),
"lora_stack": ("LORA_STACK", {"default": None}),
}
} }
RETURN_TYPES = ("LORA_STACK", IO.STRING) RETURN_TYPES = ("LORA_STACK", IO.STRING)
@@ -55,13 +52,13 @@ class LoraStacker:
basename = os.path.basename(lora_path) basename = os.path.basename(lora_path)
return os.path.splitext(basename)[0] return os.path.splitext(basename)[0]
def stack_loras(self, text, lora_stack=None, **kwargs): def stack_loras(self, text, **kwargs):
print("stack_loras kwargs: ", kwargs)
"""Stacks multiple LoRAs based on the kwargs input without loading them.""" """Stacks multiple LoRAs based on the kwargs input without loading them."""
stack = [] stack = []
all_trigger_words = [] all_trigger_words = []
# Process existing lora_stack if available # Process existing lora_stack if available
lora_stack = kwargs.get('lora_stack', None)
if lora_stack: if lora_stack:
stack.extend(lora_stack) stack.extend(lora_stack)
# Get trigger words from existing stack entries # Get trigger words from existing stack entries

View File

@@ -24,7 +24,6 @@ class TriggerWordToggle:
FUNCTION = "process_trigger_words" FUNCTION = "process_trigger_words"
def process_trigger_words(self, id, **kwargs): def process_trigger_words(self, id, **kwargs):
print("trigger_words ", kwargs)
trigger_words = kwargs.get("trigger_words", "") trigger_words = kwargs.get("trigger_words", "")
# Send trigger words to frontend # Send trigger words to frontend
PromptServer.instance.send_sync("trigger_word_update", { PromptServer.instance.send_sync("trigger_word_update", {

View File

@@ -35,8 +35,12 @@ app.registerExtension({
// Enable widget serialization // Enable widget serialization
node.serialize_widgets = true; node.serialize_widgets = true;
node.addInput("lora_stack", 'LORA_STACK', {
"shape": 7 // 7 is the shape of the optional input
});
// Wait for node to be properly initialized // Wait for node to be properly initialized
requestAnimationFrame(() => { requestAnimationFrame(() => {
// Restore saved value if exists // Restore saved value if exists
let existingLoras = []; let existingLoras = [];
if (node.widgets_values && node.widgets_values.length > 0) { if (node.widgets_values && node.widgets_values.length > 0) {

View File

@@ -35,6 +35,10 @@ app.registerExtension({
// Enable widget serialization // Enable widget serialization
node.serialize_widgets = true; node.serialize_widgets = true;
node.addInput("lora_stack", 'LORA_STACK', {
"shape": 7 // 7 is the shape of the optional input
});
// Wait for node to be properly initialized // Wait for node to be properly initialized
requestAnimationFrame(() => { requestAnimationFrame(() => {
// Restore saved value if exists // Restore saved value if exists
@@ -105,8 +109,6 @@ app.registerExtension({
} }
}; };
}); });
console.log("Lora Stacker node created:", node);
} }
}, },
}); });

View File

@@ -750,7 +750,6 @@ export function addLorasWidget(node, name, opts, callback) {
widget.callback = callback; widget.callback = callback;
widget.serializeValue = () => { widget.serializeValue = () => {
console.log("Serializing loras data: ", widgetValue);
// Add dummy items to avoid the 2-element serialization issue, a bug in comfyui // Add dummy items to avoid the 2-element serialization issue, a bug in comfyui
return [...widgetValue, return [...widgetValue,
{ name: "__dummy_item1__", strength: 0, active: false, _isDummy: true }, { name: "__dummy_item1__", strength: 0, active: false, _isDummy: true },

View File

@@ -20,14 +20,13 @@ app.registerExtension({
if (node.comfyClass === "TriggerWord Toggle (LoraManager)") { if (node.comfyClass === "TriggerWord Toggle (LoraManager)") {
// Enable widget serialization // Enable widget serialization
node.serialize_widgets = true; node.serialize_widgets = true;
node.addInput("trigger_words", 'string', {
"shape": 7 // 7 is the shape of the optional input
});
// Wait for node to be properly initialized // Wait for node to be properly initialized
requestAnimationFrame(() => { requestAnimationFrame(() => {
node.addInput("trigger_words", 'string', {
"default": "",
"defaultInput": false, // Changed to make it optional
"optional": true // Marking the input as optional
});
// Get the widget object directly from the returned object // Get the widget object directly from the returned object
const result = addTagsWidget(node, "toggle_trigger_words", { const result = addTagsWidget(node, "toggle_trigger_words", {
defaultVal: [] defaultVal: []
@@ -60,8 +59,6 @@ app.registerExtension({
this.updateTagsBasedOnMode(node, node.widgets[2].value, value); this.updateTagsBasedOnMode(node, node.widgets[2].value, value);
} }
} }
console.log("node ", node);
}); });
} }
}, },