Skip to content

Commit 36fbaab

Browse files
kamnxtltdrdata
andauthored
Improve wildcards and fix a bug (#319)
* Improve wildcards and fix a bug This commit fixes two issues with wildcards: - Using a single count value no longer worked due to .strip() being called on a None value from matching the upper range, when using a wildcard like {2$$a|b|c}, while {2-2$$a|b|c} worked fine. Added a check to fix that. - Choosing options was implemented in an odd way. The code would choose up to `count` values, then put them in a `set` to prevent duplicates. Then retry up to 10 times to get values in case the correct count wasn't reached. This had a few issues: {2$$a|a|b} would always choose "b a", always in this order! However, {2$$1::a|a|b}, which should be identical, gives either "a a" or "b a"! - When the number of items to choose was more than the count of items to choose, the items would be returned in the original order, meaning for example {3-6$$a|b|c|d} returns "a b c d" way more often than it should. This is changed to shuffle the order when choosing all the items. - As NumPy already had a way to choose N items without replacement and with weights, the code has been changed to use a NumPy Generator. This means previous seeds are no longer compatible, but also means we don't re-seed the built-in Python `random` generator. - I have also added a "ImpactWildcardUnprocessed" node, in order to have a multiline text input node that doesn't do ComfyUI's built in wildcard replacement, so it's possible to put a prompt in a separate node from the WildcardProcessor (or have a few ones to connect manually). Due to the way things are processed both on the JS side and the backend side, sadly concatenating text for use in wildcards doesn't work yet. * fix: random_gen.shuffle is side-effect function * version marker --------- Co-authored-by: Dr.Lt.Data <dr.lt.data@gmail.com>
1 parent c5cdfa2 commit 36fbaab

File tree

2 files changed

+11
-17
lines changed

2 files changed

+11
-17
lines changed

modules/impact/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import os
33

44

5-
version = "V4.54.2"
5+
version = "V4.55"
66

77
dependency_version = 20
88

modules/impact/wildcards.py

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import nodes
55
import folder_paths
66
import yaml
7+
import numpy as np
78
import threading
89
from impact import utils
910

@@ -69,6 +70,7 @@ def read_wildcard_dict(wildcard_path):
6970
def process(text, seed=None):
7071
if seed is not None:
7172
random.seed(seed)
73+
random_gen = np.random.default_rng(seed)
7274

7375
def replace_options(string):
7476
replacements_found = False
@@ -92,10 +94,9 @@ def replace_option(match):
9294
b = r.group(1).strip()
9395
else:
9496
a = r.group(1).strip()
95-
try:
96-
b = r.group(3).strip()
97-
except:
98-
b = None
97+
b = r.group(3)
98+
if b is not None:
99+
b = b.strip()
99100

100101
if r is not None:
101102
if b is not None and is_numeric_string(a) and is_numeric_string(b):
@@ -133,20 +134,13 @@ def replace_option(match):
133134
if select_range is None:
134135
select_count = 1
135136
else:
136-
select_count = random.randint(select_range[0], select_range[1])
137+
select_count = random_gen.integers(low=select_range[0], high=select_range[1]+1, size=1)
137138

138139
if select_count > len(options):
140+
random_gen.shuffle(options)
139141
selected_items = options
140142
else:
141-
selected_items = random.choices(options, weights=normalized_probabilities, k=select_count)
142-
selected_items = set(selected_items)
143-
144-
try_count = 0
145-
while len(selected_items) < select_count and try_count < 10:
146-
remaining_count = select_count - len(selected_items)
147-
additional_items = random.choices(options, weights=normalized_probabilities, k=remaining_count)
148-
selected_items |= set(additional_items)
149-
try_count += 1
143+
selected_items = random_gen.choice(options, p=normalized_probabilities, size=select_count, replace=False)
150144

151145
selected_items2 = [re.sub(r'^\s*[0-9.]+::', '', x, 1) for x in selected_items]
152146
replacement = select_sep.join(selected_items2)
@@ -172,7 +166,7 @@ def replace_wildcard(string):
172166
keyword = match.lower()
173167
keyword = wildcard_normalize(keyword)
174168
if keyword in local_wildcard_dict:
175-
replacement = random.choice(local_wildcard_dict[keyword])
169+
replacement = random_gen.choice(local_wildcard_dict[keyword])
176170
replacements_found = True
177171
string = string.replace(f"__{match}__", replacement, 1)
178172
elif '*' in keyword:
@@ -185,7 +179,7 @@ def replace_wildcard(string):
185179
found = True
186180

187181
if found:
188-
replacement = random.choice(total_patterns)
182+
replacement = random_gen.choice(total_patterns)
189183
replacements_found = True
190184
string = string.replace(f"__{match}__", replacement, 1)
191185
elif '/' not in keyword:

0 commit comments

Comments
 (0)