Parenthesis and brackets now convert to weightings

Might have some weird issues when combining composable diffusion with square bracketing. It converts, but may not be correct.
pull/18/head
blongty 2023-04-27 20:52:55 -07:00
parent 1695f72821
commit c394787c3d
1 changed files with 206 additions and 16 deletions

View File

@ -4,10 +4,6 @@ import unicodedata
from modules import script_callbacks
brackets_opening = '([{<'
brackets_closing = ')]}>'
brackets_opening = '([{<'
brackets_closing = ')]}>'
@ -23,7 +19,9 @@ re_tokenize = re.compile(r',')
re_brackets_fix_whitespace = re.compile(r'([\(\[{<])\s*|\s*([\)\]}>}])')
re_opposing_brackets = re.compile(r'([)\]}>])([([{<])')
re_networks = re.compile(r'<.+?>')
re_brackets_open = re.compile(r'[(\[{]+')
re_bracket_open = re.compile(r'[(\[]')
re_brackets_open = re.compile(r'\(+|\[+')
re_brackets_closing = re.compile(r'\)+|\]+')
# re_colon_spacing_composite = re.compile(r'(?P<A>[^:]*?)\s*?(?P<COLON>:)\s*?(?P<B>\S*)(?P<S>\s*)(?(S)\s*?)(?P<AND>AND)')
re_colon_spacing_composite = re.compile(r'\s*(:)\s*(?=\d*?\.?\d*?\s*?AND)')
re_colon_spacing = re.compile(r'\s*(:)\s*')
@ -88,7 +86,7 @@ def align_colons(prompt: str):
return ' ' + match.group(1)
def composite_end(match: re.Match):
print(f'match: {match}')
# print(f'match: {match}')
return ' ' + match.group(1)
ret = re_colon_spacing.sub(normalize, prompt)
@ -128,15 +126,15 @@ def align_commas(prompt: str):
return ', '.join(split)
def brackets_to_weights(tokens: list, power: int = 0):
print(tokens)
ret = []
re_opening_paren = re.compile('\([^\(]')
re_opening_square = re.compile('\[[^\[]')
# def brackets_to_weights(tokens: list, power: int = 0):
# print(tokens)
# ret = []
# re_opening_paren = re.compile('\([^\(]')
# re_opening_square = re.compile('\[[^\[]')
for token in tokens:
if re_opening_paren.match(token):
pass
# for token in tokens:
# if re_opening_paren.match(token):
# pass
# Assumes colons have already been spaced corretly
@ -252,10 +250,10 @@ def remove_mismatched_brackets(prompt: str):
def space_bracekts(prompt: str):
def helper(match : re.Match):
print(' '.join(match.groups()))
# print(' '.join(match.groups()))
return ' '.join(match.groups())
print(prompt)
# print(prompt)
return re_opposing_brackets.sub(helper, prompt)
@ -266,8 +264,199 @@ def align_alternating(prompt:str):
return re_alternating.sub(helper, prompt)
def bracket_to_weights(prompt: str):
"""
when scanning, we need a way to ignore prompt editing, composable, and alternating
we still need to weigh their individual words within them, however...
use a depth counter to ensure that we find closing brackets
the problem is that as we modify the string, we will be changing it's length,
which will mess with iterations...
we can simply edit the string backwards, that way the operations don't effect
the length of the parts we're working on... however, if we do this, then we can't
remove consecutive brackets of the same type, we we would need to remove bracketing
to the left of the part of the string we're working on.
well, i think we should be fine with a while pos != end of string, and if we find
a weight to add, break from the enumerate loop and resume at position to re-enumerate
the new string
go until we reach a [(, ignore networks < and wildcards {
if (
count if consecutive repeating bracket
look forward to find its corresponding closing bracket
check if those closing brackets are also consecutive
add weighting at the end
remove excessive bracket
convert bracket to ()
if [
count if consecutive repeating bracket
look forward
if we find a : or |, return/break from this weight search
else, to find its corresponding closing bracket
check if those closing brackets are also consecutive
add weighting at the end
remove excessive bracket
convert bracket to ()
IF BRACKETS ARE CONSECUTIVE, AND AFTER THEIR SLOPE, BOTH THEIR
INNER-NEXT DEPTH ARE THE SAME, IT IS A WEIGHT.
Example using map_depth.
c, ((a, b))
(( ))
00012222210
---^^----vv
2 ____ 2
1 /===>\ 1
0___/=====>\0
Because 01 can meet on the other side, these are matching
c, (a, (b))
( ( ))
00011112210
---^---^-vv
2 _ 2
1 ___/>\ 1
0___/=====>\0
0 and 1 match, but since gradients are not exactly mirrored,
thier weights should not be combined.
c, ((a), b)
(( ) )
00012211110
---^^-v---v
2 _ 2
1 /=\___ 1
0___/=====>\0
Similar idea to above example.
c, ((a), ((b)))
(( ) (( )))
000122111233210
---^^-v--^^-vvv
3 _ 3
2 _ />\ 2
1 />\__/==>\ 1
0___/=========>\0
Tricky one. Here, 01 open together, so there's a potential that their
weights should be combined if they close together, but instead 1 closes
early. We only need to check for closure initial checking depth - 1.
"""
re_existing_weight = re.compile(r'(:\d+.?\d*)[)\]]$')
depths, gradients, brackets = get_mappings(prompt)
pos = 0
ret = prompt
gradient_search = []
while pos < len(ret):
current_position = ret[pos:]
if ret[pos] in '([':
open_bracketing = re_brackets_open.match(ret, pos)
consecutive = len(open_bracketing.group(0))
gradient_search = ''.join(map(str, reversed(range(int(depths[pos])-1, int(depths[pos])+consecutive))))
is_square_brackets = True if '[' in open_bracketing.group(0) else False
insert_at, weight, valid_consecutive = get_weight(
ret,
gradients,
depths,
brackets,
open_bracketing.end(),
consecutive,
gradient_search,
is_square_brackets)
# Check if weight already exists
if weight:
if re_existing_weight.search(ret[:insert_at + 1]):
ret = ret[:open_bracketing.start()] + '(' + ret[open_bracketing.start()+valid_consecutive:insert_at] + ')' + ret[insert_at + consecutive:]
else:
ret = ret[:open_bracketing.start()] + '(' + ret[open_bracketing.start()+valid_consecutive:insert_at] + f':{weight:.2f}' + ')' + ret[insert_at + consecutive:]
# offset = len(str(f'{weight:.2f}'))
depths, gradients, brackets = get_mappings(ret)
pos += 1
match = re_bracket_open.search(ret, pos)
if not match: # no more potential weight brackets to parse
return ret
pos = match.start()
def depth_to_map(s: str):
ret = ''
depth = 0
for c in s:
if c in '([':
depth += 1
if c in ')]':
depth -= 1
ret += str(depth)
return ret
def depth_to_gradeint(s: str):
ret = ''
for c in s:
if c in '([':
ret += str('^')
elif c in ')]':
ret += str('v')
else:
ret += str('-')
return ret
def filter_brackets(s: str):
return ''.join(list(map(lambda c : c if c in '[]()' else ' ', s)))
def get_mappings(s: str):
return depth_to_map(s), depth_to_gradeint(s), filter_brackets(s)
def calculate_weight(d: str, is_square_brackets: bool):
return 1 / 1.1 ** int(d) if is_square_brackets else 1 * 1.1 ** int(d)
def get_weight(prompt: str, map_gradient: list, map_depth: list, map_brackets: list, pos: int, ctv: int, gradient_search: str, is_square_brackets :bool=False):
'''
Returns 0 if bracket was recognized as prompt editing, alternation, or composable
'''
# CURRENTLY DOES NOT TAKE INTO ACCOUNT COMPOSABLE?? DO WE EVEN NEED TO?
# E.G. [a AND B :1.2] == (a AND B:1.1) != (a AND B:1.1) ????
while pos+ctv <= len(prompt):
if ctv == 0:
return prompt, 0, 1
a, b = pos, pos+ctv
if prompt[a] in ':|' and is_square_brackets:
if map_depth[-2] == map_depth[a]:
return prompt, 0, 1
if map_depth[a] in gradient_search:
gradient_search = gradient_search.replace(map_depth[a], '')
ctv -= 1
elif (map_gradient[a:b] == 'v' * ctv and
map_depth[a-1:b] == gradient_search):
return a, calculate_weight(ctv, is_square_brackets), ctv
elif ('v' == map_gradient[a] and
map_depth[a-1:b-1] in gradient_search):
narrowing = map_gradient[a:b].count('v')
gradient_search = gradient_search[narrowing:]
ctv -= 1
pos += 1
raise Exception(f'Somehow weight index searching has gone outside of prompt length with prompt: {prompt}')
def format_prompt(*prompts: list):
ret = []
for prompt in prompts:
# Clean up the string
prompt = normalize_characters(prompt)
@ -281,6 +470,7 @@ def format_prompt(*prompts: list):
prompt = align_colons(prompt)
prompt = align_commas(prompt)
prompt = align_alternating(prompt)
prompt = bracket_to_weights(prompt)
# Further processing for usability
# prompt = brackets_to_weights(prompt)