mirror of
https://github.com/vladmandic/automatic
synced 2026-09-20 01:31:13 +02:00
prompt paste improvements
This commit is contained in:
@@ -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; }
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)"
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user