From 67e41eff7d8d2d012366f4f52221a2fba362fa2f Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 14 Feb 2024 17:00:42 +0100 Subject: [PATCH] Settings cleanup --- extras/expansion.py | 6 +- extras/face_crop.py | 4 +- extras/interrogate.py | 4 +- extras/vae_interpose.py | 4 +- extras/wd14tagger.py | 6 +- launch.py | 30 +- modules/async_worker.py | 18 +- modules/config.py | 530 ------------------------------------ modules/core.py | 9 +- modules/default_pipeline.py | 12 +- modules/meta_parser.py | 6 +- modules/private_logger.py | 7 +- modules/settings.py | 274 +++++++++++++++++++ modules/upscaler.py | 4 +- webui.py | 68 ++--- 15 files changed, 362 insertions(+), 620 deletions(-) delete mode 100644 modules/config.py create mode 100644 modules/settings.py diff --git a/extras/expansion.py b/extras/expansion.py index c1b59b8a42..64e842bc10 100644 --- a/extras/expansion.py +++ b/extras/expansion.py @@ -12,7 +12,7 @@ from transformers.generation.logits_process import LogitsProcessorList from transformers import AutoTokenizer, AutoModelForCausalLM, set_seed -from modules.config import path_fooocus_expansion +from modules.settings import settings from ldm_patched.modules.model_patcher import ModelPatcher @@ -36,9 +36,9 @@ def remove_pattern(x, pattern): class FooocusExpansion: def __init__(self): - self.tokenizer = AutoTokenizer.from_pretrained(path_fooocus_expansion) + self.tokenizer = AutoTokenizer.from_pretrained(settings.path_fooocus_expansion) - positive_words = open(os.path.join(path_fooocus_expansion, 'positive.txt'), + positive_words = open(os.path.join(settings.path_fooocus_expansion, 'positive.txt'), encoding='utf-8').read().splitlines() positive_words = ['Ġ' + x.lower() for x in positive_words if x != ''] diff --git a/extras/face_crop.py b/extras/face_crop.py index d4da7e81d5..1909135d1f 100644 --- a/extras/face_crop.py +++ b/extras/face_crop.py @@ -1,6 +1,6 @@ import cv2 import numpy as np -import modules.config +from modules.settings import settings faceRestoreHelper = None @@ -28,7 +28,7 @@ def crop_image(img_rgb): from extras.facexlib.utils.face_restoration_helper import FaceRestoreHelper faceRestoreHelper = FaceRestoreHelper( upscale_factor=1, - model_rootpath=modules.config.path_controlnet, + model_rootpath=settings.path_controlnet, device='cpu' # use cpu is safer since we are out of memory management ) diff --git a/extras/interrogate.py b/extras/interrogate.py index 410d685f64..f41a91b00b 100644 --- a/extras/interrogate.py +++ b/extras/interrogate.py @@ -5,7 +5,7 @@ from torchvision import transforms from torchvision.transforms.functional import InterpolationMode from modules.model_loader import load_file_from_url -from modules.config import path_clip_vision +from modules.settings import settings from ldm_patched.modules.model_patcher import ModelPatcher from extras.BLIP.models.blip import blip_decoder @@ -27,7 +27,7 @@ def interrogate(self, img_rgb): if self.blip_model is None: filename = load_file_from_url( url='https://huggingface.co/lllyasviel/misc/resolve/main/model_base_caption_capfilt_large.pth', - model_dir=path_clip_vision, + model_dir=settings.path_clip_vision, file_name='model_base_caption_capfilt_large.pth', ) diff --git a/extras/vae_interpose.py b/extras/vae_interpose.py index 72fb09a415..fa2604a1bf 100644 --- a/extras/vae_interpose.py +++ b/extras/vae_interpose.py @@ -7,7 +7,7 @@ import ldm_patched.modules.model_management from ldm_patched.modules.model_patcher import ModelPatcher -from modules.config import path_vae_approx +from modules.settings import settings class Block(nn.Module): @@ -63,7 +63,7 @@ def forward(self, x): vae_approx_model = None -vae_approx_filename = os.path.join(path_vae_approx, 'xl-to-v1_interposer-v3.1.safetensors') +vae_approx_filename = os.path.join(settings.path_vae_approx, 'xl-to-v1_interposer-v3.1.safetensors') def parse(x): diff --git a/extras/wd14tagger.py b/extras/wd14tagger.py index 368c13dfa7..ba2fe13671 100644 --- a/extras/wd14tagger.py +++ b/extras/wd14tagger.py @@ -16,7 +16,7 @@ from PIL import Image from onnxruntime import InferenceSession -from modules.config import path_clip_vision +from modules.settings import settings from modules.model_loader import load_file_from_url @@ -31,13 +31,13 @@ def default_interrogator(image_rgb, threshold=0.35, character_threshold=0.85, ex model_onnx_filename = load_file_from_url( url=f'https://huggingface.co/lllyasviel/misc/resolve/main/{model_name}.onnx', - model_dir=path_clip_vision, + model_dir=settings.path_clip_vision, file_name=f'{model_name}.onnx', ) model_csv_filename = load_file_from_url( url=f'https://huggingface.co/lllyasviel/misc/resolve/main/{model_name}.csv', - model_dir=path_clip_vision, + model_dir=settings.path_clip_vision, file_name=f'{model_name}.csv', ) diff --git a/launch.py b/launch.py index db174f54c7..ad746db846 100644 --- a/launch.py +++ b/launch.py @@ -84,15 +84,15 @@ def ini_args(): print("Set device to:", args.gpu_device_id) -from modules import config +from modules.settings import settings def download_models(): for file_name, url in vae_approx_filenames: - load_file_from_url(url=url, model_dir=config.path_vae_approx, file_name=file_name) + load_file_from_url(url=url, model_dir=settings.path_vae_approx, file_name=file_name) load_file_from_url( url='https://huggingface.co/lllyasviel/misc/resolve/main/fooocus_expansion.bin', - model_dir=config.path_fooocus_expansion, + model_dir=settings.path_fooocus_expansion, file_name='pytorch_model.bin' ) @@ -101,23 +101,23 @@ def download_models(): return if not args.always_download_new_model: - if not os.path.exists(os.path.join(config.path_checkpoints, config.default_base_model_name)): - for alternative_model_name in config.previous_default_models: - if os.path.exists(os.path.join(config.path_checkpoints, alternative_model_name)): - print(f'You do not have [{config.default_base_model_name}] but you have [{alternative_model_name}].') + if not os.path.exists(os.path.join(settings.path_checkpoints, settings.default_base_model_name)): + for alternative_model_name in settings.previous_default_models: + if os.path.exists(os.path.join(settings.path_checkpoints, alternative_model_name)): + print(f'You do not have [{settings.default_base_model_name}] but you have [{alternative_model_name}].') print(f'Fooocus will use [{alternative_model_name}] to avoid downloading new models, ' f'but you are not using latest models.') print('Use --always-download-new-model to avoid fallback and always get new models.') - config.checkpoint_downloads = {} - config.default_base_model_name = alternative_model_name + settings.checkpoint_downloads = {} + settings.default_base_model_name = alternative_model_name break - for file_name, url in config.checkpoint_downloads.items(): - load_file_from_url(url=url, model_dir=config.path_checkpoints, file_name=file_name) - for file_name, url in config.embeddings_downloads.items(): - load_file_from_url(url=url, model_dir=config.path_embeddings, file_name=file_name) - for file_name, url in config.lora_downloads.items(): - load_file_from_url(url=url, model_dir=config.path_loras, file_name=file_name) + for file_name, url in settings.checkpoint_downloads.items(): + load_file_from_url(url=url, model_dir=settings.path_checkpoints, file_name=file_name) + for file_name, url in settings.embeddings_downloads.items(): + load_file_from_url(url=url, model_dir=settings.path_embeddings, file_name=file_name) + for file_name, url in settings.lora_downloads.items(): + load_file_from_url(url=url, model_dir=settings.path_loras, file_name=file_name) return diff --git a/modules/async_worker.py b/modules/async_worker.py index 40abb7fa42..1e941d5bde 100644 --- a/modules/async_worker.py +++ b/modules/async_worker.py @@ -25,7 +25,7 @@ def worker(): import modules.default_pipeline as pipeline import modules.core as core import modules.flags as flags - import modules.config + import modules.settings import modules.patch import ldm_patched.modules.model_management import extras.preprocessors as preprocessors @@ -180,7 +180,7 @@ def handler(async_task): if performance_selection == 'Extreme Speed': print('Enter LCM mode.') progressbar(async_task, 1, 'Downloading LCM components ...') - loras += [(modules.config.downloading_sdxl_lcm_lora(), 1.0)] + loras += [(modules.settings.downloading_sdxl_lcm_lora(), 1.0)] if refiner_model_name != 'None': print(f'Refiner disabled in LCM mode.') @@ -269,7 +269,7 @@ def handler(async_task): steps = 8 progressbar(async_task, 1, 'Downloading upscale models ...') - modules.config.downloading_upscale_model() + modules.settings.downloading_upscale_model() if (current_tab == 'inpaint' or ( current_tab == 'ip' and advanced_parameters.mixing_image_prompt_and_inpaint)) \ and isinstance(inpaint_input_image, dict): @@ -295,10 +295,10 @@ def handler(async_task): if isinstance(inpaint_image, np.ndarray) and isinstance(inpaint_mask, np.ndarray) \ and (np.any(inpaint_mask > 127) or len(outpaint_selections) > 0): progressbar(async_task, 1, 'Downloading upscale models ...') - modules.config.downloading_upscale_model() + modules.settings.downloading_upscale_model() if inpaint_parameterized: progressbar(async_task, 1, 'Downloading inpainter ...') - inpaint_head_model_path, inpaint_patch_model_path = modules.config.downloading_inpaint_models( + inpaint_head_model_path, inpaint_patch_model_path = modules.settings.downloading_inpaint_models( advanced_parameters.inpaint_engine) base_model_additional_loras += [(inpaint_patch_model_path, 1.0)] print(f'[Inpaint] Current inpaint model is {inpaint_patch_model_path}') @@ -320,13 +320,13 @@ def handler(async_task): goals.append('cn') progressbar(async_task, 1, 'Downloading control models ...') if len(cn_tasks[flags.cn_canny]) > 0: - controlnet_canny_path = modules.config.downloading_controlnet_canny() + controlnet_canny_path = modules.settings.downloading_controlnet_canny() if len(cn_tasks[flags.cn_cpds]) > 0: - controlnet_cpds_path = modules.config.downloading_controlnet_cpds() + controlnet_cpds_path = modules.settings.downloading_controlnet_cpds() if len(cn_tasks[flags.cn_ip]) > 0: - clip_vision_path, ip_negative_path, ip_adapter_path = modules.config.downloading_ip_adapters('ip') + clip_vision_path, ip_negative_path, ip_adapter_path = modules.settings.downloading_ip_adapters('ip') if len(cn_tasks[flags.cn_ip_face]) > 0: - clip_vision_path, ip_negative_path, ip_adapter_face_path = modules.config.downloading_ip_adapters( + clip_vision_path, ip_negative_path, ip_adapter_face_path = modules.settings.downloading_ip_adapters( 'face') progressbar(async_task, 1, 'Loading control models ...') diff --git a/modules/config.py b/modules/config.py deleted file mode 100644 index 1f4e82eb54..0000000000 --- a/modules/config.py +++ /dev/null @@ -1,530 +0,0 @@ -import os -import json -import math -import numbers -import args_manager -import modules.flags -import modules.sdxl_styles - -from modules.model_loader import load_file_from_url -from modules.util import get_files_from_folder - - -config_path = os.path.abspath("./config.txt") -config_example_path = os.path.abspath("config_modification_tutorial.txt") -config_dict = {} -always_save_keys = [] -visited_keys = [] - -try: - with open(os.path.abspath(f'./presets/default.json'), "r", encoding="utf-8") as json_file: - config_dict.update(json.load(json_file)) -except Exception as e: - print(f'Load default preset failed.') - print(e) - -try: - if os.path.exists(config_path): - with open(config_path, "r", encoding="utf-8") as json_file: - config_dict.update(json.load(json_file)) - always_save_keys = list(config_dict.keys()) -except Exception as e: - print(f'Failed to load config file "{config_path}" . The reason is: {str(e)}') - print('Please make sure that:') - print(f'1. The file "{config_path}" is a valid text file, and you have access to read it.') - print('2. Use "\\\\" instead of "\\" when describing paths.') - print('3. There is no "," before the last "}".') - print('4. All key/value formats are correct.') - - -def try_load_deprecated_user_path_config(): - global config_dict - - if not os.path.exists('user_path_config.txt'): - return - - try: - deprecated_config_dict = json.load(open('user_path_config.txt', "r", encoding="utf-8")) - - def replace_config(old_key, new_key): - if old_key in deprecated_config_dict: - config_dict[new_key] = deprecated_config_dict[old_key] - del deprecated_config_dict[old_key] - - replace_config('modelfile_path', 'path_checkpoints') - replace_config('lorafile_path', 'path_loras') - replace_config('embeddings_path', 'path_embeddings') - replace_config('vae_approx_path', 'path_vae_approx') - replace_config('upscale_models_path', 'path_upscale_models') - replace_config('inpaint_models_path', 'path_inpaint') - replace_config('controlnet_models_path', 'path_controlnet') - replace_config('clip_vision_models_path', 'path_clip_vision') - replace_config('fooocus_expansion_path', 'path_fooocus_expansion') - replace_config('temp_outputs_path', 'path_outputs') - - if deprecated_config_dict.get("default_model", None) == 'juggernautXL_version6Rundiffusion.safetensors': - os.replace('user_path_config.txt', 'user_path_config-deprecated.txt') - print('Config updated successfully in silence. ' - 'A backup of previous config is written to "user_path_config-deprecated.txt".') - return - - if input("Newer models and configs are available. " - "Download and update files? [Y/n]:") in ['n', 'N', 'No', 'no', 'NO']: - config_dict.update(deprecated_config_dict) - print('Loading using deprecated old models and deprecated old configs.') - return - else: - os.replace('user_path_config.txt', 'user_path_config-deprecated.txt') - print('Config updated successfully by user. ' - 'A backup of previous config is written to "user_path_config-deprecated.txt".') - return - except Exception as e: - print('Processing deprecated config failed') - print(e) - return - - -try_load_deprecated_user_path_config() - -preset = args_manager.args.preset - -if isinstance(preset, str): - preset_path = os.path.abspath(f'./presets/{preset}.json') - try: - if os.path.exists(preset_path): - with open(preset_path, "r", encoding="utf-8") as json_file: - config_dict.update(json.load(json_file)) - print(f'Loaded preset: {preset_path}') - else: - raise FileNotFoundError - except Exception as e: - print(f'Load preset [{preset_path}] failed') - print(e) - - -def get_path_output() -> str: - """ - Checking output path argument and overriding default path. - """ - global config_dict - path_output = get_dir_or_set_default('path_outputs', '../outputs/') - if args_manager.args.output_path: - print(f'[CONFIG] Overriding config value path_outputs with {args_manager.args.output_path}') - config_dict['path_outputs'] = path_output = args_manager.args.output_path - return path_output - - -def get_dir_or_set_default(key, default_value): - global config_dict, visited_keys, always_save_keys - - if key not in visited_keys: - visited_keys.append(key) - - if key not in always_save_keys: - always_save_keys.append(key) - - v = config_dict.get(key, None) - if isinstance(v, str) and os.path.exists(v) and os.path.isdir(v): - return v - else: - if v is not None: - print(f'Failed to load config key: {json.dumps({key:v})} is invalid or does not exist; will use {json.dumps({key:default_value})} instead.') - dp = os.path.abspath(os.path.join(os.path.dirname(__file__), default_value)) - os.makedirs(dp, exist_ok=True) - config_dict[key] = dp - return dp - - -path_checkpoints = get_dir_or_set_default('path_checkpoints', '../models/checkpoints/') -path_loras = get_dir_or_set_default('path_loras', '../models/loras/') -path_embeddings = get_dir_or_set_default('path_embeddings', '../models/embeddings/') -path_vae_approx = get_dir_or_set_default('path_vae_approx', '../models/vae_approx/') -path_upscale_models = get_dir_or_set_default('path_upscale_models', '../models/upscale_models/') -path_inpaint = get_dir_or_set_default('path_inpaint', '../models/inpaint/') -path_controlnet = get_dir_or_set_default('path_controlnet', '../models/controlnet/') -path_clip_vision = get_dir_or_set_default('path_clip_vision', '../models/clip_vision/') -path_fooocus_expansion = get_dir_or_set_default('path_fooocus_expansion', '../models/prompt_expansion/fooocus_expansion') -path_outputs = get_path_output() - - -def get_config_item_or_set_default(key, default_value, validator, disable_empty_as_none=False): - global config_dict, visited_keys - - if key not in visited_keys: - visited_keys.append(key) - - if key not in config_dict: - config_dict[key] = default_value - return default_value - - v = config_dict.get(key, None) - if not disable_empty_as_none: - if v is None or v == '': - v = 'None' - if validator(v): - return v - else: - if v is not None: - print(f'Failed to load config key: {json.dumps({key:v})} is invalid; will use {json.dumps({key:default_value})} instead.') - config_dict[key] = default_value - return default_value - - -default_base_model_name = get_config_item_or_set_default( - key='default_model', - default_value='model.safetensors', - validator=lambda x: isinstance(x, str) -) -previous_default_models = get_config_item_or_set_default( - key='previous_default_models', - default_value=[], - validator=lambda x: isinstance(x, list) and all(isinstance(k, str) for k in x) -) -default_refiner_model_name = get_config_item_or_set_default( - key='default_refiner', - default_value='None', - validator=lambda x: isinstance(x, str) -) -default_refiner_switch = get_config_item_or_set_default( - key='default_refiner_switch', - default_value=0.8, - validator=lambda x: isinstance(x, numbers.Number) and 0 <= x <= 1 -) -default_loras = get_config_item_or_set_default( - key='default_loras', - default_value=[ - [ - "None", - 1.0 - ], - [ - "None", - 1.0 - ], - [ - "None", - 1.0 - ], - [ - "None", - 1.0 - ], - [ - "None", - 1.0 - ] - ], - validator=lambda x: isinstance(x, list) and all(len(y) == 2 and isinstance(y[0], str) and isinstance(y[1], numbers.Number) for y in x) -) -default_cfg_scale = get_config_item_or_set_default( - key='default_cfg_scale', - default_value=7.0, - validator=lambda x: isinstance(x, numbers.Number) -) -default_sample_sharpness = get_config_item_or_set_default( - key='default_sample_sharpness', - default_value=2.0, - validator=lambda x: isinstance(x, numbers.Number) -) -default_sampler = get_config_item_or_set_default( - key='default_sampler', - default_value='dpmpp_2m_sde_gpu', - validator=lambda x: x in modules.flags.sampler_list -) -default_scheduler = get_config_item_or_set_default( - key='default_scheduler', - default_value='karras', - validator=lambda x: x in modules.flags.scheduler_list -) -default_styles = get_config_item_or_set_default( - key='default_styles', - default_value=[ - "Fooocus V2", - "Fooocus Enhance", - "Fooocus Sharp" - ], - validator=lambda x: isinstance(x, list) and all(y in modules.sdxl_styles.legal_style_names for y in x) -) -default_prompt_negative = get_config_item_or_set_default( - key='default_prompt_negative', - default_value='', - validator=lambda x: isinstance(x, str), - disable_empty_as_none=True -) -default_prompt = get_config_item_or_set_default( - key='default_prompt', - default_value='', - validator=lambda x: isinstance(x, str), - disable_empty_as_none=True -) -default_performance = get_config_item_or_set_default( - key='default_performance', - default_value='Speed', - validator=lambda x: x in modules.flags.performance_selections -) -default_advanced_checkbox = get_config_item_or_set_default( - key='default_advanced_checkbox', - default_value=False, - validator=lambda x: isinstance(x, bool) -) -default_max_image_number = get_config_item_or_set_default( - key='default_max_image_number', - default_value=32, - validator=lambda x: isinstance(x, int) and x >= 1 -) -default_image_number = get_config_item_or_set_default( - key='default_image_number', - default_value=2, - validator=lambda x: isinstance(x, int) and 1 <= x <= default_max_image_number -) -checkpoint_downloads = get_config_item_or_set_default( - key='checkpoint_downloads', - default_value={}, - validator=lambda x: isinstance(x, dict) and all(isinstance(k, str) and isinstance(v, str) for k, v in x.items()) -) -lora_downloads = get_config_item_or_set_default( - key='lora_downloads', - default_value={}, - validator=lambda x: isinstance(x, dict) and all(isinstance(k, str) and isinstance(v, str) for k, v in x.items()) -) -embeddings_downloads = get_config_item_or_set_default( - key='embeddings_downloads', - default_value={}, - validator=lambda x: isinstance(x, dict) and all(isinstance(k, str) and isinstance(v, str) for k, v in x.items()) -) -available_aspect_ratios = get_config_item_or_set_default( - key='available_aspect_ratios', - default_value=[ - '704*1408', '704*1344', '768*1344', '768*1280', '832*1216', '832*1152', - '896*1152', '896*1088', '960*1088', '960*1024', '1024*1024', '1024*960', - '1088*960', '1088*896', '1152*896', '1152*832', '1216*832', '1280*768', - '1344*768', '1344*704', '1408*704', '1472*704', '1536*640', '1600*640', - '1664*576', '1728*576' - ], - validator=lambda x: isinstance(x, list) and all('*' in v for v in x) and len(x) > 1 -) -default_aspect_ratio = get_config_item_or_set_default( - key='default_aspect_ratio', - default_value='1152*896' if '1152*896' in available_aspect_ratios else available_aspect_ratios[0], - validator=lambda x: x in available_aspect_ratios -) -default_inpaint_engine_version = get_config_item_or_set_default( - key='default_inpaint_engine_version', - default_value='v2.6', - validator=lambda x: x in modules.flags.inpaint_engine_versions -) -default_cfg_tsnr = get_config_item_or_set_default( - key='default_cfg_tsnr', - default_value=7.0, - validator=lambda x: isinstance(x, numbers.Number) -) -default_overwrite_step = get_config_item_or_set_default( - key='default_overwrite_step', - default_value=-1, - validator=lambda x: isinstance(x, int) -) -default_overwrite_switch = get_config_item_or_set_default( - key='default_overwrite_switch', - default_value=-1, - validator=lambda x: isinstance(x, int) -) -example_inpaint_prompts = get_config_item_or_set_default( - key='example_inpaint_prompts', - default_value=[ - 'highly detailed face', 'detailed girl face', 'detailed man face', 'detailed hand', 'beautiful eyes' - ], - validator=lambda x: isinstance(x, list) and all(isinstance(v, str) for v in x) -) - -example_inpaint_prompts = [[x] for x in example_inpaint_prompts] - -config_dict["default_loras"] = default_loras = default_loras[:5] + [['None', 1.0] for _ in range(5 - len(default_loras))] - -possible_preset_keys = [ - "default_model", - "default_refiner", - "default_refiner_switch", - "default_loras", - "default_cfg_scale", - "default_sample_sharpness", - "default_sampler", - "default_scheduler", - "default_performance", - "default_prompt", - "default_prompt_negative", - "default_styles", - "default_aspect_ratio", - "checkpoint_downloads", - "embeddings_downloads", - "lora_downloads", -] - - -REWRITE_PRESET = False - -if REWRITE_PRESET and isinstance(args_manager.args.preset, str): - save_path = 'presets/' + args_manager.args.preset + '.json' - with open(save_path, "w", encoding="utf-8") as json_file: - json.dump({k: config_dict[k] for k in possible_preset_keys}, json_file, indent=4) - print(f'Preset saved to {save_path}. Exiting ...') - exit(0) - - -def add_ratio(x): - a, b = x.replace('*', ' ').split(' ')[:2] - a, b = int(a), int(b) - g = math.gcd(a, b) - return f'{a}×{b} \U00002223 {a // g}:{b // g}' - - -default_aspect_ratio = add_ratio(default_aspect_ratio) -available_aspect_ratios = [add_ratio(x) for x in available_aspect_ratios] - - -# Only write config in the first launch. -if not os.path.exists(config_path): - with open(config_path, "w", encoding="utf-8") as json_file: - json.dump({k: config_dict[k] for k in always_save_keys}, json_file, indent=4) - - -# Always write tutorials. -with open(config_example_path, "w", encoding="utf-8") as json_file: - cpa = config_path.replace("\\", "\\\\") - json_file.write(f'You can modify your "{cpa}" using the below keys, formats, and examples.\n' - f'Do not modify this file. Modifications in this file will not take effect.\n' - f'This file is a tutorial and example. Please edit "{cpa}" to really change any settings.\n' - + 'Remember to split the paths with "\\\\" rather than "\\", ' - 'and there is no "," before the last "}". \n\n\n') - json.dump({k: config_dict[k] for k in visited_keys}, json_file, indent=4) - - -os.makedirs(path_outputs, exist_ok=True) - -model_filenames = [] -lora_filenames = [] - - -def get_model_filenames(folder_path, name_filter=None): - return get_files_from_folder(folder_path, ['.pth', '.ckpt', '.bin', '.safetensors', '.fooocus.patch'], name_filter) - - -def update_all_model_names(): - global model_filenames, lora_filenames - model_filenames = get_model_filenames(path_checkpoints) - lora_filenames = get_model_filenames(path_loras) - return - - -def downloading_inpaint_models(v): - assert v in modules.flags.inpaint_engine_versions - - load_file_from_url( - url='https://huggingface.co/lllyasviel/fooocus_inpaint/resolve/main/fooocus_inpaint_head.pth', - model_dir=path_inpaint, - file_name='fooocus_inpaint_head.pth' - ) - head_file = os.path.join(path_inpaint, 'fooocus_inpaint_head.pth') - patch_file = None - - if v == 'v1': - load_file_from_url( - url='https://huggingface.co/lllyasviel/fooocus_inpaint/resolve/main/inpaint.fooocus.patch', - model_dir=path_inpaint, - file_name='inpaint.fooocus.patch' - ) - patch_file = os.path.join(path_inpaint, 'inpaint.fooocus.patch') - - if v == 'v2.5': - load_file_from_url( - url='https://huggingface.co/lllyasviel/fooocus_inpaint/resolve/main/inpaint_v25.fooocus.patch', - model_dir=path_inpaint, - file_name='inpaint_v25.fooocus.patch' - ) - patch_file = os.path.join(path_inpaint, 'inpaint_v25.fooocus.patch') - - if v == 'v2.6': - load_file_from_url( - url='https://huggingface.co/lllyasviel/fooocus_inpaint/resolve/main/inpaint_v26.fooocus.patch', - model_dir=path_inpaint, - file_name='inpaint_v26.fooocus.patch' - ) - patch_file = os.path.join(path_inpaint, 'inpaint_v26.fooocus.patch') - - return head_file, patch_file - - -def downloading_sdxl_lcm_lora(): - load_file_from_url( - url='https://huggingface.co/lllyasviel/misc/resolve/main/sdxl_lcm_lora.safetensors', - model_dir=path_loras, - file_name='sdxl_lcm_lora.safetensors' - ) - return 'sdxl_lcm_lora.safetensors' - - -def downloading_controlnet_canny(): - load_file_from_url( - url='https://huggingface.co/lllyasviel/misc/resolve/main/control-lora-canny-rank128.safetensors', - model_dir=path_controlnet, - file_name='control-lora-canny-rank128.safetensors' - ) - return os.path.join(path_controlnet, 'control-lora-canny-rank128.safetensors') - - -def downloading_controlnet_cpds(): - load_file_from_url( - url='https://huggingface.co/lllyasviel/misc/resolve/main/fooocus_xl_cpds_128.safetensors', - model_dir=path_controlnet, - file_name='fooocus_xl_cpds_128.safetensors' - ) - return os.path.join(path_controlnet, 'fooocus_xl_cpds_128.safetensors') - - -def downloading_ip_adapters(v): - assert v in ['ip', 'face'] - - results = [] - - load_file_from_url( - url='https://huggingface.co/lllyasviel/misc/resolve/main/clip_vision_vit_h.safetensors', - model_dir=path_clip_vision, - file_name='clip_vision_vit_h.safetensors' - ) - results += [os.path.join(path_clip_vision, 'clip_vision_vit_h.safetensors')] - - load_file_from_url( - url='https://huggingface.co/lllyasviel/misc/resolve/main/fooocus_ip_negative.safetensors', - model_dir=path_controlnet, - file_name='fooocus_ip_negative.safetensors' - ) - results += [os.path.join(path_controlnet, 'fooocus_ip_negative.safetensors')] - - if v == 'ip': - load_file_from_url( - url='https://huggingface.co/lllyasviel/misc/resolve/main/ip-adapter-plus_sdxl_vit-h.bin', - model_dir=path_controlnet, - file_name='ip-adapter-plus_sdxl_vit-h.bin' - ) - results += [os.path.join(path_controlnet, 'ip-adapter-plus_sdxl_vit-h.bin')] - - if v == 'face': - load_file_from_url( - url='https://huggingface.co/lllyasviel/misc/resolve/main/ip-adapter-plus-face_sdxl_vit-h.bin', - model_dir=path_controlnet, - file_name='ip-adapter-plus-face_sdxl_vit-h.bin' - ) - results += [os.path.join(path_controlnet, 'ip-adapter-plus-face_sdxl_vit-h.bin')] - - return results - - -def downloading_upscale_model(): - load_file_from_url( - url='https://huggingface.co/lllyasviel/misc/resolve/main/fooocus_upscaler_s409985e5.bin', - model_dir=path_upscale_models, - file_name='fooocus_upscaler_s409985e5.bin' - ) - return os.path.join(path_upscale_models, 'fooocus_upscaler_s409985e5.bin') - - -update_all_model_names() diff --git a/modules/core.py b/modules/core.py index 989b8e321d..d5f4299d7e 100644 --- a/modules/core.py +++ b/modules/core.py @@ -25,7 +25,7 @@ from ldm_patched.modules.sample import prepare_mask from modules.lora import match_lora from ldm_patched.modules.lora import model_lora_keys_unet, model_lora_keys_clip -from modules.config import path_embeddings +from modules.settings import settings from ldm_patched.contrib.external_model_advanced import ModelSamplingDiscrete @@ -85,7 +85,7 @@ def refresh_loras(self, loras): if os.path.exists(name): lora_filename = name else: - lora_filename = os.path.join(modules.config.path_loras, name) + lora_filename = os.path.join(settings.path_loras, name) if not os.path.exists(lora_filename): print(f'Lora file not found: {lora_filename}') @@ -148,7 +148,7 @@ def apply_controlnet(positive, negative, control_net, image, strength, start_per @torch.no_grad() @torch.inference_mode() def load_model(ckpt_filename): - unet, clip, vae, clip_vision = load_checkpoint_guess_config(ckpt_filename, embedding_directory=path_embeddings) + unet, clip, vae, clip_vision = load_checkpoint_guess_config(ckpt_filename, embedding_directory=settings.path_embeddings) return StableDiffusionModel(unet=unet, clip=clip, vae=vae, clip_vision=clip_vision, filename=ckpt_filename) @@ -227,9 +227,8 @@ def forward(self, x): def get_previewer(model): global VAE_approx_models - from modules.config import path_vae_approx is_sdxl = isinstance(model.model.latent_format, ldm_patched.modules.latent_formats.SDXL) - vae_approx_filename = os.path.join(path_vae_approx, 'xlvaeapp.pth' if is_sdxl else 'vaeapp_sd15.pth') + vae_approx_filename = os.path.join(settings.path_vae_approx, 'xlvaeapp.pth' if is_sdxl else 'vaeapp_sd15.pth') if vae_approx_filename in VAE_approx_models: VAE_approx_model = VAE_approx_models[vae_approx_filename] diff --git a/modules/default_pipeline.py b/modules/default_pipeline.py index 6001d97f06..8a542586a1 100644 --- a/modules/default_pipeline.py +++ b/modules/default_pipeline.py @@ -2,7 +2,6 @@ import os import torch import modules.patch -import modules.config import ldm_patched.modules.model_management import ldm_patched.modules.latent_formats import modules.inpaint_worker @@ -11,6 +10,7 @@ from ldm_patched.modules.model_base import SDXL, SDXLRefiner from modules.sample_hijack import clip_separate +from modules.settings import settings model_base = core.StableDiffusionModel() @@ -60,7 +60,7 @@ def assert_model_integrity(): def refresh_base_model(name): global model_base - filename = os.path.abspath(os.path.realpath(os.path.join(modules.config.path_checkpoints, name))) + filename = os.path.abspath(os.path.realpath(os.path.join(settings.path_checkpoints, name))) if model_base.filename == filename: return @@ -76,7 +76,7 @@ def refresh_base_model(name): def refresh_refiner_model(name): global model_refiner - filename = os.path.abspath(os.path.realpath(os.path.join(modules.config.path_checkpoints, name))) + filename = os.path.abspath(os.path.realpath(os.path.join(settings.path_checkpoints, name))) if model_refiner.filename == filename: return @@ -251,9 +251,9 @@ def refresh_everything(refiner_model_name, base_model_name, loras, refresh_everything( - refiner_model_name=modules.config.default_refiner_model_name, - base_model_name=modules.config.default_base_model_name, - loras=modules.config.default_loras + refiner_model_name=settings.default_refiner_model_name, + base_model_name=settings.default_base_model_name, + loras=settings.default_loras ) diff --git a/modules/meta_parser.py b/modules/meta_parser.py index 07b42a160f..fb44aef4a4 100644 --- a/modules/meta_parser.py +++ b/modules/meta_parser.py @@ -1,6 +1,6 @@ import json import gradio as gr -import modules.config +import modules.settings def load_parameter_button_click(raw_prompt_txt, is_generating): @@ -41,8 +41,8 @@ def load_parameter_button_click(raw_prompt_txt, is_generating): try: h = loaded_parameter_dict.get('Resolution', None) width, height = eval(h) - formatted = modules.config.add_ratio(f'{width}*{height}') - if formatted in modules.config.available_aspect_ratios: + formatted = modules.settings.add_ratio(f'{width}*{height}') + if formatted in modules.settings.available_aspect_ratios: results.append(formatted) results.append(-1) results.append(-1) diff --git a/modules/private_logger.py b/modules/private_logger.py index 49f17dcadd..4373c1eb56 100644 --- a/modules/private_logger.py +++ b/modules/private_logger.py @@ -1,18 +1,17 @@ import os import args_manager -import modules.config import json import urllib.parse from PIL import Image from modules.util import generate_temp_filename - +from modules.settings import settings log_cache = {} def get_current_html_path(): - date_string, local_temp_filename, only_name = generate_temp_filename(folder=modules.config.path_outputs, + date_string, local_temp_filename, only_name = generate_temp_filename(folder=settings.path_outputs, extension='png') html_name = os.path.join(os.path.dirname(local_temp_filename), 'log.html') return html_name @@ -22,7 +21,7 @@ def log(img, dic): if args_manager.args.disable_image_log: return - date_string, local_temp_filename, only_name = generate_temp_filename(folder=modules.config.path_outputs, extension='png') + date_string, local_temp_filename, only_name = generate_temp_filename(folder=settings.path_outputs, extension='png') os.makedirs(os.path.dirname(local_temp_filename), exist_ok=True) Image.fromarray(img).save(local_temp_filename) html_name = os.path.join(os.path.dirname(local_temp_filename), 'log.html') diff --git a/modules/settings.py b/modules/settings.py new file mode 100644 index 0000000000..479c27698a --- /dev/null +++ b/modules/settings.py @@ -0,0 +1,274 @@ +import json +import os +import math +import numbers +import re +from attrs import asdict, define, field, validators +from pathlib import Path + +import args_manager +import modules.flags +import modules.sdxl_styles + +from modules.model_loader import load_file_from_url +from modules.util import get_files_from_folder + + +def load_settings(): + config_path = Path("./config.txt").absolute() + + if not config_path.exists(): + with config_path.open("w", encoding="utf-8") as file: + json.dump(asdict(SettingsDefault()), file, indent=4) + + settings = SettingsDefault() + settings.update_with_file(config_path) + + preset_path = Path(f'./presets/{args_manager.args.preset}.json').absolute() + if preset_path.exists(): + settings.update_with_file(preset_path) + + return settings + + +def validator_path_exist(instance, attribute, value): + if not Path(value).exists(): + raise ValueError(f"Path {value} does not exist") + + +def validator_list_of_strings(instance, attribute, value): + if not (isinstance(value, list) and all(isinstance(elem, str) for elem in value)): + raise ValueError(f"Value {value} is not list of strings") + + +def validator_legal_styles(instance, attribute, value): + if not all(style in modules.sdxl_styles.legal_style_names for style in value): + raise ValueError(f"Value {value} is not list of legal styles") + + +def validator_list_of_resolutions(instance, attribute, value): + resolution_pattern = re.compile(r'^\d+\*\d+$') + for resolution in value: + if not resolution_pattern.match(resolution): + raise ValueError(f"Value {resolution} is not a valid resolution") + + +_default_resolutions = [ + '704*1408', '704*1344', '768*1344', '768*1280', '832*1216', '832*1152', + '896*1152', '896*1088', '960*1088', '960*1024', '1024*1024', '1024*960', + '1088*960', '1088*896', '1152*896', '1152*832', '1216*832', '1280*768', + '1344*768', '1344*704', '1408*704', '1472*704', '1536*640', '1600*640', + '1664*576', '1728*576' +] + + +@define +class SettingsDefault: + # paths + path_checkpoints = field(default="./models/checkpoints/", validator=validator_path_exist) + path_loras = field(default="./models/loras/", validator=validator_path_exist) + path_embeddings = field(default="./models/embeddings/", validator=validator_path_exist) + path_vae_approx = field(default="./models/vae_approx/", validator=validator_path_exist) + path_upscale_models = field(default="./models/upscale_models/", validator=validator_path_exist) + path_inpaint = field(default="./models/inpaint/", validator=validator_path_exist) + path_controlnet = field(default="./models/controlnet/", validator=validator_path_exist) + path_clip_vision = field(default="./models/clip_vision/", validator=validator_path_exist) + path_fooocus_expansion = field(default="./models/prompt_expansion/", validator=validator_path_exist) + path_outputs = field(default="./outputs/") + # models + default_base_model_name = field(default="juggernautXL_v8Rundiffusion.safetensors", + validator=validators.instance_of(str)) + previous_default_models = field(default=[], validator=validators.instance_of(list)) + default_refiner_model_name = field(default="None", validator=validators.instance_of(str)) + default_refiner_switch = field(default=0.5, validator=[validators.ge(0), validators.le(1)]) + # loras + lora1_name = field(default="None", validator=validators.instance_of(str)) + lora1_weight = field(default=1.0, validator=[validators.ge(-2), validators.le(2)]) + lora2_name = field(default="None", validator=validators.instance_of(str)) + lora2_weight = field(default=1.0, validator=[validators.ge(-2), validators.le(2)]) + lora3_name = field(default="None", validator=validators.instance_of(str)) + lora3_weight = field(default=1.0, validator=[validators.ge(-2), validators.le(2)]) + lora4_name = field(default="None", validator=validators.instance_of(str)) + lora4_weight = field(default=1.0, validator=[validators.ge(-2), validators.le(2)]) + lora5_name = field(default="None", validator=validators.instance_of(str)) + lora5_weight = field(default=1.0, validator=[validators.ge(-2), validators.le(2)]) + # config + default_cfg_scale = field(default=7.0, validator=validators.instance_of(numbers.Number)) + default_sample_sharpness = field(default=2.0, validator=validators.instance_of(numbers.Number)) + default_sampler = field(default="dpmpp_2m_sde_gpu", validator=validators.in_(modules.flags.sampler_list)) + default_scheduler = field(default="karras", validator=validators.in_(modules.flags.scheduler_list)) + default_styles = field(default=["Fooocus V2", "Fooocus Enhance", "Fooocus Sharp"], validator=validator_legal_styles) + default_prompt = field(default="", validator=validators.instance_of(str)) + default_prompt_negative = field(default="", validator=validators.instance_of(str)) + default_performance = field(default="Speed", validator=validators.in_(modules.flags.performance_selections)) + default_advanced_checkbox = field(default=False, validator=validators.instance_of(bool)) + default_max_image_number = field(default=32, validator=[validators.instance_of(int), validators.ge(1)]) + default_image_number = field(default=2, validator=[validators.instance_of(int), validators.ge(1)]) + checkpoint_downloads = field(default={}, validator=validators.instance_of(dict)) + lora_downloads = field(default={}, validator=validators.instance_of(dict)) + embeddings_downloads = field(default={}, validator=validators.instance_of(dict)) + available_aspect_ratios = field(default=_default_resolutions, validator=validator_list_of_resolutions) + default_aspect_ratio = field(default='1152*896', validator=validators.matches_re(r'^\d+\*\d+$')) + default_inpaint_engine_version = field(default="v2.6", validator=validators.in_(modules.flags.inpaint_engine_versions)) + default_cfg_tsnr = field(default=7.0, validator=validators.instance_of(numbers.Number)) + default_overwrite_step = field(default=-1, validator=validators.instance_of(int)) + default_overwrite_switch = field(default=-1, validator=validators.instance_of(int)) + + def update_key(self, key, value): + if hasattr(self, key): + setattr(self, key, value) + else: + print(f"Invalid attribute name: {key}. Ignoring") + + def update_with_file(self, path): + cfg = {} + with path.open("r", encoding="utf-8") as file: + cfg.update(json.load(file)) + + for k, v in cfg.items(): + try: + self.update_key(k, v) + except ValueError as e: + print(e) + print(f"Error: key {k} has invalid value {v}. Will use default {getattr(self, k)}") + + +def get_model_filenames(folder_path, name_filter=None): + return get_files_from_folder(folder_path, ['.pth', '.ckpt', '.bin', '.safetensors', '.fooocus.patch'], name_filter) + + +def update_all_model_names(): + global model_filenames, lora_filenames + model_filenames = get_model_filenames(settings.path_checkpoints) + lora_filenames = get_model_filenames(settings.path_loras) + return + + +def downloading_inpaint_models(v): + assert v in modules.flags.inpaint_engine_versions + + load_file_from_url( + url='https://huggingface.co/lllyasviel/fooocus_inpaint/resolve/main/fooocus_inpaint_head.pth', + model_dir=settings.path_inpaint, + file_name='fooocus_inpaint_head.pth' + ) + head_file = os.path.join(settings.path_inpaint, 'fooocus_inpaint_head.pth') + patch_file = None + + if v == 'v1': + load_file_from_url( + url='https://huggingface.co/lllyasviel/fooocus_inpaint/resolve/main/inpaint.fooocus.patch', + model_dir=settings.path_inpaint, + file_name='inpaint.fooocus.patch' + ) + patch_file = os.path.join(settings.path_inpaint, 'inpaint.fooocus.patch') + + if v == 'v2.5': + load_file_from_url( + url='https://huggingface.co/lllyasviel/fooocus_inpaint/resolve/main/inpaint_v25.fooocus.patch', + model_dir=settings.path_inpaint, + file_name='inpaint_v25.fooocus.patch' + ) + patch_file = os.path.join(settings.path_inpaint, 'inpaint_v25.fooocus.patch') + + if v == 'v2.6': + load_file_from_url( + url='https://huggingface.co/lllyasviel/fooocus_inpaint/resolve/main/inpaint_v26.fooocus.patch', + model_dir=settings.path_inpaint, + file_name='inpaint_v26.fooocus.patch' + ) + patch_file = os.path.join(settings.path_inpaint, 'inpaint_v26.fooocus.patch') + + return head_file, patch_file + + +def downloading_sdxl_lcm_lora(): + load_file_from_url( + url='https://huggingface.co/lllyasviel/misc/resolve/main/sdxl_lcm_lora.safetensors', + model_dir=settings.path_loras, + file_name='sdxl_lcm_lora.safetensors' + ) + return 'sdxl_lcm_lora.safetensors' + + +def downloading_controlnet_canny(): + load_file_from_url( + url='https://huggingface.co/lllyasviel/misc/resolve/main/control-lora-canny-rank128.safetensors', + model_dir=settings.path_controlnet, + file_name='control-lora-canny-rank128.safetensors' + ) + return os.path.join(settings.path_controlnet, 'control-lora-canny-rank128.safetensors') + + +def downloading_controlnet_cpds(): + load_file_from_url( + url='https://huggingface.co/lllyasviel/misc/resolve/main/fooocus_xl_cpds_128.safetensors', + model_dir=settings.path_controlnet, + file_name='fooocus_xl_cpds_128.safetensors' + ) + return os.path.join(settings.path_controlnet, 'fooocus_xl_cpds_128.safetensors') + + +def downloading_ip_adapters(v): + assert v in ['ip', 'face'] + + results = [] + + load_file_from_url( + url='https://huggingface.co/lllyasviel/misc/resolve/main/clip_vision_vit_h.safetensors', + model_dir=settings.path_clip_vision, + file_name='clip_vision_vit_h.safetensors' + ) + results += [os.path.join(settings.path_clip_vision, 'clip_vision_vit_h.safetensors')] + + load_file_from_url( + url='https://huggingface.co/lllyasviel/misc/resolve/main/fooocus_ip_negative.safetensors', + model_dir=settings.path_controlnet, + file_name='fooocus_ip_negative.safetensors' + ) + results += [os.path.join(settings.path_controlnet, 'fooocus_ip_negative.safetensors')] + + if v == 'ip': + load_file_from_url( + url='https://huggingface.co/lllyasviel/misc/resolve/main/ip-adapter-plus_sdxl_vit-h.bin', + model_dir=settings.path_controlnet, + file_name='ip-adapter-plus_sdxl_vit-h.bin' + ) + results += [os.path.join(settings.path_controlnet, 'ip-adapter-plus_sdxl_vit-h.bin')] + + if v == 'face': + load_file_from_url( + url='https://huggingface.co/lllyasviel/misc/resolve/main/ip-adapter-plus-face_sdxl_vit-h.bin', + model_dir=settings.path_controlnet, + file_name='ip-adapter-plus-face_sdxl_vit-h.bin' + ) + results += [os.path.join(settings.path_controlnet, 'ip-adapter-plus-face_sdxl_vit-h.bin')] + + return results + + +def downloading_upscale_model(): + load_file_from_url( + url='https://huggingface.co/lllyasviel/misc/resolve/main/fooocus_upscaler_s409985e5.bin', + model_dir=settings.path_upscale_models, + file_name='fooocus_upscaler_s409985e5.bin' + ) + return os.path.join(settings.path_upscale_models, 'fooocus_upscaler_s409985e5.bin') + + +def add_ratio(x): + a, b = x.replace('*', ' ').split(' ')[:2] + a, b = int(a), int(b) + g = math.gcd(a, b) + return f'{a}×{b} \U00002223 {a // g}:{b // g}' + + +settings = load_settings() +os.makedirs(settings.path_outputs, exist_ok=True) + +model_filenames = [] +lora_filenames = [] +update_all_model_names() + +default_aspect_ratio = add_ratio(settings.default_aspect_ratio) +available_aspect_ratios = [add_ratio(x) for x in settings.available_aspect_ratios] diff --git a/modules/upscaler.py b/modules/upscaler.py index 974e4f37c8..a213845f7c 100644 --- a/modules/upscaler.py +++ b/modules/upscaler.py @@ -5,9 +5,9 @@ from ldm_patched.pfn.architecture.RRDB import RRDBNet as ESRGAN from ldm_patched.contrib.external_upscale_model import ImageUpscaleWithModel from collections import OrderedDict -from modules.config import path_upscale_models +from modules.settings import settings -model_filename = os.path.join(path_upscale_models, 'fooocus_upscaler_s409985e5.bin') +model_filename = os.path.join(settings.path_upscale_models, 'fooocus_upscaler_s409985e5.bin') opImageUpscaleWithModel = ImageUpscaleWithModel() model = None diff --git a/webui.py b/webui.py index b9b620d243..8e31a837b7 100644 --- a/webui.py +++ b/webui.py @@ -4,7 +4,6 @@ import json import time import shared -import modules.config import fooocus_version import modules.html import modules.async_worker as worker @@ -21,6 +20,7 @@ from modules.private_logger import get_current_html_path from modules.ui_gradio_extensions import reload_javascript from modules.auth import auth_enabled, check_auth +from modules.settings import settings def generate_clicked(*args): @@ -105,7 +105,7 @@ def generate_clicked(*args): prompt = gr.Textbox(show_label=False, placeholder="Type prompt here or paste parameters.", elem_id='positive_prompt', container=False, autofocus=True, elem_classes='type_row', lines=1024) - default_prompt = modules.config.default_prompt + default_prompt = settings.default_prompt if isinstance(default_prompt, str) and default_prompt != '': shared.gradio_root.load(lambda: default_prompt, outputs=prompt) @@ -132,7 +132,7 @@ def skip_clicked(): skip_button.click(skip_clicked, queue=False, show_progress=False) with gr.Row(elem_classes='advanced_check_row'): input_image_checkbox = gr.Checkbox(label='Input Image', value=False, container=False, elem_classes='min_check') - advanced_checkbox = gr.Checkbox(label='Advanced', value=modules.config.default_advanced_checkbox, container=False, elem_classes='min_check') + advanced_checkbox = gr.Checkbox(label='Advanced', value=settings.default_advanced_checkbox, container=False, elem_classes='min_check') with gr.Row(visible=False) as image_input_panel: with gr.Tabs(): with gr.TabItem(label='Upscale or Variation') as uov_tab: @@ -194,7 +194,7 @@ def ip_advance_checked(x): inpaint_additional_prompt = gr.Textbox(placeholder="Describe what you want to inpaint.", elem_id='inpaint_additional_prompt', label='Inpaint Additional Prompt', visible=False) outpaint_selections = gr.CheckboxGroup(choices=['Left', 'Right', 'Top', 'Bottom'], value=[], label='Outpaint Direction') inpaint_mode = gr.Dropdown(choices=modules.flags.inpaint_options, value=modules.flags.inpaint_option_default, label='Method') - example_inpaint_prompts = gr.Dataset(samples=modules.config.example_inpaint_prompts, label='Additional Prompt Quick List', components=[inpaint_additional_prompt], visible=False) + example_inpaint_prompts = gr.Dataset(samples=settings.example_inpaint_prompts, label='Additional Prompt Quick List', components=[inpaint_additional_prompt], visible=False) gr.HTML('* Powered by Fooocus Inpaint Engine \U0001F4D4 Document') example_inpaint_prompts.click(lambda x: x[0], inputs=example_inpaint_prompts, outputs=inpaint_additional_prompt, show_progress=False, queue=False) with gr.TabItem(label='Describe') as desc_tab: @@ -221,19 +221,19 @@ def ip_advance_checked(x): ip_tab.select(lambda: 'ip', outputs=current_tab, queue=False, _js=down_js, show_progress=False) desc_tab.select(lambda: 'desc', outputs=current_tab, queue=False, _js=down_js, show_progress=False) - with gr.Column(scale=1, visible=modules.config.default_advanced_checkbox) as advanced_column: + with gr.Column(scale=1, visible=settings.default_advanced_checkbox) as advanced_column: with gr.Tab(label='Setting'): performance_selection = gr.Radio(label='Performance', choices=modules.flags.performance_selections, - value=modules.config.default_performance) - aspect_ratios_selection = gr.Radio(label='Aspect Ratios', choices=modules.config.available_aspect_ratios, - value=modules.config.default_aspect_ratio, info='width × height', + value=settings.default_performance) + aspect_ratios_selection = gr.Radio(label='Aspect Ratios', choices=modules.settings.available_aspect_ratios, + value=modules.settings.default_aspect_ratio, info='width × height', elem_classes='aspect_ratios') - image_number = gr.Slider(label='Image Number', minimum=1, maximum=modules.config.default_max_image_number, step=1, value=modules.config.default_image_number) + image_number = gr.Slider(label='Image Number', minimum=1, maximum=settings.default_max_image_number, step=1, value=settings.default_image_number) negative_prompt = gr.Textbox(label='Negative Prompt', show_label=True, placeholder="Type prompt here.", info='Describing what you do not want to see.', lines=2, elem_id='negative_prompt', - value=modules.config.default_prompt_negative) + value=settings.default_prompt_negative) seed_random = gr.Checkbox(label='Random', value=True) image_seed = gr.Textbox(label='Seed', value=0, max_lines=1, visible=False) # workaround for https://github.com/gradio-app/gradio/issues/5354 @@ -267,7 +267,7 @@ def update_history_link(): with gr.Tab(label='Style'): style_sorter.try_load_sorted_styles( style_names=legal_style_names, - default_selected=modules.config.default_styles) + default_selected=settings.default_styles) style_search_bar = gr.Textbox(show_label=False, container=False, placeholder="\U0001F50E Type here to search styles ...", @@ -275,7 +275,7 @@ def update_history_link(): label='Search Styles') style_selections = gr.CheckboxGroup(show_label=False, container=False, choices=copy.deepcopy(style_sorter.all_styles), - value=copy.deepcopy(modules.config.default_styles), + value=copy.deepcopy(settings.default_styles), label='Selected Styles', elem_classes=['style_selections']) gradio_receiver_style_selections = gr.Textbox(elem_id='gradio_receiver_style_selections', visible=False) @@ -300,16 +300,16 @@ def update_history_link(): with gr.Tab(label='Model'): with gr.Group(): with gr.Row(): - base_model = gr.Dropdown(label='Base Model (SDXL only)', choices=modules.config.model_filenames, value=modules.config.default_base_model_name, show_label=True) - refiner_model = gr.Dropdown(label='Refiner (SDXL or SD 1.5)', choices=['None'] + modules.config.model_filenames, value=modules.config.default_refiner_model_name, show_label=True) + base_model = gr.Dropdown(label='Base Model (SDXL only)', choices=settings.model_filenames, value=settings.default_base_model_name, show_label=True) + refiner_model = gr.Dropdown(label='Refiner (SDXL or SD 1.5)', choices=['None'] + settings.model_filenames, value=settings.default_refiner_model_name, show_label=True) refiner_switch = gr.Slider(label='Refiner Switch At', minimum=0.1, maximum=1.0, step=0.0001, info='Use 0.4 for SD1.5 realistic models; ' 'or 0.667 for SD1.5 anime models; ' 'or 0.8 for XL-refiners; ' 'or any value for switching two SDXL models.', - value=modules.config.default_refiner_switch, - visible=modules.config.default_refiner_model_name != 'None') + value=settings.default_refiner_switch, + visible=settings.default_refiner_model_name != 'None') refiner_model.change(lambda x: gr.update(visible=x != 'None'), inputs=refiner_model, outputs=refiner_switch, show_progress=False, queue=False) @@ -317,10 +317,10 @@ def update_history_link(): with gr.Group(): lora_ctrls = [] - for i, (n, v) in enumerate(modules.config.default_loras): + for i, (n, v) in enumerate(settings.default_loras): with gr.Row(): lora_model = gr.Dropdown(label=f'LoRA {i + 1}', - choices=['None'] + modules.config.lora_filenames, value=n) + choices=['None'] + settings.lora_filenames, value=n) lora_weight = gr.Slider(label='Weight', minimum=-2, maximum=2, step=0.01, value=v, elem_classes='lora_weight') lora_ctrls += [lora_model, lora_weight] @@ -329,10 +329,10 @@ def update_history_link(): model_refresh = gr.Button(label='Refresh', value='\U0001f504 Refresh All Files', variant='secondary', elem_classes='refresh_button') with gr.Tab(label='Advanced'): guidance_scale = gr.Slider(label='Guidance Scale', minimum=1.0, maximum=30.0, step=0.01, - value=modules.config.default_cfg_scale, + value=settings.default_cfg_scale, info='Higher value means style is cleaner, vivider, and more artistic.') sharpness = gr.Slider(label='Image Sharpness', minimum=0.0, maximum=30.0, step=0.001, - value=modules.config.default_sample_sharpness, + value=settings.default_sample_sharpness, info='Higher value means image and texture are sharper.') gr.HTML('\U0001F4D4 Document') dev_mode = gr.Checkbox(label='Developer Debug Mode', value=False, container=False) @@ -351,13 +351,13 @@ def update_history_link(): choices=['joint', 'separate', 'vae']) adaptive_cfg = gr.Slider(label='CFG Mimicking from TSNR', minimum=1.0, maximum=30.0, step=0.01, - value=modules.config.default_cfg_tsnr, + value=settings.default_cfg_tsnr, info='Enabling Fooocus\'s implementation of CFG mimicking for TSNR ' '(effective when real CFG > mimicked CFG).') sampler_name = gr.Dropdown(label='Sampler', choices=flags.sampler_list, - value=modules.config.default_sampler) + value=settings.default_sampler) scheduler_name = gr.Dropdown(label='Scheduler', choices=flags.scheduler_list, - value=modules.config.default_scheduler) + value=settings.default_scheduler) generate_image_grid = gr.Checkbox(label='Generate Image Grid for Each Batch', info='(Experimental) This may cause performance problems on some computers and certain internet conditions.', @@ -365,11 +365,11 @@ def update_history_link(): overwrite_step = gr.Slider(label='Forced Overwrite of Sampling Step', minimum=-1, maximum=200, step=1, - value=modules.config.default_overwrite_step, + value=settings.default_overwrite_step, info='Set as -1 to disable. For developer debugging.') overwrite_switch = gr.Slider(label='Forced Overwrite of Refiner Switch Step', minimum=-1, maximum=200, step=1, - value=modules.config.default_overwrite_switch, + value=settings.default_overwrite_switch, info='Set as -1 to disable. For developer debugging.') overwrite_width = gr.Slider(label='Forced Overwrite of Generating Width', minimum=-1, maximum=2048, step=1, value=-1, @@ -413,7 +413,7 @@ def update_history_link(): debugging_inpaint_preprocessor = gr.Checkbox(label='Debug Inpaint Preprocessing', value=False) inpaint_disable_initial_latent = gr.Checkbox(label='Disable initial latent in inpaint', value=False) inpaint_engine = gr.Dropdown(label='Inpaint Engine', - value=modules.config.default_inpaint_engine_version, + value=settings.default_inpaint_engine_version, choices=flags.inpaint_engine_versions, info='Version of Fooocus inpaint model') inpaint_strength = gr.Slider(label='Inpaint Denoising Strength', @@ -469,11 +469,11 @@ def dev_mode_checked(r): queue=False, show_progress=False) def model_refresh_clicked(): - modules.config.update_all_model_names() + settings.update_all_model_names() results = [] - results += [gr.update(choices=modules.config.model_filenames), gr.update(choices=['None'] + modules.config.model_filenames)] + results += [gr.update(choices=settings.model_filenames), gr.update(choices=['None'] + settings.model_filenames)] for i in range(5): - results += [gr.update(choices=['None'] + modules.config.lora_filenames), gr.update()] + results += [gr.update(choices=['None'] + settings.lora_filenames), gr.update()] return results model_refresh.click(model_refresh_clicked, [], [base_model, refiner_model] + lora_ctrls, @@ -502,21 +502,21 @@ def inpaint_mode_change(mode): if mode == modules.flags.inpaint_option_detail: return [ gr.update(visible=True), gr.update(visible=False, value=[]), - gr.Dataset.update(visible=True, samples=modules.config.example_inpaint_prompts), + gr.Dataset.update(visible=True, samples=settings.example_inpaint_prompts), False, 'None', 0.5, 0.0 ] if mode == modules.flags.inpaint_option_modify: return [ gr.update(visible=True), gr.update(visible=False, value=[]), - gr.Dataset.update(visible=False, samples=modules.config.example_inpaint_prompts), - True, modules.config.default_inpaint_engine_version, 1.0, 0.0 + gr.Dataset.update(visible=False, samples=settings.example_inpaint_prompts), + True, settings.default_inpaint_engine_version, 1.0, 0.0 ] return [ gr.update(visible=False, value=''), gr.update(visible=True), - gr.Dataset.update(visible=False, samples=modules.config.example_inpaint_prompts), - False, modules.config.default_inpaint_engine_version, 1.0, 0.618 + gr.Dataset.update(visible=False, samples=settings.example_inpaint_prompts), + False, settings.default_inpaint_engine_version, 1.0, 0.618 ] inpaint_mode.input(inpaint_mode_change, inputs=inpaint_mode, outputs=[