Branch for invokeai 3.0-beta bugfixes (#3683)

Model installer and documentation fixes for the beta branch.
This commit is contained in:
Lincoln Stein 2023-07-11 16:22:18 -04:00 committed by GitHub
commit e0a7ec6e95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 435 additions and 370 deletions

View File

@ -20,7 +20,7 @@ echo 9. Update InvokeAI
echo 10. Command-line help echo 10. Command-line help
echo Q - Quit echo Q - Quit
set /P choice="Please enter 1-10, Q: [2] " set /P choice="Please enter 1-10, Q: [2] "
if not defined choice set choice=2 if not defined choice set choice=1
IF /I "%choice%" == "1" ( IF /I "%choice%" == "1" (
echo Starting the InvokeAI browser-based UI.. echo Starting the InvokeAI browser-based UI..
python .venv\Scripts\invokeai-web.exe %* python .venv\Scripts\invokeai-web.exe %*
@ -56,7 +56,7 @@ IF /I "%choice%" == "1" (
call cmd /k call cmd /k
) ELSE IF /I "%choice%" == "9" ( ) ELSE IF /I "%choice%" == "9" (
echo Running invokeai-update... echo Running invokeai-update...
python .venv\Scripts\invokeai-update.exe %* python -m invokeai.frontend.install.invokeai_update
) ELSE IF /I "%choice%" == "10" ( ) ELSE IF /I "%choice%" == "10" (
echo Displaying command line help... echo Displaying command line help...
python .venv\Scripts\invokeai.exe --help %* python .venv\Scripts\invokeai.exe --help %*

View File

@ -93,7 +93,7 @@ do_choice() {
9) 9)
clear clear
printf "Update InvokeAI\n" printf "Update InvokeAI\n"
invokeai-update python -m invokeai.frontend.install.invokeai_update
;; ;;
10) 10)
clear clear

View File

@ -17,6 +17,7 @@ from invokeai.app.services.metadata import CoreMetadataService
from invokeai.app.services.resource_name import SimpleNameService from invokeai.app.services.resource_name import SimpleNameService
from invokeai.app.services.urls import LocalUrlService from invokeai.app.services.urls import LocalUrlService
from invokeai.backend.util.logging import InvokeAILogger from invokeai.backend.util.logging import InvokeAILogger
from invokeai.version.invokeai_version import __version__
from ..services.default_graphs import create_system_graphs from ..services.default_graphs import create_system_graphs
from ..services.latent_storage import DiskLatentsStorage, ForwardCacheLatentsStorage from ..services.latent_storage import DiskLatentsStorage, ForwardCacheLatentsStorage
@ -58,7 +59,8 @@ class ApiDependencies:
@staticmethod @staticmethod
def initialize(config, event_handler_id: int, logger: Logger = logger): def initialize(config, event_handler_id: int, logger: Logger = logger):
logger.info(f"Internet connectivity is {config.internet_available}") logger.debug(f'InvokeAI version {__version__}')
logger.debug(f"Internet connectivity is {config.internet_available}")
events = FastAPIEventService(event_handler_id) events = FastAPIEventService(event_handler_id)

View File

@ -1,5 +1,6 @@
# Copyright (c) 2022 Kyle Schouviller (https://github.com/kyle0654) # Copyright (c) 2022-2023 Kyle Schouviller (https://github.com/kyle0654) and the InvokeAI Team
import asyncio import asyncio
import sys
from inspect import signature from inspect import signature
import uvicorn import uvicorn
@ -20,6 +21,13 @@ from ..backend.util.logging import InvokeAILogger
app_config = InvokeAIAppConfig.get_config() app_config = InvokeAIAppConfig.get_config()
app_config.parse_args() app_config.parse_args()
logger = InvokeAILogger.getLogger(config=app_config) logger = InvokeAILogger.getLogger(config=app_config)
from invokeai.version.invokeai_version import __version__
# we call this early so that the message appears before
# other invokeai initialization messages
if app_config.version:
print(f'InvokeAI version {__version__}')
sys.exit(0)
import invokeai.frontend.web as web_dir import invokeai.frontend.web as web_dir
import mimetypes import mimetypes
@ -28,6 +36,7 @@ from .api.dependencies import ApiDependencies
from .api.routers import sessions, models, images, boards, board_images, app_info from .api.routers import sessions, models, images, boards, board_images, app_info
from .api.sockets import SocketIO from .api.sockets import SocketIO
from .invocations.baseinvocation import BaseInvocation from .invocations.baseinvocation import BaseInvocation
import torch import torch
if torch.backends.mps.is_available(): if torch.backends.mps.is_available():

View File

@ -16,6 +16,12 @@ from invokeai.backend.util.logging import InvokeAILogger
config = InvokeAIAppConfig.get_config() config = InvokeAIAppConfig.get_config()
config.parse_args() config.parse_args()
logger = InvokeAILogger().getLogger(config=config) logger = InvokeAILogger().getLogger(config=config)
from invokeai.version.invokeai_version import __version__
# we call this early so that the message appears before other invokeai initialization messages
if config.version:
print(f'InvokeAI version {__version__}')
sys.exit(0)
from invokeai.app.services.board_image_record_storage import ( from invokeai.app.services.board_image_record_storage import (
SqliteBoardImageRecordStorage, SqliteBoardImageRecordStorage,
@ -208,6 +214,7 @@ def invoke_all(context: CliContext):
raise SessionError() raise SessionError()
def invoke_cli(): def invoke_cli():
logger.info(f'InvokeAI version {__version__}')
# get the optional list of invocations to execute on the command line # get the optional list of invocations to execute on the command line
parser = config.get_parser() parser = config.get_parser()
parser.add_argument('commands',nargs='*') parser.add_argument('commands',nargs='*')

View File

@ -23,7 +23,8 @@ InvokeAI:
xformers_enabled: false xformers_enabled: false
sequential_guidance: false sequential_guidance: false
precision: float16 precision: float16
max_loaded_models: 4 max_cache_size: 6
max_vram_cache_size: 2.7
always_use_cpu: false always_use_cpu: false
free_gpu_mem: false free_gpu_mem: false
Features: Features:
@ -168,7 +169,7 @@ from argparse import ArgumentParser
from omegaconf import OmegaConf, DictConfig from omegaconf import OmegaConf, DictConfig
from pathlib import Path from pathlib import Path
from pydantic import BaseSettings, Field, parse_obj_as from pydantic import BaseSettings, Field, parse_obj_as
from typing import ClassVar, Dict, List, Literal, Union, get_origin, get_type_hints, get_args from typing import ClassVar, Dict, List, Set, Literal, Union, get_origin, get_type_hints, get_args
INIT_FILE = Path('invokeai.yaml') INIT_FILE = Path('invokeai.yaml')
MODEL_CORE = Path('models/core') MODEL_CORE = Path('models/core')
@ -270,7 +271,8 @@ class InvokeAISettings(BaseSettings):
@classmethod @classmethod
def _excluded(self)->List[str]: def _excluded(self)->List[str]:
return ['type','initconf'] # combination of deprecated parameters and internal ones
return ['type','initconf', 'gpu_mem_reserved', 'max_loaded_models', 'version']
class Config: class Config:
env_file_encoding = 'utf-8' env_file_encoding = 'utf-8'
@ -363,8 +365,10 @@ setting environment variables INVOKEAI_<setting>.
always_use_cpu : bool = Field(default=False, description="If true, use the CPU for rendering even if a GPU is available.", category='Memory/Performance') always_use_cpu : bool = Field(default=False, description="If true, use the CPU for rendering even if a GPU is available.", category='Memory/Performance')
free_gpu_mem : bool = Field(default=False, description="If true, purge model from GPU after each generation.", category='Memory/Performance') free_gpu_mem : bool = Field(default=False, description="If true, purge model from GPU after each generation.", category='Memory/Performance')
max_loaded_models : int = Field(default=3, gt=0, description="(DEPRECATED: use max_cache_size) Maximum number of models to keep in memory for rapid switching", category='Memory/Performance') max_loaded_models : int = Field(default=3, gt=0, description="(DEPRECATED: use max_cache_size) Maximum number of models to keep in memory for rapid switching", category='DEPRECATED')
max_cache_size : float = Field(default=6.0, gt=0, description="Maximum memory amount used by model cache for rapid switching", category='Memory/Performance') max_cache_size : float = Field(default=6.0, gt=0, description="Maximum memory amount used by model cache for rapid switching", category='Memory/Performance')
max_vram_cache_size : float = Field(default=2.75, ge=0, description="Amount of VRAM reserved for model storage", category='Memory/Performance')
gpu_mem_reserved : float = Field(default=2.75, ge=0, description="DEPRECATED: use max_vram_cache_size. Amount of VRAM reserved for model storage", category='DEPRECATED')
precision : Literal[tuple(['auto','float16','float32','autocast'])] = Field(default='float16',description='Floating point precision', category='Memory/Performance') precision : Literal[tuple(['auto','float16','float32','autocast'])] = Field(default='float16',description='Floating point precision', category='Memory/Performance')
sequential_guidance : bool = Field(default=False, description="Whether to calculate guidance in serial instead of in parallel, lowering memory requirements", category='Memory/Performance') sequential_guidance : bool = Field(default=False, description="Whether to calculate guidance in serial instead of in parallel, lowering memory requirements", category='Memory/Performance')
xformers_enabled : bool = Field(default=True, description="Enable/disable memory-efficient attention", category='Memory/Performance') xformers_enabled : bool = Field(default=True, description="Enable/disable memory-efficient attention", category='Memory/Performance')
@ -389,6 +393,8 @@ setting environment variables INVOKEAI_<setting>.
# note - would be better to read the log_format values from logging.py, but this creates circular dependencies issues # note - would be better to read the log_format values from logging.py, but this creates circular dependencies issues
log_format : Literal[tuple(['plain','color','syslog','legacy'])] = Field(default="color", description='Log format. Use "plain" for text-only, "color" for colorized output, "legacy" for 2.3-style logging and "syslog" for syslog-style', category="Logging") log_format : Literal[tuple(['plain','color','syslog','legacy'])] = Field(default="color", description='Log format. Use "plain" for text-only, "color" for colorized output, "legacy" for 2.3-style logging and "syslog" for syslog-style', category="Logging")
log_level : Literal[tuple(["debug","info","warning","error","critical"])] = Field(default="debug", description="Emit logging messages at this level or higher", category="Logging") log_level : Literal[tuple(["debug","info","warning","error","critical"])] = Field(default="debug", description="Emit logging messages at this level or higher", category="Logging")
version : bool = Field(default=False, description="Show InvokeAI version and exit", category="Other")
#fmt: on #fmt: on
def parse_args(self, argv: List[str]=None, conf: DictConfig = None, clobber=False): def parse_args(self, argv: List[str]=None, conf: DictConfig = None, clobber=False):

View File

@ -258,9 +258,7 @@ class ModelManagerService(ModelManagerServiceBase):
config_file = config.model_conf_path config_file = config.model_conf_path
else: else:
config_file = config.root_dir / "configs/models.yaml" config_file = config.root_dir / "configs/models.yaml"
if not config_file.exists():
raise IOError(f"The file {config_file} could not be found.")
logger.debug(f'config file={config_file}') logger.debug(f'config file={config_file}')
device = torch.device(choose_torch_device()) device = torch.device(choose_torch_device())

View File

@ -104,6 +104,7 @@ class DefaultInvocationProcessor(InvocationProcessorABC):
except Exception as e: except Exception as e:
error = traceback.format_exc() error = traceback.format_exc()
logger.error(error)
# Save error # Save error
graph_execution_state.set_node_error(invocation.id, error) graph_execution_state.set_node_error(invocation.id, error)

View File

@ -36,6 +36,9 @@ from .models import BaseModelType, ModelType, SubModelType, ModelBase
# Default is roughly enough to hold three fp16 diffusers models in RAM simultaneously # Default is roughly enough to hold three fp16 diffusers models in RAM simultaneously
DEFAULT_MAX_CACHE_SIZE = 6.0 DEFAULT_MAX_CACHE_SIZE = 6.0
# amount of GPU memory to hold in reserve for use by generations (GB)
DEFAULT_MAX_VRAM_CACHE_SIZE= 2.75
# actual size of a gig # actual size of a gig
GIG = 1073741824 GIG = 1073741824
@ -82,6 +85,7 @@ class ModelCache(object):
def __init__( def __init__(
self, self,
max_cache_size: float=DEFAULT_MAX_CACHE_SIZE, max_cache_size: float=DEFAULT_MAX_CACHE_SIZE,
max_vram_cache_size: float=DEFAULT_MAX_VRAM_CACHE_SIZE,
execution_device: torch.device=torch.device('cuda'), execution_device: torch.device=torch.device('cuda'),
storage_device: torch.device=torch.device('cpu'), storage_device: torch.device=torch.device('cpu'),
precision: torch.dtype=torch.float16, precision: torch.dtype=torch.float16,
@ -99,12 +103,11 @@ class ModelCache(object):
:param sequential_offload: Conserve VRAM by loading and unloading each stage of the pipeline sequentially :param sequential_offload: Conserve VRAM by loading and unloading each stage of the pipeline sequentially
:param sha_chunksize: Chunksize to use when calculating sha256 model hash :param sha_chunksize: Chunksize to use when calculating sha256 model hash
''' '''
#max_cache_size = 9999
self.model_infos: Dict[str, ModelBase] = dict() self.model_infos: Dict[str, ModelBase] = dict()
self.lazy_offloading = lazy_offloading self.lazy_offloading = lazy_offloading
#self.sequential_offload: bool=sequential_offload
self.precision: torch.dtype=precision self.precision: torch.dtype=precision
self.max_cache_size: int=max_cache_size self.max_cache_size: float=max_cache_size
self.max_vram_cache_size: float=max_vram_cache_size
self.execution_device: torch.device=execution_device self.execution_device: torch.device=execution_device
self.storage_device: torch.device=storage_device self.storage_device: torch.device=storage_device
self.sha_chunksize=sha_chunksize self.sha_chunksize=sha_chunksize
@ -201,14 +204,22 @@ class ModelCache(object):
self._cache_stack.remove(key) self._cache_stack.remove(key)
self._cache_stack.append(key) self._cache_stack.append(key)
return self.ModelLocker(self, key, cache_entry.model, gpu_load) return self.ModelLocker(self, key, cache_entry.model, gpu_load, cache_entry.size)
class ModelLocker(object): class ModelLocker(object):
def __init__(self, cache, key, model, gpu_load): def __init__(self, cache, key, model, gpu_load, size_needed):
'''
:param cache: The model_cache object
:param key: The key of the model to lock in GPU
:param model: The model to lock
:param gpu_load: True if load into gpu
:param size_needed: Size of the model to load
'''
self.gpu_load = gpu_load self.gpu_load = gpu_load
self.cache = cache self.cache = cache
self.key = key self.key = key
self.model = model self.model = model
self.size_needed = size_needed
self.cache_entry = self.cache._cached_models[self.key] self.cache_entry = self.cache._cached_models[self.key]
def __enter__(self) -> Any: def __enter__(self) -> Any:
@ -222,7 +233,7 @@ class ModelCache(object):
try: try:
if self.cache.lazy_offloading: if self.cache.lazy_offloading:
self.cache._offload_unlocked_models() self.cache._offload_unlocked_models(self.size_needed)
if self.model.device != self.cache.execution_device: if self.model.device != self.cache.execution_device:
self.cache.logger.debug(f'Moving {self.key} into {self.cache.execution_device}') self.cache.logger.debug(f'Moving {self.key} into {self.cache.execution_device}')
@ -337,14 +348,20 @@ class ModelCache(object):
self.logger.debug(f"After unloading: cached_models={len(self._cached_models)}") self.logger.debug(f"After unloading: cached_models={len(self._cached_models)}")
def _offload_unlocked_models(self, size_needed: int=0):
def _offload_unlocked_models(self): reserved = self.max_vram_cache_size * GIG
for model_key, cache_entry in self._cached_models.items(): vram_in_use = torch.cuda.memory_allocated()
self.logger.debug(f'{(vram_in_use/GIG):.2f}GB VRAM used for models; max allowed={(reserved/GIG):.2f}GB')
for model_key, cache_entry in sorted(self._cached_models.items(), key=lambda x:x[1].size):
if vram_in_use <= reserved:
break
if not cache_entry.locked and cache_entry.loaded: if not cache_entry.locked and cache_entry.loaded:
self.logger.debug(f'Offloading {model_key} from {self.execution_device} into {self.storage_device}') self.logger.debug(f'Offloading {model_key} from {self.execution_device} into {self.storage_device}')
with VRAMUsage() as mem: with VRAMUsage() as mem:
cache_entry.model.to(self.storage_device) cache_entry.model.to(self.storage_device)
self.logger.debug(f'GPU VRAM freed: {(mem.vram_used/GIG):.2f} GB') self.logger.debug(f'GPU VRAM freed: {(mem.vram_used/GIG):.2f} GB')
vram_in_use += mem.vram_used # note vram_used is negative
self.logger.debug(f'{(vram_in_use/GIG):.2f}GB VRAM used for models; max allowed={(reserved/GIG):.2f}GB')
def _local_model_hash(self, model_path: Union[str, Path]) -> str: def _local_model_hash(self, model_path: Union[str, Path]) -> str:
sha = hashlib.sha256() sha = hashlib.sha256()

View File

@ -231,6 +231,7 @@ from __future__ import annotations
import os import os
import hashlib import hashlib
import textwrap import textwrap
import yaml
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import Optional, List, Tuple, Union, Dict, Set, Callable, types from typing import Optional, List, Tuple, Union, Dict, Set, Callable, types
@ -314,6 +315,9 @@ class ModelManager(object):
self.config_path = None self.config_path = None
if isinstance(config, (str, Path)): if isinstance(config, (str, Path)):
self.config_path = Path(config) self.config_path = Path(config)
if not self.config_path.exists():
logger.warning(f'The file {self.config_path} was not found. Initializing a new file')
self.initialize_model_config(self.config_path)
config = OmegaConf.load(self.config_path) config = OmegaConf.load(self.config_path)
elif not isinstance(config, DictConfig): elif not isinstance(config, DictConfig):
@ -336,6 +340,7 @@ class ModelManager(object):
self.logger = logger self.logger = logger
self.cache = ModelCache( self.cache = ModelCache(
max_cache_size=max_cache_size, max_cache_size=max_cache_size,
max_vram_cache_size = self.app_config.max_vram_cache_size,
execution_device = device_type, execution_device = device_type,
precision = precision, precision = precision,
sequential_offload = sequential_offload, sequential_offload = sequential_offload,
@ -386,6 +391,16 @@ class ModelManager(object):
def _get_model_cache_path(self, model_path): def _get_model_cache_path(self, model_path):
return self.app_config.models_path / ".cache" / hashlib.md5(str(model_path).encode()).hexdigest() return self.app_config.models_path / ".cache" / hashlib.md5(str(model_path).encode()).hexdigest()
@classmethod
def initialize_model_config(cls, config_path: Path):
"""Create empty config file"""
with open(config_path,'w') as yaml_file:
yaml_file.write(yaml.dump({'__metadata__':
{'version':'3.0.0'}
}
)
)
def get_model( def get_model(
self, self,
model_name: str, model_name: str,
@ -853,16 +868,22 @@ class ModelManager(object):
scanned_dirs.add(path) scanned_dirs.add(path)
continue continue
if any([(path/x).exists() for x in {'config.json','model_index.json','learned_embeds.bin','pytorch_lora_weights.bin'}]): if any([(path/x).exists() for x in {'config.json','model_index.json','learned_embeds.bin','pytorch_lora_weights.bin'}]):
new_models_found.update(installer.heuristic_import(path)) try:
scanned_dirs.add(path) new_models_found.update(installer.heuristic_import(path))
scanned_dirs.add(path)
except ValueError as e:
self.logger.warning(str(e))
for f in files: for f in files:
path = Path(root) / f path = Path(root) / f
if path in known_paths or path.parent in scanned_dirs: if path in known_paths or path.parent in scanned_dirs:
continue continue
if path.suffix in {'.ckpt','.bin','.pth','.safetensors','.pt'}: if path.suffix in {'.ckpt','.bin','.pth','.safetensors','.pt'}:
import_result = installer.heuristic_import(path) try:
new_models_found.update(import_result) import_result = installer.heuristic_import(path)
new_models_found.update(import_result)
except ValueError as e:
self.logger.warning(str(e))
self.logger.info(f'Scanned {items_scanned} files and directories, imported {len(new_models_found)} models') self.logger.info(f'Scanned {items_scanned} files and directories, imported {len(new_models_found)} models')
installed.update(new_models_found) installed.update(new_models_found)

View File

@ -59,7 +59,7 @@ class ModelProbe(object):
elif isinstance(model,(dict,ModelMixin,ConfigMixin)): elif isinstance(model,(dict,ModelMixin,ConfigMixin)):
return cls.probe(model_path=None, model=model, prediction_type_helper=prediction_type_helper) return cls.probe(model_path=None, model=model, prediction_type_helper=prediction_type_helper)
else: else:
raise Exception("model parameter {model} is neither a Path, nor a model") raise ValueError("model parameter {model} is neither a Path, nor a model")
@classmethod @classmethod
def probe(cls, def probe(cls,
@ -237,7 +237,7 @@ class CheckpointProbeBase(ProbeBase):
elif in_channels == 4: elif in_channels == 4:
return ModelVariantType.Normal return ModelVariantType.Normal
else: else:
raise Exception("Cannot determine variant type") raise ValueError(f"Cannot determine variant type (in_channels={in_channels}) at {self.checkpoint_path}")
class PipelineCheckpointProbe(CheckpointProbeBase): class PipelineCheckpointProbe(CheckpointProbeBase):
def get_base_type(self)->BaseModelType: def get_base_type(self)->BaseModelType:
@ -248,7 +248,7 @@ class PipelineCheckpointProbe(CheckpointProbeBase):
return BaseModelType.StableDiffusion1 return BaseModelType.StableDiffusion1
if key_name in state_dict and state_dict[key_name].shape[-1] == 1024: if key_name in state_dict and state_dict[key_name].shape[-1] == 1024:
return BaseModelType.StableDiffusion2 return BaseModelType.StableDiffusion2
raise Exception("Cannot determine base type") raise ValueError("Cannot determine base type")
def get_scheduler_prediction_type(self)->SchedulerPredictionType: def get_scheduler_prediction_type(self)->SchedulerPredictionType:
type = self.get_base_type() type = self.get_base_type()
@ -329,7 +329,7 @@ class ControlNetCheckpointProbe(CheckpointProbeBase):
return BaseModelType.StableDiffusion2 return BaseModelType.StableDiffusion2
elif self.checkpoint_path and self.helper: elif self.checkpoint_path and self.helper:
return self.helper(self.checkpoint_path) return self.helper(self.checkpoint_path)
raise Exception("Unable to determine base type for {self.checkpoint_path}") raise ValueError("Unable to determine base type for {self.checkpoint_path}")
######################################################## ########################################################
# classes for probing folders # classes for probing folders
@ -418,7 +418,7 @@ class ControlNetFolderProbe(FolderProbeBase):
def get_base_type(self)->BaseModelType: def get_base_type(self)->BaseModelType:
config_file = self.folder_path / 'config.json' config_file = self.folder_path / 'config.json'
if not config_file.exists(): if not config_file.exists():
raise Exception(f"Cannot determine base type for {self.folder_path}") raise ValueError(f"Cannot determine base type for {self.folder_path}")
with open(config_file,'r') as file: with open(config_file,'r') as file:
config = json.load(file) config = json.load(file)
# no obvious way to distinguish between sd2-base and sd2-768 # no obvious way to distinguish between sd2-base and sd2-768
@ -435,7 +435,7 @@ class LoRAFolderProbe(FolderProbeBase):
model_file = base_file model_file = base_file
break break
if not model_file: if not model_file:
raise Exception('Unknown LoRA format encountered') raise ValueError('Unknown LoRA format encountered')
return LoRACheckpointProbe(model_file,None).get_base_type() return LoRACheckpointProbe(model_file,None).get_base_type()
############## register probe classes ###### ############## register probe classes ######

View File

@ -773,7 +773,7 @@ def main():
config.parse_args(invoke_args) config.parse_args(invoke_args)
logger = InvokeAILogger().getLogger(config=config) logger = InvokeAILogger().getLogger(config=config)
if not (config.root_dir / config.conf_path.parent).exists(): if not (config.conf_path / 'models.yaml').exists():
logger.info( logger.info(
"Your InvokeAI root directory is not set up. Calling invokeai-configure." "Your InvokeAI root directory is not set up. Calling invokeai-configure."
) )

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -12,7 +12,7 @@
margin: 0; margin: 0;
} }
</style> </style>
<script type="module" crossorigin src="./assets/index-581af3d4.js"></script> <script type="module" crossorigin src="./assets/index-078526aa.js"></script>
</head> </head>
<body dir="ltr"> <body dir="ltr">

View File

@ -53,7 +53,7 @@
"linear": "Linear", "linear": "Linear",
"nodes": "Node Editor", "nodes": "Node Editor",
"batch": "Batch Manager", "batch": "Batch Manager",
"modelmanager": "Model Manager", "modelManager": "Model Manager",
"postprocessing": "Post Processing", "postprocessing": "Post Processing",
"nodesDesc": "A node based system for the generation of images is under development currently. Stay tuned for updates about this amazing feature.", "nodesDesc": "A node based system for the generation of images is under development currently. Stay tuned for updates about this amazing feature.",
"postProcessing": "Post Processing", "postProcessing": "Post Processing",
@ -527,7 +527,9 @@
"showOptionsPanel": "Show Options Panel", "showOptionsPanel": "Show Options Panel",
"hidePreview": "Hide Preview", "hidePreview": "Hide Preview",
"showPreview": "Show Preview", "showPreview": "Show Preview",
"controlNetControlMode": "Control Mode" "controlNetControlMode": "Control Mode",
"clipSkip": "Clip Skip",
"aspectRatio": "Ratio"
}, },
"settings": { "settings": {
"models": "Models", "models": "Models",
@ -551,7 +553,8 @@
"generation": "Generation", "generation": "Generation",
"ui": "User Interface", "ui": "User Interface",
"favoriteSchedulers": "Favorite Schedulers", "favoriteSchedulers": "Favorite Schedulers",
"favoriteSchedulersPlaceholder": "No schedulers favorited" "favoriteSchedulersPlaceholder": "No schedulers favorited",
"showAdvancedOptions": "Show Advanced Options"
}, },
"toast": { "toast": {
"serverError": "Server Error", "serverError": "Server Error",
@ -669,6 +672,7 @@
}, },
"ui": { "ui": {
"showProgressImages": "Show Progress Images", "showProgressImages": "Show Progress Images",
"hideProgressImages": "Hide Progress Images" "hideProgressImages": "Hide Progress Images",
"swapSizes": "Swap Sizes"
} }
} }

View File

@ -53,7 +53,7 @@
"linear": "Linear", "linear": "Linear",
"nodes": "Node Editor", "nodes": "Node Editor",
"batch": "Batch Manager", "batch": "Batch Manager",
"modelmanager": "Model Manager", "modelManager": "Model Manager",
"postprocessing": "Post Processing", "postprocessing": "Post Processing",
"nodesDesc": "A node based system for the generation of images is under development currently. Stay tuned for updates about this amazing feature.", "nodesDesc": "A node based system for the generation of images is under development currently. Stay tuned for updates about this amazing feature.",
"postProcessing": "Post Processing", "postProcessing": "Post Processing",

View File

@ -1 +1 @@
__version__ = "3.0.0+b1" __version__ = "3.0.0+b5"