add models-dir to settings and simplify path improts

This commit is contained in:
Vladimir Mandic
2023-10-30 08:31:42 -04:00
parent 05a250cbf7
commit 8734445ae9
12 changed files with 108 additions and 51 deletions
+9 -2
View File
@@ -4,8 +4,11 @@
*Note*: Pending release of `diffusers==0.22.0`
Support for several new models and additional optimizations.
Plus tons of fixes...
Another pretty big release, this time with focus on
new models, new backends and optimizations and tons of fixes
Also, [Wiki](https://github.com/vladmandic/automatic/wiki) has been updated with new content, so check it out!
Some highlights: [OpenVINO](https://github.com/vladmandic/automatic/wiki/OpenVINO), [IntelArc](https://github.com/vladmandic/automatic/wiki/Intel-ARC), [DirectML](https://github.com/vladmandic/automatic/wiki/DirectML), [ONNX/Olive>](https://github.com/vladmandic/automatic/wiki/ONNX-Runtime)
- **Diffusers**
- new model type: [Segmind SSD-1B](https://huggingface.co/segmind/SSD-1B)
@@ -24,6 +27,8 @@ Plus tons of fixes...
- new custom pipeline: `Disty0/zero123plus-pipeline`
generate 4 output images with different camera positions: front, side, top, back!
for more details, see <https://github.com/vladmandic/automatic/discussions/2421>
- new backend: **ONNX/Olive** (experimental)
for details, see WiKi
- extend support for [Free-U](https://github.com/ChenyangSi/FreeU)
improve generations quality at no cost (other than finding params that work for you)
- **General**
@@ -35,6 +40,8 @@ Plus tons of fixes...
- **Extra networks** sort by name, size, date, etc.
- new option: *settings -> images -> keep incomplete*
can be used to skip vae decode on aborted/skipped/interrupted image generations
- new option: *settings -> system paths -> models*
can be used to set custom base path for *all* models (previously only as cli option)
- remove external clone of items in `/repositories`
- switch core font in default theme to **noto-sans**
previously default font was simply *system-ui*, but it lead to too much variations between browsers and platforms
+12 -10
View File
@@ -56,21 +56,23 @@ Additional models will be added as they become available and there is public int
- [Stable Diffusion](https://github.com/Stability-AI/stablediffusion/) 1.x and 2.x *(all variants)*
- [Stable Diffusion XL](https://github.com/Stability-AI/generative-models)
- [Kandinsky](https://github.com/ai-forever/Kandinsky-2) 2.1 and 2.2
- [DeepFloyd IF](https://github.com/deep-floyd/IF)
- [UniDiffusion](https://github.com/thu-ml/unidiffuser)
- [SD-Distilled](https://huggingface.co/blog/sd_distillation) *(all variants)*
- [Wuerstchen](https://huggingface.co/blog/wuertschen)
- [Segmind SSD-1B](https://huggingface.co/segmind/SSD-1B)
- [UniDiffusion](https://github.com/thu-ml/unidiffuser)
- [DeepFloyd IF](https://github.com/deep-floyd/IF)
## Platform support
- *nVidia* GPUs using **CUDA** libraries on both *Windows and Linux*
- *AMD* GPUs using **ROCm** libraries on *Linux*.
Support will be extended to *Windows* once AMD releases ROCm for Windows
- *Intel Arc* GPUs using **OneAPI** with *IPEX XPU* libraries on both *Windows and Linux*
- Any GPU compatible with *DirectX* on *Windows* using **DirectML** libraries.
This includes support for AMD GPUs that are not supported by native ROCm libraries
- Any GPU or device compatible with **OpenVINO** libraries on both *Windows and Linux*
- *Apple M1/M2* on *OSX* using built-in support in Torch with **MPS** optimizations
- *nVidia* GPUs using **CUDA** libraries on both *Windows and Linux*
- *AMD* GPUs using **ROCm** libraries on *Linux*
Support will be extended to *Windows* once AMD releases ROCm for Windows
- *Intel Arc* GPUs using **OneAPI** with *IPEX XPU* libraries on both *Windows and Linux*
- Any GPU compatible with *DirectX* on *Windows* using **DirectML** libraries
This includes support for AMD GPUs that are not supported by native ROCm libraries
- Any GPU or device compatible with **OpenVINO** libraries on both *Windows and Linux*
- *Apple M1/M2* on *OSX* using built-in support in Torch with **MPS** optimizations
- *ONNX/Olive* (experimental)
## Install & Run
+3 -3
View File
@@ -661,7 +661,7 @@ def install_extensions():
pkg_resources._initialize_master_working_set() # pylint: disable=protected-access
pkgs = [f'{p.project_name}=={p._version}' for p in pkg_resources.working_set] # pylint: disable=protected-access,not-an-iterable
log.debug(f'Installed packages: {len(pkgs)}')
from modules.paths_internal import extensions_builtin_dir, extensions_dir
from modules.paths import extensions_builtin_dir, extensions_dir
extensions_duplicates = []
extensions_enabled = []
extension_folders = [extensions_builtin_dir] if args.safe else [extensions_builtin_dir, extensions_dir]
@@ -795,7 +795,7 @@ def set_environment():
def check_extensions():
newest_all = os.path.getmtime('requirements.txt')
from modules.paths_internal import extensions_builtin_dir, extensions_dir
from modules.paths import extensions_builtin_dir, extensions_dir
extension_folders = [extensions_builtin_dir] if args.safe else [extensions_builtin_dir, extensions_dir]
disabled_extensions_all = opts.get('disable_all_extensions', 'none')
if disabled_extensions_all != 'none':
@@ -983,7 +983,7 @@ def extensions_preload(parser):
log.info('Running in safe mode without user extensions')
try:
from modules.script_loading import preload_extensions
from modules.paths_internal import extensions_builtin_dir, extensions_dir
from modules.paths import extensions_builtin_dir, extensions_dir
extension_folders = [extensions_builtin_dir] if args.safe else [extensions_builtin_dir, extensions_dir]
preload_time = {}
for ext_dir in extension_folders:
+3 -3
View File
@@ -28,9 +28,9 @@ def init_modules():
parser = modules.cmd_args.parser
installer.add_args(parser)
args, _ = parser.parse_known_args()
import modules.paths_internal
script_path = modules.paths_internal.script_path
extensions_dir = modules.paths_internal.extensions_dir
import modules.paths
script_path = modules.paths.script_path
extensions_dir = modules.paths.extensions_dir
def get_custom_args():
+1 -1
View File
@@ -1,6 +1,6 @@
import os
import argparse
from modules.paths_internal import data_path
from modules.paths import data_path
parser = argparse.ArgumentParser(description="SD.Next", conflict_handler='resolve', epilog='For other options see UI Settings page', prog='', add_help=True, formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=55, indent_increment=2, width=200))
parser._optionals = parser.add_argument_group('Other options') # pylint: disable=protected-access
+1 -1
View File
@@ -2,7 +2,7 @@ import os
from datetime import datetime
import git
from modules import shared, errors
from modules.paths_internal import extensions_dir, extensions_builtin_dir
from modules.paths import extensions_dir, extensions_builtin_dir
extensions = []
+50 -15
View File
@@ -1,9 +1,43 @@
# this module must not have any dependencies as it first import
import os
import sys
from modules import paths_internal, errors
import json
import argparse
from modules.errors import log
# parse args, parse again after we have the data-dir and early-read the config file
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument("--ckpt", type=str, default=os.environ.get("SD_MODEL", None), help="Path to model checkpoint to load immediately, default: %(default)s")
parser.add_argument("--data-dir", type=str, default=os.environ.get("SD_DATADIR", ''), help="Base path where all user data is stored, default: %(default)s")
parser.add_argument("--models-dir", type=str, default=os.environ.get("SD_MODELSDIR", None), help="Base path where all models are stored, default: %(default)s",)
cli = parser.parse_known_args()[0]
parser.add_argument("--config", type=str, default=os.environ.get("SD_CONFIG", os.path.join(cli.data_dir, 'config.json')), help="Use specific server configuration file, default: %(default)s")
cli = parser.parse_known_args()[0]
config_path = cli.config if os.path.isabs(cli.config) else os.path.join(cli.data_dir, cli.config)
try:
with open(config_path, 'r', encoding='utf8') as f:
config = json.load(f)
except Exception as err:
print('Error loading config file: ${config_path} {err}')
config = {}
debug = errors.log.info if os.environ.get('SD_PATH_DEBUG', None) is not None else lambda *args, **kwargs: None
modules_path = os.path.dirname(os.path.realpath(__file__))
script_path = os.path.dirname(modules_path)
data_path = cli.data_dir
models_config = cli.models_dir or config.get('models_dir') or 'models'
models_path = models_config if os.path.isabs(models_config) else os.path.join(data_path, models_config)
extensions_dir = os.path.join(data_path, "extensions")
extensions_builtin_dir = "extensions-builtin"
sd_configs_path = os.path.join(script_path, "configs")
sd_default_config = os.path.join(sd_configs_path, "v1-inference.yaml")
sd_model_file = cli.ckpt or os.path.join(script_path, 'model.ckpt') # not used
default_sd_model_file = sd_model_file # not used
debug = log.info if os.environ.get('SD_PATH_DEBUG', None) is not None else lambda *args, **kwargs: None
if os.environ.get('SD_PATH_DEBUG', None) is not None:
print(f'Paths: script-path="{script_path}" data-dir="{data_path}" models-dir="{models_path}" config="{config_path}"')
"""
data_path = paths_internal.data_path
script_path = paths_internal.script_path
models_path = paths_internal.models_path
@@ -13,8 +47,8 @@ sd_model_file = paths_internal.sd_model_file
default_sd_model_file = paths_internal.default_sd_model_file
extensions_dir = paths_internal.extensions_dir
extensions_builtin_dir = paths_internal.extensions_builtin_dir
"""
# data_path = cmd_opts_pre.data
sys.path.insert(0, script_path)
sd_path = os.path.join(script_path, 'repositories')
@@ -31,25 +65,26 @@ paths = {}
for d, must_exist, what, _options in path_dirs:
must_exist_path = os.path.abspath(os.path.join(script_path, d, must_exist))
if not os.path.exists(must_exist_path):
errors.log.error(f'Required path not found: path={must_exist_path} item={what}')
log.error(f'Required path not found: path={must_exist_path} item={what}')
else:
d = os.path.abspath(d)
sys.path.append(d)
paths[what] = d
def create_paths(opts):
def create_path(folder):
if folder is None or folder == '':
return
if os.path.exists(folder):
return
try:
os.makedirs(folder, exist_ok=True)
errors.log.info(f'Create folder={folder}')
except Exception as e:
errors.log.error(f'Create Failed folder={folder} {e}')
def create_path(folder):
if folder is None or folder == '':
return
if os.path.exists(folder):
return
try:
os.makedirs(folder, exist_ok=True)
log.info(f'Create folder={folder}')
except Exception as e:
log.error(f'Create Failed folder={folder} {e}')
def create_paths(opts):
def fix_path(folder):
tgt = opts.data.get(folder, None) or opts.data_labels[folder].default
if tgt is None or tgt == '':
+14 -5
View File
@@ -1,5 +1,8 @@
"""this module defines internal paths used by program and is safe to import before dependencies are installed in launch.py"""
# no longer used, all paths are defined in paths.py
from modules.paths import modules_path, script_path, sd_configs_path, sd_default_config, sd_model_file, default_sd_model_file, data_path, models_path, extensions_dir, extensions_builtin_dir # pylint: disable=unused-import
"""
import argparse
import os
@@ -7,15 +10,21 @@ modules_path = os.path.dirname(os.path.realpath(__file__))
script_path = os.path.dirname(modules_path)
sd_configs_path = os.path.join(script_path, "configs")
sd_default_config = os.path.join(sd_configs_path, "v1-inference.yaml")
sd_model_file = os.path.join(script_path, 'model.ckpt')
default_sd_model_file = sd_model_file
# Parse the --data-dir flag first so we can use it as a base for our other argument default values
parser_pre = argparse.ArgumentParser(add_help=False)
parser_pre.add_argument("--data-dir", type=str, default="", help="base path where all user data is stored", )
parser_pre.add_argument("--models-dir", type=str, default="models", help="base path where all models are stored",)
parser_pre.add_argument("--ckpt", type=str, default=os.environ.get("SD_MODEL", None), help="Path to model checkpoint to load immediately, default: %(default)s")
parser_pre.add_argument("--data-dir", type=str, default=os.environ.get("SD_DATADIR", ''), help="Base path where all user data is stored, default: %(default)s")
parser_pre.add_argument("--models-dir", type=str, default=os.environ.get("SD_MODELSDIR", 'models'), help="Base path where all models are stored, default: %(default)s",)
cmd_opts_pre = parser_pre.parse_known_args()[0]
# parser_pre.add_argument("--config", type=str, default=os.environ.get("SD_CONFIG", os.path.join(data_path, 'config.json')), help="Use specific server configuration file, default: %(default)s")
data_path = cmd_opts_pre.data_dir
models_path = cmd_opts_pre.models_dir if os.path.isabs(cmd_opts_pre.models_dir) else os.path.join(data_path, cmd_opts_pre.models_dir)
extensions_dir = os.path.join(data_path, "extensions")
extensions_builtin_dir = "extensions-builtin"
sd_model_file = cmd_opts_pre.ckpt or os.path.join(script_path, 'model.ckpt') # not used
default_sd_model_file = sd_model_file # not used
"""
+1 -1
View File
@@ -24,7 +24,7 @@ from modules import paths, shared, shared_items, shared_state, modelloader, devi
from modules.sd_hijack_inpainting import do_inpainting_hijack
from modules.timer import Timer
from modules.memstats import memory_stats
from modules.paths_internal import models_path, script_path
from modules.paths import models_path, script_path
try:
import diffusers
+2 -2
View File
@@ -3,7 +3,7 @@ import collections
import glob
from copy import deepcopy
import torch
from modules import shared, paths, paths_internal, devices, script_callbacks, sd_models
from modules import shared, paths, devices, script_callbacks, sd_models
vae_ignore_keys = {"model_ema.decay", "model_ema.num_updates"}
@@ -200,7 +200,7 @@ def load_vae_diffusers(model_file, vae_file=None, vae_source="unknown-source"):
import diffusers
if os.path.isfile(vae_file):
_pipeline, model_type = sd_models.detect_pipeline(model_file, 'vae')
diffusers_load_config = { "config_file": paths_internal.sd_default_config if model_type != 'Stable Diffusion XL' else os.path.join(paths_internal.sd_configs_path, 'sd_xl_base.yaml')}
diffusers_load_config = { "config_file": paths.sd_default_config if model_type != 'Stable Diffusion XL' else os.path.join(paths.sd_configs_path, 'sd_xl_base.yaml')}
vae = diffusers.AutoencoderKL.from_single_file(vae_file, **diffusers_load_config)
vae = vae.to(devices.dtype_vae)
else:
+8 -4
View File
@@ -12,13 +12,13 @@ import gradio as gr
import fasteners
from rich.console import Console
from modules import errors, shared_items, shared_state, cmd_args, ui_components, theme
from modules.paths_internal import models_path, script_path, data_path, sd_configs_path, sd_default_config, sd_model_file, default_sd_model_file, extensions_dir, extensions_builtin_dir # pylint: disable=W0611
from modules.paths import models_path, script_path, data_path, sd_configs_path, sd_default_config, sd_model_file, default_sd_model_file, extensions_dir, extensions_builtin_dir # pylint: disable=W0611
from modules.dml import memory_providers, default_memory_provider, directml_do_hijack
import modules.interrogate
import modules.memmon
import modules.styles
import modules.devices as devices # pylint: disable=R0402
import modules.paths_internal as paths
import modules.paths as paths
from installer import print_dict
from installer import log as central_logger # pylint: disable=E0611
@@ -346,8 +346,8 @@ options_templates.update(options_section(('diffusers', "Diffusers Settings"), {
}))
options_templates.update(options_section(('system-paths', "System Paths"), {
"temp_dir": OptionInfo("", "Directory for temporary images; leave empty for default", folder=True),
"clean_temp_dir_at_start": OptionInfo(True, "Cleanup non-default temporary directory when starting webui"),
"models_paths_sep_options": OptionInfo("<h2>Models paths</h2>", "", gr.HTML),
"models_dir": OptionInfo('models', "Base path where all models are stored", folder=True),
"ckpt_dir": OptionInfo(os.path.join(paths.models_path, 'Stable-diffusion'), "Folder with stable diffusion models", folder=True),
"diffusers_dir": OptionInfo(os.path.join(paths.models_path, 'Diffusers'), "Folder with Hugggingface models", folder=True),
"vae_dir": OptionInfo(os.path.join(paths.models_path, 'VAE'), "Folder with VAE files", folder=True),
@@ -366,6 +366,10 @@ options_templates.update(options_section(('system-paths', "System Paths"), {
"swinir_models_path": OptionInfo(os.path.join(paths.models_path, 'SwinIR'), "Folder with SwinIR models", folder=True),
"ldsr_models_path": OptionInfo(os.path.join(paths.models_path, 'LDSR'), "Folder with LDSR models", folder=True),
"clip_models_path": OptionInfo(os.path.join(paths.models_path, 'CLIP'), "Folder with CLIP models", folder=True),
"other_paths_sep_options": OptionInfo("<h2>Other paths</h2>", "", gr.HTML),
"temp_dir": OptionInfo("", "Directory for temporary images; leave empty for default", folder=True),
"clean_temp_dir_at_start": OptionInfo(True, "Cleanup non-default temporary directory when starting webui"),
}))
options_templates.update(options_section(('saving-images', "Image Options"), {
+4 -4
View File
@@ -6,7 +6,7 @@ https://github.com/madebyollin/taesd
"""
import os
from PIL import Image
from modules import devices, paths_internal
from modules import devices, paths
from modules.taesd.taesd import TAESD
taesd_models = { 'sd-decoder': None, 'sd-encoder': None, 'sdxl-decoder': None, 'sdxl-encoder': None }
@@ -25,7 +25,7 @@ def download_model(model_path):
def model(model_class = 'sd', model_type = 'decoder'):
vae = taesd_models[f'{model_class}-{model_type}']
if vae is None:
model_path = os.path.join(paths_internal.models_path, "TAESD", f"tae{model_class}_{model_type}.pth")
model_path = os.path.join(paths.models_path, "TAESD", f"tae{model_class}_{model_type}.pth")
download_model(model_path)
if os.path.exists(model_path):
from modules.shared import log
@@ -52,7 +52,7 @@ def decode(latents):
return Image.new('RGB', (8, 8), color = (0, 0, 0))
vae = taesd_models[f'{model_class}-decoder']
if vae is None:
model_path = os.path.join(paths_internal.models_path, "TAESD", f"tae{model_class}_decoder.pth")
model_path = os.path.join(paths.models_path, "TAESD", f"tae{model_class}_decoder.pth")
download_model(model_path)
if os.path.exists(model_path):
taesd_models[f'{model_class}-decoder'] = TAESD(decoder_path=model_path, encoder_path=None)
@@ -73,7 +73,7 @@ def encode(image):
return Image.new('RGB', (8, 8), color = (0, 0, 0))
vae = taesd_models[f'{model_class}-encoder']
if vae is None:
model_path = os.path.join(paths_internal.models_path, "TAESD", f"tae{model_class}_encoder.pth")
model_path = os.path.join(paths.models_path, "TAESD", f"tae{model_class}_encoder.pth")
download_model(model_path)
if os.path.exists(model_path):
taesd_models[f'{model_class}-encoder'] = TAESD(encoder_path=model_path, decoder_path=None)