mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
fix formatting bugs in both textual_inversion and merge front ends
- Issue is that if insufficient diffusers models are defined in models.yaml the frontend would ungraciously crash. - Now it emits appropriate error messages telling user what the problem is.
This commit is contained in:
parent
466a82bcc2
commit
142016827f
@ -15,20 +15,18 @@ from pathlib import Path
|
|||||||
from typing import List, Union
|
from typing import List, Union
|
||||||
|
|
||||||
import npyscreen
|
import npyscreen
|
||||||
from diffusers import DiffusionPipeline, logging as dlogging
|
from diffusers import DiffusionPipeline
|
||||||
|
from diffusers import logging as dlogging
|
||||||
|
from npyscreen import widget
|
||||||
from omegaconf import OmegaConf
|
from omegaconf import OmegaConf
|
||||||
|
|
||||||
from ldm.invoke.globals import (
|
from ldm.invoke.globals import (Globals, global_cache_dir, global_config_file,
|
||||||
Globals,
|
global_models_dir, global_set_root)
|
||||||
global_cache_dir,
|
|
||||||
global_config_file,
|
|
||||||
global_models_dir,
|
|
||||||
global_set_root,
|
|
||||||
)
|
|
||||||
from ldm.invoke.model_manager import ModelManager
|
from ldm.invoke.model_manager import ModelManager
|
||||||
|
|
||||||
DEST_MERGED_MODEL_DIR = "merged_models"
|
DEST_MERGED_MODEL_DIR = "merged_models"
|
||||||
|
|
||||||
|
|
||||||
def merge_diffusion_models(
|
def merge_diffusion_models(
|
||||||
model_ids_or_paths: List[Union[str, Path]],
|
model_ids_or_paths: List[Union[str, Path]],
|
||||||
alpha: float = 0.5,
|
alpha: float = 0.5,
|
||||||
@ -48,7 +46,7 @@ def merge_diffusion_models(
|
|||||||
cache_dir, resume_download, force_download, proxies, local_files_only, use_auth_token, revision, torch_dtype, device_map
|
cache_dir, resume_download, force_download, proxies, local_files_only, use_auth_token, revision, torch_dtype, device_map
|
||||||
"""
|
"""
|
||||||
with warnings.catch_warnings():
|
with warnings.catch_warnings():
|
||||||
warnings.simplefilter('ignore')
|
warnings.simplefilter("ignore")
|
||||||
verbosity = dlogging.get_verbosity()
|
verbosity = dlogging.get_verbosity()
|
||||||
dlogging.set_verbosity_error()
|
dlogging.set_verbosity_error()
|
||||||
|
|
||||||
@ -188,7 +186,6 @@ class FloatTitleSlider(npyscreen.TitleText):
|
|||||||
|
|
||||||
|
|
||||||
class mergeModelsForm(npyscreen.FormMultiPageAction):
|
class mergeModelsForm(npyscreen.FormMultiPageAction):
|
||||||
|
|
||||||
interpolations = ["weighted_sum", "sigmoid", "inv_sigmoid", "add_difference"]
|
interpolations = ["weighted_sum", "sigmoid", "inv_sigmoid", "add_difference"]
|
||||||
|
|
||||||
def __init__(self, parentApp, name):
|
def __init__(self, parentApp, name):
|
||||||
@ -214,20 +211,20 @@ class mergeModelsForm(npyscreen.FormMultiPageAction):
|
|||||||
|
|
||||||
self.add_widget_intelligent(
|
self.add_widget_intelligent(
|
||||||
npyscreen.FixedText,
|
npyscreen.FixedText,
|
||||||
color='CONTROL',
|
color="CONTROL",
|
||||||
value=f"Select two models to merge and optionally a third.",
|
value=f"Select two models to merge and optionally a third.",
|
||||||
editable=False,
|
editable=False,
|
||||||
)
|
)
|
||||||
self.add_widget_intelligent(
|
self.add_widget_intelligent(
|
||||||
npyscreen.FixedText,
|
npyscreen.FixedText,
|
||||||
color='CONTROL',
|
color="CONTROL",
|
||||||
value=f"Use up and down arrows to move, <space> to select an item, <tab> and <shift-tab> to move from one field to the next.",
|
value=f"Use up and down arrows to move, <space> to select an item, <tab> and <shift-tab> to move from one field to the next.",
|
||||||
editable=False,
|
editable=False,
|
||||||
)
|
)
|
||||||
self.add_widget_intelligent(
|
self.add_widget_intelligent(
|
||||||
npyscreen.FixedText,
|
npyscreen.FixedText,
|
||||||
value='MODEL 1',
|
value="MODEL 1",
|
||||||
color='GOOD',
|
color="GOOD",
|
||||||
editable=False,
|
editable=False,
|
||||||
rely=4 if horizontal_layout else None,
|
rely=4 if horizontal_layout else None,
|
||||||
)
|
)
|
||||||
@ -242,15 +239,15 @@ class mergeModelsForm(npyscreen.FormMultiPageAction):
|
|||||||
)
|
)
|
||||||
self.add_widget_intelligent(
|
self.add_widget_intelligent(
|
||||||
npyscreen.FixedText,
|
npyscreen.FixedText,
|
||||||
value='MODEL 2',
|
value="MODEL 2",
|
||||||
color='GOOD',
|
color="GOOD",
|
||||||
editable=False,
|
editable=False,
|
||||||
relx=max_width + 3 if horizontal_layout else None,
|
relx=max_width + 3 if horizontal_layout else None,
|
||||||
rely=4 if horizontal_layout else None,
|
rely=4 if horizontal_layout else None,
|
||||||
)
|
)
|
||||||
self.model2 = self.add_widget_intelligent(
|
self.model2 = self.add_widget_intelligent(
|
||||||
npyscreen.SelectOne,
|
npyscreen.SelectOne,
|
||||||
name='(2)',
|
name="(2)",
|
||||||
values=self.model_names,
|
values=self.model_names,
|
||||||
value=1,
|
value=1,
|
||||||
max_height=len(self.model_names),
|
max_height=len(self.model_names),
|
||||||
@ -261,17 +258,17 @@ class mergeModelsForm(npyscreen.FormMultiPageAction):
|
|||||||
)
|
)
|
||||||
self.add_widget_intelligent(
|
self.add_widget_intelligent(
|
||||||
npyscreen.FixedText,
|
npyscreen.FixedText,
|
||||||
value='MODEL 3',
|
value="MODEL 3",
|
||||||
color='GOOD',
|
color="GOOD",
|
||||||
editable=False,
|
editable=False,
|
||||||
relx=max_width * 2 + 3 if horizontal_layout else None,
|
relx=max_width * 2 + 3 if horizontal_layout else None,
|
||||||
rely=4 if horizontal_layout else None,
|
rely=4 if horizontal_layout else None,
|
||||||
)
|
)
|
||||||
models_plus_none = self.model_names.copy()
|
models_plus_none = self.model_names.copy()
|
||||||
models_plus_none.insert(0,'None')
|
models_plus_none.insert(0, "None")
|
||||||
self.model3 = self.add_widget_intelligent(
|
self.model3 = self.add_widget_intelligent(
|
||||||
npyscreen.SelectOne,
|
npyscreen.SelectOne,
|
||||||
name='(3)',
|
name="(3)",
|
||||||
values=models_plus_none,
|
values=models_plus_none,
|
||||||
value=0,
|
value=0,
|
||||||
max_height=len(self.model_names) + 1,
|
max_height=len(self.model_names) + 1,
|
||||||
@ -285,14 +282,14 @@ class mergeModelsForm(npyscreen.FormMultiPageAction):
|
|||||||
self.merged_model_name = self.add_widget_intelligent(
|
self.merged_model_name = self.add_widget_intelligent(
|
||||||
npyscreen.TitleText,
|
npyscreen.TitleText,
|
||||||
name="Name for merged model:",
|
name="Name for merged model:",
|
||||||
labelColor='CONTROL',
|
labelColor="CONTROL",
|
||||||
value="",
|
value="",
|
||||||
scroll_exit=True,
|
scroll_exit=True,
|
||||||
)
|
)
|
||||||
self.force = self.add_widget_intelligent(
|
self.force = self.add_widget_intelligent(
|
||||||
npyscreen.Checkbox,
|
npyscreen.Checkbox,
|
||||||
name="Force merge of incompatible models",
|
name="Force merge of incompatible models",
|
||||||
labelColor='CONTROL',
|
labelColor="CONTROL",
|
||||||
value=False,
|
value=False,
|
||||||
scroll_exit=True,
|
scroll_exit=True,
|
||||||
)
|
)
|
||||||
@ -301,7 +298,7 @@ class mergeModelsForm(npyscreen.FormMultiPageAction):
|
|||||||
name="Merge Method:",
|
name="Merge Method:",
|
||||||
values=self.interpolations,
|
values=self.interpolations,
|
||||||
value=0,
|
value=0,
|
||||||
labelColor='CONTROL',
|
labelColor="CONTROL",
|
||||||
max_height=len(self.interpolations) + 1,
|
max_height=len(self.interpolations) + 1,
|
||||||
scroll_exit=True,
|
scroll_exit=True,
|
||||||
)
|
)
|
||||||
@ -312,7 +309,7 @@ class mergeModelsForm(npyscreen.FormMultiPageAction):
|
|||||||
step=0.05,
|
step=0.05,
|
||||||
lowest=0,
|
lowest=0,
|
||||||
value=0.5,
|
value=0.5,
|
||||||
labelColor='CONTROL',
|
labelColor="CONTROL",
|
||||||
scroll_exit=True,
|
scroll_exit=True,
|
||||||
)
|
)
|
||||||
self.model1.editing = True
|
self.model1.editing = True
|
||||||
@ -322,12 +319,12 @@ class mergeModelsForm(npyscreen.FormMultiPageAction):
|
|||||||
selected_model1 = self.model1.value[0]
|
selected_model1 = self.model1.value[0]
|
||||||
selected_model2 = self.model2.value[0]
|
selected_model2 = self.model2.value[0]
|
||||||
selected_model3 = self.model3.value[0]
|
selected_model3 = self.model3.value[0]
|
||||||
merged_model_name = f'{models[selected_model1]}+{models[selected_model2]}'
|
merged_model_name = f"{models[selected_model1]}+{models[selected_model2]}"
|
||||||
self.merged_model_name.value = merged_model_name
|
self.merged_model_name.value = merged_model_name
|
||||||
|
|
||||||
if selected_model3 > 0:
|
if selected_model3 > 0:
|
||||||
self.merge_method.values=['add_difference'],
|
self.merge_method.values = (["add_difference"],)
|
||||||
self.merged_model_name.value += f'+{models[selected_model3]}'
|
self.merged_model_name.value += f"+{models[selected_model3]}"
|
||||||
else:
|
else:
|
||||||
self.merge_method.values = self.interpolations
|
self.merge_method.values = self.interpolations
|
||||||
self.merge_method.value = 0
|
self.merge_method.value = 0
|
||||||
@ -337,7 +334,7 @@ class mergeModelsForm(npyscreen.FormMultiPageAction):
|
|||||||
self.parentApp.setNextForm(None)
|
self.parentApp.setNextForm(None)
|
||||||
self.editing = False
|
self.editing = False
|
||||||
self.parentApp.merge_arguments = self.marshall_arguments()
|
self.parentApp.merge_arguments = self.marshall_arguments()
|
||||||
npyscreen.notify('Starting the merge...')
|
npyscreen.notify("Starting the merge...")
|
||||||
else:
|
else:
|
||||||
self.editing = True
|
self.editing = True
|
||||||
|
|
||||||
@ -374,15 +371,19 @@ class mergeModelsForm(npyscreen.FormMultiPageAction):
|
|||||||
def validate_field_values(self) -> bool:
|
def validate_field_values(self) -> bool:
|
||||||
bad_fields = []
|
bad_fields = []
|
||||||
model_names = self.model_names
|
model_names = self.model_names
|
||||||
selected_models = set((model_names[self.model1.value[0]],model_names[self.model2.value[0]]))
|
selected_models = set(
|
||||||
|
(model_names[self.model1.value[0]], model_names[self.model2.value[0]])
|
||||||
|
)
|
||||||
if self.model3.value[0] > 0:
|
if self.model3.value[0] > 0:
|
||||||
selected_models.add(model_names[self.model3.value[0] - 1])
|
selected_models.add(model_names[self.model3.value[0] - 1])
|
||||||
if len(selected_models) < 2:
|
if len(selected_models) < 2:
|
||||||
bad_fields.append(f'Please select two or three DIFFERENT models to compare. You selected {selected_models}')
|
bad_fields.append(
|
||||||
|
f"Please select two or three DIFFERENT models to compare. You selected {selected_models}"
|
||||||
|
)
|
||||||
if len(bad_fields) > 0:
|
if len(bad_fields) > 0:
|
||||||
message = 'The following problems were detected and must be corrected:'
|
message = "The following problems were detected and must be corrected:"
|
||||||
for problem in bad_fields:
|
for problem in bad_fields:
|
||||||
message += f'\n* {problem}'
|
message += f"\n* {problem}"
|
||||||
npyscreen.notify_confirm(message)
|
npyscreen.notify_confirm(message)
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
@ -410,6 +411,7 @@ class Mergeapp(npyscreen.NPSAppManaged):
|
|||||||
npyscreen.setTheme(npyscreen.Themes.ElegantTheme)
|
npyscreen.setTheme(npyscreen.Themes.ElegantTheme)
|
||||||
self.main = self.addForm("MAIN", mergeModelsForm, name="Merge Models Settings")
|
self.main = self.addForm("MAIN", mergeModelsForm, name="Merge Models Settings")
|
||||||
|
|
||||||
|
|
||||||
def run_gui(args: Namespace):
|
def run_gui(args: Namespace):
|
||||||
mergeapp = Mergeapp()
|
mergeapp = Mergeapp()
|
||||||
mergeapp.run()
|
mergeapp.run()
|
||||||
@ -450,5 +452,27 @@ def main():
|
|||||||
] = cache_dir # because not clear the merge pipeline is honoring cache_dir
|
] = cache_dir # because not clear the merge pipeline is honoring cache_dir
|
||||||
args.cache_dir = cache_dir
|
args.cache_dir = cache_dir
|
||||||
|
|
||||||
|
try:
|
||||||
|
if args.front_end:
|
||||||
|
run_gui(args)
|
||||||
|
else:
|
||||||
|
run_cli(args)
|
||||||
|
print(f">> Conversion successful. New model is named {args.merged_model_name}")
|
||||||
|
except widget.NotEnoughSpaceForWidget as e:
|
||||||
|
if str(e).startswith("Height of 1 allocated"):
|
||||||
|
print(
|
||||||
|
"** You need to have at least two diffusers models defined in models.yaml in order to merge"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print(f"** A layout error has occurred: {str(e)}")
|
||||||
|
sys.exit(-1)
|
||||||
|
except Exception as e:
|
||||||
|
print(">> An error occurred:")
|
||||||
|
traceback.print_exc()
|
||||||
|
sys.exit(-1)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
@ -17,6 +17,7 @@ from pathlib import Path
|
|||||||
from typing import List, Tuple
|
from typing import List, Tuple
|
||||||
|
|
||||||
import npyscreen
|
import npyscreen
|
||||||
|
from npyscreen import widget
|
||||||
from omegaconf import OmegaConf
|
from omegaconf import OmegaConf
|
||||||
|
|
||||||
from ldm.invoke.globals import Globals, global_set_root
|
from ldm.invoke.globals import Globals, global_set_root
|
||||||
@ -438,11 +439,20 @@ def main():
|
|||||||
do_front_end(args)
|
do_front_end(args)
|
||||||
else:
|
else:
|
||||||
do_textual_inversion_training(**vars(args))
|
do_textual_inversion_training(**vars(args))
|
||||||
|
except widget.NotEnoughSpaceForWidget as e:
|
||||||
|
if str(e).startswith("Height of 1 allocated"):
|
||||||
|
print(
|
||||||
|
"** You need to have at least one diffusers models defined in models.yaml in order to train"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print(f"** A layout error has occurred: {str(e)}")
|
||||||
|
sys.exit(-1)
|
||||||
except AssertionError as e:
|
except AssertionError as e:
|
||||||
print(str(e))
|
print(str(e))
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
Loading…
Reference in New Issue
Block a user