mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Branch for invokeai 3.0-beta bugfixes (#3683)
Model installer and documentation fixes for the beta branch.
This commit is contained in:
commit
e0a7ec6e95
@ -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 %*
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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():
|
||||||
|
@ -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='*')
|
||||||
|
@ -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):
|
||||||
|
@ -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())
|
||||||
|
@ -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)
|
||||||
|
@ -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()
|
||||||
|
@ -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)
|
||||||
|
@ -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 ######
|
||||||
|
@ -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."
|
||||||
)
|
)
|
||||||
|
199
invokeai/frontend/web/dist/assets/App-9a48e001.js
vendored
199
invokeai/frontend/web/dist/assets/App-9a48e001.js
vendored
File diff suppressed because one or more lines are too long
199
invokeai/frontend/web/dist/assets/App-a44d46fe.js
vendored
Normal file
199
invokeai/frontend/web/dist/assets/App-a44d46fe.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
invokeai/frontend/web/dist/assets/MantineProvider-8988d217.js
vendored
Normal file
1
invokeai/frontend/web/dist/assets/MantineProvider-8988d217.js
vendored
Normal file
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
125
invokeai/frontend/web/dist/assets/index-078526aa.js
vendored
Normal file
125
invokeai/frontend/web/dist/assets/index-078526aa.js
vendored
Normal file
File diff suppressed because one or more lines are too long
125
invokeai/frontend/web/dist/assets/index-581af3d4.js
vendored
125
invokeai/frontend/web/dist/assets/index-581af3d4.js
vendored
File diff suppressed because one or more lines are too long
2
invokeai/frontend/web/dist/index.html
vendored
2
invokeai/frontend/web/dist/index.html
vendored
@ -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">
|
||||||
|
12
invokeai/frontend/web/dist/locales/en.json
vendored
12
invokeai/frontend/web/dist/locales/en.json
vendored
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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",
|
||||||
|
@ -1 +1 @@
|
|||||||
__version__ = "3.0.0+b1"
|
__version__ = "3.0.0+b5"
|
||||||
|
Loading…
Reference in New Issue
Block a user