Files
Bane a90982d169 Enhance randomize_weights with comma insertion options
Added options to randomly insert commas between tags and specify the number of commas., better comma logic
2025-12-23 03:55:50 +02:00

269 lines
8.9 KiB
Python

import random
import re
class RandomTagWeights:
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"text": (
"STRING",
{
"multiline": True,
"default": "",
"tooltip": "Default input text if no external input_text is provided."
}
),
"min_weight": (
"FLOAT",
{
"default": 0.0,
"min": 0.0,
"max": 10.0,
"step": 0.1,
"tooltip": "The lowest possible random weight assigned."
}
),
"max_weight": (
"FLOAT",
{
"default": 1.3,
"min": 0.0,
"max": 10.0,
"step": 0.1,
"tooltip": "The highest possible random weight assigned."
}
),
"threshold": (
"FLOAT",
{
"default": 0.0,
"min": 0.0,
"max": 10.0,
"step": 0.1,
"tooltip": "Tags with generated weight below this value are discarded."
}
),
"max_tags": (
"INT",
{
"default": 30,
"min": 1,
"max": 10000,
"step": 1,
"tooltip": "Maximum number of tags allowed in the output."
}
),
"seed": (
"INT",
{
"default": 0,
"min": 0,
"max": 0xffffffffffffffff,
"tooltip": "Random seed for consistent repeatable output."
}
),
"shuffle_tags": (
"BOOLEAN",
{
"default": True,
"tooltip": "Randomize the order of output tags."
}
),
"detect_by_commas": (
"BOOLEAN",
{
"default": True,
"tooltip": "If ON: tags are split by commas. If OFF: tags are split by spaces."
}
),
"group_parentheses": (
"BOOLEAN",
{
"default": True,
"tooltip": "If ON: anything inside (...) is treated as one tag."
}
),
"preserve_existing_weights": (
"BOOLEAN",
{
"default": False,
"tooltip": "If ON: tags already containing weights (tag:1.0) will not be modified."
}
),
"output_with_commas": (
"BOOLEAN",
{
"default": True,
"tooltip": "Choose output format: commas or spaces between final tags."
}
),
"add_random_commas": (
"BOOLEAN",
{
"default": False,
"tooltip": "If ON: randomly insert commas between tags at the end."
}
),
"num_random_commas": (
"INT",
{
"default": 1,
"min": 1,
"max": 100,
"step": 1,
"tooltip": "Number of commas to randomly insert between tags."
}
),
},
"optional": {
"input_text": (
"STRING",
{
"multiline": True,
"default": "",
"forceInput": True,
"tooltip": "External text input from another node."
}
),
}
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("modified_text",)
FUNCTION = "randomize_weights"
CATEGORY = "text"
def randomize_weights(
self,
text,
min_weight,
max_weight,
threshold,
max_tags,
seed,
shuffle_tags,
detect_by_commas,
group_parentheses,
preserve_existing_weights,
output_with_commas,
add_random_commas,
num_random_commas,
input_text=None
):
if input_text and input_text.strip():
source_text = input_text
else:
source_text = text
if not isinstance(source_text, str):
source_text = str(source_text)
random.seed(seed)
weighted_pattern = r"\(([^()]+?):([\d.]+)\)"
parentheses_group_pattern = r"\([^()]*\)"
final_tags = []
# 1. Extract weighted tags
def extract_weighted(match):
tag = match.group(1).strip()
weight = match.group(2).strip()
if preserve_existing_weights:
final_tags.append((tag, float(weight)))
else:
new_weight = round(random.uniform(min_weight, max_weight), 2)
if new_weight >= threshold:
final_tags.append((tag, new_weight))
return ""
remainder = re.sub(weighted_pattern, extract_weighted, source_text)
# 2. Extract grouped parentheses tags
grouped_tags = set()
if group_parentheses:
for match in re.findall(parentheses_group_pattern, remainder):
cleaned = match.strip("()").strip()
grouped_tags.add(cleaned)
remainder = remainder.replace(match, " ")
for tag in grouped_tags:
new_weight = round(random.uniform(min_weight, max_weight), 2)
if new_weight >= threshold:
final_tags.append((tag, new_weight))
# 3. Split remaining plain tags
remainder = remainder.replace("\n", " ")
if detect_by_commas:
raw_tags = [t.strip() for t in remainder.split(",") if t.strip()]
else:
raw_tags = [t.strip() for t in remainder.split(" ") if t.strip()]
for tag in raw_tags:
if not tag:
continue
# FIX: remove commas when output_with_commas is OFF
if not output_with_commas:
tag = tag.replace(",", "").strip()
if any(tag == existing for existing, _ in final_tags):
continue
if preserve_existing_weights and re.match(weighted_pattern, tag):
continue
new_weight = round(random.uniform(min_weight, max_weight), 2)
if new_weight >= threshold:
final_tags.append((tag, new_weight))
# 4. Shuffle + limit count
if shuffle_tags:
random.shuffle(final_tags)
final_tags = final_tags[:max_tags]
# 5. Output format
sep = ", " if output_with_commas else " "
modified_text = sep.join(f"({tag}:{weight})" for tag, weight in final_tags)
# 6. Add random commas if enabled
if add_random_commas and len(final_tags) > 1:
# Find positions after each tag (where we can insert commas)
# We'll look for positions right after tag patterns like "(tag:weight)"
tag_pattern = r"\([^)]+:[^)]+\)"
matches = list(re.finditer(tag_pattern, modified_text))
if matches:
# Get positions right after each tag (except the last one)
insertion_positions = [match.end() for match in matches[:-1]]
# Limit number of commas to available positions
num_commas_to_add = min(num_random_commas, len(insertion_positions))
# Randomly select positions to insert commas
selected_positions = random.sample(insertion_positions, num_commas_to_add)
selected_positions.sort(reverse=True) # Sort in reverse to maintain indices when inserting
# Insert commas at selected positions
for pos in selected_positions:
modified_text = modified_text[:pos] + "," + modified_text[pos:]
return (modified_text,)
NODE_CLASS_MAPPINGS = {
"RandomTagWeights": RandomTagWeights
}
NODE_DISPLAY_NAME_MAPPINGS = {
"RandomTagWeights": "Random Tag Weights"
}