diff --git a/.gitignore b/.gitignore index 71fe116..4fc61ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,242 @@ -venv -__pycache__ +# Kohya_SS Specifics cudnn_windows .vscode -*.egg-info -build wd14_tagger_model .DS_Store locon gui-user.bat -gui-user.ps1 \ No newline at end of file +gui-user.ps1 +*.whl* +.idea + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser \ No newline at end of file diff --git a/dreambooth_gui.py b/dreambooth_gui.py index a72acff..6fbdbf0 100644 --- a/dreambooth_gui.py +++ b/dreambooth_gui.py @@ -3,13 +3,15 @@ # v3: Add new Utilities tab for Dreambooth folder preparation # v3.1: Adding captionning of images to utilities -import gradio as gr +import argparse import json import math import os -import subprocess import pathlib -import argparse +import subprocess + +import gradio as gr + from library.common_gui import ( get_folder_path, remove_doublequote, @@ -26,88 +28,87 @@ from library.common_gui import ( gradio_source_model, # set_legacy_8bitadam, update_my_data, - check_if_model_exist, + check_if_model_exist, is_valid_config, show_message_box, ) +from library.dreambooth_folder_creation_gui import ( + gradio_dreambooth_folder_creation_tab, +) +from library.sampler_gui import sample_gradio_config, run_cmd_sample from library.tensorboard_gui import ( gradio_tensorboard, start_tensorboard, stop_tensorboard, ) -from library.dreambooth_folder_creation_gui import ( - gradio_dreambooth_folder_creation_tab, -) from library.utilities import utilities_tab -from library.sampler_gui import sample_gradio_config, run_cmd_sample -from easygui import msgbox folder_symbol = '\U0001f4c2' # 📂 refresh_symbol = '\U0001f504' # 🔄 save_style_symbol = '\U0001f4be' # 💾 -document_symbol = '\U0001F4C4' # 📄 +document_symbol = '\U0001F4C4' # 📄 def save_configuration( - save_as, - file_path, - pretrained_model_name_or_path, - v2, - v_parameterization, - logging_dir, - train_data_dir, - reg_data_dir, - output_dir, - max_resolution, - learning_rate, - lr_scheduler, - lr_warmup, - train_batch_size, - epoch, - save_every_n_epochs, - mixed_precision, - save_precision, - seed, - num_cpu_threads_per_process, - cache_latents, - caption_extension, - enable_bucket, - gradient_checkpointing, - full_fp16, - no_token_padding, - stop_text_encoder_training, - # use_8bit_adam, - xformers, - save_model_as, - shuffle_caption, - save_state, - resume, - prior_loss_weight, - color_aug, - flip_aug, - clip_skip, - vae, - output_name, - max_token_length, - max_train_epochs, - max_data_loader_n_workers, - mem_eff_attn, - gradient_accumulation_steps, - model_list, - keep_tokens, - persistent_data_loader_workers, - bucket_no_upscale, - random_crop, - bucket_reso_steps, - caption_dropout_every_n_epochs, - caption_dropout_rate, - optimizer, - optimizer_args, - noise_offset, - sample_every_n_steps, - sample_every_n_epochs, - sample_sampler, - sample_prompts, - additional_parameters, - vae_batch_size, + save_as, + file_path, + pretrained_model_name_or_path, + v2, + v_parameterization, + logging_dir, + train_data_dir, + reg_data_dir, + output_dir, + max_resolution, + learning_rate, + lr_scheduler, + lr_warmup, + train_batch_size, + epoch, + save_every_n_epochs, + mixed_precision, + save_precision, + seed, + num_cpu_threads_per_process, + cache_latents, + caption_extension, + enable_bucket, + gradient_checkpointing, + full_fp16, + no_token_padding, + stop_text_encoder_training, + # use_8bit_adam, + xformers, + save_model_as, + shuffle_caption, + save_state, + resume, + prior_loss_weight, + color_aug, + flip_aug, + clip_skip, + vae, + output_name, + max_token_length, + max_train_epochs, + max_data_loader_n_workers, + mem_eff_attn, + gradient_accumulation_steps, + model_list, + keep_tokens, + persistent_data_loader_workers, + bucket_no_upscale, + random_crop, + bucket_reso_steps, + caption_dropout_every_n_epochs, + caption_dropout_rate, + optimizer, + optimizer_args, + noise_offset, + sample_every_n_steps, + sample_every_n_epochs, + sample_sampler, + sample_prompts, + additional_parameters, + vae_batch_size, ): # Get list of function parameters and values parameters = list(locals().items()) @@ -134,10 +135,10 @@ def save_configuration( name: value for name, value in parameters # locals().items() if name - not in [ - 'file_path', - 'save_as', - ] + not in [ + 'file_path', + 'save_as', + ] } # Extract the destination directory from the file path @@ -155,67 +156,67 @@ def save_configuration( def open_configuration( - ask_for_file, - file_path, - pretrained_model_name_or_path, - v2, - v_parameterization, - logging_dir, - train_data_dir, - reg_data_dir, - output_dir, - max_resolution, - learning_rate, - lr_scheduler, - lr_warmup, - train_batch_size, - epoch, - save_every_n_epochs, - mixed_precision, - save_precision, - seed, - num_cpu_threads_per_process, - cache_latents, - caption_extension, - enable_bucket, - gradient_checkpointing, - full_fp16, - no_token_padding, - stop_text_encoder_training, - # use_8bit_adam, - xformers, - save_model_as, - shuffle_caption, - save_state, - resume, - prior_loss_weight, - color_aug, - flip_aug, - clip_skip, - vae, - output_name, - max_token_length, - max_train_epochs, - max_data_loader_n_workers, - mem_eff_attn, - gradient_accumulation_steps, - model_list, - keep_tokens, - persistent_data_loader_workers, - bucket_no_upscale, - random_crop, - bucket_reso_steps, - caption_dropout_every_n_epochs, - caption_dropout_rate, - optimizer, - optimizer_args, - noise_offset, - sample_every_n_steps, - sample_every_n_epochs, - sample_sampler, - sample_prompts, - additional_parameters, - vae_batch_size, + ask_for_file, + file_path, + pretrained_model_name_or_path, + v2, + v_parameterization, + logging_dir, + train_data_dir, + reg_data_dir, + output_dir, + max_resolution, + learning_rate, + lr_scheduler, + lr_warmup, + train_batch_size, + epoch, + save_every_n_epochs, + mixed_precision, + save_precision, + seed, + num_cpu_threads_per_process, + cache_latents, + caption_extension, + enable_bucket, + gradient_checkpointing, + full_fp16, + no_token_padding, + stop_text_encoder_training, + # use_8bit_adam, + xformers, + save_model_as, + shuffle_caption, + save_state, + resume, + prior_loss_weight, + color_aug, + flip_aug, + clip_skip, + vae, + output_name, + max_token_length, + max_train_epochs, + max_data_loader_n_workers, + mem_eff_attn, + gradient_accumulation_steps, + model_list, + keep_tokens, + persistent_data_loader_workers, + bucket_no_upscale, + random_crop, + bucket_reso_steps, + caption_dropout_every_n_epochs, + caption_dropout_rate, + optimizer, + optimizer_args, + noise_offset, + sample_every_n_steps, + sample_every_n_epochs, + sample_sampler, + sample_prompts, + additional_parameters, + vae_batch_size, ): # Get list of function parameters and values parameters = list(locals().items()) @@ -225,17 +226,20 @@ def open_configuration( original_file_path = file_path if ask_for_file: - file_path = get_file_path(file_path) + file_path = get_file_path(file_path, filedialog_type="json") - if not file_path == '' and not file_path == None: - # load variables from JSON file + if not file_path == '' and file_path is not None: with open(file_path, 'r') as f: my_data = json.load(f) - print('Loading config...') - # Update values to fix deprecated use_8bit_adam checkbox and set appropriate optimizer if it is set to True - my_data = update_my_data(my_data) + if is_valid_config(my_data): + print('Loading config...') + my_data = update_my_data(my_data) + else: + print("Invalid configuration file.") + my_data = {} + show_message_box("Invalid configuration file.") else: - file_path = original_file_path # In case a file_path was provided and the user decide to cancel the open action + file_path = original_file_path my_data = {} values = [file_path] @@ -247,85 +251,85 @@ def open_configuration( def train_model( - pretrained_model_name_or_path, - v2, - v_parameterization, - logging_dir, - train_data_dir, - reg_data_dir, - output_dir, - max_resolution, - learning_rate, - lr_scheduler, - lr_warmup, - train_batch_size, - epoch, - save_every_n_epochs, - mixed_precision, - save_precision, - seed, - num_cpu_threads_per_process, - cache_latents, - caption_extension, - enable_bucket, - gradient_checkpointing, - full_fp16, - no_token_padding, - stop_text_encoder_training_pct, - # use_8bit_adam, - xformers, - save_model_as, - shuffle_caption, - save_state, - resume, - prior_loss_weight, - color_aug, - flip_aug, - clip_skip, - vae, - output_name, - max_token_length, - max_train_epochs, - max_data_loader_n_workers, - mem_eff_attn, - gradient_accumulation_steps, - model_list, # Keep this. Yes, it is unused here but required given the common list used - keep_tokens, - persistent_data_loader_workers, - bucket_no_upscale, - random_crop, - bucket_reso_steps, - caption_dropout_every_n_epochs, - caption_dropout_rate, - optimizer, - optimizer_args, - noise_offset, - sample_every_n_steps, - sample_every_n_epochs, - sample_sampler, - sample_prompts, - additional_parameters, - vae_batch_size, + pretrained_model_name_or_path, + v2, + v_parameterization, + logging_dir, + train_data_dir, + reg_data_dir, + output_dir, + max_resolution, + learning_rate, + lr_scheduler, + lr_warmup, + train_batch_size, + epoch, + save_every_n_epochs, + mixed_precision, + save_precision, + seed, + num_cpu_threads_per_process, + cache_latents, + caption_extension, + enable_bucket, + gradient_checkpointing, + full_fp16, + no_token_padding, + stop_text_encoder_training_pct, + # use_8bit_adam, + xformers, + save_model_as, + shuffle_caption, + save_state, + resume, + prior_loss_weight, + color_aug, + flip_aug, + clip_skip, + vae, + output_name, + max_token_length, + max_train_epochs, + max_data_loader_n_workers, + mem_eff_attn, + gradient_accumulation_steps, + model_list, # Keep this. Yes, it is unused here but required given the common list used + keep_tokens, + persistent_data_loader_workers, + bucket_no_upscale, + random_crop, + bucket_reso_steps, + caption_dropout_every_n_epochs, + caption_dropout_rate, + optimizer, + optimizer_args, + noise_offset, + sample_every_n_steps, + sample_every_n_epochs, + sample_sampler, + sample_prompts, + additional_parameters, + vae_batch_size, ): if pretrained_model_name_or_path == '': - msgbox('Source model information is missing') + show_message_box('Source model information is missing') return if train_data_dir == '': - msgbox('Image folder path is missing') + show_message_box('Image folder path is missing') return if not os.path.exists(train_data_dir): - msgbox('Image folder does not exist') + show_message_box('Image folder does not exist') return if reg_data_dir != '': if not os.path.exists(reg_data_dir): - msgbox('Regularisation folder does not exist') + show_message_box('Regularisation folder does not exist') return if output_dir == '': - msgbox('Output folder path is missing') + show_message_box('Output folder path is missing') return if check_if_model_exist(output_name, output_dir, save_model_as): @@ -351,7 +355,8 @@ def train_model( try: repeats = int(folder.split('_')[0]) except ValueError: - print('\033[33mSubfolder', folder, 'does not have a proper repeat value, please correct the name or remove it... can\'t train...\033[0m') + print('\033[33mSubfolder', folder, + 'does not have a proper repeat value, please correct the name or remove it... can\'t train...\033[0m') continue # Count the number of images in the folder @@ -360,12 +365,12 @@ def train_model( f for f in os.listdir(os.path.join(train_data_dir, folder)) if f.endswith('.jpg') - or f.endswith('.jpeg') - or f.endswith('.png') - or f.endswith('.webp') + or f.endswith('.jpeg') + or f.endswith('.png') + or f.endswith('.webp') ] ) - + if num_images == 0: print(f'{folder} folder contain no images, skipping...') else: @@ -525,10 +530,10 @@ def train_model( def dreambooth_tab( - train_data_dir=gr.Textbox(), - reg_data_dir=gr.Textbox(), - output_dir=gr.Textbox(), - logging_dir=gr.Textbox(), + train_data_dir=gr.Textbox(), + reg_data_dir=gr.Textbox(), + output_dir=gr.Textbox(), + logging_dir=gr.Textbox(), ): dummy_db_true = gr.Label(value=True, visible=False) dummy_db_false = gr.Label(value=False, visible=False) diff --git a/library/basic_caption_gui.py b/library/basic_caption_gui.py index b2d208d..d36dae1 100644 --- a/library/basic_caption_gui.py +++ b/library/basic_caption_gui.py @@ -1,8 +1,9 @@ -import gradio as gr -from easygui import msgbox -import subprocess -from .common_gui import get_folder_path, add_pre_postfix, find_replace import os +import subprocess + +import gradio as gr + +from .common_gui import get_folder_path, add_pre_postfix, find_replace def caption_images( @@ -17,11 +18,11 @@ def caption_images( ): # Check for images_dir if not images_dir: - msgbox('Image folder is missing...') + show_message_box('Image folder is missing...') return if not caption_ext: - msgbox('Please provide an extension for the caption files.') + show_message_box('Please provide an extension for the caption files.') return if caption_text: @@ -60,7 +61,7 @@ def caption_images( ) else: if prefix or postfix: - msgbox( + show_message_box( 'Could not modify caption files with requested change because the "Overwrite existing captions in folder" option is not selected...' ) diff --git a/library/blip_caption_gui.py b/library/blip_caption_gui.py index 2e0081d..35fd513 100644 --- a/library/blip_caption_gui.py +++ b/library/blip_caption_gui.py @@ -1,7 +1,8 @@ -import gradio as gr -from easygui import msgbox -import subprocess import os +import subprocess + +import gradio as gr + from .common_gui import get_folder_path, add_pre_postfix PYTHON = 'python3' if os.name == 'posix' else './venv/Scripts/python.exe' @@ -21,16 +22,16 @@ def caption_images( ): # Check for caption_text_input # if caption_text_input == "": - # msgbox("Caption text is missing...") + # show_message_box("Caption text is missing...") # return # Check for images_dir_input if train_data_dir == '': - msgbox('Image folder is missing...') + show_message_box('Image folder is missing...') return if caption_file_ext == '': - msgbox('Please provide an extension for the caption files.') + show_message_box('Please provide an extension for the caption files.') return print(f'Captioning files in {train_data_dir}...') diff --git a/library/common_gui.py b/library/common_gui.py index 25e7379..f47dfcc 100644 --- a/library/common_gui.py +++ b/library/common_gui.py @@ -1,14 +1,17 @@ -from tkinter import filedialog, Tk -from easygui import msgbox import os -import gradio as gr -import easygui import shutil +import subprocess +from tkinter import filedialog, Tk + +import easygui +import gradio as gr + +from library.gui_subprocesses import save_file_dialog folder_symbol = '\U0001f4c2' # 📂 refresh_symbol = '\U0001f504' # 🔄 save_style_symbol = '\U0001f4be' # 💾 -document_symbol = '\U0001F4C4' # 📄 +document_symbol = '\U0001F4C4' # 📄 # define a list of substrings to search for v2 base models V2_BASE_MODELS = [ @@ -34,6 +37,31 @@ ALL_PRESET_MODELS = V2_BASE_MODELS + V_PARAMETERIZATION_MODELS + V1_MODELS FILE_ENV_EXCLUSION = ['COLAB_GPU', 'RUNPOD_ENVIRONMENT'] +def open_file_dialog(initial_dir, initial_file, file_types="all"): + current_directory = os.path.dirname(os.path.abspath(__file__)) + + args = ["python", f"{current_directory}/gui_subprocesses.py", "file_dialog"] + if initial_dir: + args.append(initial_dir) + if initial_file: + args.append(initial_file) + if file_types: + args.append(file_types) + + file_path = subprocess.check_output(args).decode("utf-8").strip() + return file_path + + +def show_message_box(message, title=""): + current_directory = os.path.dirname(os.path.abspath(__file__)) + + args = ["python", f"{current_directory}/gui_subprocesses.py", "msgbox", message] + if title: + args.append(title) + + subprocess.run(args) + + def check_if_model_exist(output_name, output_dir, save_model_as): if save_model_as in ['diffusers', 'diffusers_safetendors']: ckpt_folder = os.path.join(output_dir, output_name) @@ -62,6 +90,22 @@ def check_if_model_exist(output_name, output_dir, save_model_as): return False +def is_valid_config(data): + # Check if the data is a dictionary + if not isinstance(data, dict): + return False + + # Add checks for expected keys and valid values + # For example, check if 'use_8bit_adam' is a boolean + if "use_8bit_adam" in data and not isinstance(data["use_8bit_adam"], bool): + return False + + # Add more checks for other keys as needed + + # If all checks pass, return True + return True + + def update_my_data(my_data): # Update the optimizer based on the use_8bit_adam flag use_8bit_adam = my_data.get('use_8bit_adam', False) @@ -87,8 +131,8 @@ def update_my_data(my_data): # Update model save choices due to changes for LoRA and TI training if ( - (my_data.get('LoRA_type') or my_data.get('num_vectors_per_token')) - and my_data.get('save_model_as') not in ['safetensors', 'ckpt'] + (my_data.get('LoRA_type') or my_data.get('num_vectors_per_token')) + and my_data.get('save_model_as') not in ['safetensors', 'ckpt'] ): message = ( 'Updating save_model_as to safetensors because the current value in the config file is no longer applicable to {}' @@ -102,11 +146,6 @@ def update_my_data(my_data): return my_data -def get_dir_and_file(file_path): - dir_path, file_name = os.path.split(file_path) - return (dir_path, file_name) - - # def has_ext_files(directory, extension): # # Iterate through all the files in the directory # for file in os.listdir(directory): @@ -117,67 +156,36 @@ def get_dir_and_file(file_path): # return False -def get_file_path( - file_path='', default_extension='.json', extension_name='Config files' -): - if not any(var in os.environ for var in FILE_ENV_EXCLUSION): - current_file_path = file_path - # print(f'current file path: {current_file_path}') +def get_file_path(file_path='', filedialog_type="lora"): + current_file_path = file_path - initial_dir, initial_file = get_dir_and_file(file_path) + initial_dir, initial_file = os.path.split(file_path) + file_path = open_file_dialog(initial_dir, initial_file, file_types=filedialog_type) - # Create a hidden Tkinter root window - root = Tk() - root.wm_attributes('-topmost', 1) - root.withdraw() - - # Show the open file dialog and get the selected file path - file_path = filedialog.askopenfilename( - filetypes=( - (extension_name, f'*{default_extension}'), - ('All files', '*.*'), - ), - defaultextension=default_extension, - initialfile=initial_file, - initialdir=initial_dir, - ) - - # Destroy the hidden root window - root.destroy() - - # If no file is selected, use the current file path - if not file_path: - file_path = current_file_path - current_file_path = file_path - # print(f'current file path: {current_file_path}') + # If no file is selected, use the current file path + if not file_path: + file_path = current_file_path + current_file_path = file_path return file_path + def get_any_file_path(file_path=''): - if not any(var in os.environ for var in FILE_ENV_EXCLUSION): - current_file_path = file_path - # print(f'current file path: {current_file_path}') + current_file_path = file_path + # print(f'current file path: {current_file_path}') - initial_dir, initial_file = get_dir_and_file(file_path) + initial_dir, initial_file = os.path.split(file_path) + file_path = open_file_dialog(initial_dir, initial_file, "all") - root = Tk() - root.wm_attributes('-topmost', 1) - root.withdraw() - file_path = filedialog.askopenfilename( - initialdir=initial_dir, - initialfile=initial_file, - ) - root.destroy() - - if file_path == '': - file_path = current_file_path + if file_path == '': + file_path = current_file_path return file_path def remove_doublequote(file_path): - if file_path != None: + if file_path is not None: file_path = file_path.replace('"', '') return file_path @@ -196,62 +204,37 @@ def remove_doublequote(file_path): # ) -def get_folder_path(folder_path=''): - if not any(var in os.environ for var in FILE_ENV_EXCLUSION): - current_folder_path = folder_path +def get_folder_path(folder_path='', filedialog_type="directory"): + current_folder_path = folder_path - initial_dir, initial_file = get_dir_and_file(folder_path) + initial_dir, initial_file = os.path.split(folder_path) + file_path = open_file_dialog(initial_dir, initial_file, filedialog_type) - root = Tk() - root.wm_attributes('-topmost', 1) - root.withdraw() - folder_path = filedialog.askdirectory(initialdir=initial_dir) - root.destroy() - - if folder_path == '': - folder_path = current_folder_path + if folder_path == '': + folder_path = current_folder_path return folder_path def get_saveasfile_path( - file_path='', defaultextension='.json', extension_name='Config files' + file_path='', filedialog_type="json" ): - if not any(var in os.environ for var in FILE_ENV_EXCLUSION): - current_file_path = file_path - # print(f'current file path: {current_file_path}') + current_file_path = file_path - initial_dir, initial_file = get_dir_and_file(file_path) + initial_dir, initial_file = os.path.split(file_path) + save_file_path = save_file_dialog(initial_dir, initial_file, filedialog_type) - root = Tk() - root.wm_attributes('-topmost', 1) - root.withdraw() - save_file_path = filedialog.asksaveasfile( - filetypes=( - (f'{extension_name}', f'{defaultextension}'), - ('All files', '*'), - ), - defaultextension=defaultextension, - initialdir=initial_dir, - initialfile=initial_file, - ) - root.destroy() - - # print(save_file_path) - - if save_file_path == None: - file_path = current_file_path - else: - print(save_file_path.name) - file_path = save_file_path.name - - # print(file_path) + if save_file_path is None: + file_path = current_file_path + else: + print(save_file_path.name) + file_path = save_file_path.name return file_path def get_saveasfilename_path( - file_path='', extensions='*', extension_name='Config files' + file_path='', extensions='*', extension_name='Config files' ): if not any(var in os.environ for var in FILE_ENV_EXCLUSION): current_file_path = file_path @@ -280,10 +263,10 @@ def get_saveasfilename_path( def add_pre_postfix( - folder: str = '', - prefix: str = '', - postfix: str = '', - caption_file_ext: str = '.caption', + folder: str = '', + prefix: str = '', + postfix: str = '', + caption_file_ext: str = '.caption', ) -> None: """ Add prefix and/or postfix to the content of caption files within a folder. @@ -343,10 +326,10 @@ def has_ext_files(folder_path: str, file_extension: str) -> bool: def find_replace( - folder_path: str = '', - caption_file_ext: str = '.caption', - search_text: str = '', - replace_text: str = '', + folder_path: str = '', + caption_file_ext: str = '.caption', + search_text: str = '', + replace_text: str = '', ) -> None: """ Find and replace text in caption files within a folder. @@ -360,7 +343,7 @@ def find_replace( print('Running caption find/replace') if not has_ext_files(folder_path, caption_file_ext): - msgbox( + show_message_box( f'No files with extension {caption_file_ext} were found in {folder_path}...' ) return @@ -374,7 +357,7 @@ def find_replace( for caption_file in caption_files: with open( - os.path.join(folder_path, caption_file), 'r', errors='ignore' + os.path.join(folder_path, caption_file), 'r', errors='ignore' ) as f: content = f.read() @@ -386,7 +369,7 @@ def find_replace( def color_aug_changed(color_aug): if color_aug: - msgbox( + show_message_box( 'Disabling "Cache latent" because "Color augmentation" has been selected...' ) return gr.Checkbox.update(value=False, interactive=False) @@ -427,7 +410,7 @@ def save_inference_file(output_dir, v2, v_parameterization, output_name): def set_pretrained_model_name_or_path_input( - model_list, pretrained_model_name_or_path, v2, v_parameterization + model_list, pretrained_model_name_or_path, v2, v_parameterization ): # check if $v2 and $v_parameterization are empty and if $pretrained_model_name_or_path contains any of the substrings in the v2 list if str(model_list) in V2_BASE_MODELS: @@ -452,9 +435,9 @@ def set_pretrained_model_name_or_path_input( if model_list == 'custom': if ( - str(pretrained_model_name_or_path) in V1_MODELS - or str(pretrained_model_name_or_path) in V2_BASE_MODELS - or str(pretrained_model_name_or_path) in V_PARAMETERIZATION_MODELS + str(pretrained_model_name_or_path) in V1_MODELS + or str(pretrained_model_name_or_path) in V2_BASE_MODELS + or str(pretrained_model_name_or_path) in V_PARAMETERIZATION_MODELS ): pretrained_model_name_or_path = '' v2 = False @@ -481,12 +464,11 @@ def set_v2_checkbox(model_list, v2, v_parameterization): def set_model_list( - model_list, - pretrained_model_name_or_path, - v2, - v_parameterization, + model_list, + pretrained_model_name_or_path, + v2, + v_parameterization, ): - if not pretrained_model_name_or_path in ALL_PRESET_MODELS: model_list = 'custom' else: @@ -529,7 +511,7 @@ def gradio_config(): def get_pretrained_model_name_or_path_file( - model_list, pretrained_model_name_or_path + model_list, pretrained_model_name_or_path ): pretrained_model_name_or_path = get_any_file_path( pretrained_model_name_or_path @@ -537,13 +519,13 @@ def get_pretrained_model_name_or_path_file( set_model_list(model_list, pretrained_model_name_or_path) -def gradio_source_model(save_model_as_choices = [ - 'same as source model', - 'ckpt', - 'diffusers', - 'diffusers_safetensors', - 'safetensors', - ]): +def gradio_source_model(save_model_as_choices=[ + 'same as source model', + 'ckpt', + 'diffusers', + 'diffusers_safetensors', + 'safetensors', +]): with gr.Tab('Source model'): # Define the input elements with gr.Row(): @@ -648,9 +630,9 @@ def gradio_source_model(save_model_as_choices = [ def gradio_training( - learning_rate_value='1e-6', - lr_scheduler_value='constant', - lr_warmup_value='0', + learning_rate_value='1e-6', + lr_scheduler_value='constant', + lr_warmup_value='0', ): with gr.Row(): train_batch_size = gr.Slider( diff --git a/library/convert_model_gui.py b/library/convert_model_gui.py index aaa39b8..dd43b0e 100644 --- a/library/convert_model_gui.py +++ b/library/convert_model_gui.py @@ -1,8 +1,9 @@ -import gradio as gr -from easygui import msgbox -import subprocess import os import shutil +import subprocess + +import gradio as gr + from .common_gui import get_folder_path, get_file_path folder_symbol = '\U0001f4c2' # 📂 @@ -22,7 +23,7 @@ def convert_model( ): # Check for caption_text_input if source_model_type == '': - msgbox('Invalid source model type') + show_message_box('Invalid source model type') return # Check if source model exist @@ -31,14 +32,14 @@ def convert_model( elif os.path.isdir(source_model_input): print('The provided model is a folder') else: - msgbox('The provided source model is neither a file nor a folder') + show_message_box('The provided source model is neither a file nor a folder') return # Check if source model exist if os.path.isdir(target_model_folder_input): print('The provided model folder exist') else: - msgbox('The provided target folder does not exist') + show_message_box('The provided target folder does not exist') return run_cmd = f'{PYTHON} "tools/convert_diffusers20_original_sd.py"' diff --git a/library/dataset_balancing_gui.py b/library/dataset_balancing_gui.py index 2e6bc98..34292f6 100644 --- a/library/dataset_balancing_gui.py +++ b/library/dataset_balancing_gui.py @@ -1,9 +1,12 @@ import os import re + import gradio as gr -from easygui import msgbox, boolbox +from easygui import boolbox + from .common_gui import get_folder_path + # def select_folder(): # # Open a file dialog to select a directory # folder = filedialog.askdirectory() @@ -16,14 +19,14 @@ def dataset_balancing(concept_repeats, folder, insecure): if not concept_repeats > 0: # Display an error message if the total number of repeats is not a valid integer - msgbox('Please enter a valid integer for the total number of repeats.') + show_message_box('Please enter a valid integer for the total number of repeats.') return concept_repeats = int(concept_repeats) # Check if folder exist if folder == '' or not os.path.isdir(folder): - msgbox('Please enter a valid folder for balancing.') + show_message_box('Please enter a valid folder for balancing.') return pattern = re.compile(r'^\d+_.+$') @@ -85,7 +88,7 @@ def dataset_balancing(concept_repeats, folder, insecure): f'Skipping folder {subdir} because it does not match kohya_ss expected syntax...' ) - msgbox('Dataset balancing completed...') + show_message_box('Dataset balancing completed...') def warning(insecure): diff --git a/library/dreambooth_folder_creation_gui.py b/library/dreambooth_folder_creation_gui.py index b5d5ff4..53ec71a 100644 --- a/library/dreambooth_folder_creation_gui.py +++ b/library/dreambooth_folder_creation_gui.py @@ -1,8 +1,9 @@ -import gradio as gr -from easygui import diropenbox, msgbox -from .common_gui import get_folder_path -import shutil import os +import shutil + +import gradio as gr + +from .common_gui import get_folder_path def copy_info_to_Folders_tab(training_folder): @@ -39,12 +40,12 @@ def dreambooth_folder_preparation( # Check for instance prompt if util_instance_prompt_input == '': - msgbox('Instance prompt missing...') + show_message_box('Instance prompt missing...') return # Check for class prompt if util_class_prompt_input == '': - msgbox('Class prompt missing...') + show_message_box('Class prompt missing...') return # Create the training_dir path diff --git a/library/extract_lora_gui.py b/library/extract_lora_gui.py index 5f48686..6a5df1b 100644 --- a/library/extract_lora_gui.py +++ b/library/extract_lora_gui.py @@ -1,11 +1,10 @@ -import gradio as gr -from easygui import msgbox -import subprocess import os +import subprocess + +import gradio as gr + from .common_gui import ( - get_saveasfilename_path, - get_any_file_path, - get_file_path, + get_file_path, get_saveasfile_path, ) folder_symbol = '\U0001f4c2' # 📂 @@ -27,20 +26,20 @@ def extract_lora( ): # Check for caption_text_input if model_tuned == '': - msgbox('Invalid finetuned model file') + show_message_box('Invalid finetuned model file') return if model_org == '': - msgbox('Invalid base model file') + show_message_box('Invalid base model file') return # Check if source model exist if not os.path.isfile(model_tuned): - msgbox('The provided finetuned model is not a file') + show_message_box('The provided finetuned model is not a file') return if not os.path.isfile(model_org): - msgbox('The provided base model is not a file') + show_message_box('The provided base model is not a file') return run_cmd = ( @@ -121,7 +120,7 @@ def gradio_extract_lora_tab(): folder_symbol, elem_id='open_folder_small' ) button_save_to.click( - get_saveasfilename_path, + get_saveasfile_path, inputs=[save_to, lora_ext, lora_ext_name], outputs=save_to, show_progress=False, diff --git a/library/extract_lycoris_locon_gui.py b/library/extract_lycoris_locon_gui.py index 13575bb..f95bf96 100644 --- a/library/extract_lycoris_locon_gui.py +++ b/library/extract_lycoris_locon_gui.py @@ -1,11 +1,10 @@ -import gradio as gr -from easygui import msgbox -import subprocess import os +import subprocess + +import gradio as gr + from .common_gui import ( - get_saveasfilename_path, - get_any_file_path, - get_file_path, + get_file_path, get_saveasfile_path, ) folder_symbol = '\U0001f4c2' # 📂 @@ -36,20 +35,20 @@ def extract_lycoris_locon( ): # Check for caption_text_input if db_model == '': - msgbox('Invalid finetuned model file') + show_message_box('Invalid finetuned model file') return if base_model == '': - msgbox('Invalid base model file') + show_message_box('Invalid base model file') return # Check if source model exist if not os.path.isfile(db_model): - msgbox('The provided finetuned model is not a file') + show_message_box('The provided finetuned model is not a file') return if not os.path.isfile(base_model): - msgbox('The provided base model is not a file') + show_message_box('The provided base model is not a file') return run_cmd = f'{PYTHON} "{os.path.join("tools","lycoris_locon_extract.py")}"' @@ -167,7 +166,7 @@ def gradio_extract_lycoris_locon_tab(): folder_symbol, elem_id='open_folder_small' ) button_output_name.click( - get_saveasfilename_path, + get_saveasfile_path, inputs=[output_name, lora_ext, lora_ext_name], outputs=output_name, show_progress=False, diff --git a/library/git_caption_gui.py b/library/git_caption_gui.py index 9aaf3d9..4ef87b4 100644 --- a/library/git_caption_gui.py +++ b/library/git_caption_gui.py @@ -1,7 +1,8 @@ -import gradio as gr -from easygui import msgbox -import subprocess import os +import subprocess + +import gradio as gr + from .common_gui import get_folder_path, add_pre_postfix PYTHON = 'python3' if os.name == 'posix' else './venv/Scripts/python.exe' @@ -19,11 +20,11 @@ def caption_images( ): # Check for images_dir_input if train_data_dir == '': - msgbox('Image folder is missing...') + show_message_box('Image folder is missing...') return if caption_ext == '': - msgbox('Please provide an extension for the caption files.') + show_message_box('Please provide an extension for the caption files.') return print(f'GIT captioning files in {train_data_dir}...') diff --git a/library/gui_subprocesses.py b/library/gui_subprocesses.py new file mode 100644 index 0000000..87e65fc --- /dev/null +++ b/library/gui_subprocesses.py @@ -0,0 +1,84 @@ +import sys +import tkinter as tk +from tkinter import filedialog, messagebox + + +def open_file_dialog(initial_dir=None, initial_file=None, file_types="all"): + file_type_filters = { + "all": [("All files", "*.*")], + "video": [("Video files", "*.mp4;*.avi;*.mkv;*.mov;*.flv;*.wmv")], + "images": [("Image files", "*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.tiff")], + "json": [("JSON files", "*.json")], + "lora": [("LoRa files", "*.ckpt;*.pt;*.safetensors")], + "directory": [], + } + + if file_types in file_type_filters: + filters = file_type_filters[file_types] + else: + filters = file_type_filters["all"] + + if file_types == "directory": + return filedialog.askdirectory(initialdir=initial_dir) + else: + return filedialog.askopenfilename(initialdir=initial_dir, initialfile=initial_file, filetypes=filters) + + +def save_file_dialog(initial_dir, initial_file, files_type="all"): + root = tk.Tk() + root.withdraw() + + filetypes_switch = { + "all": [("All files", "*.*")], + "video": [("Video files", "*.mp4;*.avi;*.mkv;*.webm;*.flv;*.mov;*.wmv")], + "images": [("Image files", "*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.tiff;*.ico")], + "json": [("JSON files", "*.json")], + "lora": [("LoRa files", "*.ckpt;*.pt;*.safetensors")], + } + + filetypes = filetypes_switch.get(files_type, filetypes_switch["all"]) + save_file_path = filedialog.asksaveasfilename(initialdir=initial_dir, initialfile=initial_file, filetypes=filetypes, + defaultextension=filetypes) + + root.destroy() + + return save_file_path + + +def show_message_box(_message, _title="Message", _level="info"): + root = tk.Tk() + root.withdraw() + + message_type = { + "warning": messagebox.showwarning, + "error": messagebox.showerror, + "info": messagebox.showinfo, + "question": messagebox.askquestion, + "okcancel": messagebox.askokcancel, + "retrycancel": messagebox.askretrycancel, + "yesno": messagebox.askyesno, + "yesnocancel": messagebox.askyesnocancel + } + + if _level in message_type: + message_type[_level](_title, _message) + else: + messagebox.showinfo(_title, _message) + + root.destroy() + + +if __name__ == '__main__': + mode = sys.argv[1] + + if mode == 'file_dialog': + starting_dir = sys.argv[2] if len(sys.argv) > 2 else None + starting_file = sys.argv[3] if len(sys.argv) > 3 else None + file_class = sys.argv[2] if len(sys.argv) > 2 else None + file_path = open_file_dialog(starting_dir, starting_file, file_class) + print(file_path) + + elif mode == 'msgbox': + message = sys.argv[2] + title = sys.argv[3] if len(sys.argv) > 3 else "" + show_message_box(message, title) diff --git a/library/merge_lora_gui.py b/library/merge_lora_gui.py index 21cd16a..e5f6b9b 100644 --- a/library/merge_lora_gui.py +++ b/library/merge_lora_gui.py @@ -1,11 +1,10 @@ -import gradio as gr -from easygui import msgbox -import subprocess import os +import subprocess + +import gradio as gr + from .common_gui import ( - get_saveasfilename_path, - get_any_file_path, - get_file_path, + get_file_path, get_saveasfile_path, ) folder_symbol = '\U0001f4c2' # 📂 @@ -25,20 +24,20 @@ def merge_lora( ): # Check for caption_text_input if lora_a_model == '': - msgbox('Invalid model A file') + show_message_box('Invalid model A file') return if lora_b_model == '': - msgbox('Invalid model B file') + show_message_box('Invalid model B file') return # Check if source model exist if not os.path.isfile(lora_a_model): - msgbox('The provided model A is not a file') + show_message_box('The provided model A is not a file') return if not os.path.isfile(lora_b_model): - msgbox('The provided model B is not a file') + show_message_box('The provided model B is not a file') return ratio_a = ratio @@ -122,7 +121,7 @@ def gradio_merge_lora_tab(): folder_symbol, elem_id='open_folder_small' ) button_save_to.click( - get_saveasfilename_path, + get_saveasfile_path, inputs=[save_to, lora_ext, lora_ext_name], outputs=save_to, show_progress=False, diff --git a/library/resize_lora_gui.py b/library/resize_lora_gui.py index 05a7734..a47e407 100644 --- a/library/resize_lora_gui.py +++ b/library/resize_lora_gui.py @@ -1,8 +1,9 @@ -import gradio as gr -from easygui import msgbox -import subprocess import os -from .common_gui import get_saveasfilename_path, get_file_path +import subprocess + +import gradio as gr + +from .common_gui import get_file_path, get_saveasfile_path PYTHON = 'python3' if os.name == 'posix' else './venv/Scripts/python.exe' folder_symbol = '\U0001f4c2' # 📂 @@ -23,24 +24,24 @@ def resize_lora( ): # Check for caption_text_input if model == '': - msgbox('Invalid model file') + show_message_box('Invalid model file') return # Check if source model exist if not os.path.isfile(model): - msgbox('The provided model is not a file') + show_message_box('The provided model is not a file') return if dynamic_method == 'sv_ratio': if float(dynamic_param) < 2: - msgbox( + show_message_box( f'Dynamic parameter for {dynamic_method} need to be 2 or greater...' ) return if dynamic_method == 'sv_fro' or dynamic_method == 'sv_cumulative': if float(dynamic_param) < 0 or float(dynamic_param) > 1: - msgbox( + show_message_box( f'Dynamic parameter for {dynamic_method} need to be between 0 and 1...' ) return @@ -134,7 +135,7 @@ def gradio_resize_lora_tab(): folder_symbol, elem_id='open_folder_small' ) button_save_to.click( - get_saveasfilename_path, + get_saveasfile_path, inputs=[save_to, lora_ext, lora_ext_name], outputs=save_to, show_progress=False, diff --git a/library/sampler_gui.py b/library/sampler_gui.py index ce95313..c1ba146 100644 --- a/library/sampler_gui.py +++ b/library/sampler_gui.py @@ -1,7 +1,6 @@ import tempfile import os import gradio as gr -from easygui import msgbox folder_symbol = '\U0001f4c2' # 📂 refresh_symbol = '\U0001f504' # 🔄 diff --git a/library/svd_merge_lora_gui.py b/library/svd_merge_lora_gui.py index 042be2e..a2b040c 100644 --- a/library/svd_merge_lora_gui.py +++ b/library/svd_merge_lora_gui.py @@ -1,11 +1,10 @@ -import gradio as gr -from easygui import msgbox -import subprocess import os +import subprocess + +import gradio as gr + from .common_gui import ( - get_saveasfilename_path, - get_any_file_path, - get_file_path, + get_file_path, get_saveasfile_path, ) folder_symbol = '\U0001f4c2' # 📂 @@ -28,20 +27,20 @@ def svd_merge_lora( ): # Check for caption_text_input if lora_a_model == '': - msgbox('Invalid model A file') + show_message_box('Invalid model A file') return if lora_b_model == '': - msgbox('Invalid model B file') + show_message_box('Invalid model B file') return # Check if source model exist if not os.path.isfile(lora_a_model): - msgbox('The provided model A is not a file') + show_message_box('The provided model A is not a file') return if not os.path.isfile(lora_b_model): - msgbox('The provided model B is not a file') + show_message_box('The provided model B is not a file') return ratio_a = ratio @@ -144,7 +143,7 @@ def gradio_svd_merge_lora_tab(): folder_symbol, elem_id='open_folder_small' ) button_save_to.click( - get_saveasfilename_path, + get_saveasfile_path, inputs=[save_to, lora_ext, lora_ext_name], outputs=save_to, show_progress=False, diff --git a/library/tensorboard_gui.py b/library/tensorboard_gui.py index d08a02d..f2dd74f 100644 --- a/library/tensorboard_gui.py +++ b/library/tensorboard_gui.py @@ -1,9 +1,9 @@ import os -import gradio as gr -from easygui import msgbox import subprocess import time +import gradio as gr + tensorboard_proc = None # I know... bad but heh TENSORBOARD = 'tensorboard' if os.name == 'posix' else 'tensorboard.exe' @@ -13,7 +13,7 @@ def start_tensorboard(logging_dir): if not os.listdir(logging_dir): print('Error: log folder is empty') - msgbox(msg='Error: log folder is empty') + show_message_box(msg='Error: log folder is empty') return run_cmd = [f'{TENSORBOARD}', '--logdir', f'{logging_dir}'] diff --git a/library/verify_lora_gui.py b/library/verify_lora_gui.py index a7a0bf9..a72160e 100644 --- a/library/verify_lora_gui.py +++ b/library/verify_lora_gui.py @@ -1,10 +1,9 @@ -import gradio as gr -from easygui import msgbox -import subprocess import os +import subprocess + +import gradio as gr + from .common_gui import ( - get_saveasfilename_path, - get_any_file_path, get_file_path, ) @@ -20,12 +19,12 @@ def verify_lora( ): # verify for caption_text_input if lora_model == '': - msgbox('Invalid model A file') + show_message_box('Invalid model A file') return # verify if source model exist if not os.path.isfile(lora_model): - msgbox('The provided model A is not a file') + show_message_box('The provided model A is not a file') return run_cmd = [ diff --git a/library/wd14_caption_gui.py b/library/wd14_caption_gui.py index 1970849..a9f7742 100644 --- a/library/wd14_caption_gui.py +++ b/library/wd14_caption_gui.py @@ -1,8 +1,9 @@ -import gradio as gr -from easygui import msgbox -import subprocess -from .common_gui import get_folder_path import os +import subprocess + +import gradio as gr + +from .common_gui import get_folder_path def replace_underscore_with_space(folder_path, file_extension): @@ -20,16 +21,16 @@ def caption_images( ): # Check for caption_text_input # if caption_text_input == "": - # msgbox("Caption text is missing...") + # show_message_box("Caption text is missing...") # return # Check for images_dir_input if train_data_dir == '': - msgbox('Image folder is missing...') + show_message_box('Image folder is missing...') return if caption_extension == '': - msgbox('Please provide an extension for the caption files.') + show_message_box('Please provide an extension for the caption files.') return print(f'Captioning files in {train_data_dir}...') diff --git a/lora_gui.py b/lora_gui.py index e7ada89..819927c 100644 --- a/lora_gui.py +++ b/lora_gui.py @@ -3,14 +3,15 @@ # v3: Add new Utilities tab for Dreambooth folder preparation # v3.1: Adding captionning of images to utilities -import gradio as gr -import easygui +import argparse import json import math import os -import subprocess import pathlib -import argparse +import subprocess + +import gradio as gr + from library.common_gui import ( get_folder_path, remove_doublequote, @@ -27,24 +28,23 @@ from library.common_gui import ( run_cmd_training, # set_legacy_8bitadam, update_my_data, - check_if_model_exist, + check_if_model_exist, show_message_box, ) +from library.dataset_balancing_gui import gradio_dataset_balancing_tab from library.dreambooth_folder_creation_gui import ( gradio_dreambooth_folder_creation_tab, ) +from library.merge_lora_gui import gradio_merge_lora_tab +from library.resize_lora_gui import gradio_resize_lora_tab +from library.sampler_gui import sample_gradio_config, run_cmd_sample +from library.svd_merge_lora_gui import gradio_svd_merge_lora_tab from library.tensorboard_gui import ( gradio_tensorboard, start_tensorboard, stop_tensorboard, ) -from library.dataset_balancing_gui import gradio_dataset_balancing_tab from library.utilities import utilities_tab -from library.merge_lora_gui import gradio_merge_lora_tab -from library.svd_merge_lora_gui import gradio_svd_merge_lora_tab from library.verify_lora_gui import gradio_verify_lora_tab -from library.resize_lora_gui import gradio_resize_lora_tab -from library.sampler_gui import sample_gradio_config, run_cmd_sample -from easygui import msgbox folder_symbol = '\U0001f4c2' # 📂 refresh_symbol = '\U0001f504' # 🔄 @@ -353,35 +353,35 @@ def train_model( print_only_bool = True if print_only.get('label') == 'True' else False if pretrained_model_name_or_path == '': - msgbox('Source model information is missing') + show_message_box('Source model information is missing') return if train_data_dir == '': - msgbox('Image folder path is missing') + show_message_box('Image folder path is missing') return if not os.path.exists(train_data_dir): - msgbox('Image folder does not exist') + show_message_box('Image folder does not exist') return if reg_data_dir != '': if not os.path.exists(reg_data_dir): - msgbox('Regularisation folder does not exist') + show_message_box('Regularisation folder does not exist') return if output_dir == '': - msgbox('Output folder path is missing') + show_message_box('Output folder path is missing') return if int(bucket_reso_steps) < 1: - msgbox('Bucket resolution steps need to be greater than 0') + show_message_box('Bucket resolution steps need to be greater than 0') return if not os.path.exists(output_dir): os.makedirs(output_dir) if stop_text_encoder_training_pct > 0: - msgbox( + show_message_box( 'Output "stop text encoder training" is not yet supported. Ignoring' ) stop_text_encoder_training_pct = 0 @@ -396,7 +396,7 @@ def train_model( unet_lr = 0 # if (float(text_encoder_lr) == 0) and (float(unet_lr) == 0): - # msgbox( + # show_message_box( # 'At least one Learning Rate value for "Text encoder" or "Unet" need to be provided' # ) # return @@ -532,7 +532,7 @@ def train_model( run_cmd += f' --network_train_unet_only' else: if float(text_encoder_lr) == 0: - msgbox('Please input learning rate values.') + show_message_box('Please input learning rate values.') return run_cmd += f' --network_dim={network_dim}' diff --git a/textual_inversion_gui.py b/textual_inversion_gui.py index 7b8c19c..f48904a 100644 --- a/textual_inversion_gui.py +++ b/textual_inversion_gui.py @@ -3,13 +3,15 @@ # v3: Add new Utilities tab for Dreambooth folder preparation # v3.1: Adding captionning of images to utilities -import gradio as gr +import argparse import json import math import os -import subprocess import pathlib -import argparse +import subprocess + +import gradio as gr + from library.common_gui import ( get_folder_path, remove_doublequote, @@ -28,17 +30,16 @@ from library.common_gui import ( update_my_data, check_if_model_exist, ) +from library.dreambooth_folder_creation_gui import ( + gradio_dreambooth_folder_creation_tab, +) +from library.sampler_gui import sample_gradio_config, run_cmd_sample from library.tensorboard_gui import ( gradio_tensorboard, start_tensorboard, stop_tensorboard, ) -from library.dreambooth_folder_creation_gui import ( - gradio_dreambooth_folder_creation_tab, -) from library.utilities import utilities_tab -from library.sampler_gui import sample_gradio_config, run_cmd_sample -from easygui import msgbox folder_symbol = '\U0001f4c2' # 📂 refresh_symbol = '\U0001f504' # 🔄 @@ -323,32 +324,32 @@ def train_model( additional_parameters,vae_batch_size, ): if pretrained_model_name_or_path == '': - msgbox('Source model information is missing') + show_message_box('Source model information is missing') return if train_data_dir == '': - msgbox('Image folder path is missing') + show_message_box('Image folder path is missing') return if not os.path.exists(train_data_dir): - msgbox('Image folder does not exist') + show_message_box('Image folder does not exist') return if reg_data_dir != '': if not os.path.exists(reg_data_dir): - msgbox('Regularisation folder does not exist') + show_message_box('Regularisation folder does not exist') return if output_dir == '': - msgbox('Output folder path is missing') + show_message_box('Output folder path is missing') return if token_string == '': - msgbox('Token string is missing') + show_message_box('Token string is missing') return if init_word == '': - msgbox('Init word is missing') + show_message_box('Init word is missing') return if not os.path.exists(output_dir):