Files
ComfyUI-Lora-Manager/py/nodes/trigger_word_toggle.py
Will Miao dd27411ebf feat(trigger-word-toggle): add strength value support for trigger words
- Extract and preserve strength values from trigger words in format "(word:strength)"
- Maintain strength formatting when filtering active trigger words in both group and individual modes
- Update active state tracking to handle strength-modified words correctly
- Ensure backward compatibility with existing trigger word formats
2025-11-07 16:38:04 +08:00

152 lines
7.3 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."
}),
},
"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, **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)
strength = float(strength_match.group(2))
active_state[original_word] = active
strength_map[original_word] = strength
else:
active_state[text] = active
if group_mode:
# 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:
# 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]:
# If this word has a strength value, use that instead of the original
if word_comparison in strength_map:
active_group_words.append(f"({word_comparison}:{strength_map[word_comparison]:.2f})")
else:
# Preserve existing strength formatting if the word was previously modified
# Check if the original word had strength formatting
strength_match = re.match(r'\((.+):([\d.]+)\)', word)
if strength_match:
active_group_words.append(word)
else:
active_group_words.append(word)
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]:
# If this word has a strength value, use that instead of the original
if word_comparison in strength_map:
filtered_words.append(f"({word_comparison}:{strength_map[word_comparison]:.2f})")
else:
# Preserve existing strength formatting if the word was previously modified
# Check if the original word had strength formatting
strength_match = re.match(r'\((.+):([\d.]+)\)', word)
if strength_match:
filtered_words.append(word)
else:
filtered_words.append(word)
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,)