From e554c2607f00a5e51c03052acb9861ff21ec1c12 Mon Sep 17 00:00:00 2001 From: Damian at mba Date: Tue, 1 Nov 2022 10:08:42 +0100 Subject: [PATCH 1/9] Rebuilt prompt parsing logic Complete re-write of the prompt parsing logic to be more readable and logical, and therefore also hopefully easier to debug, maintain, and augment. In the process it has also become more robust to badly-formed prompts. Squashed commit of the following: commit 8fcfa88a16e1390d41717e940d72aed64712171c Author: Damian at mba Date: Sun Oct 30 17:05:57 2022 +0100 further cleanup commit 1a1fd78bcfeb49d072e3e6d5808aa8df15441629 Author: Damian at mba Date: Sun Oct 30 16:07:57 2022 +0100 cleanup and document commit 099c9659fa8b8135876f9a5a50fe80b20bc0635c Author: Damian at mba Date: Sun Oct 30 15:54:58 2022 +0100 works fully commit 5e6887ea8c25a1e21438ff6defb381fd027d25fd Author: Damian at mba Date: Sun Oct 30 15:24:31 2022 +0100 further... commit 492fda120844d9bc1ad4ec7dd408a3374762d0ff Author: Damian at mba Date: Sun Oct 30 14:08:57 2022 +0100 getting there... commit c6aab05a8450cc3c95c8691daf38fdc64c74f52d Author: Damian at mba Date: Fri Oct 28 14:29:03 2022 +0200 wip doesn't compile commit 5e533f731cfd20cd435330eeb0012e5689e87e81 Author: Damian at mba Date: Fri Oct 28 13:21:43 2022 +0200 working with CrossAttentionCtonrol but no Attention support yet commit 9678348773431e500e110e8aede99086bb7b5955 Author: Damian at mba Date: Fri Oct 28 13:04:52 2022 +0200 wip rebuiling prompt parser --- ldm/invoke/prompt_parser.py | 475 +++++++++++++++++------------------- tests/test_prompt_parser.py | 132 +++++++--- 2 files changed, 314 insertions(+), 293 deletions(-) diff --git a/ldm/invoke/prompt_parser.py b/ldm/invoke/prompt_parser.py index 0b3890597f..96f002778b 100644 --- a/ldm/invoke/prompt_parser.py +++ b/ldm/invoke/prompt_parser.py @@ -28,7 +28,7 @@ class Prompt(): def __init__(self, parts: list): for c in parts: if type(c) is not Attention and not issubclass(type(c), BaseFragment) and type(c) is not pp.ParseResults: - raise PromptParser.ParsingException(f"Prompt cannot contain {type(c).__name__} {c}, only {BaseFragment.__subclasses__()} are allowed") + raise PromptParser.ParsingException(f"Prompt cannot contain {type(c).__name__} ({c}), only {[c.__name__ for c in BaseFragment.__subclasses__()]} are allowed") self.children = parts def __repr__(self): return f"Prompt:{self.children}" @@ -102,12 +102,18 @@ class Attention(): Do not traverse directly; instead obtain a FlattenedPrompt by calling Flatten() on a top-level Conjunction object. """ def __init__(self, weight: float, children: list): + if type(weight) is not float: + raise PromptParser.ParsingException( + f"Attention weight must be float (got {type(weight).__name__} {weight})") self.weight = weight + if type(children) is not list: + raise PromptParser.ParsingException(f"cannot make Attention with non-list of children (got {type(children)})") + assert(type(children) is list) self.children = children #print(f"A: requested attention '{children}' to {weight}") def __repr__(self): - return f"Attention:'{self.children}' @ {self.weight}" + return f"Attention:{self.children} * {self.weight}" def __eq__(self, other): return type(other) is Attention and other.weight == self.weight and other.fragment == self.fragment @@ -136,9 +142,9 @@ class CrossAttentionControlSubstitute(CrossAttentionControlledFragment): Fragment('sitting on a car') ]) """ - def __init__(self, original: Union[Fragment, list], edited: Union[Fragment, list], options: dict=None): + def __init__(self, original: list, edited: list, options: dict=None): self.original = original - self.edited = edited + self.edited = edited if len(edited)>0 else [Fragment('')] default_options = { 's_start': 0.0, @@ -190,12 +196,12 @@ class Conjunction(): """ def __init__(self, prompts: list, weights: list = None): # force everything to be a Prompt - #print("making conjunction with", parts) + #print("making conjunction with", prompts, "types", [type(p).__name__ for p in prompts]) self.prompts = [x if (type(x) is Prompt or type(x) is Blend or type(x) is FlattenedPrompt) else Prompt(x) for x in prompts] - self.weights = [1.0]*len(self.prompts) if weights is None else list(weights) + self.weights = [1.0]*len(self.prompts) if (weights is None or len(weights)==0) else list(weights) if len(self.weights) != len(self.prompts): raise PromptParser.ParsingException(f"while parsing Conjunction: mismatched parts/weights counts {prompts}, {weights}") self.type = 'AND' @@ -216,6 +222,7 @@ class Blend(): """ def __init__(self, prompts: list, weights: list[float], normalize_weights: bool=True): #print("making Blend with prompts", prompts, "and weights", weights) + weights = [1.0]*len(prompts) if (weights is None or len(weights)==0) else list(weights) if len(prompts) != len(weights): raise PromptParser.ParsingException(f"while parsing Blend: mismatched prompts/weights counts {prompts}, {weights}") for p in prompts: @@ -244,6 +251,10 @@ class PromptParser(): class ParsingException(Exception): pass + class UnrecognizedOperatorException(Exception): + def __init__(self, operator:str): + super().__init__("Unrecognized operator: " + operator) + def __init__(self, attention_plus_base=1.1, attention_minus_base=0.9): self.conjunction, self.prompt = build_parser_syntax(attention_plus_base, attention_minus_base) @@ -279,7 +290,7 @@ class PromptParser(): return Blend(prompts=flattened_prompts, weights=weights, normalize_weights=True) - def flatten(self, root: Conjunction) -> Conjunction: + def flatten(self, root: Conjunction, verbose = False) -> Conjunction: """ Flattening a Conjunction traverses all of the nested tree-like structures in each of its Prompts or Blends, producing from each of these walks a linear sequence of Fragment or CrossAttentionControlSubstitute objects @@ -289,8 +300,6 @@ class PromptParser(): :return: A Conjunction containing the result of flattening each of the prompts in the passed-in root. """ - #print("flattening", root) - def fuse_fragments(items): # print("fusing fragments in ", items) result = [] @@ -313,8 +322,8 @@ class PromptParser(): return result def flatten_internal(node, weight_scale, results, prefix): - #print(prefix + "flattening", node, "...") - if type(node) is pp.ParseResults: + verbose and print(prefix + "flattening", node, "...") + if type(node) is pp.ParseResults or type(node) is list: for x in node: results = flatten_internal(x, weight_scale, results, prefix+' pr ') #print(prefix, " ParseResults expanded, results is now", results) @@ -345,67 +354,59 @@ class PromptParser(): #print(prefix + "after flattening Prompt, results is", results) else: raise PromptParser.ParsingException(f"unhandled node type {type(node)} when flattening {node}") - #print(prefix + "-> after flattening", type(node).__name__, "results is", results) + verbose and print(prefix + "-> after flattening", type(node).__name__, "results is", results) return results + verbose and print("flattening", root) flattened_parts = [] for part in root.prompts: flattened_parts += flatten_internal(part, 1.0, [], ' C| ') - #print("flattened to", flattened_parts) + verbose and print("flattened to", flattened_parts) weights = root.weights return Conjunction(flattened_parts, weights) + def build_parser_syntax(attention_plus_base: float, attention_minus_base: float): + def make_operator_object(x): + #print('making operator for', x) + target = x[0] + operator = x[1] + arguments = x[2] + if operator == '.attend': + weight_raw = arguments[0] + weight = 1.0 + if type(weight_raw) is float or type(weight_raw) is int: + weight = weight_raw + elif type(weight_raw) is str: + base = attention_plus_base if weight_raw[0] == '+' else attention_minus_base + weight = pow(base, len(weight_raw)) + return Attention(weight=weight, children=[x for x in x[0]]) + elif operator == '.swap': + return CrossAttentionControlSubstitute(target, arguments, x.as_dict()) + elif operator == '.blend': + prompts = [Prompt(p) for p in x[0]] + weights_raw = x[2] + normalize_weights = True + if len(weights_raw) > 0 and weights_raw[-1][0] == 'no_normalize': + normalize_weights = False + weights_raw = weights_raw[:-1] + weights = [float(w[0]) for w in weights_raw] + return Blend(prompts=prompts, weights=weights, normalize_weights=normalize_weights) + elif operator == '.and' or operator == '.add': + prompts = [Prompt(p) for p in x[0]] + weights = [float(w[0]) for w in x[2]] + return Conjunction(prompts=prompts, weights=weights) - lparen = pp.Literal("(").suppress() - rparen = pp.Literal(")").suppress() - quotes = pp.Literal('"').suppress() - comma = pp.Literal(",").suppress() + raise PromptParser.UnrecognizedOperatorException(operator) - # accepts int or float notation, always maps to float - number = pp.pyparsing_common.real | \ - pp.Combine(pp.Optional("-")+pp.Word(pp.nums)).set_parse_action(pp.token_map(float)) - - attention = pp.Forward() - quoted_fragment = pp.Forward() - parenthesized_fragment = pp.Forward() - cross_attention_substitute = pp.Forward() - - def make_text_fragment(x): - #print("### making fragment for", x) - if type(x[0]) is Fragment: - assert(False) - if type(x) is str: - return Fragment(x) - elif type(x) is pp.ParseResults or type(x) is list: - #print(f'converting {type(x).__name__} to Fragment') - return Fragment(' '.join([s for s in x])) - else: - raise PromptParser.ParsingException("Cannot make fragment from " + str(x)) - - def build_escaped_word_parser_charbychar(escaped_chars_to_ignore: str): - escapes = [] - for c in escaped_chars_to_ignore: - escapes.append(pp.Literal('\\'+c)) - return pp.Combine(pp.OneOrMore( - pp.MatchFirst(escapes + [pp.CharsNotIn( - string.whitespace + escaped_chars_to_ignore, - exact=1 - )]) - )) - - - - def parse_fragment_str(x, in_quotes: bool=False, in_parens: bool=False): + def parse_fragment_str(x, expression: pp.ParseExpression, in_quotes: bool = False, in_parens: bool = False): #print(f"parsing fragment string for {x}") fragment_string = x[0] - #print(f"ppparsing fragment string \"{fragment_string}\"") - if len(fragment_string.strip()) == 0: return Fragment('') @@ -413,234 +414,198 @@ def build_parser_syntax(attention_plus_base: float, attention_minus_base: float) # escape unescaped quotes fragment_string = fragment_string.replace('"', '\\"') - #fragment_parser = pp.Group(pp.OneOrMore(attention | cross_attention_substitute | (greedy_word.set_parse_action(make_text_fragment)))) try: - result = pp.Group(pp.MatchFirst([ - pp.OneOrMore(quoted_fragment | attention | unquoted_word).set_name('pf_str_qfuq'), - pp.Empty().set_parse_action(make_text_fragment) + pp.StringEnd() - ])).set_name('blend-result').set_debug(False).parse_string(fragment_string) + result = (expression + pp.StringEnd()).parse_string(fragment_string) #print("parsed to", result) return result except pp.ParseException as e: #print("parse_fragment_str couldn't parse prompt string:", e) raise + # meaningful symbols + lparen = pp.Literal("(").suppress() + rparen = pp.Literal(")").suppress() + quote = pp.Literal('"').suppress() + comma = pp.Literal(",").suppress() + dot = pp.Literal(".").suppress() + equals = pp.Literal("=").suppress() + + escaped_lparen = pp.Literal('\\(') + escaped_rparen = pp.Literal('\\)') + escaped_quote = pp.Literal('\\"') + escaped_comma = pp.Literal('\\,') + escaped_dot = pp.Literal('\\.') + escaped_plus = pp.Literal('\\+') + escaped_minus = pp.Literal('\\-') + escaped_equals = pp.Literal('\\=') + + syntactic_symbols = { + '(': escaped_lparen, + ')': escaped_rparen, + '"': escaped_quote, + ',': escaped_comma, + '.': escaped_dot, + '+': escaped_plus, + '-': escaped_minus, + '=': escaped_equals, + } + syntactic_chars = "".join(syntactic_symbols.keys()) + + # accepts int or float notation, always maps to float + number = pp.pyparsing_common.real | \ + pp.Combine(pp.Optional("-")+pp.Word(pp.nums)).set_parse_action(pp.token_map(float)) + + # for options + keyword = pp.Word(pp.alphanums + '_') + + # a word that absolutely does not contain any meaningful syntax + non_syntax_word = pp.Combine(pp.OneOrMore(pp.MatchFirst([ + pp.Or(syntactic_symbols.values()), + pp.one_of(['-', '+']) + pp.NotAny(pp.White() | pp.Char(syntactic_chars) | pp.StringEnd()), + # build character-by-character + pp.CharsNotIn(string.whitespace + syntactic_chars, exact=1) + ]))) + non_syntax_word.set_parse_action(lambda x: [Fragment(t) for t in x]) + non_syntax_word.set_name('non_syntax_word') + non_syntax_word.set_debug(False) + + # a word that can contain any character at all - greedily consumes syntax, so use with care + free_word = pp.CharsNotIn(string.whitespace).set_parse_action(lambda x: Fragment(x[0])) + free_word.set_name('free_word') + free_word.set_debug(False) + + + # ok here we go. forward declare some things.. + attention = pp.Forward() + cross_attention_substitute = pp.Forward() + parenthesized_fragment = pp.Forward() + quoted_fragment = pp.Forward() + + # the types of things that can go into a fragment, consisting of syntax-full and/or strictly syntax-free components + fragment_part_expressions = [ + attention, + cross_attention_substitute, + parenthesized_fragment, + quoted_fragment, + non_syntax_word + ] + # a fragment that is permitted to contain commas + fragment_including_commas = pp.ZeroOrMore(pp.MatchFirst( + fragment_part_expressions + [ + pp.Literal(',').set_parse_action(lambda x: Fragment(x[0])) + ] + )) + # a fragment that is not permitted to contain commas + fragment_excluding_commas = pp.ZeroOrMore(pp.MatchFirst( + fragment_part_expressions + )) + + # a fragment in double quotes (may be nested) quoted_fragment << pp.QuotedString(quote_char='"', esc_char=None, esc_quote='\\"') - quoted_fragment.set_parse_action(lambda x: parse_fragment_str(x, in_quotes=True)).set_name('quoted_fragment') + quoted_fragment.set_parse_action(lambda x: parse_fragment_str(x, fragment_including_commas, in_quotes=True)) - escaped_quote = pp.Literal('\\"')#.set_parse_action(lambda x: '"') - escaped_lparen = pp.Literal('\\(')#.set_parse_action(lambda x: '(') - escaped_rparen = pp.Literal('\\)')#.set_parse_action(lambda x: ')') - escaped_backslash = pp.Literal('\\\\')#.set_parse_action(lambda x: '"') + # a fragment inside parentheses (may be nested) + parenthesized_fragment << (lparen + fragment_including_commas + rparen) + parenthesized_fragment.set_name('parenthesized_fragment') + parenthesized_fragment.set_debug(False) - empty = ( - (lparen + pp.ZeroOrMore(pp.Word(string.whitespace)) + rparen) | - (quotes + pp.ZeroOrMore(pp.Word(string.whitespace)) + quotes)).set_debug(False).set_name('empty') - - - def not_ends_with_swap(x): - #print("trying to match:", x) - return not x[0].endswith('.swap') - - unquoted_word = (pp.Combine(pp.OneOrMore( - escaped_rparen | escaped_lparen | escaped_quote | escaped_backslash | - (pp.CharsNotIn(string.whitespace + '\\"()', exact=1) - ))) - # don't whitespace when the next word starts with +, eg "badly +formed" - + (pp.White().suppress() | - # don't eat +/- - pp.NotAny(pp.Word('+') | pp.Word('-')) - ) - ) - - unquoted_word.set_parse_action(make_text_fragment).set_name('unquoted_word').set_debug(False) - #print(unquoted_fragment.parse_string("cat.swap(dog)")) - - parenthesized_fragment << (lparen + - pp.Or([ - (parenthesized_fragment), - (quoted_fragment.copy().set_parse_action(lambda x: parse_fragment_str(x, in_quotes=True)).set_debug(False)).set_name('-quoted_paren_internal').set_debug(False), - (pp.Combine(pp.OneOrMore( - escaped_quote | escaped_lparen | escaped_rparen | escaped_backslash | - pp.CharsNotIn(string.whitespace + '\\"()', exact=1) | - pp.White() - )).set_name('--combined').set_parse_action(lambda x: parse_fragment_str(x, in_parens=True)).set_debug(False)), - pp.Empty() - ]) + rparen) - parenthesized_fragment.set_name('parenthesized_fragment').set_debug(False) - - debug_attention = False - # attention control of the form (phrase)+ / (phrase)+ / (phrase) - # phrase can be multiple words, can have multiple +/- signs to increase the effect or type a floating point or integer weight - attention_with_parens = pp.Forward() - attention_without_parens = pp.Forward() - - attention_with_parens_foot = (number | pp.Word('+') | pp.Word('-'))\ - .set_name("attention_foot")\ - .set_debug(False) - attention_with_parens <<= pp.Group( - lparen + - pp.ZeroOrMore(quoted_fragment | attention_with_parens | parenthesized_fragment | cross_attention_substitute | attention_without_parens | - (pp.Empty() + build_escaped_word_parser_charbychar('()')).set_name('undecorated_word').set_debug(debug_attention)#.set_parse_action(lambda t: t[0]) - ) - + rparen + attention_with_parens_foot) - attention_with_parens.set_name('attention_with_parens').set_debug(debug_attention) - - attention_without_parens_foot = (pp.NotAny(pp.White()) + pp.Or([pp.Word('+'), pp.Word('-')]) + pp.FollowedBy(pp.StringEnd() | pp.White() | pp.Literal('(') | pp.Literal(')') | pp.Literal(',') | pp.Literal('"')) ).set_name('attention_without_parens_foots') - attention_without_parens <<= pp.Group(pp.MatchFirst([ - quoted_fragment.copy().set_name('attention_quoted_fragment_without_parens').set_debug(debug_attention) + attention_without_parens_foot, - pp.Combine(build_escaped_word_parser_charbychar('()+-')).set_name('attention_word_without_parens').set_debug(debug_attention)#.set_parse_action(lambda x: print('escapéd', x)) - + attention_without_parens_foot#.leave_whitespace() + # a string of the form (= | | ) where keyword is alphanumeric + '_' + option = pp.Group(pp.MatchFirst([ + keyword + equals + (number | keyword), # option=value + number.copy().set_parse_action(pp.token_map(str)), # weight + keyword # flag ])) - attention_without_parens.set_name('attention_without_parens').set_debug(debug_attention) + # options for an operator, eg "s_start=0.1, 0.3, no_normalize" + options = pp.Dict(pp.Optional(pp.delimited_list(option))) + options.set_name('options') + options.set_debug(False) + # a fragment which can be used as the target for an operator - either quoted or in parentheses, or a bare vanilla word + potential_operator_target = (quoted_fragment | parenthesized_fragment | non_syntax_word) - attention << pp.MatchFirst([attention_with_parens, - attention_without_parens - ]) + # a fragment whose weight has been increased or decreased by a given amount + attention_weight_operator = pp.Word('+') | pp.Word('-') | number + attention_explicit = ( + pp.Group(potential_operator_target) + + pp.Literal('.attend') + + lparen + + pp.Group(attention_weight_operator) + + rparen + ) + attention_explicit.set_parse_action(make_operator_object) + attention_implicit = ( + pp.Group(potential_operator_target) + + pp.NotAny(pp.White()) # do not permit whitespace between term and operator + + pp.Group(attention_weight_operator) + ) + attention_implicit.set_parse_action(lambda x: make_operator_object([x[0], '.attend', x[1]])) + attention << (attention_explicit | attention_implicit) attention.set_name('attention') + attention.set_debug(False) - def make_attention(x): - #print("entered make_attention with", x) - children = x[0][:-1] - weight_raw = x[0][-1] - weight = 1.0 - if type(weight_raw) is float or type(weight_raw) is int: - weight = weight_raw - elif type(weight_raw) is str: - base = attention_plus_base if weight_raw[0] == '+' else attention_minus_base - weight = pow(base, len(weight_raw)) - - #print("making Attention from", children, "with weight", weight) - - return Attention(weight=weight, children=[(Fragment(x) if type(x) is str else x) for x in children]) - - attention_with_parens.set_parse_action(make_attention) - attention_without_parens.set_parse_action(make_attention) - - #print("parsing test:", attention_with_parens.parse_string("mountain (man)1.1")) - - # cross-attention control - empty_string = ((lparen + rparen) | - pp.Literal('""').suppress() | - (lparen + pp.Literal('""').suppress() + rparen) - ).set_parse_action(lambda x: Fragment("")) - empty_string.set_name('empty_string') - - # cross attention control - debug_cross_attention_control = False - original_fragment = pp.MatchFirst([ - quoted_fragment.set_debug(debug_cross_attention_control), - parenthesized_fragment.set_debug(debug_cross_attention_control), - pp.Combine(pp.OneOrMore(pp.CharsNotIn(string.whitespace + '.', exact=1))).set_parse_action(make_text_fragment) + pp.FollowedBy(".swap"), - empty_string.set_debug(debug_cross_attention_control), - ]) - # support keyword=number arguments - cross_attention_option_keyword = pp.Or([pp.Keyword("s_start"), pp.Keyword("s_end"), pp.Keyword("t_start"), pp.Keyword("t_end"), pp.Keyword("shape_freedom")]) - cross_attention_option = pp.Group(cross_attention_option_keyword + pp.Literal("=").suppress() + number) - edited_fragment = pp.MatchFirst([ - (lparen + rparen).set_parse_action(lambda x: Fragment('')), - lparen + - (quoted_fragment | attention | - pp.Group(pp.ZeroOrMore(build_escaped_word_parser_charbychar(',)').set_parse_action(make_text_fragment))) - ) + - pp.Dict(pp.ZeroOrMore(comma + cross_attention_option)) + - rparen, - parenthesized_fragment - ]) - cross_attention_substitute << original_fragment + pp.Literal(".swap").set_debug(False).suppress() + edited_fragment - - original_fragment.set_name('original_fragment').set_debug(debug_cross_attention_control) - edited_fragment.set_name('edited_fragment').set_debug(debug_cross_attention_control) - cross_attention_substitute.set_name('cross_attention_substitute').set_debug(debug_cross_attention_control) - - def make_cross_attention_substitute(x): - #print("making cacs for", x[0], "->", x[1], "with options", x.as_dict()) - #if len(x>2): - cacs = CrossAttentionControlSubstitute(x[0], x[1], options=x.as_dict()) - #print("made", cacs) - return cacs - cross_attention_substitute.set_parse_action(make_cross_attention_substitute) + # cross-attention control by swapping one fragment for another + cross_attention_substitute << ( + pp.Group(potential_operator_target).set_name('ca-target').set_debug(False) + + pp.Literal(".swap").set_name('ca-operator').set_debug(False) + + lparen + + pp.Group(fragment_excluding_commas).set_name('ca-replacement').set_debug(False) + + pp.Optional(comma + options).set_name('ca-options').set_debug(False) + + rparen + ) + cross_attention_substitute.set_name('cross_attention_substitute') + cross_attention_substitute.set_debug(False) + cross_attention_substitute.set_parse_action(make_operator_object) - # root prompt definition - debug_root_prompt = False - prompt = (pp.OneOrMore(pp.MatchFirst([cross_attention_substitute.set_debug(debug_root_prompt), - attention.set_debug(debug_root_prompt), - quoted_fragment.set_debug(debug_root_prompt), - parenthesized_fragment.set_debug(debug_root_prompt), - unquoted_word.set_debug(debug_root_prompt), - empty.set_parse_action(make_text_fragment).set_debug(debug_root_prompt)]) - ) + pp.StringEnd()) \ - .set_name('prompt') \ - .set_parse_action(lambda x: Prompt(x)) \ - .set_debug(debug_root_prompt) + # an entire self-contained prompt, which can be used in a Blend or Conjunction + prompt = pp.ZeroOrMore(pp.MatchFirst([ + cross_attention_substitute, + attention, + quoted_fragment, + parenthesized_fragment, + free_word, + pp.White().suppress() + ])) + quoted_prompt = quoted_fragment.copy().set_parse_action(lambda x: parse_fragment_str(x, prompt, in_quotes=True)) - #print("parsing test:", prompt.parse_string("spaced eyes--")) - #print("parsing test:", prompt.parse_string("eyes--")) - # weighted blend of prompts - # ("promptA", "promptB").blend(a, b) where "promptA" and "promptB" are valid prompts and a and b are float or - # int weights. - # can specify more terms eg ("promptA", "promptB", "promptC").blend(a,b,c) + # a blend/lerp between the feature vectors for two or more prompts + blend = ( + lparen + + pp.Group(pp.delimited_list(pp.Group(potential_operator_target | quoted_prompt), min=1)).set_name('bl-target').set_debug(False) + + rparen + + pp.Literal(".blend").set_name('bl-operator').set_debug(False) + + lparen + + pp.Group(options).set_name('bl-options').set_debug(False) + + rparen + ) + blend.set_name('blend') + blend.set_debug(False) + blend.set_parse_action(make_operator_object) - def make_prompt_from_quoted_string(x): - #print(' got quoted prompt', x) + # an operator to direct stable diffusion to step multiple times, once for each target, and then add the results together with different weights + explicit_conjunction = ( + lparen + + pp.Group(pp.delimited_list(pp.Group(potential_operator_target | quoted_prompt), min=1)).set_name('cj-target').set_debug(False) + + rparen + + pp.one_of([".and", ".add"]).set_name('cj-operator').set_debug(False) + + lparen + + pp.Group(options).set_name('cj-options').set_debug(False) + + rparen + ) + explicit_conjunction.set_name('explicit_conjunction') + explicit_conjunction.set_debug(False) + explicit_conjunction.set_parse_action(make_operator_object) - x_unquoted = x[0][1:-1] - if len(x_unquoted.strip()) == 0: - # print(' b : just an empty string') - return Prompt([Fragment('')]) - #print(f' b parsing \'{x_unquoted}\'') - x_parsed = prompt.parse_string(x_unquoted) - #print(" quoted prompt was parsed to", type(x_parsed),":", x_parsed) - return x_parsed[0] - - quoted_prompt = pp.dbl_quoted_string.set_parse_action(make_prompt_from_quoted_string) - quoted_prompt.set_name('quoted_prompt') - - debug_blend=False - blend_terms = pp.delimited_list(quoted_prompt).set_name('blend_terms').set_debug(debug_blend) - blend_weights = (pp.delimited_list(number) + pp.Optional(pp.Char(",").suppress() + "no_normalize")).set_name('blend_weights').set_debug(debug_blend) - blend = pp.Group(lparen + pp.Group(blend_terms) + rparen - + pp.Literal(".blend").suppress() - + lparen + pp.Group(blend_weights) + rparen).set_name('blend') - blend.set_debug(debug_blend) - - def make_blend(x): - prompts = x[0][0] - weights = x[0][1] - normalize = True - if weights[-1] == 'no_normalize': - normalize = False - weights = weights[:-1] - return Blend(prompts=prompts, weights=weights, normalize_weights=normalize) - - blend.set_parse_action(make_blend) - - conjunction_terms = blend_terms.copy().set_name('conjunction_terms') - conjunction_weights = blend_weights.copy().set_name('conjunction_weights') - conjunction_with_parens_and_quotes = pp.Group(lparen + pp.Group(conjunction_terms) + rparen - + pp.Literal(".and").suppress() - + lparen + pp.Optional(pp.Group(conjunction_weights)) + rparen).set_name('conjunction') - def make_conjunction(x): - parts_raw = x[0][0] - weights = x[0][1] if len(x[0])>1 else [1.0]*len(parts_raw) - parts = [part for part in parts_raw] - return Conjunction(parts, weights) - conjunction_with_parens_and_quotes.set_parse_action(make_conjunction) - - implicit_conjunction = pp.OneOrMore(blend | prompt).set_name('implicit_conjunction') + # by default a prompt consists of a Conjunction with a single term + implicit_conjunction = (blend | pp.Group(prompt)) + pp.StringEnd() implicit_conjunction.set_parse_action(lambda x: Conjunction(x)) - conjunction = conjunction_with_parens_and_quotes | implicit_conjunction - conjunction.set_debug(False) + conjunction = (explicit_conjunction | implicit_conjunction) - # top-level is a conjunction of one or more blends or prompts return conjunction, prompt - def split_weighted_subprompts(text, skip_normalize=False)->list: """ Legacy blend parsing. diff --git a/tests/test_prompt_parser.py b/tests/test_prompt_parser.py index 03db9274d4..6884b62748 100644 --- a/tests/test_prompt_parser.py +++ b/tests/test_prompt_parser.py @@ -28,8 +28,8 @@ class PromptParserTestCase(unittest.TestCase): self.assertEqual(make_weighted_conjunction([('', 1)]), parse_prompt('')) def test_basic(self): - self.assertEqual(make_weighted_conjunction([('fire flames', 1)]), parse_prompt("fire (flames)")) self.assertEqual(make_weighted_conjunction([("fire flames", 1)]), parse_prompt("fire flames")) + self.assertEqual(make_weighted_conjunction([('fire flames', 1)]), parse_prompt("fire (flames)")) self.assertEqual(make_weighted_conjunction([("fire, flames", 1)]), parse_prompt("fire, flames")) self.assertEqual(make_weighted_conjunction([("fire, flames , fire", 1)]), parse_prompt("fire, flames , fire")) self.assertEqual(make_weighted_conjunction([("cat hot-dog eating", 1)]), parse_prompt("cat hot-dog eating")) @@ -37,14 +37,25 @@ class PromptParserTestCase(unittest.TestCase): def test_attention(self): self.assertEqual(make_weighted_conjunction([('flames', 0.5)]), parse_prompt("(flames)0.5")) + self.assertEqual(make_weighted_conjunction([('flames', 0.5)]), parse_prompt("(flames).attend(0.5)")) + self.assertEqual(make_weighted_conjunction([('flames', 0.5)]), parse_prompt("flames.attend(0.5)")) + self.assertEqual(make_weighted_conjunction([('flames', 0.5)]), parse_prompt("\"flames\".attend(0.5)")) self.assertEqual(make_weighted_conjunction([('fire flames', 0.5)]), parse_prompt("(fire flames)0.5")) + self.assertEqual(make_weighted_conjunction([('fire flames', 0.5)]), parse_prompt("(fire flames).attend(0.5)")) + self.assertEqual(make_weighted_conjunction([('flames', 1.1)]), parse_prompt("(flames)+")) self.assertEqual(make_weighted_conjunction([('flames', 1.1)]), parse_prompt("flames+")) self.assertEqual(make_weighted_conjunction([('flames', 1.1)]), parse_prompt("\"flames\"+")) + self.assertEqual(make_weighted_conjunction([('flames', 1.1)]), parse_prompt("flames.attend(+)")) + self.assertEqual(make_weighted_conjunction([('flames', 1.1)]), parse_prompt("(flames).attend(+)")) + self.assertEqual(make_weighted_conjunction([('flames', 1.1)]), parse_prompt("\"flames\".attend(+)")) self.assertEqual(make_weighted_conjunction([('flames', 0.9)]), parse_prompt("(flames)-")) self.assertEqual(make_weighted_conjunction([('flames', 0.9)]), parse_prompt("flames-")) self.assertEqual(make_weighted_conjunction([('flames', 0.9)]), parse_prompt("\"flames\"-")) self.assertEqual(make_weighted_conjunction([('fire', 1), ('flames', 0.5)]), parse_prompt("fire (flames)0.5")) + self.assertEqual(make_weighted_conjunction([('fire', 1), ('flames', 0.5)]), parse_prompt("fire flames.attend(0.5)")) + self.assertEqual(make_weighted_conjunction([('fire', 1), ('flames', 0.5)]), parse_prompt("fire (flames).attend(0.5)")) + self.assertEqual(make_weighted_conjunction([('fire', 1), ('flames', 0.5)]), parse_prompt("fire \"flames\".attend(0.5)")) self.assertEqual(make_weighted_conjunction([('flames', pow(1.1, 2))]), parse_prompt("(flames)++")) self.assertEqual(make_weighted_conjunction([('flames', pow(0.9, 2))]), parse_prompt("(flames)--")) self.assertEqual(make_weighted_conjunction([('flowers', pow(0.9, 3)), ('flames', pow(1.1, 3))]), parse_prompt("(flowers)--- flames+++")) @@ -102,20 +113,17 @@ class PromptParserTestCase(unittest.TestCase): assert_if_prompt_string_not_untouched('a test prompt') assert_if_prompt_string_not_untouched('a badly formed +test prompt') - with self.assertRaises(pyparsing.ParseException): - parse_prompt('a badly (formed test prompt') + assert_if_prompt_string_not_untouched('a badly (formed test prompt') + #with self.assertRaises(pyparsing.ParseException): - with self.assertRaises(pyparsing.ParseException): - parse_prompt('a badly (formed +test prompt') + assert_if_prompt_string_not_untouched('a badly (formed +test prompt') self.assertEqual(Conjunction([FlattenedPrompt([Fragment('a badly formed +test prompt',1)])]) , parse_prompt('a badly (formed +test )prompt')) - with self.assertRaises(pyparsing.ParseException): - parse_prompt('(((a badly (formed +test )prompt') - with self.assertRaises(pyparsing.ParseException): - parse_prompt('(a (ba)dly (f)ormed +test prompt') - with self.assertRaises(pyparsing.ParseException): - parse_prompt('(a (ba)dly (f)ormed +test +prompt') - with self.assertRaises(pyparsing.ParseException): - parse_prompt('("((a badly (formed +test ").blend(1.0)') + self.assertEqual(Conjunction([FlattenedPrompt([Fragment('(((a badly formed +test prompt',1)])]) , parse_prompt('(((a badly (formed +test )prompt')) + + self.assertEqual(Conjunction([FlattenedPrompt([Fragment('(a ba dly f ormed +test prompt',1)])]) , parse_prompt('(a (ba)dly (f)ormed +test prompt')) + self.assertEqual(Conjunction([FlattenedPrompt([Fragment('(a ba dly f ormed +test +prompt',1)])]) , parse_prompt('(a (ba)dly (f)ormed +test +prompt')) + self.assertEqual(Conjunction([Blend([FlattenedPrompt([Fragment('((a badly (formed +test', 1)])], [1.0])]), + parse_prompt('("((a badly (formed +test ").blend(1.0)')) self.assertEqual(Conjunction([FlattenedPrompt([Fragment('hamburger bun', 1)])]), parse_prompt("hamburger ((bun))")) @@ -128,6 +136,26 @@ class PromptParserTestCase(unittest.TestCase): def test_blend(self): + self.assertEqual(Conjunction( + [Blend([FlattenedPrompt([('mountain', 1.0)]), FlattenedPrompt([('man', 1.0)])], [1.0, 1.0])]), + parse_prompt("(\"mountain\", \"man\").blend()") + ) + self.assertEqual(Conjunction( + [Blend([FlattenedPrompt([('mountain', 1.0)]), FlattenedPrompt([('man', 1.0)])], [1.0, 1.0])]), + parse_prompt("(mountain, man).blend()") + ) + self.assertEqual(Conjunction( + [Blend([FlattenedPrompt([('mountain', 1.0)]), FlattenedPrompt([('man', 1.0)])], [1.0, 1.0])]), + parse_prompt("((mountain), (man)).blend()") + ) + self.assertEqual(Conjunction( + [Blend([FlattenedPrompt([('mountain', 1.0)]), FlattenedPrompt([('tall man', 1.0)])], [1.0, 1.0])]), + parse_prompt("((mountain), (tall man)).blend()") + ) + + with self.assertRaises(PromptParser.ParsingException): + print(parse_prompt("((mountain), \"cat.swap(dog)\").blend()")) + self.assertEqual(Conjunction( [Blend([FlattenedPrompt([('fire', 1.0)]), FlattenedPrompt([('fire flames', 1.0)])], [0.7, 0.3])]), parse_prompt("(\"fire\", \"fire flames\").blend(0.7, 0.3)") @@ -166,10 +194,20 @@ class PromptParserTestCase(unittest.TestCase): ) self.assertEqual( - Conjunction([Blend([FlattenedPrompt([('mountain, man, hairy', 1)]), - FlattenedPrompt([('face, teeth,', 1), ('eyes', 0.9*0.9)])], weights=[1.0,-1.0])]), + Conjunction([Blend([FlattenedPrompt([('mountain , man , hairy', 1)]), + FlattenedPrompt([('face , teeth ,', 1), ('eyes', 0.9*0.9)])], weights=[1.0,-1.0], normalize_weights=True)]), parse_prompt('("mountain, man, hairy", "face, teeth, eyes--").blend(1,-1)') ) + self.assertEqual( + Conjunction([Blend([FlattenedPrompt([('mountain , man , hairy', 1)]), + FlattenedPrompt([('face , teeth ,', 1), ('eyes', 0.9 * 0.9)])], weights=[1.0, -1.0], normalize_weights=False)]), + parse_prompt('("mountain, man, hairy", "face, teeth, eyes--").blend(1,-1,no_normalize)') + ) + + with self.assertRaises(PromptParser.ParsingException): + parse_prompt("(\"fire\", \"fire flames\").blend(0.7, 0.3, 0.1)") + with self.assertRaises(PromptParser.ParsingException): + parse_prompt("(\"fire\", \"fire flames\").blend(0.7)") def test_nested(self): @@ -182,6 +220,9 @@ class PromptParserTestCase(unittest.TestCase): def test_cross_attention_control(self): + self.assertEqual(Conjunction([FlattenedPrompt([CrossAttentionControlSubstitute([Fragment('sun')], [Fragment('moon')])])]), + parse_prompt("sun.swap(moon)")) + self.assertEqual(Conjunction([ FlattenedPrompt([Fragment('a', 1), CrossAttentionControlSubstitute([Fragment('cat', 1)], [Fragment('dog', 1)]), @@ -259,6 +300,12 @@ class PromptParserTestCase(unittest.TestCase): Fragment(',', 1), Fragment('fire', 2.0)])]) self.assertEqual(flames_to_trees_fire, parse_prompt('"(fire (flames)0.5)0.5".swap("(trees)0.7 houses"), (fire)2.0')) + self.assertEqual(Conjunction([FlattenedPrompt([Fragment('a', 1), + CrossAttentionControlSubstitute([Fragment('cat',1)], [Fragment('dog',1)]), + Fragment('eating a', 1), + CrossAttentionControlSubstitute([Fragment('hotdog',1)], [Fragment('hotdog', pow(1.1,4))]) + ])]), + parse_prompt("a cat.swap(dog) eating a hotdog.swap(hotdog++++)")) self.assertEqual(Conjunction([FlattenedPrompt([Fragment('a', 1), CrossAttentionControlSubstitute([Fragment('cat',1)], [Fragment('dog',1)]), Fragment('eating a', 1), @@ -343,31 +390,31 @@ class PromptParserTestCase(unittest.TestCase): self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain', 1.1), ('\(man\)', 1.1*1.1)]),parse_prompt('hairy (mountain (\(man\))+)+')) self.assertEqual(make_weighted_conjunction([('hairy', 1), ('\(man\)', 1.1*1.1), ('mountain', 1.1)]),parse_prompt('hairy ((\(man\))1.1 "mountain")+')) self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain', 1.1), ('\(man\)', 1.1*1.1)]),parse_prompt('hairy ("mountain" (\(man\))1.1 )+')) - self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain, man', 1.1)]),parse_prompt('hairy ("mountain, man")+')) - self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain, man with a', 1.1), ('beard', 1.1*1.1)]), parse_prompt('hairy ("mountain, man" with a beard+)+')) - self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain, man with a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, man" with a (beard)2.0)+')) - self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain, \"man\" with a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, \\"man\\"" with a (beard)2.0)+')) - self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain, m\"an\" with a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, m\\"an\\"" with a (beard)2.0)+')) + self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain , man', 1.1)]),parse_prompt('hairy ("mountain, man")+')) + self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain , man with a', 1.1), ('beard', 1.1*1.1)]), parse_prompt('hairy ("mountain, man" with a beard+)+')) + self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain , man with a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, man" with a (beard)2.0)+')) + self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain , \"man\" with a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, \\"man\\"" with a (beard)2.0)+')) + self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain , m\"an\" with a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, m\\"an\\"" with a (beard)2.0)+')) - self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain, \"man (with a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, \\\"man\" \(with a (beard)2.0)+')) - self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain, \"man w(ith a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, \\\"man\" w\(ith a (beard)2.0)+')) - self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain, \"man with( a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, \\\"man\" with\( a (beard)2.0)+')) - self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain, \"man )with a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, \\\"man\" \)with a (beard)2.0)+')) - self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain, \"man w)ith a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, \\\"man\" w\)ith a (beard)2.0)+')) - self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain, \"man with) a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, \\\"man\" with\) a (beard)2.0)+')) - self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mou)ntain, \"man (wit(h a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mou\)ntain, \\\"man\" \(wit\(h a (beard)2.0)+')) - self.assertEqual(make_weighted_conjunction([('hai(ry', 1), ('mountain, \"man w)ith a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hai\(ry ("mountain, \\\"man\" w\)ith a (beard)2.0)+')) - self.assertEqual(make_weighted_conjunction([('hairy((', 1), ('mountain, \"man with a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy\(\( ("mountain, \\\"man\" with a (beard)2.0)+')) + self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain , \"man (with a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, \\\"man\" \(with a (beard)2.0)+')) + self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain , \"man w(ith a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, \\\"man\" w\(ith a (beard)2.0)+')) + self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain , \"man with( a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, \\\"man\" with\( a (beard)2.0)+')) + self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain , \"man )with a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, \\\"man\" \)with a (beard)2.0)+')) + self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain , \"man w)ith a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, \\\"man\" w\)ith a (beard)2.0)+')) + self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mountain , \"man with) a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mountain, \\\"man\" with\) a (beard)2.0)+')) + self.assertEqual(make_weighted_conjunction([('hairy', 1), ('mou)ntain , \"man (wit(h a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy ("mou\)ntain, \\\"man\" \(wit\(h a (beard)2.0)+')) + self.assertEqual(make_weighted_conjunction([('hai(ry', 1), ('mountain , \"man w)ith a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hai\(ry ("mountain, \\\"man\" w\)ith a (beard)2.0)+')) + self.assertEqual(make_weighted_conjunction([('hairy((', 1), ('mountain , \"man with a', 1.1), ('beard', 1.1*2.0)]), parse_prompt('hairy\(\( ("mountain, \\\"man\" with a (beard)2.0)+')) - self.assertEqual(make_weighted_conjunction([('mountain, \"man (with a', 1.1), ('beard', 1.1*2.0), ('hairy', 1)]), parse_prompt('("mountain, \\\"man\" \(with a (beard)2.0)+ hairy')) - self.assertEqual(make_weighted_conjunction([('mountain, \"man w(ith a', 1.1), ('beard', 1.1*2.0), ('hairy', 1)]), parse_prompt('("mountain, \\\"man\" w\(ith a (beard)2.0)+hairy')) - self.assertEqual(make_weighted_conjunction([('mountain, \"man with( a', 1.1), ('beard', 1.1*2.0), ('hairy', 1)]), parse_prompt('("mountain, \\\"man\" with\( a (beard)2.0)+ hairy')) - self.assertEqual(make_weighted_conjunction([('mountain, \"man )with a', 1.1), ('beard', 1.1*2.0), ('hairy', 1)]), parse_prompt('("mountain, \\\"man\" \)with a (beard)2.0)+ hairy')) - self.assertEqual(make_weighted_conjunction([('mountain, \"man w)ith a', 1.1), ('beard', 1.1*2.0), ('hairy', 1)]), parse_prompt('("mountain, \\\"man\" w\)ith a (beard)2.0)+ hairy')) - self.assertEqual(make_weighted_conjunction([('mountain, \"man with) a', 1.1), ('beard', 1.1*2.0), ('hairy', 1)]), parse_prompt(' ("mountain, \\\"man\" with\) a (beard)2.0)+ hairy')) - self.assertEqual(make_weighted_conjunction([('mou)ntain, \"man (wit(h a', 1.1), ('beard', 1.1*2.0), ('hairy', 1)]), parse_prompt('("mou\)ntain, \\\"man\" \(wit\(h a (beard)2.0)+ hairy')) - self.assertEqual(make_weighted_conjunction([('mountain, \"man w)ith a', 1.1), ('beard', 1.1*2.0), ('hai(ry', 1)]), parse_prompt('("mountain, \\\"man\" w\)ith a (beard)2.0)+ hai\(ry ')) - self.assertEqual(make_weighted_conjunction([('mountain, \"man with a', 1.1), ('beard', 1.1*2.0), ('hairy((', 1)]), parse_prompt('("mountain, \\\"man\" with a (beard)2.0)+ hairy\(\( ')) + self.assertEqual(make_weighted_conjunction([('mountain , \"man (with a', 1.1), ('beard', 1.1*2.0), ('hairy', 1)]), parse_prompt('("mountain, \\\"man\" \(with a (beard)2.0)+ hairy')) + self.assertEqual(make_weighted_conjunction([('mountain , \"man w(ith a', 1.1), ('beard', 1.1*2.0), ('hairy', 1)]), parse_prompt('("mountain, \\\"man\" w\(ith a (beard)2.0)+hairy')) + self.assertEqual(make_weighted_conjunction([('mountain , \"man with( a', 1.1), ('beard', 1.1*2.0), ('hairy', 1)]), parse_prompt('("mountain, \\\"man\" with\( a (beard)2.0)+ hairy')) + self.assertEqual(make_weighted_conjunction([('mountain , \"man )with a', 1.1), ('beard', 1.1*2.0), ('hairy', 1)]), parse_prompt('("mountain, \\\"man\" \)with a (beard)2.0)+ hairy')) + self.assertEqual(make_weighted_conjunction([('mountain , \"man w)ith a', 1.1), ('beard', 1.1*2.0), ('hairy', 1)]), parse_prompt('("mountain, \\\"man\" w\)ith a (beard)2.0)+ hairy')) + self.assertEqual(make_weighted_conjunction([('mountain , \"man with) a', 1.1), ('beard', 1.1*2.0), ('hairy', 1)]), parse_prompt(' ("mountain, \\\"man\" with\) a (beard)2.0)+ hairy')) + self.assertEqual(make_weighted_conjunction([('mou)ntain , \"man (wit(h a', 1.1), ('beard', 1.1*2.0), ('hairy', 1)]), parse_prompt('("mou\)ntain, \\\"man\" \(wit\(h a (beard)2.0)+ hairy')) + self.assertEqual(make_weighted_conjunction([('mountain , \"man w)ith a', 1.1), ('beard', 1.1*2.0), ('hai(ry', 1)]), parse_prompt('("mountain, \\\"man\" w\)ith a (beard)2.0)+ hai\(ry ')) + self.assertEqual(make_weighted_conjunction([('mountain , \"man with a', 1.1), ('beard', 1.1*2.0), ('hairy((', 1)]), parse_prompt('("mountain, \\\"man\" with a (beard)2.0)+ hairy\(\( ')) def test_cross_attention_escaping(self): @@ -433,6 +480,15 @@ class PromptParserTestCase(unittest.TestCase): def test_single(self): + self.assertEqual(Conjunction([FlattenedPrompt([("mountain man", 1.0)]), + FlattenedPrompt([("a person with a hat", 1.0), + ("riding a", 1.1*1.1), + CrossAttentionControlSubstitute( + [Fragment("bicycle", pow(1.1,2))], + [Fragment("skateboard", pow(1.1,2))]) + ]) + ], weights=[0.5, 0.5]), + parse_prompt("(\"mountain man\", \"a person with a hat (riding a bicycle.swap(skateboard))++\").and(0.5, 0.5)")) pass From be1393a41ce7a75ed8de7f648a93c5e5974a50d2 Mon Sep 17 00:00:00 2001 From: damian Date: Tue, 1 Nov 2022 10:16:55 +0100 Subject: [PATCH 2/9] ensure existing exception handling code also handles new exception class --- ldm/invoke/prompt_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ldm/invoke/prompt_parser.py b/ldm/invoke/prompt_parser.py index 96f002778b..43eea8736f 100644 --- a/ldm/invoke/prompt_parser.py +++ b/ldm/invoke/prompt_parser.py @@ -251,7 +251,7 @@ class PromptParser(): class ParsingException(Exception): pass - class UnrecognizedOperatorException(Exception): + class UnrecognizedOperatorException(ParsingException): def __init__(self, operator:str): super().__init__("Unrecognized operator: " + operator) From cdb107dcda858a8bb64455cc60a196a42345f8f7 Mon Sep 17 00:00:00 2001 From: damian Date: Tue, 1 Nov 2022 11:17:43 +0100 Subject: [PATCH 3/9] add option to show intermediate latent space --- backend/invoke_ai_web_server.py | 11 +- frontend/dist/assets/index.ae92a637.js | 690 ++++++++++++++++++ .../src/common/util/parameterTranslation.ts | 3 +- .../system/SettingsModal/SettingsModal.tsx | 10 + frontend/src/features/system/systemSlice.ts | 6 + ldm/generate.py | 3 + ldm/invoke/generator/base.py | 23 + ldm/invoke/server.py | 10 +- server/models.py | 2 + 9 files changed, 751 insertions(+), 7 deletions(-) create mode 100644 frontend/dist/assets/index.ae92a637.js diff --git a/backend/invoke_ai_web_server.py b/backend/invoke_ai_web_server.py index 8ae79855ab..4adae53e6f 100644 --- a/backend/invoke_ai_web_server.py +++ b/backend/invoke_ai_web_server.py @@ -604,12 +604,15 @@ class InvokeAIWebServer: progress.set_current_status("Generating") progress.set_current_status_has_steps(True) + wants_progress_image = generation_parameters['progress_images'] and step % 5 == 0 + wants_progress_latents = generation_parameters['progress_latents'] + if ( - generation_parameters["progress_images"] - and step % 5 == 0 - and step < generation_parameters["steps"] - 1 + wants_progress_image | wants_progress_latents + and step < generation_parameters['steps'] - 1 ): - image = self.generate.sample_to_image(sample) + image = self.generate.sample_to_image(sample) if wants_progress_image \ + else self.generate.sample_to_lowres_estimated_image(sample) metadata = self.parameters_to_generated_image_metadata( generation_parameters ) diff --git a/frontend/dist/assets/index.ae92a637.js b/frontend/dist/assets/index.ae92a637.js new file mode 100644 index 0000000000..c2a097832c --- /dev/null +++ b/frontend/dist/assets/index.ae92a637.js @@ -0,0 +1,690 @@ +function nq(e,t){for(var n=0;ni[o]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))i(o);new MutationObserver(o=>{for(const s of o)if(s.type==="childList")for(const l of s.addedNodes)l.tagName==="LINK"&&l.rel==="modulepreload"&&i(l)}).observe(document,{childList:!0,subtree:!0});function n(o){const s={};return o.integrity&&(s.integrity=o.integrity),o.referrerpolicy&&(s.referrerPolicy=o.referrerpolicy),o.crossorigin==="use-credentials"?s.credentials="include":o.crossorigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function i(o){if(o.ep)return;o.ep=!0;const s=n(o);fetch(o.href,s)}})();var jc=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function rq(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var E={exports:{}},lE={exports:{}};/** + * @license React + * react.development.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */(function(e,t){(function(){typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart=="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error);var n="18.2.0",i=Symbol.for("react.element"),o=Symbol.for("react.portal"),s=Symbol.for("react.fragment"),l=Symbol.for("react.strict_mode"),p=Symbol.for("react.profiler"),m=Symbol.for("react.provider"),v=Symbol.for("react.context"),g=Symbol.for("react.forward_ref"),b=Symbol.for("react.suspense"),w=Symbol.for("react.suspense_list"),C=Symbol.for("react.memo"),T=Symbol.for("react.lazy"),R=Symbol.for("react.offscreen"),L=Symbol.iterator,D="@@iterator";function P(S){if(S===null||typeof S!="object")return null;var O=L&&S[L]||S[D];return typeof O=="function"?O:null}var I={current:null},F={transition:null},z={current:null,isBatchingLegacy:!1,didScheduleLegacyUpdate:!1},q={current:null},Y={},Q=null;function ie(S){Q=S}Y.setExtraStackFrame=function(S){Q=S},Y.getCurrentStack=null,Y.getStackAddendum=function(){var S="";Q&&(S+=Q);var O=Y.getCurrentStack;return O&&(S+=O()||""),S};var ae=!1,me=!1,ze=!1,te=!1,ee=!1,we={ReactCurrentDispatcher:I,ReactCurrentBatchConfig:F,ReactCurrentOwner:q};we.ReactDebugCurrentFrame=Y,we.ReactCurrentActQueue=z;function ye(S){{for(var O=arguments.length,V=new Array(O>1?O-1:0),G=1;G1?O-1:0),G=1;G1){for(var $t=Array(Nt),xt=0;xt1){for(var Gt=Array(xt),Lt=0;Lt is not supported and will be removed in a future major release. Did you mean to render instead?")),O.Provider},set:function(Te){O.Provider=Te}},_currentValue:{get:function(){return O._currentValue},set:function(Te){O._currentValue=Te}},_currentValue2:{get:function(){return O._currentValue2},set:function(Te){O._currentValue2=Te}},_threadCount:{get:function(){return O._threadCount},set:function(Te){O._threadCount=Te}},Consumer:{get:function(){return V||(V=!0,K("Rendering is not supported and will be removed in a future major release. Did you mean to render instead?")),O.Consumer}},displayName:{get:function(){return O.displayName},set:function(Te){se||(ye("Setting `displayName` on Context.Consumer has no effect. You should set it directly on the context with Context.displayName = '%s'.",Te),se=!0)}}}),O.Consumer=Ue}return O._currentRenderer=null,O._currentRenderer2=null,O}var xr=-1,Yi=0,Ja=1,qi=2;function X(S){if(S._status===xr){var O=S._result,V=O();if(V.then(function(Ue){if(S._status===Yi||S._status===xr){var Te=S;Te._status=Ja,Te._result=Ue}},function(Ue){if(S._status===Yi||S._status===xr){var Te=S;Te._status=qi,Te._result=Ue}}),S._status===xr){var G=S;G._status=Yi,G._result=V}}if(S._status===Ja){var se=S._result;return se===void 0&&K(`lazy: Expected the result of a dynamic import() call. Instead received: %s + +Your code should look like: + const MyComponent = lazy(() => import('./MyComponent')) + +Did you accidentally put curly braces around the import?`,se),"default"in se||K(`lazy: Expected the result of a dynamic import() call. Instead received: %s + +Your code should look like: + const MyComponent = lazy(() => import('./MyComponent'))`,se),se.default}else throw S._result}function Ve(S){var O={_status:xr,_result:S},V={$$typeof:T,_payload:O,_init:X};{var G,se;Object.defineProperties(V,{defaultProps:{configurable:!0,get:function(){return G},set:function(Ue){K("React.lazy(...): It is not supported to assign `defaultProps` to a lazy component import. Either specify them where the component is defined, or create a wrapping component around it."),G=Ue,Object.defineProperty(V,"defaultProps",{enumerable:!0})}},propTypes:{configurable:!0,get:function(){return se},set:function(Ue){K("React.lazy(...): It is not supported to assign `propTypes` to a lazy component import. Either specify them where the component is defined, or create a wrapping component around it."),se=Ue,Object.defineProperty(V,"propTypes",{enumerable:!0})}}})}return V}function Qe(S){S!=null&&S.$$typeof===C?K("forwardRef requires a render function but received a `memo` component. Instead of forwardRef(memo(...)), use memo(forwardRef(...))."):typeof S!="function"?K("forwardRef requires a render function but was given %s.",S===null?"null":typeof S):S.length!==0&&S.length!==2&&K("forwardRef render functions accept exactly two parameters: props and ref. %s",S.length===1?"Did you forget to use the ref parameter?":"Any additional parameter will be undefined."),S!=null&&(S.defaultProps!=null||S.propTypes!=null)&&K("forwardRef render functions do not support propTypes or defaultProps. Did you accidentally pass a React component?");var O={$$typeof:g,render:S};{var V;Object.defineProperty(O,"displayName",{enumerable:!1,configurable:!0,get:function(){return V},set:function(G){V=G,!S.name&&!S.displayName&&(S.displayName=G)}})}return O}var _t;_t=Symbol.for("react.module.reference");function un(S){return!!(typeof S=="string"||typeof S=="function"||S===s||S===p||ee||S===l||S===b||S===w||te||S===R||ae||me||ze||typeof S=="object"&&S!==null&&(S.$$typeof===T||S.$$typeof===C||S.$$typeof===m||S.$$typeof===v||S.$$typeof===g||S.$$typeof===_t||S.getModuleId!==void 0))}function Cn(S,O){un(S)||K("memo: The first argument must be a component. Instead received: %s",S===null?"null":typeof S);var V={$$typeof:C,type:S,compare:O===void 0?null:O};{var G;Object.defineProperty(V,"displayName",{enumerable:!1,configurable:!0,get:function(){return G},set:function(se){G=se,!S.name&&!S.displayName&&(S.displayName=se)}})}return V}function st(){var S=I.current;return S===null&&K(`Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: +1. You might have mismatching versions of React and the renderer (such as React DOM) +2. You might be breaking the Rules of Hooks +3. You might have more than one copy of React in the same app +See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.`),S}function Kt(S){var O=st();if(S._context!==void 0){var V=S._context;V.Consumer===S?K("Calling useContext(Context.Consumer) is not supported, may cause bugs, and will be removed in a future major release. Did you mean to call useContext(Context) instead?"):V.Provider===S&&K("Calling useContext(Context.Provider) is not supported. Did you mean to call useContext(Context) instead?")}return O.useContext(S)}function Hn(S){var O=st();return O.useState(S)}function Un(S,O,V){var G=st();return G.useReducer(S,O,V)}function fn(S){var O=st();return O.useRef(S)}function Kr(S,O){var V=st();return V.useEffect(S,O)}function Aa(S,O){var V=st();return V.useInsertionEffect(S,O)}function qo(S,O){var V=st();return V.useLayoutEffect(S,O)}function ki(S,O){var V=st();return V.useCallback(S,O)}function wo(S,O){var V=st();return V.useMemo(S,O)}function Xu(S,O,V){var G=st();return G.useImperativeHandle(S,O,V)}function La(S,O){{var V=st();return V.useDebugValue(S,O)}}function cl(){var S=st();return S.useTransition()}function eo(S){var O=st();return O.useDeferredValue(S)}function tn(){var S=st();return S.useId()}function to(S,O,V){var G=st();return G.useSyncExternalStore(S,O,V)}var Ai=0,Zo,Cs,Ko,Ns,Es,Xo,Qo;function _s(){}_s.__reactDisabledLog=!0;function fl(){{if(Ai===0){Zo=console.log,Cs=console.info,Ko=console.warn,Ns=console.error,Es=console.group,Xo=console.groupCollapsed,Qo=console.groupEnd;var S={configurable:!0,enumerable:!0,value:_s,writable:!0};Object.defineProperties(console,{info:S,log:S,warn:S,error:S,group:S,groupCollapsed:S,groupEnd:S})}Ai++}}function dl(){{if(Ai--,Ai===0){var S={configurable:!0,enumerable:!0,writable:!0};Object.defineProperties(console,{log:Oe({},S,{value:Zo}),info:Oe({},S,{value:Cs}),warn:Oe({},S,{value:Ko}),error:Oe({},S,{value:Ns}),group:Oe({},S,{value:Es}),groupCollapsed:Oe({},S,{value:Xo}),groupEnd:Oe({},S,{value:Qo})})}Ai<0&&K("disabledDepth fell below zero. This is a bug in React. Please file an issue.")}}var Oa=we.ReactCurrentDispatcher,Gr;function Zi(S,O,V){{if(Gr===void 0)try{throw Error()}catch(se){var G=se.stack.trim().match(/\n( *(at )?)/);Gr=G&&G[1]||""}return` +`+Gr+S}}var Li=!1,Ki;{var Ts=typeof WeakMap=="function"?WeakMap:Map;Ki=new Ts}function Jo(S,O){if(!S||Li)return"";{var V=Ki.get(S);if(V!==void 0)return V}var G;Li=!0;var se=Error.prepareStackTrace;Error.prepareStackTrace=void 0;var Ue;Ue=Oa.current,Oa.current=null,fl();try{if(O){var Te=function(){throw Error()};if(Object.defineProperty(Te.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(Te,[])}catch(jt){G=jt}Reflect.construct(S,[],Te)}else{try{Te.call()}catch(jt){G=jt}S.call(Te.prototype)}}else{try{throw Error()}catch(jt){G=jt}S()}}catch(jt){if(jt&&G&&typeof jt.stack=="string"){for(var Ye=jt.stack.split(` +`),ft=G.stack.split(` +`),Nt=Ye.length-1,$t=ft.length-1;Nt>=1&&$t>=0&&Ye[Nt]!==ft[$t];)$t--;for(;Nt>=1&&$t>=0;Nt--,$t--)if(Ye[Nt]!==ft[$t]){if(Nt!==1||$t!==1)do if(Nt--,$t--,$t<0||Ye[Nt]!==ft[$t]){var xt=` +`+Ye[Nt].replace(" at new "," at ");return S.displayName&&xt.includes("")&&(xt=xt.replace("",S.displayName)),typeof S=="function"&&Ki.set(S,xt),xt}while(Nt>=1&&$t>=0);break}}}finally{Li=!1,Oa.current=Ue,dl(),Error.prepareStackTrace=se}var Gt=S?S.displayName||S.name:"",Lt=Gt?Zi(Gt):"";return typeof S=="function"&&Ki.set(S,Lt),Lt}function Rs(S,O,V){return Jo(S,!1)}function Jl(S){var O=S.prototype;return!!(O&&O.isReactComponent)}function Oi(S,O,V){if(S==null)return"";if(typeof S=="function")return Jo(S,Jl(S));if(typeof S=="string")return Zi(S);switch(S){case b:return Zi("Suspense");case w:return Zi("SuspenseList")}if(typeof S=="object")switch(S.$$typeof){case g:return Rs(S.render);case C:return Oi(S.type,O,V);case T:{var G=S,se=G._payload,Ue=G._init;try{return Oi(Ue(se),O,V)}catch{}}}return""}var es={},Xi=we.ReactDebugCurrentFrame;function Ma(S){if(S){var O=S._owner,V=Oi(S.type,S._source,O?O.type:null);Xi.setExtraStackFrame(V)}else Xi.setExtraStackFrame(null)}function pl(S,O,V,G,se){{var Ue=Function.call.bind(ln);for(var Te in S)if(Ue(S,Te)){var Ye=void 0;try{if(typeof S[Te]!="function"){var ft=Error((G||"React class")+": "+V+" type `"+Te+"` is invalid; it must be a function, usually from the `prop-types` package, but received `"+typeof S[Te]+"`.This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.");throw ft.name="Invariant Violation",ft}Ye=S[Te](O,Te,G,V,null,"SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED")}catch(Nt){Ye=Nt}Ye&&!(Ye instanceof Error)&&(Ma(se),K("%s: type specification of %s `%s` is invalid; the type checker function must return `null` or an `Error` but returned a %s. You may have forgotten to pass an argument to the type checker creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and shape all require an argument).",G||"React class",V,Te,typeof Ye),Ma(null)),Ye instanceof Error&&!(Ye.message in es)&&(es[Ye.message]=!0,Ma(se),K("Failed %s type: %s",V,Ye.message),Ma(null))}}}function dn(S){if(S){var O=S._owner,V=Oi(S.type,S._source,O?O.type:null);ie(V)}else ie(null)}var Pa;Pa=!1;function ts(){if(q.current){var S=Tt(q.current.type);if(S)return` + +Check the render method of \``+S+"`."}return""}function Wt(S){if(S!==void 0){var O=S.fileName.replace(/^.*[\\\/]/,""),V=S.lineNumber;return` + +Check your code at `+O+":"+V+"."}return""}function ml(S){return S!=null?Wt(S.__source):""}var _r={};function no(S){var O=ts();if(!O){var V=typeof S=="string"?S:S.displayName||S.name;V&&(O=` + +Check the top-level render call using <`+V+">.")}return O}function oa(S,O){if(!(!S._store||S._store.validated||S.key!=null)){S._store.validated=!0;var V=no(O);if(!_r[V]){_r[V]=!0;var G="";S&&S._owner&&S._owner!==q.current&&(G=" It was passed a child from "+Tt(S._owner.type)+"."),dn(S),K('Each child in a list should have a unique "key" prop.%s%s See https://reactjs.org/link/warning-keys for more information.',V,G),dn(null)}}}function Co(S,O){if(typeof S=="object"){if(Vt(S))for(var V=0;V",se=" Did you accidentally export a JSX literal instead of a component?"):Te=typeof S,K("React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s",Te,se)}var Ye=ut.apply(this,arguments);if(Ye==null)return Ye;if(G)for(var ft=2;ft10&&ye("Detected a large number of updates inside startTransition. If this is due to a subscription please re-write it to use React provided hooks. Otherwise concurrent mode guarantees are off the table."),G._updatedFibers.clear()}}}var No=!1,Ia=null;function hl(S){if(Ia===null)try{var O=("require"+Math.random()).slice(0,7),V=e&&e[O];Ia=V.call(e,"timers").setImmediate}catch{Ia=function(se){No===!1&&(No=!0,typeof MessageChannel>"u"&&K("This browser does not have a MessageChannel implementation, so enqueuing tasks via await act(async () => ...) will fail. Please file an issue at https://github.com/facebook/react/issues if you encounter this warning."));var Ue=new MessageChannel;Ue.port1.onmessage=se,Ue.port2.postMessage(void 0)}}return Ia(S)}var bn=0,zn=!1;function eu(S){{var O=bn;bn++,z.current===null&&(z.current=[]);var V=z.isBatchingLegacy,G;try{if(z.isBatchingLegacy=!0,G=S(),!V&&z.didScheduleLegacyUpdate){var se=z.current;se!==null&&(z.didScheduleLegacyUpdate=!1,be(se))}}catch(Gt){throw Qi(O),Gt}finally{z.isBatchingLegacy=V}if(G!==null&&typeof G=="object"&&typeof G.then=="function"){var Ue=G,Te=!1,Ye={then:function(Gt,Lt){Te=!0,Ue.then(function(jt){Qi(O),bn===0?W(jt,Gt,Lt):Gt(jt)},function(jt){Qi(O),Lt(jt)})}};return!zn&&typeof Promise<"u"&&Promise.resolve().then(function(){}).then(function(){Te||(zn=!0,K("You called act(async () => ...) without await. This could lead to unexpected testing behaviour, interleaving multiple act calls and mixing their scopes. You should - await act(async () => ...);"))}),Ye}else{var ft=G;if(Qi(O),bn===0){var Nt=z.current;Nt!==null&&(be(Nt),z.current=null);var $t={then:function(Gt,Lt){z.current===null?(z.current=[],W(ft,Gt,Lt)):Gt(ft)}};return $t}else{var xt={then:function(Gt,Lt){Gt(ft)}};return xt}}}}function Qi(S){S!==bn-1&&K("You seem to have overlapping act() calls, this is not supported. Be sure to await previous act() calls before making a new one. "),bn=S}function W(S,O,V){{var G=z.current;if(G!==null)try{be(G),hl(function(){G.length===0?(z.current=null,O(S)):W(S,O,V)})}catch(se){V(se)}else O(S)}}var ne=!1;function be(S){if(!ne){ne=!0;var O=0;try{for(;O0;){var en=gn-1>>>1,Rn=Ge[en];if(v(Rn,ut)>0)Ge[en]=ut,Ge[gn]=Rn,gn=en;else return}}function m(Ge,ut,At){for(var gn=At,en=Ge.length,Rn=en>>>1;gnAt&&(!Ge||On()));){var gn=te.callback;if(typeof gn=="function"){te.callback=null,ee=te.priorityLevel;var en=te.expirationTime<=At,Rn=gn(en);At=e.unstable_now(),typeof Rn=="function"?te.callback=Rn:te===s(ae)&&l(ae),Ee(At)}else l(ae);te=s(ae)}if(te!==null)return!0;var Fn=s(me);return Fn!==null&&Dt(Oe,Fn.startTime-At),!1}function et(Ge,ut){switch(Ge){case g:case b:case w:case C:case T:break;default:Ge=w}var At=ee;ee=Ge;try{return ut()}finally{ee=At}}function at(Ge){var ut;switch(ee){case g:case b:case w:ut=w;break;default:ut=ee;break}var At=ee;ee=ut;try{return Ge()}finally{ee=At}}function kt(Ge){var ut=ee;return function(){var At=ee;ee=ut;try{return Ge.apply(this,arguments)}finally{ee=At}}}function He(Ge,ut,At){var gn=e.unstable_now(),en;if(typeof At=="object"&&At!==null){var Rn=At.delay;typeof Rn=="number"&&Rn>0?en=gn+Rn:en=gn}else en=gn;var Fn;switch(Ge){case g:Fn=z;break;case b:Fn=q;break;case T:Fn=ie;break;case C:Fn=Q;break;case w:default:Fn=Y;break}var zr=en+Fn,Pn={id:ze++,callback:ut,priorityLevel:Ge,startTime:en,expirationTime:zr,sortIndex:-1};return en>gn?(Pn.sortIndex=en,o(me,Pn),s(ae)===null&&Pn===s(me)&&(K?Ie():K=!0,Dt(Oe,en-gn))):(Pn.sortIndex=zr,o(ae,Pn),!ye&&!we&&(ye=!0,rn(Pe))),Pn}function ot(){}function wt(){!ye&&!we&&(ye=!0,rn(Pe))}function It(){return s(ae)}function We(Ge){Ge.callback=null}function Vt(){return ee}var Ce=!1,nt=null,Ct=-1,rt=i,sn=-1;function On(){var Ge=e.unstable_now()-sn;return!(Ge125){console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported");return}Ge>0?rt=Math.floor(1e3/Ge):rt=i}var Mn=function(){if(nt!==null){var Ge=e.unstable_now();sn=Ge;var ut=!0,At=!0;try{At=nt(ut,Ge)}finally{At?yn():(Ce=!1,nt=null)}}else Ce=!1},yn;if(typeof pe=="function")yn=function(){pe(Mn)};else if(typeof MessageChannel<"u"){var Ze=new MessageChannel,tt=Ze.port2;Ze.port1.onmessage=Mn,yn=function(){tt.postMessage(null)}}else yn=function(){le(Mn,0)};function rn(Ge){nt=Ge,Ce||(Ce=!0,yn())}function Dt(Ge,ut){Ct=le(function(){Ge(e.unstable_now())},ut)}function Ie(){ge(Ct),Ct=-1}var Zt=Tt,Tn=null;e.unstable_IdlePriority=T,e.unstable_ImmediatePriority=g,e.unstable_LowPriority=C,e.unstable_NormalPriority=w,e.unstable_Profiling=Tn,e.unstable_UserBlockingPriority=b,e.unstable_cancelCallback=We,e.unstable_continueExecution=wt,e.unstable_forceFrameRate=ln,e.unstable_getCurrentPriorityLevel=Vt,e.unstable_getFirstCallbackNode=It,e.unstable_next=at,e.unstable_pauseExecution=ot,e.unstable_requestPaint=Zt,e.unstable_runWithPriority=et,e.unstable_scheduleCallback=He,e.unstable_shouldYield=On,e.unstable_wrapCallback=kt,typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop=="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(new Error)})()})(LD);(function(e){e.exports=LD})(AD);/** + * @license React + * react-dom.development.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */(function(){typeof __REACT_DEVTOOLS_GLOBAL_HOOK__<"u"&&typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart=="function"&&__REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(new Error);var e=E.exports,t=AD.exports,n=e.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,i=!1;function o(r){i=r}function s(r){if(!i){for(var a=arguments.length,u=new Array(a>1?a-1:0),f=1;f1?a-1:0),f=1;f2&&(r[0]==="o"||r[0]==="O")&&(r[1]==="n"||r[1]==="N")}function zr(r,a,u,f){if(u!==null&&u.type===Ze)return!1;switch(typeof a){case"function":case"symbol":return!0;case"boolean":{if(f)return!1;if(u!==null)return!u.acceptsBooleans;var h=r.toLowerCase().slice(0,5);return h!=="data-"&&h!=="aria-"}default:return!1}}function Pn(r,a,u,f){if(a===null||typeof a>"u"||zr(r,a,u,f))return!0;if(f)return!1;if(u!==null)switch(u.type){case Dt:return!a;case Ie:return a===!1;case Zt:return isNaN(a);case Tn:return isNaN(a)||a<1}return!1}function Ti(r){return kn.hasOwnProperty(r)?kn[r]:null}function Vn(r,a,u,f,h,x,_){this.acceptsBooleans=a===rn||a===Dt||a===Ie,this.attributeName=f,this.attributeNamespace=h,this.mustUseProperty=u,this.propertyName=r,this.type=a,this.sanitizeURL=x,this.removeEmptyString=_}var kn={},Ri=["children","dangerouslySetInnerHTML","defaultValue","defaultChecked","innerHTML","suppressContentEditableWarning","suppressHydrationWarning","style"];Ri.forEach(function(r){kn[r]=new Vn(r,Ze,!1,r,null,!1,!1)}),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(r){var a=r[0],u=r[1];kn[a]=new Vn(a,tt,!1,u,null,!1,!1)}),["contentEditable","draggable","spellCheck","value"].forEach(function(r){kn[r]=new Vn(r,rn,!1,r.toLowerCase(),null,!1,!1)}),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(r){kn[r]=new Vn(r,rn,!1,r,null,!1,!1)}),["allowFullScreen","async","autoFocus","autoPlay","controls","default","defer","disabled","disablePictureInPicture","disableRemotePlayback","formNoValidate","hidden","loop","noModule","noValidate","open","playsInline","readOnly","required","reversed","scoped","seamless","itemScope"].forEach(function(r){kn[r]=new Vn(r,Dt,!1,r.toLowerCase(),null,!1,!1)}),["checked","multiple","muted","selected"].forEach(function(r){kn[r]=new Vn(r,Dt,!0,r,null,!1,!1)}),["capture","download"].forEach(function(r){kn[r]=new Vn(r,Ie,!1,r,null,!1,!1)}),["cols","rows","size","span"].forEach(function(r){kn[r]=new Vn(r,Tn,!1,r,null,!1,!1)}),["rowSpan","start"].forEach(function(r){kn[r]=new Vn(r,Zt,!1,r.toLowerCase(),null,!1,!1)});var Er=/[\-\:]([a-z])/g,Wo=function(r){return r[1].toUpperCase()};["accent-height","alignment-baseline","arabic-form","baseline-shift","cap-height","clip-path","clip-rule","color-interpolation","color-interpolation-filters","color-profile","color-rendering","dominant-baseline","enable-background","fill-opacity","fill-rule","flood-color","flood-opacity","font-family","font-size","font-size-adjust","font-stretch","font-style","font-variant","font-weight","glyph-name","glyph-orientation-horizontal","glyph-orientation-vertical","horiz-adv-x","horiz-origin-x","image-rendering","letter-spacing","lighting-color","marker-end","marker-mid","marker-start","overline-position","overline-thickness","paint-order","panose-1","pointer-events","rendering-intent","shape-rendering","stop-color","stop-opacity","strikethrough-position","strikethrough-thickness","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-anchor","text-decoration","text-rendering","underline-position","underline-thickness","unicode-bidi","unicode-range","units-per-em","v-alphabetic","v-hanging","v-ideographic","v-mathematical","vector-effect","vert-adv-y","vert-origin-x","vert-origin-y","word-spacing","writing-mode","xmlns:xlink","x-height"].forEach(function(r){var a=r.replace(Er,Wo);kn[a]=new Vn(a,tt,!1,r,null,!1,!1)}),["xlink:actuate","xlink:arcrole","xlink:role","xlink:show","xlink:title","xlink:type"].forEach(function(r){var a=r.replace(Er,Wo);kn[a]=new Vn(a,tt,!1,r,"http://www.w3.org/1999/xlink",!1,!1)}),["xml:base","xml:lang","xml:space"].forEach(function(r){var a=r.replace(Er,Wo);kn[a]=new Vn(a,tt,!1,r,"http://www.w3.org/XML/1998/namespace",!1,!1)}),["tabIndex","crossOrigin"].forEach(function(r){kn[r]=new Vn(r,tt,!1,r.toLowerCase(),null,!1,!1)});var Ss="xlinkHref";kn[Ss]=new Vn("xlinkHref",tt,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach(function(r){kn[r]=new Vn(r,tt,!1,r.toLowerCase(),null,!0,!0)});var ws=/^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*\:/i,Go=!1;function Yo(r){!Go&&ws.test(r)&&(Go=!0,l("A future version of React will block javascript: URLs as a security precaution. Use event handlers instead if you can. If you need to generate unsafe HTML try using dangerouslySetInnerHTML instead. React was passed %s.",JSON.stringify(r)))}function xr(r,a,u,f){if(f.mustUseProperty){var h=f.propertyName;return r[h]}else{sn(u,a),f.sanitizeURL&&Yo(""+u);var x=f.attributeName,_=null;if(f.type===Ie){if(r.hasAttribute(x)){var A=r.getAttribute(x);return A===""?!0:Pn(a,u,f,!1)?A:A===""+u?u:A}}else if(r.hasAttribute(x)){if(Pn(a,u,f,!1))return r.getAttribute(x);if(f.type===Dt)return u;_=r.getAttribute(x)}return Pn(a,u,f,!1)?_===null?u:_:_===""+u?u:_}}function Yi(r,a,u,f){{if(!Rn(a))return;if(!r.hasAttribute(a))return u===void 0?void 0:null;var h=r.getAttribute(a);return sn(u,a),h===""+u?u:h}}function Ja(r,a,u,f){var h=Ti(a);if(!Fn(a,h,f)){if(Pn(a,u,h,f)&&(u=null),f||h===null){if(Rn(a)){var x=a;u===null?r.removeAttribute(x):(sn(u,a),r.setAttribute(x,""+u))}return}var _=h.mustUseProperty;if(_){var A=h.propertyName;if(u===null){var M=h.type;r[A]=M===Dt?!1:""}else r[A]=u;return}var U=h.attributeName,H=h.attributeNamespace;if(u===null)r.removeAttribute(U);else{var oe=h.type,re;oe===Dt||oe===Ie&&u===!0?re="":(sn(u,U),re=""+u,h.sanitizeURL&&Yo(re.toString())),H?r.setAttributeNS(H,U,re):r.setAttribute(U,re)}}}var qi=Symbol.for("react.element"),X=Symbol.for("react.portal"),Ve=Symbol.for("react.fragment"),Qe=Symbol.for("react.strict_mode"),_t=Symbol.for("react.profiler"),un=Symbol.for("react.provider"),Cn=Symbol.for("react.context"),st=Symbol.for("react.forward_ref"),Kt=Symbol.for("react.suspense"),Hn=Symbol.for("react.suspense_list"),Un=Symbol.for("react.memo"),fn=Symbol.for("react.lazy"),Kr=Symbol.for("react.scope"),Aa=Symbol.for("react.debug_trace_mode"),qo=Symbol.for("react.offscreen"),ki=Symbol.for("react.legacy_hidden"),wo=Symbol.for("react.cache"),Xu=Symbol.for("react.tracing_marker"),La=Symbol.iterator,cl="@@iterator";function eo(r){if(r===null||typeof r!="object")return null;var a=La&&r[La]||r[cl];return typeof a=="function"?a:null}var tn=Object.assign,to=0,Ai,Zo,Cs,Ko,Ns,Es,Xo;function Qo(){}Qo.__reactDisabledLog=!0;function _s(){{if(to===0){Ai=console.log,Zo=console.info,Cs=console.warn,Ko=console.error,Ns=console.group,Es=console.groupCollapsed,Xo=console.groupEnd;var r={configurable:!0,enumerable:!0,value:Qo,writable:!0};Object.defineProperties(console,{info:r,log:r,warn:r,error:r,group:r,groupCollapsed:r,groupEnd:r})}to++}}function fl(){{if(to--,to===0){var r={configurable:!0,enumerable:!0,writable:!0};Object.defineProperties(console,{log:tn({},r,{value:Ai}),info:tn({},r,{value:Zo}),warn:tn({},r,{value:Cs}),error:tn({},r,{value:Ko}),group:tn({},r,{value:Ns}),groupCollapsed:tn({},r,{value:Es}),groupEnd:tn({},r,{value:Xo})})}to<0&&l("disabledDepth fell below zero. This is a bug in React. Please file an issue.")}}var dl=n.ReactCurrentDispatcher,Oa;function Gr(r,a,u){{if(Oa===void 0)try{throw Error()}catch(h){var f=h.stack.trim().match(/\n( *(at )?)/);Oa=f&&f[1]||""}return` +`+Oa+r}}var Zi=!1,Li;{var Ki=typeof WeakMap=="function"?WeakMap:Map;Li=new Ki}function Ts(r,a){if(!r||Zi)return"";{var u=Li.get(r);if(u!==void 0)return u}var f;Zi=!0;var h=Error.prepareStackTrace;Error.prepareStackTrace=void 0;var x;x=dl.current,dl.current=null,_s();try{if(a){var _=function(){throw Error()};if(Object.defineProperty(_.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(_,[])}catch(Se){f=Se}Reflect.construct(r,[],_)}else{try{_.call()}catch(Se){f=Se}r.call(_.prototype)}}else{try{throw Error()}catch(Se){f=Se}r()}}catch(Se){if(Se&&f&&typeof Se.stack=="string"){for(var A=Se.stack.split(` +`),M=f.stack.split(` +`),U=A.length-1,H=M.length-1;U>=1&&H>=0&&A[U]!==M[H];)H--;for(;U>=1&&H>=0;U--,H--)if(A[U]!==M[H]){if(U!==1||H!==1)do if(U--,H--,H<0||A[U]!==M[H]){var oe=` +`+A[U].replace(" at new "," at ");return r.displayName&&oe.includes("")&&(oe=oe.replace("",r.displayName)),typeof r=="function"&&Li.set(r,oe),oe}while(U>=1&&H>=0);break}}}finally{Zi=!1,dl.current=x,fl(),Error.prepareStackTrace=h}var re=r?r.displayName||r.name:"",xe=re?Gr(re):"";return typeof r=="function"&&Li.set(r,xe),xe}function Jo(r,a,u){return Ts(r,!0)}function Rs(r,a,u){return Ts(r,!1)}function Jl(r){var a=r.prototype;return!!(a&&a.isReactComponent)}function Oi(r,a,u){if(r==null)return"";if(typeof r=="function")return Ts(r,Jl(r));if(typeof r=="string")return Gr(r);switch(r){case Kt:return Gr("Suspense");case Hn:return Gr("SuspenseList")}if(typeof r=="object")switch(r.$$typeof){case st:return Rs(r.render);case Un:return Oi(r.type,a,u);case fn:{var f=r,h=f._payload,x=f._init;try{return Oi(x(h),a,u)}catch{}}}return""}function es(r){switch(r._debugOwner&&r._debugOwner.type,r._debugSource,r.tag){case C:return Gr(r.type);case Q:return Gr("Lazy");case z:return Gr("Suspense");case me:return Gr("SuspenseList");case m:case g:case Y:return Rs(r.type);case I:return Rs(r.type.render);case v:return Jo(r.type);default:return""}}function Xi(r){try{var a="",u=r;do a+=es(u),u=u.return;while(u);return a}catch(f){return` +Error generating stack: `+f.message+` +`+f.stack}}function Ma(r,a,u){var f=r.displayName;if(f)return f;var h=a.displayName||a.name||"";return h!==""?u+"("+h+")":u}function pl(r){return r.displayName||"Context"}function dn(r){if(r==null)return null;if(typeof r.tag=="number"&&l("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),typeof r=="function")return r.displayName||r.name||null;if(typeof r=="string")return r;switch(r){case Ve:return"Fragment";case X:return"Portal";case _t:return"Profiler";case Qe:return"StrictMode";case Kt:return"Suspense";case Hn:return"SuspenseList"}if(typeof r=="object")switch(r.$$typeof){case Cn:var a=r;return pl(a)+".Consumer";case un:var u=r;return pl(u._context)+".Provider";case st:return Ma(r,r.render,"ForwardRef");case Un:var f=r.displayName||null;return f!==null?f:dn(r.type)||"Memo";case fn:{var h=r,x=h._payload,_=h._init;try{return dn(_(x))}catch{return null}}}return null}function Pa(r,a,u){var f=a.displayName||a.name||"";return r.displayName||(f!==""?u+"("+f+")":u)}function ts(r){return r.displayName||"Context"}function Wt(r){var a=r.tag,u=r.type;switch(a){case we:return"Cache";case D:var f=u;return ts(f)+".Consumer";case P:var h=u;return ts(h._context)+".Provider";case ae:return"DehydratedFragment";case I:return Pa(u,u.render,"ForwardRef");case R:return"Fragment";case C:return u;case w:return"Portal";case b:return"Root";case T:return"Text";case Q:return dn(u);case L:return u===Qe?"StrictMode":"Mode";case te:return"Offscreen";case F:return"Profiler";case ze:return"Scope";case z:return"Suspense";case me:return"SuspenseList";case ye:return"TracingMarker";case v:case m:case ie:case g:case q:case Y:if(typeof u=="function")return u.displayName||u.name||null;if(typeof u=="string")return u;break}return null}var ml=n.ReactDebugCurrentFrame,_r=null,no=!1;function oa(){{if(_r===null)return null;var r=_r._debugOwner;if(r!==null&&typeof r<"u")return Wt(r)}return null}function Co(){return _r===null?"":Xi(_r)}function Pr(){ml.getCurrentStack=null,_r=null,no=!1}function lr(r){ml.getCurrentStack=r===null?null:Co,_r=r,no=!1}function ns(){return _r}function ri(r){no=r}function br(r){return""+r}function di(r){switch(typeof r){case"boolean":case"number":case"string":case"undefined":return r;case"object":return yn(r),r;default:return""}}var Qu={button:!0,checkbox:!0,image:!0,hidden:!0,radio:!0,reset:!0,submit:!0};function No(r,a){Qu[a.type]||a.onChange||a.onInput||a.readOnly||a.disabled||a.value==null||l("You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`."),a.onChange||a.readOnly||a.disabled||a.checked==null||l("You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.")}function Ia(r){var a=r.type,u=r.nodeName;return u&&u.toLowerCase()==="input"&&(a==="checkbox"||a==="radio")}function hl(r){return r._valueTracker}function bn(r){r._valueTracker=null}function zn(r){var a="";return r&&(Ia(r)?a=r.checked?"true":"false":a=r.value),a}function eu(r){var a=Ia(r)?"checked":"value",u=Object.getOwnPropertyDescriptor(r.constructor.prototype,a);yn(r[a]);var f=""+r[a];if(!(r.hasOwnProperty(a)||typeof u>"u"||typeof u.get!="function"||typeof u.set!="function")){var h=u.get,x=u.set;Object.defineProperty(r,a,{configurable:!0,get:function(){return h.call(this)},set:function(A){yn(A),f=""+A,x.call(this,A)}}),Object.defineProperty(r,a,{enumerable:u.enumerable});var _={getValue:function(){return f},setValue:function(A){yn(A),f=""+A},stopTracking:function(){bn(r),delete r[a]}};return _}}function Qi(r){hl(r)||(r._valueTracker=eu(r))}function W(r){if(!r)return!1;var a=hl(r);if(!a)return!0;var u=a.getValue(),f=zn(r);return f!==u?(a.setValue(f),!0):!1}function ne(r){if(r=r||(typeof document<"u"?document:void 0),typeof r>"u")return null;try{return r.activeElement||r.body}catch{return r.body}}var be=!1,ct=!1,pn=!1,Bn=!1;function Xt(r){var a=r.type==="checkbox"||r.type==="radio";return a?r.checked!=null:r.value!=null}function S(r,a){var u=r,f=a.checked,h=tn({},a,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:f??u._wrapperState.initialChecked});return h}function O(r,a){No("input",a),a.checked!==void 0&&a.defaultChecked!==void 0&&!ct&&(l("%s contains an input of type %s with both checked and defaultChecked props. Input elements must be either controlled or uncontrolled (specify either the checked prop, or the defaultChecked prop, but not both). Decide between using a controlled or uncontrolled input element and remove one of these props. More info: https://reactjs.org/link/controlled-components",oa()||"A component",a.type),ct=!0),a.value!==void 0&&a.defaultValue!==void 0&&!be&&(l("%s contains an input of type %s with both value and defaultValue props. Input elements must be either controlled or uncontrolled (specify either the value prop, or the defaultValue prop, but not both). Decide between using a controlled or uncontrolled input element and remove one of these props. More info: https://reactjs.org/link/controlled-components",oa()||"A component",a.type),be=!0);var u=r,f=a.defaultValue==null?"":a.defaultValue;u._wrapperState={initialChecked:a.checked!=null?a.checked:a.defaultChecked,initialValue:di(a.value!=null?a.value:f),controlled:Xt(a)}}function V(r,a){var u=r,f=a.checked;f!=null&&Ja(u,"checked",f,!1)}function G(r,a){var u=r;{var f=Xt(a);!u._wrapperState.controlled&&f&&!Bn&&(l("A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components"),Bn=!0),u._wrapperState.controlled&&!f&&!pn&&(l("A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components"),pn=!0)}V(r,a);var h=di(a.value),x=a.type;if(h!=null)x==="number"?(h===0&&u.value===""||u.value!=h)&&(u.value=br(h)):u.value!==br(h)&&(u.value=br(h));else if(x==="submit"||x==="reset"){u.removeAttribute("value");return}a.hasOwnProperty("value")?Ye(u,a.type,h):a.hasOwnProperty("defaultValue")&&Ye(u,a.type,di(a.defaultValue)),a.checked==null&&a.defaultChecked!=null&&(u.defaultChecked=!!a.defaultChecked)}function se(r,a,u){var f=r;if(a.hasOwnProperty("value")||a.hasOwnProperty("defaultValue")){var h=a.type,x=h==="submit"||h==="reset";if(x&&(a.value===void 0||a.value===null))return;var _=br(f._wrapperState.initialValue);u||_!==f.value&&(f.value=_),f.defaultValue=_}var A=f.name;A!==""&&(f.name=""),f.defaultChecked=!f.defaultChecked,f.defaultChecked=!!f._wrapperState.initialChecked,A!==""&&(f.name=A)}function Ue(r,a){var u=r;G(u,a),Te(u,a)}function Te(r,a){var u=a.name;if(a.type==="radio"&&u!=null){for(var f=r;f.parentNode;)f=f.parentNode;sn(u,"name");for(var h=f.querySelectorAll("input[name="+JSON.stringify(""+u)+'][type="radio"]'),x=0;x.")))}):a.dangerouslySetInnerHTML!=null&&($t||($t=!0,l("Pass a `value` prop if you set dangerouslyInnerHTML so React knows which value should be selected.")))),a.selected!=null&&!ft&&(l("Use the `defaultValue` or `value` props on must be a scalar value if `multiple` is false.%s",u,Mi())}}}}function In(r,a,u,f){var h=r.options;if(a){for(var x=u,_={},A=0;A.");var f=tn({},a,{value:void 0,defaultValue:void 0,children:br(u._wrapperState.initialValue)});return f}function h0(r,a){var u=r;No("textarea",a),a.value!==void 0&&a.defaultValue!==void 0&&!cy&&(l("%s contains a textarea with both value and defaultValue props. Textarea elements must be either controlled or uncontrolled (specify either the value prop, or the defaultValue prop, but not both). Decide between using a controlled or uncontrolled textarea and remove one of these props. More info: https://reactjs.org/link/controlled-components",oa()||"A component"),cy=!0);var f=a.value;if(f==null){var h=a.children,x=a.defaultValue;if(h!=null){l("Use the `defaultValue` or `value` props instead of setting children on