prompt paste improvements

This commit is contained in:
Vladimir Mandic
2024-03-22 09:41:15 -04:00
parent 3994761b8e
commit 3efc93b90e
19 changed files with 59 additions and 52 deletions
+2 -2
View File
@@ -100,8 +100,8 @@ button.custom-button{ border-radius: var(--button-large-radius); padding: var(--
#control_generate_box { min-width: unset; width: 100%; }
#txt2img_actions_column, #img2img_actions_column, #control_actions { flex-flow: wrap; justify-content: space-between; }
#txt2img_enqueue_wrapper, #img2img_enqueue_wrapper, #control_enqueue_wrapper { min-width: unset !important; width: 32%; }
.interrogate-clip { position: absolute; right: 3em; top: -2.5em; max-width: fit-content; background: none !important; }
.interrogate-blip { position: absolute; right: 1em; top: -2.5em; max-width: fit-content; background: none !important; }
.interrogate-clip { position: absolute; right: 6em; top: 8px; max-width: fit-content; background: none !important; z-index: 50; }
.interrogate-blip { position: absolute; right: 4em; top: 8px; max-width: fit-content; background: none !important; z-index: 50; }
.interrogate-col { min-width: 0 !important; max-width: fit-content; margin-right: var(--spacing-xxl); }
.interrogate-col>button { flex: 1; width: 7em; max-height: 84px; }
#sampler_selection_img2img { margin-top: 1em; }
+4
View File
@@ -132,6 +132,10 @@ def control_run(units: List[unit.Unit], inputs, inits, mask, unit_type: str, is_
if p.enable_hr and (p.hr_resize_x == 0 or p.hr_resize_y == 0):
p.hr_upscale_to_x, p.hr_upscale_to_y = 8 * int(p.width * p.hr_scale / 8), 8 * int(p.height * p.hr_scale / 8)
if shared.sd_model is None:
shared.log.warning('Model not loaded')
return [], '', '', 'Error: model not loaded'
t0 = time.time()
num_units = 0
for u in units:
+8 -24
View File
@@ -47,56 +47,40 @@ class DeepDanbooru:
return res
def tag_multi(self, pil_image, force_disable_ranks=False):
threshold = shared.opts.interrogate_deepbooru_score_threshold
use_spaces = shared.opts.deepbooru_use_spaces
use_escape = shared.opts.deepbooru_escape
alpha_sort = shared.opts.deepbooru_sort_alpha
include_ranks = shared.opts.interrogate_return_ranks and not force_disable_ranks
if isinstance(pil_image, list):
pil_image = pil_image[0]
pil_image = pil_image[0] if len(pil_image) > 0 else None
if isinstance(pil_image, dict) and 'name' in pil_image:
pil_image = Image.open(pil_image['name'])
if pil_image is None:
return ''
pic = images.resize_image(2, pil_image.convert("RGB"), 512, 512)
a = np.expand_dims(np.array(pic, dtype=np.float32), 0) / 255
with devices.inference_context(), devices.autocast():
x = torch.from_numpy(a).to(devices.device)
y = self.model(x)[0].detach().float().cpu().numpy()
probability_dict = {}
for tag, probability in zip(self.model.tags, y):
if probability < threshold:
if probability < shared.opts.interrogate_deepbooru_score_threshold:
continue
if tag.startswith("rating:"):
continue
probability_dict[tag] = probability
if alpha_sort:
if shared.opts.deepbooru_sort_alpha:
tags = sorted(probability_dict)
else:
tags = [tag for tag, _ in sorted(probability_dict.items(), key=lambda x: -x[1])]
res = []
filtertags = {x.strip().replace(' ', '_') for x in shared.opts.deepbooru_filter_tags.split(",")}
for tag in [x for x in tags if x not in filtertags]:
probability = probability_dict[tag]
tag_outformat = tag
if use_spaces:
if shared.opts.deepbooru_use_spaces:
tag_outformat = tag_outformat.replace('_', ' ')
if use_escape:
if shared.opts.deepbooru_escape:
tag_outformat = re.sub(re_special, r'\\\1', tag_outformat)
if include_ranks:
if shared.opts.interrogate_return_ranks and not force_disable_ranks:
tag_outformat = f"({tag_outformat}:{probability:.3f})"
res.append(tag_outformat)
return ", ".join(res)
+1 -1
View File
@@ -21,7 +21,7 @@ def instant_id(p: processing.StableDiffusionProcessing, app, source_images, stre
shared.log.warning('InstantID: no input images')
return None
c = shared.sd_model.__class__.__name__ if shared.sd_model is not None else ''
c = shared.sd_model.__class__.__name__ if shared.sd_loaded else ''
if c != 'StableDiffusionXLPipeline':
shared.log.warning(f'InstantID invalid base model: current={c} required=StableDiffusionXLPipeline')
return None
+1 -1
View File
@@ -11,7 +11,7 @@ def photo_maker(p: processing.StableDiffusionProcessing, input_images, trigger,
shared.log.warning('PhotoMaker: no input images')
return None
c = shared.sd_model.__class__.__name__ if shared.sd_model is not None else ''
c = shared.sd_model.__class__.__name__ if shared.sd_loaded else ''
if c != 'StableDiffusionXLPipeline':
shared.log.warning(f'PhotoMaker invalid base model: current={c} required=StableDiffusionXLPipeline')
return None
+13 -6
View File
@@ -187,7 +187,7 @@ def send_image_and_dimensions(x):
return img, w, h
def parse_generation_parameters(infotext):
def parse_generation_parameters(infotext, no_prompt=False):
if not isinstance(infotext, str):
return {}
debug(f'Parse infotext: {infotext}')
@@ -236,8 +236,9 @@ def parse_generation_parameters(infotext):
params["Full quality"] = False
else:
params[k] = v
params["Prompt"] = prompt.replace('Prompt:', '').strip()
params["Negative prompt"] = negative.replace('Negative prompt:', '').strip()
if not no_prompt:
params["Prompt"] = prompt.replace('Prompt:', '').strip()
params["Negative prompt"] = negative.replace('Negative prompt:', '').strip()
debug(f"Parse: {params}")
return params
@@ -314,7 +315,7 @@ def connect_paste(button, local_paste_fields, input_comp, override_settings_comp
prompt = ''
else:
shared.log.debug(f'Paste prompt: type="current" prompt="{prompt}"')
params = parse_generation_parameters(prompt)
params = parse_generation_parameters(prompt, no_prompt=False)
script_callbacks.infotext_pasted_callback(prompt, params)
res = []
applied = {}
@@ -324,7 +325,7 @@ def connect_paste(button, local_paste_fields, input_comp, override_settings_comp
else:
v = params.get(key, None)
if v is None:
res.append(gr.update())
res.append(gr.update()) # triggers update for each gradio component even if there are no updates
elif isinstance(v, type_of_gr_update):
res.append(v)
applied[key] = v
@@ -344,6 +345,10 @@ def connect_paste(button, local_paste_fields, input_comp, override_settings_comp
if override_settings_component is not None:
def paste_settings(params):
params.pop('Prompt', None)
params.pop('Negative prompt', None)
if not params:
gr.Dropdown.update(value=[], choices=[], visible=False)
vals = {}
for param_name, setting_name in infotext_to_setting_name_mapping:
v = params.get(param_name, None)
@@ -360,8 +365,10 @@ def connect_paste(button, local_paste_fields, input_comp, override_settings_comp
continue
vals[param_name] = v
vals_pairs = [f"{k}: {v}" for k, v in vals.items()]
shared.log.debug(f'Settings overrides: {vals_pairs}')
if len(vals_pairs) > 0:
shared.log.debug(f'Settings overrides: {vals_pairs}')
return gr.Dropdown.update(value=vals_pairs, choices=vals_pairs, visible=len(vals_pairs) > 0)
local_paste_fields = local_paste_fields + [(override_settings_component, paste_settings)]
button.click(
+3 -1
View File
@@ -170,9 +170,11 @@ class InterrogateModels:
devices.torch_gc()
self.load()
if isinstance(pil_image, list):
pil_image = pil_image[0]
pil_image = pil_image[0] if len(pil_image) > 0 else None
if isinstance(pil_image, dict) and 'name' in pil_image:
pil_image = Image.open(pil_image['name'])
if pil_image is None:
return ''
pil_image = pil_image.convert("RGB")
caption = self.generate_caption(pil_image)
self.send_blip_to_ram()
+5
View File
@@ -47,6 +47,11 @@ class ModelData:
# provides shared.sd_model field as a property
class Shared(sys.modules[__name__].__class__):
@property
def sd_loaded(self):
import modules.sd_models # pylint: disable=W0621
return modules.sd_models.model_data.sd_model is not None
@property
def sd_model(self):
import modules.sd_models # pylint: disable=W0621
+1 -1
View File
@@ -103,7 +103,7 @@ class CFGDenoiser(torch.nn.Module):
time.sleep(0.1)
# at self.image_cfg_scale == 1.0 produced results for edit model are the same as with normal sampling,
# so is_edit_model is set to False to support AND composition.
is_edit_model = (shared.sd_model is not None) and hasattr(shared.sd_model, 'cond_stage_key') and (shared.sd_model.cond_stage_key == "edit") and (self.image_cfg_scale is not None) and (self.image_cfg_scale != 1.0)
is_edit_model = shared.sd_loaded and hasattr(shared.sd_model, 'cond_stage_key') and (shared.sd_model.cond_stage_key == "edit") and (self.image_cfg_scale is not None) and (self.image_cfg_scale != 1.0)
conds_list, tensor = prompt_parser.reconstruct_multicond_batch(cond, self.step)
uncond = prompt_parser.reconstruct_cond_batch(uncond, self.step)
assert not is_edit_model or all(len(conds) == 1 for conds in conds_list), "AND is not supported for InstructPix2Pix checkpoint (unless using Image CFG scale = 1.0)"
+1
View File
@@ -1078,6 +1078,7 @@ sd_model: diffusers.DiffusionPipeline = None # dummy and overwritten by class
sd_refiner: diffusers.DiffusionPipeline = None # dummy and overwritten by class
sd_model_type: str = '' # dummy and overwritten by class
sd_refiner_type: str = '' # dummy and overwritten by class
sd_loaded: bool = False # dummy and overwritten by class
compiled_model_state = None
listfiles = listdir
@@ -140,7 +140,7 @@ class EmbeddingDatabase:
def get_expected_shape(self):
if shared.backend == shared.Backend.DIFFUSERS:
return 0
if shared.sd_model is None:
if shared.sd_loaded:
shared.log.error('Model not loaded')
return 0
vec = shared.sd_model.cond_stage_model.encode_embedding_init_text(",", 1)
@@ -151,7 +151,7 @@ class EmbeddingDatabase:
embeddings_to_load = []
loaded_embeddings = {}
skipped_embeddings = []
if shared.sd_model is None:
if not shared.sd_loaded:
return 0
tokenizer = getattr(shared.sd_model, 'tokenizer', None)
tokenizer_2 = getattr(shared.sd_model, 'tokenizer_2', None)
@@ -336,7 +336,7 @@ class EmbeddingDatabase:
continue
def load_textual_inversion_embeddings(self, force_reload=False):
if shared.sd_model is None:
if not shared.sd_loaded:
return
t0 = time.time()
if not force_reload:
+9 -5
View File
@@ -286,10 +286,14 @@ def create_output_panel(tabname, preview=True, prompt=None, height=None):
debug(f'Paste field: tab={tabname} fields={paste_field_names}')
for paste_tabname, paste_button in buttons.items():
debug(f'Create output panel: source={tabname} target={paste_tabname} button={paste_button}')
bindings = generation_parameters_copypaste.ParamBinding(paste_button=paste_button, tabname=paste_tabname, source_tabname=tabname, source_image_component=result_gallery, paste_field_names=paste_field_names, source_text_component=generation_info)
# txt2img_bindings = generation_parameters_copypaste.ParamBinding(paste_button=txt2img_paste, tabname="txt2img", source_text_component=txt2img_prompt, source_image_component=None)
bindings = generation_parameters_copypaste.ParamBinding(
paste_button=paste_button,
tabname=paste_tabname,
source_tabname=tabname,
source_image_component=result_gallery,
paste_field_names=paste_field_names,
source_text_component=prompt or generation_info
)
generation_parameters_copypaste.register_paste_params_button(bindings)
return result_gallery, generation_info, html_info, html_info_formatted, html_log
@@ -373,7 +377,7 @@ def update_token_counter(text, steps):
from modules import sd_hijack
token_count, max_length = max([sd_hijack.model_hijack.get_prompt_lengths(prompt) for prompt in prompts], key=lambda args: args[0])
elif shared.backend == shared.Backend.DIFFUSERS:
if shared.sd_model is not None and hasattr(shared.sd_model, 'tokenizer') and shared.sd_model.tokenizer is not None:
if shared.sd_loaded and hasattr(shared.sd_model, 'tokenizer') and shared.sd_model.tokenizer is not None:
has_bos_token = shared.sd_model.tokenizer.bos_token_id is not None
has_eos_token = shared.sd_model.tokenizer.eos_token_id is not None
ids = [shared.sd_model.tokenizer(prompt) for prompt in prompts]
+1 -1
View File
@@ -155,7 +155,7 @@ def create_ui():
with gr.Group(elem_id="img2img_script_container"):
img2img_script_inputs = modules.scripts.scripts_img2img.setup_ui(parent='img2img', accordion=True)
img2img_gallery, img2img_generation_info, img2img_html_info, _img2img_html_info_formatted, img2img_html_log = ui_common.create_output_panel("img2img", prompt=None)
img2img_gallery, img2img_generation_info, img2img_html_info, _img2img_html_info_formatted, img2img_html_log = ui_common.create_output_panel("img2img", prompt=img2img_prompt)
ui_common.connect_reuse_seed(seed, reuse_seed, img2img_generation_info, is_subseed=False)
ui_common.connect_reuse_seed(subseed, reuse_subseed, img2img_generation_info, is_subseed=True)
+1 -1
View File
@@ -50,7 +50,7 @@ def create_ui():
with gr.Group(elem_id="txt2img_script_container"):
txt2img_script_inputs = modules.scripts.scripts_txt2img.setup_ui(parent='txt2img', accordion=True)
txt2img_gallery, txt2img_generation_info, txt2img_html_info, _txt2img_html_info_formatted, txt2img_html_log = ui_common.create_output_panel("txt2img", preview=True, prompt=None)
txt2img_gallery, txt2img_generation_info, txt2img_html_info, _txt2img_html_info_formatted, txt2img_html_log = ui_common.create_output_panel("txt2img", preview=True, prompt=txt2img_prompt)
ui_common.connect_reuse_seed(seed, reuse_seed, txt2img_generation_info, is_subseed=False)
ui_common.connect_reuse_seed(subseed, reuse_subseed, txt2img_generation_info, is_subseed=True)
+2 -2
View File
@@ -48,14 +48,14 @@ orig_pipe = None # original sd_model pipeline
def set_adapter(adapter_name: str = 'None'):
if shared.sd_model is None:
if not shared.sd_loaded:
return
if shared.backend != shared.Backend.DIFFUSERS:
shared.log.warning('AnimateDiff: not in diffusers mode')
return
global motion_adapter, loaded_adapter, orig_pipe # pylint: disable=global-statement
# adapter_name = name if name is not None and isinstance(name, str) else loaded_adapter
if adapter_name is None or adapter_name == 'None' or shared.sd_model is None:
if adapter_name is None or adapter_name == 'None' or not shared.sd_loaded:
motion_adapter = None
loaded_adapter = None
if orig_pipe is not None:
+1 -1
View File
@@ -24,7 +24,7 @@ class Script(scripts.Script):
return [source_subject, target_subject, prompt_strength]
def run(self, p: processing.StableDiffusionProcessing, source_subject, target_subject, prompt_strength): # pylint: disable=arguments-differ, unused-argument
c = shared.sd_model.__class__.__name__ if shared.sd_model is not None else ''
c = shared.sd_model.__class__.__name__ if shared.sd_loaded else ''
if c != 'BlipDiffusionPipeline':
shared.log.error(f'{title}: model selected={c} required=BLIPDiffusion')
return None
+1 -1
View File
@@ -1244,7 +1244,7 @@ class Script(scripts.Script):
return [cosine_scale_1, cosine_scale_2, cosine_scale_3, sigma, view_batch_size, stride, multi_decoder]
def run(self, p: processing.StableDiffusionProcessing, cosine_scale_1, cosine_scale_2, cosine_scale_3, sigma, view_batch_size, stride, multi_decoder): # pylint: disable=arguments-differ
c = shared.sd_model.__class__.__name__ if shared.sd_model is not None else ''
c = shared.sd_model.__class__.__name__ if shared.sd_loaded else ''
if c != 'StableDiffusionXLPipeline':
shared.log.warning(f'DemoFusion: pipeline={c} required=StableDiffusionXLPipeline')
return None
+1 -1
View File
@@ -88,7 +88,7 @@ class Script(scripts.Script):
# Run pipeline
def run(self, p: processing.StableDiffusionProcessing, *args): # pylint: disable=arguments-differ
# prepare pipeline
c = shared.sd_model.__class__.__name__ if shared.sd_model is not None else ''
c = shared.sd_model.__class__.__name__ if shared.sd_loaded else ''
if c != pipeline_base:
shared.log.warning(f'{title}: pipeline={c} required={pipeline_base}')
return None
+1 -1
View File
@@ -71,7 +71,7 @@ class Script(scripts.Script):
shared.log.error(f'SVD: no checkpoint for {model_name}')
modelloader.load_reference(model_path, variant='fp16')
c = shared.sd_model.__class__.__name__
model_loaded = shared.sd_model.sd_checkpoint_info.model_name if shared.sd_model is not None else None
model_loaded = shared.sd_model.sd_checkpoint_info.model_name if shared.sd_loaded else None
if model_name != model_loaded or c != 'StableVideoDiffusionPipeline':
shared.opts.sd_model_checkpoint = model_path
sd_models.reload_model_weights()