mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-22 13:42:12 -03:00
Add `allow_strength_adjustment` parameter to enable mouse wheel adjustment of trigger word strengths. When enabled, strength values are preserved and can be modified interactively. Also improves trigger word parsing by handling whitespace more consistently and adding debug logging for trigger data inspection.
175 lines
7.6 KiB
Python
175 lines
7.6 KiB
Python
import json
|
|
import re
|
|
from .utils import FlexibleOptionalInputType, any_type
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class TriggerWordToggle:
|
|
NAME = "TriggerWord Toggle (LoraManager)"
|
|
CATEGORY = "Lora Manager/utils"
|
|
DESCRIPTION = "Toggle trigger words on/off"
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(cls):
|
|
return {
|
|
"required": {
|
|
"group_mode": ("BOOLEAN", {
|
|
"default": True,
|
|
"tooltip": "When enabled, treats each group of trigger words as a single toggleable unit."
|
|
}),
|
|
"default_active": ("BOOLEAN", {
|
|
"default": True,
|
|
"tooltip": "Sets the default initial state (active or inactive) when trigger words are added."
|
|
}),
|
|
"allow_strength_adjustment": ("BOOLEAN", {
|
|
"default": False,
|
|
"tooltip": "Enable mouse wheel adjustment of each trigger word's strength."
|
|
}),
|
|
},
|
|
"optional": FlexibleOptionalInputType(any_type),
|
|
"hidden": {
|
|
"id": "UNIQUE_ID",
|
|
},
|
|
}
|
|
|
|
RETURN_TYPES = ("STRING",)
|
|
RETURN_NAMES = ("filtered_trigger_words",)
|
|
FUNCTION = "process_trigger_words"
|
|
|
|
def _get_toggle_data(self, kwargs, key='toggle_trigger_words'):
|
|
"""Helper to extract data from either old or new kwargs format"""
|
|
if key not in kwargs:
|
|
return None
|
|
|
|
data = kwargs[key]
|
|
# Handle new format: {'key': {'__value__': ...}}
|
|
if isinstance(data, dict) and '__value__' in data:
|
|
return data['__value__']
|
|
# Handle old format: {'key': ...}
|
|
else:
|
|
return data
|
|
|
|
def process_trigger_words(
|
|
self,
|
|
id,
|
|
group_mode,
|
|
default_active,
|
|
allow_strength_adjustment=False,
|
|
**kwargs,
|
|
):
|
|
# Handle both old and new formats for trigger_words
|
|
trigger_words_data = self._get_toggle_data(kwargs, 'orinalMessage')
|
|
trigger_words = trigger_words_data if isinstance(trigger_words_data, str) else ""
|
|
|
|
filtered_triggers = trigger_words
|
|
|
|
# Get toggle data with support for both formats
|
|
trigger_data = self._get_toggle_data(kwargs, 'toggle_trigger_words')
|
|
if trigger_data:
|
|
try:
|
|
# Convert to list if it's a JSON string
|
|
if isinstance(trigger_data, str):
|
|
trigger_data = json.loads(trigger_data)
|
|
|
|
# Create dictionaries to track active state of words or groups
|
|
# Also track strength values for each trigger word
|
|
active_state = {}
|
|
strength_map = {}
|
|
|
|
for item in trigger_data:
|
|
text = item['text']
|
|
active = item.get('active', False)
|
|
# Extract strength if it's in the format "(word:strength)"
|
|
strength_match = re.match(r'\((.+):([\d.]+)\)', text)
|
|
if strength_match:
|
|
original_word = strength_match.group(1).strip()
|
|
strength = float(strength_match.group(2))
|
|
active_state[original_word] = active
|
|
if allow_strength_adjustment:
|
|
strength_map[original_word] = strength
|
|
else:
|
|
active_state[text.strip()] = active
|
|
|
|
if group_mode:
|
|
if isinstance(trigger_data, list):
|
|
filtered_groups = []
|
|
for item in trigger_data:
|
|
text = (item.get('text') or "").strip()
|
|
if not text:
|
|
continue
|
|
if item.get('active', False):
|
|
filtered_groups.append(text)
|
|
|
|
if filtered_groups:
|
|
filtered_triggers = ', '.join(filtered_groups)
|
|
else:
|
|
filtered_triggers = ""
|
|
else:
|
|
# Split by two or more consecutive commas to get groups
|
|
groups = re.split(r',{2,}', trigger_words)
|
|
# Remove leading/trailing whitespace from each group
|
|
groups = [group.strip() for group in groups]
|
|
|
|
# Process groups: keep those not in toggle_trigger_words or those that are active
|
|
filtered_groups = []
|
|
for group in groups:
|
|
# Check if this group contains any words that are in the active_state
|
|
group_words = [word.strip() for word in group.split(',')]
|
|
active_group_words = []
|
|
|
|
for word in group_words:
|
|
word_comparison = re.sub(r'\((.+):([\d.]+)\)', r'\1', word).strip()
|
|
|
|
if word_comparison not in active_state or active_state[word_comparison]:
|
|
active_group_words.append(
|
|
self._format_word_output(
|
|
word_comparison,
|
|
strength_map,
|
|
allow_strength_adjustment,
|
|
)
|
|
)
|
|
|
|
if active_group_words:
|
|
filtered_groups.append(', '.join(active_group_words))
|
|
|
|
if filtered_groups:
|
|
filtered_triggers = ', '.join(filtered_groups)
|
|
else:
|
|
filtered_triggers = ""
|
|
else:
|
|
# Normal mode: split by commas and treat each word as a separate tag
|
|
original_words = [word.strip() for word in trigger_words.split(',')]
|
|
# Filter out empty strings
|
|
original_words = [word for word in original_words if word]
|
|
|
|
filtered_words = []
|
|
for word in original_words:
|
|
# Remove any existing strength formatting for comparison
|
|
word_comparison = re.sub(r'\((.+):([\d.]+)\)', r'\1', word).strip()
|
|
|
|
if word_comparison not in active_state or active_state[word_comparison]:
|
|
filtered_words.append(
|
|
self._format_word_output(
|
|
word_comparison,
|
|
strength_map,
|
|
allow_strength_adjustment,
|
|
)
|
|
)
|
|
|
|
if filtered_words:
|
|
filtered_triggers = ', '.join(filtered_words)
|
|
else:
|
|
filtered_triggers = ""
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error processing trigger words: {e}")
|
|
|
|
return (filtered_triggers,)
|
|
|
|
def _format_word_output(self, base_word, strength_map, allow_strength_adjustment):
|
|
if allow_strength_adjustment and base_word in strength_map:
|
|
return f"({base_word}:{strength_map[base_word]:.2f})"
|
|
return base_word
|