From 8a31e5c5e3dd7be361fdd984170fd1bac801712a Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Tue, 17 Jan 2023 00:18:09 -0500 Subject: [PATCH 01/24] allow safetensors models to be imported --- ldm/invoke/CLI.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ldm/invoke/CLI.py b/ldm/invoke/CLI.py index cfe9a64ed5..83b5281847 100644 --- a/ldm/invoke/CLI.py +++ b/ldm/invoke/CLI.py @@ -572,7 +572,7 @@ def import_model(model_path:str, gen, opt, completer): if model_path.startswith(('http:','https:','ftp:')): model_name = import_ckpt_model(model_path, gen, opt, completer) - elif os.path.exists(model_path) and model_path.endswith('.ckpt') and os.path.isfile(model_path): + elif os.path.exists(model_path) and model_path.endswith(('.ckpt','.safetensors')) and os.path.isfile(model_path): model_name = import_ckpt_model(model_path, gen, opt, completer) elif re.match('^[\w.+-]+/[\w.+-]+$',model_path): model_name = import_diffuser_model(model_path, gen, opt, completer) @@ -628,9 +628,9 @@ def import_ckpt_model(path_or_url:str, gen, opt, completer)->str: model_description=default_description ) config_file = None - + default = Path(Globals.root,'configs/stable-diffusion/v1-inference.yaml') completer.complete_extensions(('.yaml','.yml')) - completer.set_line('configs/stable-diffusion/v1-inference.yaml') + completer.set_line(str(default)) done = False while not done: config_file = input('Configuration file for this model: ').strip() From fc2098834d51f673eabdc58e311cff4e6e6bfe3e Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Tue, 17 Jan 2023 08:11:19 -0500 Subject: [PATCH 02/24] support direct loading of .safetensors models - Small fix to allow ckpt files with the .safetensors suffix to be directly loaded, rather than undergo a conversion step first. --- ldm/invoke/model_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ldm/invoke/model_manager.py b/ldm/invoke/model_manager.py index 880d75476f..eeb2208c91 100644 --- a/ldm/invoke/model_manager.py +++ b/ldm/invoke/model_manager.py @@ -142,7 +142,7 @@ class ModelManager(object): Return true if this is a legacy (.ckpt) model ''' info = self.model_info(model_name) - if 'weights' in info and info['weights'].endswith('.ckpt'): + if 'weights' in info and info['weights'].endswith(('.ckpt','.safetensors')): return True return False From 0b5c0c374e235b160238d36c6ba30d150df81d1a Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Tue, 17 Jan 2023 22:51:57 -0500 Subject: [PATCH 03/24] load safetensors vaes --- ldm/invoke/model_manager.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ldm/invoke/model_manager.py b/ldm/invoke/model_manager.py index eeb2208c91..9b0d21546a 100644 --- a/ldm/invoke/model_manager.py +++ b/ldm/invoke/model_manager.py @@ -359,7 +359,9 @@ class ModelManager(object): vae = os.path.normpath(os.path.join(Globals.root,vae)) if os.path.exists(vae): print(f' | Loading VAE weights from: {vae}') - vae_ckpt = torch.load(vae, map_location="cpu") + vae_ckpt = safetensors.torch.load_file(vae) \ + if vae.endswith('.safetensors') \ + else torch.load(vae, map_location="cpu") vae_dict = {k: v for k, v in vae_ckpt["state_dict"].items() if k[0:4] != "loss"} model.first_stage_model.load_state_dict(vae_dict, strict=False) else: From a7b207410662d9efe2ea19bc6304820c5ff08ecb Mon Sep 17 00:00:00 2001 From: Daya Adianto Date: Wed, 18 Jan 2023 18:50:08 +0700 Subject: [PATCH 04/24] =?UTF-8?q?Ignore=20free=5Fgpu=5Fmem=20when=20using?= =?UTF-8?q?=20=F0=9F=A4=97=20diffuser=20model=20(#2326)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ldm/generate.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ldm/generate.py b/ldm/generate.py index 63eaf79b50..9f19f1aefe 100644 --- a/ldm/generate.py +++ b/ldm/generate.py @@ -460,10 +460,13 @@ class Generate: init_image = None mask_image = None - - if self.free_gpu_mem and self.model.cond_stage_model.device != self.model.device: - self.model.cond_stage_model.device = self.model.device - self.model.cond_stage_model.to(self.model.device) + try: + if self.free_gpu_mem and self.model.cond_stage_model.device != self.model.device: + self.model.cond_stage_model.device = self.model.device + self.model.cond_stage_model.to(self.model.device) + except AttributeError: + print(">> Warning: '--free_gpu_mem' is not yet supported when generating image using model based on HuggingFace Diffuser.") + pass try: uc, c, extra_conditioning_info = get_uc_and_c_and_ec( From c1521be4451aa620a14ff60394f65619ea0978e7 Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Wed, 18 Jan 2023 09:31:19 -0500 Subject: [PATCH 05/24] add instructions for installing xFormers on linux --- docs/index.md | 12 +- docs/installation/070_INSTALL_XFORMERS.md | 140 ++++++++++++++++++++++ 2 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 docs/installation/070_INSTALL_XFORMERS.md diff --git a/docs/index.md b/docs/index.md index 3c5bd3904b..c38f840d32 100644 --- a/docs/index.md +++ b/docs/index.md @@ -93,9 +93,15 @@ getting InvokeAI up and running on your system. For alternative installation and upgrade instructions, please see: [InvokeAI Installation Overview](installation/) -Linux users who wish to make use of the PyPatchMatch inpainting functions will -need to perform a bit of extra work to enable this module. Instructions can be -found at [Installing PyPatchMatch](installation/060_INSTALL_PATCHMATCH.md). +Users who wish to make use of the **PyPatchMatch** inpainting functions +will need to perform a bit of extra work to enable this +module. Instructions can be found at [Installing +PyPatchMatch](installation/060_INSTALL_PATCHMATCH.md). + +If you have an NVIDIA card, you can benefit from the significant +memory savings and performance benefits provided by Facebook Lab's +**xFormers** module. Instructions for Linux and Windows users can be found +at [Installing xFormers](installation/070_INSTALL_XFORMERS.md). ## :fontawesome-solid-computer: Hardware Requirements diff --git a/docs/installation/070_INSTALL_XFORMERS.md b/docs/installation/070_INSTALL_XFORMERS.md new file mode 100644 index 0000000000..a406c28c22 --- /dev/null +++ b/docs/installation/070_INSTALL_XFORMERS.md @@ -0,0 +1,140 @@ +--- +title: Installing xFormers +--- + +# :material-image-size-select-large: Installing xformers + +xFormers is toolbox that integrates with the pyTorch and CUDA +libraries to provide accelerated performance and reduced memory +consumption for applications using the transformers machine learning +architecture. After installing xFormers, InvokeAI users who have +CUDA GPUs will see a noticeable decrease in GPU memory consumption and +an increase in speed. + +xFormers can be installed into a working InvokeAI installation without +any code changes or other updates. This document explains how to +install xFormers. + +## Linux + +Note that xFormers only works with true NVIDIA GPUs and will not work +properly with the ROCm driver for AMD acceleration. + +xFormers is not currently available as a pip binary wheel and must be +installed from source. These instructions were written for a system +running Ubuntu 22.04, but other Linux distributions should be able to +adapt this recipe. + +### 1. Install CUDA Toolkit 11.7 + +You will need the CUDA developer's toolkit in order to compile and +install xFormers. **Do not try to install Ubuntu's nvidia-cuda-toolkit +package.** It is out of date and will cause conflicts among the NVIDIA +driver and binaries. Instead install the CUDA Toolkit package provided +by NVIDIA itself. Go to [CUDA Toolkit 11.7 +Downloads](https://developer.nvidia.com/cuda-11-7-0-download-archive) +and use the target selection wizard to choose your platform and Linux +distribution. Select an installer type of "runfile (local)" at the +last step. + +This will provide you with a recipe for downloading and running a +install shell script that will install the toolkit and drivers. For +example, the install script recipe for Ubuntu 22.04 running on a +x86_64 system is: + +``` +wget https://developer.download.nvidia.com/compute/cuda/11.7.0/local_installers/cuda_11.7.0_515.43.04_linux.run +sudo sh cuda_11.7.0_515.43.04_linux.run +``` + +Rather than cut-and-paste this example, We recommend that you walk +through the toolkit wizard in order to get the most up to date +installer for your system. + +### 2. Confirm/Install pyTorch 1.13 with CUDA 11.7 support + +If you are using InvokeAI 2.3 or higher, these will already be +installed. If not, you can check whether you have the needed libraries +using a quick command. Activate the invokeai virtual environment, +either by entering the "developer's console", or manually with a +command similar to `source ~/invokeai/.venv/bin/activate` (depending +on where your `invokeai` directory is. + +Then run the command: + +```sh +python -c 'exec("import torch\nprint(torch.__version__)")' +``` + +If it prints __1.13.1+cu117__ you're good. If not, you can install the +most up to date libraries with this command: + +```sh +pip install --upgrade --force-reinstall torch torchvision +``` + +### 3. Install source code build prerequisites + +To build xFormers from source, you will need the `build-essentials` +package. If you don't have it installed already, run: + +```sh +sudo apt install build-essential +``` + +### 4. Build xFormers + +There is no pip wheel package for xFormers at this time (January +2023). Although there is a conda package, InvokeAI no longer +officially supports conda installations and you're on your own if you +wish to try this route. + +Following the recipe provided at the [xFormers GitHub +page](https://github.com/facebookresearch/xformers), and with the +InvokeAI virtual environment active (see step 1) run the following +commands: + +```sh +pip install ninja +export TORCH_CUDA_ARCH_LIST="6.0;6.1;6.2;7.0;7.2;7.5;8.0;8.6" +pip install -v -U git+https://github.com/facebookresearch/xformers.git@main#egg=xformers +``` + +The TORCH_CUDA_ARCH_LIST is a list of GPU architectures to compile +xFormer support for. You can speed up compilation by selecting +the architecture specific for your system. You'll find the list of +GPUs and their architectures at NVIDIA's [GPU Compute +Capability](https://developer.nvidia.com/cuda-gpus) table. + +If the compile and install completes successfully, you can check that +xFormers is installed with this command: + +```sh +python -m xformers.info +``` + +If suiccessful, the top of the listing should indicate "available" for +each of the `memory_efficient_attention` modules, as shown here: + +```sh +memory_efficient_attention.cutlassF: available +memory_efficient_attention.cutlassB: available +memory_efficient_attention.flshattF: available +memory_efficient_attention.flshattB: available +memory_efficient_attention.smallkF: available +memory_efficient_attention.smallkB: available +memory_efficient_attention.tritonflashattF: available +memory_efficient_attention.tritonflashattB: available +[...] +``` + +You can now launch InvokeAI and enjoy the benefits of xFormers. + +## Windows + +To come + +## Macintosh + +Since CUDA is unavailable on Macintosh systems, you will not benefit +from xFormers. From 1c62ae461e410c9c933571351cbae2e719cf3c68 Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Wed, 18 Jan 2023 12:15:57 -0500 Subject: [PATCH 06/24] fix vae safetensor loading --- ldm/invoke/model_manager.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ldm/invoke/model_manager.py b/ldm/invoke/model_manager.py index 8aeeda650a..671e00aacd 100644 --- a/ldm/invoke/model_manager.py +++ b/ldm/invoke/model_manager.py @@ -359,10 +359,14 @@ class ModelManager(object): vae = os.path.normpath(os.path.join(Globals.root,vae)) if os.path.exists(vae): print(f' | Loading VAE weights from: {vae}') - vae_ckpt = safetensors.torch.load_file(vae) \ - if vae.endswith('.safetensors') \ - else torch.load(vae, map_location="cpu") - vae_dict = {k: v for k, v in vae_ckpt["state_dict"].items() if k[0:4] != "loss"} + vae_ckpt = None + vae_dict = None + if vae.endswith('.safetensors'): + vae_ckpt = safetensors.torch.load_file(vae) + vae_dict = {k: v for k, v in vae_ckpt.items() if k[0:4] != "loss"} + else: + vae_ckpt = torch.load(vae, map_location="cpu") + vae_dict = {k: v for k, v in vae_ckpt['state_dict'].items() if k[0:4] != "loss"} model.first_stage_model.load_state_dict(vae_dict, strict=False) else: print(f' | VAE file {vae} not found. Skipping.') From 5a40aadbee2a0ffb7b14bf9f05a7e1b66d72d62d Mon Sep 17 00:00:00 2001 From: Daya Adianto Date: Wed, 18 Jan 2023 23:23:18 +0700 Subject: [PATCH 07/24] Ensure free_gpu_mem option is passed into the generator (#2326) --- ldm/generate.py | 3 ++- ldm/invoke/ckpt_generator/base.py | 2 ++ ldm/invoke/generator/base.py | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ldm/generate.py b/ldm/generate.py index 9f19f1aefe..83cdc6b852 100644 --- a/ldm/generate.py +++ b/ldm/generate.py @@ -146,7 +146,7 @@ class Generate: gfpgan=None, codeformer=None, esrgan=None, - free_gpu_mem=False, + free_gpu_mem: bool=False, safety_checker:bool=False, max_loaded_models:int=2, # these are deprecated; if present they override values in the conf file @@ -534,6 +534,7 @@ class Generate: inpaint_height = inpaint_height, inpaint_width = inpaint_width, enable_image_debugging = enable_image_debugging, + free_gpu_mem=self.free_gpu_mem, ) if init_color: diff --git a/ldm/invoke/ckpt_generator/base.py b/ldm/invoke/ckpt_generator/base.py index c84550a6e3..9d137b74d6 100644 --- a/ldm/invoke/ckpt_generator/base.py +++ b/ldm/invoke/ckpt_generator/base.py @@ -56,9 +56,11 @@ class CkptGenerator(): image_callback=None, step_callback=None, threshold=0.0, perlin=0.0, safety_checker:dict=None, attention_maps_callback = None, + free_gpu_mem: bool=False, **kwargs): scope = choose_autocast(self.precision) self.safety_checker = safety_checker + self.free_gpu_mem = free_gpu_mem attention_maps_images = [] attention_maps_callback = lambda saver: attention_maps_images.append(saver.get_stacked_maps_image()) make_image = self.get_make_image( diff --git a/ldm/invoke/generator/base.py b/ldm/invoke/generator/base.py index 3fd34765c6..a17badd022 100644 --- a/ldm/invoke/generator/base.py +++ b/ldm/invoke/generator/base.py @@ -62,9 +62,11 @@ class Generator: def generate(self,prompt,init_image,width,height,sampler, iterations=1,seed=None, image_callback=None, step_callback=None, threshold=0.0, perlin=0.0, safety_checker:dict=None, + free_gpu_mem: bool=False, **kwargs): scope = nullcontext self.safety_checker = safety_checker + self.free_gpu_mem = free_gpu_mem attention_maps_images = [] attention_maps_callback = lambda saver: attention_maps_images.append(saver.get_stacked_maps_image()) make_image = self.get_make_image( From 284b432ffd4d53a3ff313758d7e4bc978f4e74ba Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Wed, 18 Jan 2023 22:34:36 -0500 Subject: [PATCH 08/24] add triton install instructions --- docs/installation/070_INSTALL_XFORMERS.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/docs/installation/070_INSTALL_XFORMERS.md b/docs/installation/070_INSTALL_XFORMERS.md index a406c28c22..99138744f8 100644 --- a/docs/installation/070_INSTALL_XFORMERS.md +++ b/docs/installation/070_INSTALL_XFORMERS.md @@ -73,7 +73,16 @@ most up to date libraries with this command: pip install --upgrade --force-reinstall torch torchvision ``` -### 3. Install source code build prerequisites +### 3. Install the triton module + +This module isn't necessary for xFormers image inference optimization, +but avoids a startup warning. + +```sh +pip install triton +``` + +### 4. Install source code build prerequisites To build xFormers from source, you will need the `build-essentials` package. If you don't have it installed already, run: @@ -82,7 +91,7 @@ package. If you don't have it installed already, run: sudo apt install build-essential ``` -### 4. Build xFormers +### 5. Build xFormers There is no pip wheel package for xFormers at this time (January 2023). Although there is a conda package, InvokeAI no longer From 3c3d893b9d17b4360acbab3ac1f179847065b4d7 Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Thu, 19 Jan 2023 15:43:52 -0500 Subject: [PATCH 09/24] improve status reporting when loading local and remote embeddings - During trigger token processing, emit better status messages indicating which triggers were found. - Suppress message " is not known to HuggingFace library, when token is in fact a local embed. --- ldm/generate.py | 6 +++++- ldm/invoke/concepts_lib.py | 10 +++++++++- ldm/modules/textual_inversion_manager.py | 6 +++++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/ldm/generate.py b/ldm/generate.py index 63eaf79b50..ad40b5f564 100644 --- a/ldm/generate.py +++ b/ldm/generate.py @@ -445,7 +445,11 @@ class Generate: self._set_sampler() # apply the concepts library to the prompt - prompt = self.huggingface_concepts_library.replace_concepts_with_triggers(prompt, lambda concepts: self.load_huggingface_concepts(concepts)) + prompt = self.huggingface_concepts_library.replace_concepts_with_triggers( + prompt, + lambda concepts: self.load_huggingface_concepts(concepts), + self.model.textual_inversion_manager.get_all_trigger_strings() + ) # bit of a hack to change the cached sampler's karras threshold to # whatever the user asked for diff --git a/ldm/invoke/concepts_lib.py b/ldm/invoke/concepts_lib.py index 246dea362a..0d4f2e296d 100644 --- a/ldm/invoke/concepts_lib.py +++ b/ldm/invoke/concepts_lib.py @@ -115,13 +115,19 @@ class HuggingFaceConceptsLibrary(object): return self.trigger_to_concept(match.group(1)) or f'<{match.group(1)}>' return self.match_trigger.sub(do_replace, prompt) - def replace_concepts_with_triggers(self, prompt:str, load_concepts_callback: Callable[[list], any])->str: + def replace_concepts_with_triggers(self, + prompt:str, + load_concepts_callback: Callable[[list], any], + excluded_tokens:list[str])->str: ''' Given a prompt string that contains `` tags, replace these tags with the appropriate trigger. If any `` tags are found, `load_concepts_callback()` is called with a list of `concepts_name` strings. + + `excluded_tokens` are any tokens that should not be replaced, typically because they + are trigger tokens from a locally-loaded embedding. ''' concepts = self.match_concept.findall(prompt) if not concepts: @@ -129,6 +135,8 @@ class HuggingFaceConceptsLibrary(object): load_concepts_callback(concepts) def do_replace(match)->str: + if excluded_tokens and f'<{match.group(1)}>' in excluded_tokens: + return f'<{match.group(1)}>' return self.concept_to_trigger(match.group(1)) or f'<{match.group(1)}>' return self.match_concept.sub(do_replace, prompt) diff --git a/ldm/modules/textual_inversion_manager.py b/ldm/modules/textual_inversion_manager.py index f7ced79a52..dcb77d6098 100644 --- a/ldm/modules/textual_inversion_manager.py +++ b/ldm/modules/textual_inversion_manager.py @@ -38,11 +38,15 @@ class TextualInversionManager(): if concept_name in self.hf_concepts_library.concepts_loaded: continue trigger = self.hf_concepts_library.concept_to_trigger(concept_name) - if self.has_textual_inversion_for_trigger_string(trigger): + if self.has_textual_inversion_for_trigger_string(trigger) \ + or self.has_textual_inversion_for_trigger_string(concept_name) \ + or self.has_textual_inversion_for_trigger_string(f'<{concept_name}>'): # in case a token with literal angle brackets encountered + print(f'>> Loaded local embedding for trigger {concept_name}') continue bin_file = self.hf_concepts_library.get_concept_model_path(concept_name) if not bin_file: continue + print(f'>> Loaded remote embedding for trigger {concept_name}') self.load_textual_inversion(bin_file) self.hf_concepts_library.concepts_loaded[concept_name]=True From 775e1a21c7a7095f6abb35e8858a34cb9786a2fe Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Thu, 19 Jan 2023 15:46:58 -0500 Subject: [PATCH 10/24] improve embed trigger token not found error - Now indicates that the trigger is *neither* a huggingface concept, nor the trigger of a locally loaded embed. --- ldm/invoke/concepts_lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ldm/invoke/concepts_lib.py b/ldm/invoke/concepts_lib.py index 0d4f2e296d..c774f29674 100644 --- a/ldm/invoke/concepts_lib.py +++ b/ldm/invoke/concepts_lib.py @@ -59,7 +59,7 @@ class HuggingFaceConceptsLibrary(object): be downloaded. ''' if not concept_name in self.list_concepts(): - print(f'This concept is not known to the Hugging Face library. Generation will continue without the concept.') + print(f'This concept is not a local embedding trigger, nor is it a HuggingFace concept. Generation will continue without the concept.') return None return self.get_concept_file(concept_name.lower(),'learned_embeds.bin') From da81165a4bef30afed96afdbd060637566b9509b Mon Sep 17 00:00:00 2001 From: michaelk71 Date: Fri, 20 Jan 2023 19:03:12 +0100 Subject: [PATCH 11/24] Update index.md --- docs/installation/index.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/installation/index.md b/docs/installation/index.md index ef50cbab5f..51753f2c9b 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -18,7 +18,9 @@ experience and preferences. InvokeAI and its dependencies. We offer two recipes: one suited to those who prefer the `conda` tool, and one suited to those who prefer `pip` and Python virtual environments. In our hands the pip install - is faster and more reliable, but your mileage may vary. + is faster and more reliable, but your mileage may vary. + Note that the conda installation method is currently deprecated and + will not be supported at some point in the future. This method is recommended for users who have previously used `conda` or `pip` in the past, developers, and anyone who wishes to remain on From a1c0818a081bab8aace84c0ee7ecbcf27bf2ea46 Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Fri, 20 Jan 2023 17:13:32 -0500 Subject: [PATCH 12/24] ignore .DS_Store files when scanning Mac embeddings --- ldm/modules/textual_inversion_manager.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ldm/modules/textual_inversion_manager.py b/ldm/modules/textual_inversion_manager.py index dcb77d6098..cf28cf8c7a 100644 --- a/ldm/modules/textual_inversion_manager.py +++ b/ldm/modules/textual_inversion_manager.py @@ -54,6 +54,8 @@ class TextualInversionManager(): return [ti.trigger_string for ti in self.textual_inversions] def load_textual_inversion(self, ckpt_path, defer_injecting_tokens: bool=False): + if str(ckpt_path).endswith('.DS_Store'): + return try: scan_result = scan_file_path(ckpt_path) if scan_result.infected_files == 1: From 9b73292fcb5f3b2fa6eed50b118d75f328e7eed6 Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Fri, 20 Jan 2023 17:28:14 -0500 Subject: [PATCH 13/24] add pip install documentation for xformers --- docs/installation/070_INSTALL_XFORMERS.md | 77 ++++++++++++++++++++--- 1 file changed, 67 insertions(+), 10 deletions(-) diff --git a/docs/installation/070_INSTALL_XFORMERS.md b/docs/installation/070_INSTALL_XFORMERS.md index 99138744f8..be54a3ee86 100644 --- a/docs/installation/070_INSTALL_XFORMERS.md +++ b/docs/installation/070_INSTALL_XFORMERS.md @@ -15,7 +15,65 @@ xFormers can be installed into a working InvokeAI installation without any code changes or other updates. This document explains how to install xFormers. -## Linux +## Pip Install + +For both Windows and Linux, you can install `xformers` in just a +couple of steps from the command line. + +If you are used to launching `invoke.sh` or `invoke.bat` to start +InvokeAI, then run the launcher and select the "developer's console" +to get to the command line. If you run invoke.py directly from the +command line, then just be sure to activate it's virtual environment. + +Then run the following three commands: + +```sh +pip install xformers==0.0.16rc425 +pip install triton +python -m xformers.info output +``` + +The first command installs `xformers`, the second installs the +`triton` training accelerator, and the third prints out the `xformers` +installation status. If all goes well, you'll see a report like the +following: + +```sh +xFormers 0.0.16rc425 +memory_efficient_attention.cutlassF: available +memory_efficient_attention.cutlassB: available +memory_efficient_attention.flshattF: available +memory_efficient_attention.flshattB: available +memory_efficient_attention.smallkF: available +memory_efficient_attention.smallkB: available +memory_efficient_attention.tritonflashattF: available +memory_efficient_attention.tritonflashattB: available +swiglu.fused.p.cpp: available +is_triton_available: True +is_functorch_available: False +pytorch.version: 1.13.1+cu117 +pytorch.cuda: available +gpu.compute_capability: 8.6 +gpu.name: NVIDIA RTX A2000 12GB +build.info: available +build.cuda_version: 1107 +build.python_version: 3.10.9 +build.torch_version: 1.13.1+cu117 +build.env.TORCH_CUDA_ARCH_LIST: 5.0+PTX 6.0 6.1 7.0 7.5 8.0 8.6 +build.env.XFORMERS_BUILD_TYPE: Release +build.env.XFORMERS_ENABLE_DEBUG_ASSERTIONS: None +build.env.NVCC_FLAGS: None +build.env.XFORMERS_PACKAGE_FROM: wheel-v0.0.16rc425 +source.privacy: open source +``` + +## Source Builds + +`xformers` is currently under active development and at some point you +may wish to build it from sourcce to get the latest features and +bugfixes. + +### Source Build on Linux Note that xFormers only works with true NVIDIA GPUs and will not work properly with the ROCm driver for AMD acceleration. @@ -25,7 +83,7 @@ installed from source. These instructions were written for a system running Ubuntu 22.04, but other Linux distributions should be able to adapt this recipe. -### 1. Install CUDA Toolkit 11.7 +#### 1. Install CUDA Toolkit 11.7 You will need the CUDA developer's toolkit in order to compile and install xFormers. **Do not try to install Ubuntu's nvidia-cuda-toolkit @@ -51,7 +109,7 @@ Rather than cut-and-paste this example, We recommend that you walk through the toolkit wizard in order to get the most up to date installer for your system. -### 2. Confirm/Install pyTorch 1.13 with CUDA 11.7 support +#### 2. Confirm/Install pyTorch 1.13 with CUDA 11.7 support If you are using InvokeAI 2.3 or higher, these will already be installed. If not, you can check whether you have the needed libraries @@ -73,7 +131,7 @@ most up to date libraries with this command: pip install --upgrade --force-reinstall torch torchvision ``` -### 3. Install the triton module +#### 3. Install the triton module This module isn't necessary for xFormers image inference optimization, but avoids a startup warning. @@ -82,7 +140,7 @@ but avoids a startup warning. pip install triton ``` -### 4. Install source code build prerequisites +#### 4. Install source code build prerequisites To build xFormers from source, you will need the `build-essentials` package. If you don't have it installed already, run: @@ -91,7 +149,7 @@ package. If you don't have it installed already, run: sudo apt install build-essential ``` -### 5. Build xFormers +#### 5. Build xFormers There is no pip wheel package for xFormers at this time (January 2023). Although there is a conda package, InvokeAI no longer @@ -139,11 +197,10 @@ memory_efficient_attention.tritonflashattB: available You can now launch InvokeAI and enjoy the benefits of xFormers. -## Windows +### Windows To come -## Macintosh -Since CUDA is unavailable on Macintosh systems, you will not benefit -from xFormers. +--- +(c) Copyright 2023 Lincoln Stein and the InvokeAI Development Team From d35ec3398d8255f5621ec29f8c0eb0ec8a7c3129 Mon Sep 17 00:00:00 2001 From: Kevin Turner <83819+keturn@users.noreply.github.com> Date: Fri, 20 Jan 2023 19:23:12 -0800 Subject: [PATCH 14/24] fix: use pad_token for padding Stable Diffusion does not use the eos_token for padding. --- ldm/modules/encoders/modules.py | 18 ++++++++---------- ldm/modules/prompt_to_embeddings_converter.py | 11 ++++++----- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/ldm/modules/encoders/modules.py b/ldm/modules/encoders/modules.py index aafb1299ad..6715b229f1 100644 --- a/ldm/modules/encoders/modules.py +++ b/ldm/modules/encoders/modules.py @@ -1,18 +1,16 @@ import math -import os.path +from functools import partial from typing import Optional +import clip +import kornia import torch import torch.nn as nn -from functools import partial -import clip -from einops import rearrange, repeat +from einops import repeat from transformers import CLIPTokenizer, CLIPTextModel -import kornia -from ldm.invoke.devices import choose_torch_device -from ldm.invoke.globals import Globals, global_cache_dir -#from ldm.modules.textual_inversion_manager import TextualInversionManager +from ldm.invoke.devices import choose_torch_device +from ldm.invoke.globals import global_cache_dir from ldm.modules.x_transformer import ( Encoder, TransformerWrapper, @@ -663,12 +661,12 @@ class WeightedFrozenCLIPEmbedder(FrozenCLIPEmbedder): all_token_ids = all_token_ids[0:self.max_length] per_token_weights = per_token_weights[0:self.max_length] - # pad out to a 77-entry array: [eos_token, , eos_token, ..., eos_token] + # pad out to a 77-entry array: [bos_token, , eos_token, pad_token…] # (77 = self.max_length) all_token_ids = [self.tokenizer.bos_token_id] + all_token_ids + [self.tokenizer.eos_token_id] per_token_weights = [1.0] + per_token_weights + [1.0] pad_length = self.max_length - len(all_token_ids) - all_token_ids += [self.tokenizer.eos_token_id] * pad_length + all_token_ids += [self.tokenizer.pad_token_id] * pad_length per_token_weights += [1.0] * pad_length all_token_ids_tensor = torch.tensor(all_token_ids, dtype=torch.long).to(self.device) diff --git a/ldm/modules/prompt_to_embeddings_converter.py b/ldm/modules/prompt_to_embeddings_converter.py index ab989e4892..dea15d61b4 100644 --- a/ldm/modules/prompt_to_embeddings_converter.py +++ b/ldm/modules/prompt_to_embeddings_converter.py @@ -3,8 +3,9 @@ import math import torch from transformers import CLIPTokenizer, CLIPTextModel -from ldm.modules.textual_inversion_manager import TextualInversionManager from ldm.invoke.devices import torch_dtype +from ldm.modules.textual_inversion_manager import TextualInversionManager + class WeightedPromptFragmentsToEmbeddingsConverter(): @@ -22,8 +23,8 @@ class WeightedPromptFragmentsToEmbeddingsConverter(): return self.tokenizer.model_max_length def get_embeddings_for_weighted_prompt_fragments(self, - text: list[str], - fragment_weights: list[float], + text: list[list[str]], + fragment_weights: list[list[float]], should_return_tokens: bool = False, device='cpu' ) -> torch.Tensor: @@ -198,12 +199,12 @@ class WeightedPromptFragmentsToEmbeddingsConverter(): all_token_ids = all_token_ids[0:max_token_count_without_bos_eos_markers] per_token_weights = per_token_weights[0:max_token_count_without_bos_eos_markers] - # pad out to a self.max_length-entry array: [eos_token, , eos_token, ..., eos_token] + # pad out to a self.max_length-entry array: [bos_token, , eos_token, pad_token…] # (typically self.max_length == 77) all_token_ids = [self.tokenizer.bos_token_id] + all_token_ids + [self.tokenizer.eos_token_id] per_token_weights = [1.0] + per_token_weights + [1.0] pad_length = self.max_length - len(all_token_ids) - all_token_ids += [self.tokenizer.eos_token_id] * pad_length + all_token_ids += [self.tokenizer.pad_token_id] * pad_length per_token_weights += [1.0] * pad_length all_token_ids_tensor = torch.tensor(all_token_ids, dtype=torch.long, device=device) From e94c8fa285da208fc042ad16ebcb8303d19dc345 Mon Sep 17 00:00:00 2001 From: Damian Stewart Date: Sat, 21 Jan 2023 12:06:23 +0100 Subject: [PATCH 15/24] fix long prompt weighting bug in ckpt codepath --- ldm/modules/encoders/modules.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ldm/modules/encoders/modules.py b/ldm/modules/encoders/modules.py index aafb1299ad..5b5f71cffd 100644 --- a/ldm/modules/encoders/modules.py +++ b/ldm/modules/encoders/modules.py @@ -654,14 +654,15 @@ class WeightedFrozenCLIPEmbedder(FrozenCLIPEmbedder): per_token_weights += [weight] * len(this_fragment_token_ids) # leave room for bos/eos - if len(all_token_ids) > self.max_length - 2: - excess_token_count = len(all_token_ids) - self.max_length - 2 + max_token_count_without_bos_eos_markers = self.max_length - 2 + if len(all_token_ids) > max_token_count_without_bos_eos_markers: + excess_token_count = len(all_token_ids) - max_token_count_without_bos_eos_markers # TODO build nice description string of how the truncation was applied # this should be done by calling self.tokenizer.convert_ids_to_tokens() then passing the result to # self.tokenizer.convert_tokens_to_string() for the token_ids on each side of the truncation limit. print(f">> Prompt is {excess_token_count} token(s) too long and has been truncated") - all_token_ids = all_token_ids[0:self.max_length] - per_token_weights = per_token_weights[0:self.max_length] + all_token_ids = all_token_ids[0:max_token_count_without_bos_eos_markers] + per_token_weights = per_token_weights[0:max_token_count_without_bos_eos_markers] # pad out to a 77-entry array: [eos_token, , eos_token, ..., eos_token] # (77 = self.max_length) From 4ee8d104f07ea519959d18075dd8ebb597cdb44c Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Sat, 21 Jan 2023 18:39:13 -0500 Subject: [PATCH 16/24] working, but needs diffusers PR to be accepted --- scripts/merge_fe.py | 111 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 100 insertions(+), 11 deletions(-) mode change 100644 => 100755 scripts/merge_fe.py diff --git a/scripts/merge_fe.py b/scripts/merge_fe.py old mode 100644 new mode 100755 index df01235599..4f24961a18 --- a/scripts/merge_fe.py +++ b/scripts/merge_fe.py @@ -3,15 +3,17 @@ import npyscreen import os import sys -import re -import shutil import traceback import argparse -from ldm.invoke.globals import Globals, global_set_root +import safetensors.torch +from ldm.invoke.globals import Globals, global_set_root, global_cache_dir +from ldm.invoke.model_manager import ModelManager from omegaconf import OmegaConf from pathlib import Path from typing import List +CONFIG_FILE = None + class FloatSlider(npyscreen.Slider): # this is supposed to adjust display precision, but doesn't def translate_value(self): @@ -30,6 +32,14 @@ class mergeModelsForm(npyscreen.FormMultiPageAction): 'inv_sigmoid', 'add_difference'] + def __init__(self, parentApp, name): + self.parentApp = parentApp + super().__init__(parentApp, name) + + @property + def model_manager(self): + return self.parentApp.model_manager + def afterEditing(self): self.parentApp.setNextForm(None) @@ -83,6 +93,11 @@ class mergeModelsForm(npyscreen.FormMultiPageAction): lowest=0, value=0.5, ) + self.force = self.add_widget_intelligent( + npyscreen.Checkbox, + name='Force merge of incompatible models', + value=False, + ) self.merged_model_name = self.add_widget_intelligent( npyscreen.TitleText, name='Name for merged model', @@ -108,17 +123,44 @@ class mergeModelsForm(npyscreen.FormMultiPageAction): if self.validate_field_values(): self.parentApp.setNextForm(None) self.editing = False + self.parentApp.merge_arguments = self.marshall_arguments() + npyscreen.notify('Starting the merge...') + import diffusers # this keeps the message up while diffusers loads else: self.editing = True def ok_cancel(self): sys.exit(0) + def marshall_arguments(self)->dict: + model_names = self.model_names + models = [ + model_names[self.model1.value[0]], + model_names[self.model2.value[0]], + ] + if self.model3.value[0] > 0: + models.append(model_names[self.model3.value[0]-1]) + + models = [self.model_manager.model_name_or_path(x) for x in models] + + args = dict( + pretrained_model_name_or_path_list=models, + alpha = self.alpha.value, + interp = self.interpolations[self.merge_method.value[0]], + force = self.force.value, + cache_dir = global_cache_dir('diffusers'), + merged_model_name = self.merged_model_name.value, + ) + return args + def validate_field_values(self)->bool: bad_fields = [] - selected_models = set((self.model1.value[0],self.model2.value[0],self.model3.value[0])) - if len(selected_models) < 3: - bad_fields.append('Please select two or three DIFFERENT models to compare') + model_names = self.model_names + selected_models = set((model_names[self.model1.value[0]],model_names[self.model2.value[0]])) + if self.model3.value[0] > 0: + selected_models.add(model_names[self.model3.value[0]-1]) + if len(selected_models) < 2: + bad_fields.append(f'Please select two or three DIFFERENT models to compare. You selected {selected_models}') if len(bad_fields) > 0: message = 'The following problems were detected and must be corrected:' for problem in bad_fields: @@ -129,13 +171,15 @@ class mergeModelsForm(npyscreen.FormMultiPageAction): return True def get_model_names(self)->List[str]: - conf = OmegaConf.load(os.path.join(Globals.root,'configs/models.yaml')) - model_names = [name for name in conf.keys() if conf[name].get('format',None)=='diffusers'] + model_names = [name for name in self.model_manager.model_names() if self.model_manager.model_info(name).get('format') == 'diffusers'] + print(model_names) return sorted(model_names) -class MyApplication(npyscreen.NPSAppManaged): +class Mergeapp(npyscreen.NPSAppManaged): def __init__(self): super().__init__() + conf = OmegaConf.load(Path(Globals.root) / 'configs' / 'models.yaml') + self.model_manager = ModelManager(conf,'cpu','float16') # precision doesn't really matter here def onStart(self): npyscreen.setTheme(npyscreen.Themes.DefaultTheme) @@ -151,6 +195,51 @@ if __name__ == '__main__': ) args = parser.parse_args() global_set_root(args.root_dir) + + CONFIG_FILE = os.path.join(Globals.root,'configs/models.yaml') + os.environ['HF_HOME'] = str(global_cache_dir('diffusers')) + + mergeapp = Mergeapp() + mergeapp.run() + from diffusers import DiffusionPipeline + args = mergeapp.merge_arguments + merged_model_name = args['merged_model_name'] + merged_pipe = None + print(args) + + try: + print(f'DEBUG: {args["pretrained_model_name_or_path_list"][0]}') + pipe = DiffusionPipeline.from_pretrained(args['pretrained_model_name_or_path_list'][0], + custom_pipeline='checkpoint_merger' + ) + merged_pipe = pipe.merge(**args) + dump_path = Path(Globals.root) / 'models' / 'merged_diffusers' + os.makedirs(dump_path,exist_ok=True) + dump_path = dump_path / merged_model_name + merged_pipe.save_pretrained ( + dump_path, + safe_serialization=1 + ) + except Exception as e: + print(f'** An error occurred while merging the pipelines: {str(e)}') + print('** DETAILS:') + print(traceback.format_exc()) + sys.exit(-1) + + print(f'>> Merged model is saved to {dump_path}') + response = input('Import this model into InvokeAI? [y]').strip() or 'y' + if response.startswith(('y','Y')): + try: + mergeapp.model_manager.import_diffuser_model( + dump_path, + model_name = merged_model_name, + description = f'Merge of models {args["pretrained_model_name_or_path_list"]}' + ) + mergeapp.model_manager.commit(CONFIG_FILE) + print('>> Merged model imported.') + except Exception as e: + print(f'** New model could not be committed to config.yaml: {str(e)}') + print('** DETAILS:') + print(traceback.format_exc()) + - myapplication = MyApplication() - myapplication.run() From 6c31225d195ad185e48c165fa8558e3724646a92 Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Sun, 22 Jan 2023 18:07:53 -0500 Subject: [PATCH 17/24] create small module for merge importation logic --- ldm/invoke/globals.py | 4 ++ ldm/invoke/merge_diffusers.py | 59 ++++++++++++++++++++++++++++ ldm/invoke/model_manager.py | 8 +++- scripts/load_models.py | 0 scripts/merge_embeddings.py | 0 scripts/merge_fe.py | 72 +++++++++++------------------------ 6 files changed, 91 insertions(+), 52 deletions(-) create mode 100644 ldm/invoke/merge_diffusers.py mode change 100644 => 100755 scripts/load_models.py mode change 100644 => 100755 scripts/merge_embeddings.py diff --git a/ldm/invoke/globals.py b/ldm/invoke/globals.py index 5bd5597b78..538ff17703 100644 --- a/ldm/invoke/globals.py +++ b/ldm/invoke/globals.py @@ -29,6 +29,7 @@ else: # Where to look for the initialization file Globals.initfile = 'invokeai.init' +Globals.models_file = 'models.yaml' Globals.models_dir = 'models' Globals.config_dir = 'configs' Globals.autoscan_dir = 'weights' @@ -49,6 +50,9 @@ Globals.disable_xformers = False # whether we are forcing full precision Globals.full_precision = False +def global_config_file()->Path: + return Path(Globals.root, Globals.config_dir, Globals.models_file) + def global_config_dir()->Path: return Path(Globals.root, Globals.config_dir) diff --git a/ldm/invoke/merge_diffusers.py b/ldm/invoke/merge_diffusers.py new file mode 100644 index 0000000000..6a1d742aee --- /dev/null +++ b/ldm/invoke/merge_diffusers.py @@ -0,0 +1,59 @@ +''' +ldm.invoke.merge_diffusers exports a single function call merge_diffusion_models() +used to merge 2-3 models together and create a new InvokeAI-registered diffusion model. +''' +import os +from typing import List +from diffusers import DiffusionPipeline +from ldm.invoke.globals import global_config_file, global_models_dir, global_cache_dir +from ldm.invoke.model_manager import ModelManager +from omegaconf import OmegaConf + +def merge_diffusion_models(models:List['str'], + merged_model_name:str, + alpha:float=0.5, + interp:str=None, + force:bool=False, + **kwargs): + ''' + models - up to three models, designated by their InvokeAI models.yaml model name + merged_model_name = name for new model + alpha - The interpolation parameter. Ranges from 0 to 1. It affects the ratio in which the checkpoints are merged. A 0.8 alpha + would mean that the first model checkpoints would affect the final result far less than an alpha of 0.2 + interp - The interpolation method to use for the merging. Supports "sigmoid", "inv_sigmoid", "add_difference" and None. + Passing None uses the default interpolation which is weighted sum interpolation. For merging three checkpoints, only "add_difference" is supported. + force - Whether to ignore mismatch in model_config.json for the current models. Defaults to False. + + **kwargs - the default DiffusionPipeline.get_config_dict kwargs: + cache_dir, resume_download, force_download, proxies, local_files_only, use_auth_token, revision, torch_dtype, device_map + ''' + config_file = global_config_file() + model_manager = ModelManager(OmegaConf.load(config_file)) + model_ids_or_paths = [model_manager.model_name_or_path(x) for x in models] + + pipe = DiffusionPipeline.from_pretrained(model_ids_or_paths[0], + cache_dir=kwargs.get('cache_dir',global_cache_dir()), + custom_pipeline='checkpoint_merger') + merged_pipe = pipe.merge(pretrained_model_name_or_path_list=model_ids_or_paths, + alpha=alpha, + interp=interp, + force=force, + **kwargs) + dump_path = global_models_dir() / 'merged_diffusers' + os.makedirs(dump_path,exist_ok=True) + dump_path = dump_path / merged_model_name + merged_pipe.save_pretrained ( + dump_path, + safe_serialization=1 + ) + model_manager.import_diffuser_model( + dump_path, + model_name = merged_model_name, + description = f'Merge of models {", ".join(models)}' + ) + print('REMINDER: When PR 2369 is merged, replace merge_diffusers.py line 56 with vae= argument to impormodel()') + if vae := model_manager.config[models[0]].get('vae',None): + print(f'>> Using configured VAE assigned to {models[0]}') + model_manager.config[merged_model_name]['vae'] = vae + + model_manager.commit(config_file) diff --git a/ldm/invoke/model_manager.py b/ldm/invoke/model_manager.py index a5f9a47d41..650a497ad5 100644 --- a/ldm/invoke/model_manager.py +++ b/ldm/invoke/model_manager.py @@ -37,7 +37,11 @@ from ldm.util import instantiate_from_config, ask_user DEFAULT_MAX_MODELS=2 class ModelManager(object): - def __init__(self, config:OmegaConf, device_type:str, precision:str, max_loaded_models=DEFAULT_MAX_MODELS): + def __init__(self, + config:OmegaConf, + device_type:str='cpu', + precision:str='float16', + max_loaded_models=DEFAULT_MAX_MODELS): ''' Initialize with the path to the models.yaml config file, the torch device type, and precision. The optional @@ -536,7 +540,7 @@ class ModelManager(object): format='diffusers', ) if isinstance(repo_or_path,Path) and repo_or_path.exists(): - new_config.update(path=repo_or_path) + new_config.update(path=str(repo_or_path)) else: new_config.update(repo_id=repo_or_path) diff --git a/scripts/load_models.py b/scripts/load_models.py old mode 100644 new mode 100755 diff --git a/scripts/merge_embeddings.py b/scripts/merge_embeddings.py old mode 100644 new mode 100755 diff --git a/scripts/merge_fe.py b/scripts/merge_fe.py index 4f24961a18..a15e4440e5 100755 --- a/scripts/merge_fe.py +++ b/scripts/merge_fe.py @@ -5,15 +5,12 @@ import os import sys import traceback import argparse -import safetensors.torch -from ldm.invoke.globals import Globals, global_set_root, global_cache_dir +from ldm.invoke.globals import Globals, global_set_root, global_cache_dir, global_config_file from ldm.invoke.model_manager import ModelManager from omegaconf import OmegaConf from pathlib import Path from typing import List -CONFIG_FILE = None - class FloatSlider(npyscreen.Slider): # this is supposed to adjust display precision, but doesn't def translate_value(self): @@ -120,16 +117,16 @@ class mergeModelsForm(npyscreen.FormMultiPageAction): self.merge_method.value=0 def on_ok(self): - if self.validate_field_values(): + if self.validate_field_values() and self.check_for_overwrite(): self.parentApp.setNextForm(None) self.editing = False self.parentApp.merge_arguments = self.marshall_arguments() npyscreen.notify('Starting the merge...') - import diffusers # this keeps the message up while diffusers loads + import ldm.invoke.merge_diffusers # this keeps the message up while diffusers loads else: self.editing = True - def ok_cancel(self): + def on_cancel(self): sys.exit(0) def marshall_arguments(self)->dict: @@ -141,18 +138,22 @@ class mergeModelsForm(npyscreen.FormMultiPageAction): if self.model3.value[0] > 0: models.append(model_names[self.model3.value[0]-1]) - models = [self.model_manager.model_name_or_path(x) for x in models] - args = dict( - pretrained_model_name_or_path_list=models, + models=models, alpha = self.alpha.value, interp = self.interpolations[self.merge_method.value[0]], force = self.force.value, - cache_dir = global_cache_dir('diffusers'), merged_model_name = self.merged_model_name.value, ) return args + def check_for_overwrite(self)->bool: + model_out = self.merged_model_name.value + if model_out not in self.model_names: + return True + else: + return npyscreen.notify_yes_no(f'The chosen merged model destination, {model_out}, is already in use. Overwrite?') + def validate_field_values(self)->bool: bad_fields = [] model_names = self.model_names @@ -178,7 +179,7 @@ class mergeModelsForm(npyscreen.FormMultiPageAction): class Mergeapp(npyscreen.NPSAppManaged): def __init__(self): super().__init__() - conf = OmegaConf.load(Path(Globals.root) / 'configs' / 'models.yaml') + conf = OmegaConf.load(global_config_file()) self.model_manager = ModelManager(conf,'cpu','float16') # precision doesn't really matter here def onStart(self): @@ -195,51 +196,22 @@ if __name__ == '__main__': ) args = parser.parse_args() global_set_root(args.root_dir) - - CONFIG_FILE = os.path.join(Globals.root,'configs/models.yaml') - os.environ['HF_HOME'] = str(global_cache_dir('diffusers')) + + cache_dir = str(global_cache_dir('diffusers')) # because not clear the merge pipeline is honoring cache_dir + os.environ['HF_HOME'] = cache_dir mergeapp = Mergeapp() mergeapp.run() - from diffusers import DiffusionPipeline - args = mergeapp.merge_arguments - merged_model_name = args['merged_model_name'] - merged_pipe = None - print(args) + + args = mergeapp.merge_arguments + args.update(cache_dir = cache_dir) + from ldm.invoke.merge_diffusers import merge_diffusion_models try: - print(f'DEBUG: {args["pretrained_model_name_or_path_list"][0]}') - pipe = DiffusionPipeline.from_pretrained(args['pretrained_model_name_or_path_list'][0], - custom_pipeline='checkpoint_merger' - ) - merged_pipe = pipe.merge(**args) - dump_path = Path(Globals.root) / 'models' / 'merged_diffusers' - os.makedirs(dump_path,exist_ok=True) - dump_path = dump_path / merged_model_name - merged_pipe.save_pretrained ( - dump_path, - safe_serialization=1 - ) + merge_diffusion_models(**args) + print(f'>> Models merged into new model: "{args["merged_model_name"]}".') except Exception as e: print(f'** An error occurred while merging the pipelines: {str(e)}') print('** DETAILS:') print(traceback.format_exc()) sys.exit(-1) - - print(f'>> Merged model is saved to {dump_path}') - response = input('Import this model into InvokeAI? [y]').strip() or 'y' - if response.startswith(('y','Y')): - try: - mergeapp.model_manager.import_diffuser_model( - dump_path, - model_name = merged_model_name, - description = f'Merge of models {args["pretrained_model_name_or_path_list"]}' - ) - mergeapp.model_manager.commit(CONFIG_FILE) - print('>> Merged model imported.') - except Exception as e: - print(f'** New model could not be committed to config.yaml: {str(e)}') - print('** DETAILS:') - print(traceback.format_exc()) - - From 48deb3e49dec2991d7f47800910726736f5d5b7b Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Mon, 23 Jan 2023 00:20:28 -0500 Subject: [PATCH 18/24] add model merging documentation and launcher script menu entries --- docs/features/MODEL_MERGING.md | 77 ++++++++++++++++ docs/index.md | 2 + installer/templates/invoke.bat.in | 10 +- installer/templates/invoke.sh.in | 8 +- ldm/invoke/merge_diffusers.py | 3 + scripts/merge_models.py | 92 +++++++++++++++++++ scripts/{merge_fe.py => merge_models_fe.py} | 0 .../{ => orig_scripts}/merge_embeddings.py | 0 8 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 docs/features/MODEL_MERGING.md create mode 100755 scripts/merge_models.py rename scripts/{merge_fe.py => merge_models_fe.py} (100%) rename scripts/{ => orig_scripts}/merge_embeddings.py (100%) diff --git a/docs/features/MODEL_MERGING.md b/docs/features/MODEL_MERGING.md new file mode 100644 index 0000000000..b94e1e4314 --- /dev/null +++ b/docs/features/MODEL_MERGING.md @@ -0,0 +1,77 @@ +--- +title: Model Merging +--- + +# :material-image-off: Model Merging + +## How to Merge Models + +As of version 2.3, InvokeAI comes with a script that allows you to +merge two or three diffusers-type models into a new merged model. The +resulting model will combine characteristics of the original, and can +be used to teach an old model new tricks. + +You may run the merge script by starting the invoke launcher +(`invoke.sh` or `invoke.bat`) and choosing the option for _merge +models_. This will launch a text-based interactive user interface that +prompts you to select the models to merge, how to merge them, and the +merged model name. + +Alternatively you may activate InvokeAI's virtual environment from the +command line, and call the script via `merge_models_fe.py` (the "fe" +stands for "front end"). There is also a version that accepts +command-line arguments, which you can run with the command +`merge_models.py`. + +The user interface for the text-based interactive script is +straightforward. It shows you a series of setting fields. Use control-N (^N) +to move to the next field, and control-P (^P) to move to the previous +one. You can also use TAB and shift-TAB to move forward and +backward. Once you are in a multiple choice field, use the up and down +cursor arrows to move to your desired selection, and press or + to select it. Change text fields by typing in them, and adjust +scrollbars using the left and right arrow keys. + +Once you are happy with your settings, press the OK button. Note that +there may be two pages of settings, depending on the height of your +screen, and the OK button may be on the second page. Advance past the +last field of the first page to get to the second page, and reverse +this to get back. + +If the merge runs successfully, it will create a new diffusers model +under the selected name and register it with InvokeAI. + +## The Settings + +* Model Selection -- there are three multiple choice fields that + display all the diffusers-style models that InvokeAI knows about. + If you do not see the model you are looking for, then it is probably + a legacy checkpoint model and needs to be converted using the + `invoke.py` command-line client and its `!optimize` command. You + must select at least two models to merge. The third can be left at + "None" if you desire. + +* Alpha -- This is the ratio to use when combining models. It ranges + from 0 to 1. The higher the value, the more weight is given to the + 2d and (optionally) 3d models. So if you have two models named "A" + and "B", an alpha value of 0.25 will give you a merged model that is + 25% A and 75% B. + +* Interpolation Method -- This is the method used to combine + weights. The options are "weighted_sum" (the default), "sigmoid", + "inv_sigmoid" and "add_difference". Each produces slightly different + results. When three models are in use, only "add_difference" is + available. (TODO: cite a reference that describes what these + interpolation methods actually do and how to decide among them). + +* Force -- Not all models are compatible with each other. The merge + script will check for compatibility and refuse to merge ones that + are incompatible. Set this checkbox to try merging anyway. + +* Name for merged model - This is the name for the new model. Please + use InvokeAI conventions - only alphanumeric letters and the + characters ".+-". + +## Caveats + +This is a new script and may contain bugs. diff --git a/docs/index.md b/docs/index.md index c38f840d32..e20535d591 100644 --- a/docs/index.md +++ b/docs/index.md @@ -157,6 +157,8 @@ images in full-precision mode: - [Prompt Engineering](features/PROMPTS.md) +- [Model Merging](features/MODEL_MERGING.md) + - Miscellaneous - [NSFW Checker](features/NSFW.md) - [Embiggen upscaling](features/EMBIGGEN.md) diff --git a/installer/templates/invoke.bat.in b/installer/templates/invoke.bat.in index 114b8c5070..4b2e982d13 100644 --- a/installer/templates/invoke.bat.in +++ b/installer/templates/invoke.bat.in @@ -10,8 +10,9 @@ echo Do you want to generate images using the echo 1. command-line echo 2. browser-based UI echo 3. run textual inversion training -echo 4. open the developer console -echo 5. re-run the configure script to download new models +echo 4. merge models (diffusers type only) +echo 5. open the developer console +echo 6. re-run the configure script to download new models set /P restore="Please enter 1, 2, 3, 4 or 5: [5] " if not defined restore set restore=2 IF /I "%restore%" == "1" ( @@ -24,6 +25,9 @@ IF /I "%restore%" == "1" ( echo Starting textual inversion training.. python .venv\Scripts\textual_inversion_fe.py --web %* ) ELSE IF /I "%restore%" == "4" ( + echo Starting model merging script.. + python .venv\Scripts\merge_models_fe.py --web %* +) ELSE IF /I "%restore%" == "5" ( echo Developer Console echo Python command is: where python @@ -35,7 +39,7 @@ IF /I "%restore%" == "1" ( echo ************************* echo *** Type `exit` to quit this shell and deactivate the Python virtual environment *** call cmd /k -) ELSE IF /I "%restore%" == "5" ( +) ELSE IF /I "%restore%" == "6" ( echo Running configure_invokeai.py... python .venv\Scripts\configure_invokeai.py --web %* ) ELSE ( diff --git a/installer/templates/invoke.sh.in b/installer/templates/invoke.sh.in index 44ee8c5b90..d871bb7e58 100644 --- a/installer/templates/invoke.sh.in +++ b/installer/templates/invoke.sh.in @@ -20,16 +20,18 @@ if [ "$0" != "bash" ]; then echo "1. command-line" echo "2. browser-based UI" echo "3. run textual inversion training" - echo "4. open the developer console" + echo "4. merge models (diffusers type only)" echo "5. re-run the configure script to download new models" + echo "6. open the developer console" read -p "Please enter 1, 2, 3, 4 or 5: [1] " yn choice=${yn:='2'} case $choice in 1 ) printf "\nStarting the InvokeAI command-line..\n"; .venv/bin/python .venv/bin/invoke.py $*;; 2 ) printf "\nStarting the InvokeAI browser-based UI..\n"; .venv/bin/python .venv/bin/invoke.py --web $*;; 3 ) printf "\nStarting Textual Inversion:\n"; .venv/bin/python .venv/bin/textual_inversion_fe.py $*;; - 4 ) printf "\nDeveloper Console:\n"; file_name=$(basename "${BASH_SOURCE[0]}"); bash --init-file "$file_name";; - 5 ) printf "\nRunning configure_invokeai.py:\n"; .venv/bin/python .venv/bin/configure_invokeai.py $*;; + 4 ) printf "\nMerging Models:\n"; .venv/bin/python .venv/bin/merge_models_fe.py $*;; + 5 ) printf "\nDeveloper Console:\n"; file_name=$(basename "${BASH_SOURCE[0]}"); bash --init-file "$file_name";; + 6 ) printf "\nRunning configure_invokeai.py:\n"; .venv/bin/python .venv/bin/configure_invokeai.py $*;; * ) echo "Invalid selection"; exit;; esac else # in developer console diff --git a/ldm/invoke/merge_diffusers.py b/ldm/invoke/merge_diffusers.py index 6a1d742aee..b140e48369 100644 --- a/ldm/invoke/merge_diffusers.py +++ b/ldm/invoke/merge_diffusers.py @@ -29,6 +29,9 @@ def merge_diffusion_models(models:List['str'], ''' config_file = global_config_file() model_manager = ModelManager(OmegaConf.load(config_file)) + for mod in models: + assert (mod in model_manager.model_names()), f'** Unknown model "{mod}"' + assert (model_manager.model_info(mod).get('format',None) == 'diffusers'), f'** {mod} is not a diffusers model. It must be optimized before merging.' model_ids_or_paths = [model_manager.model_name_or_path(x) for x in models] pipe = DiffusionPipeline.from_pretrained(model_ids_or_paths[0], diff --git a/scripts/merge_models.py b/scripts/merge_models.py new file mode 100755 index 0000000000..1d8ac10018 --- /dev/null +++ b/scripts/merge_models.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python + +import argparse +import os +import sys +import traceback +from pathlib import Path + +from omegaconf import OmegaConf + +from ldm.invoke.globals import (Globals, global_cache_dir, global_config_file, + global_set_root) +from ldm.invoke.model_manager import ModelManager + +parser = argparse.ArgumentParser(description="InvokeAI textual inversion training") +parser.add_argument( + "--root_dir", + "--root-dir", + type=Path, + default=Globals.root, + help="Path to the invokeai runtime directory", +) +parser.add_argument( + "--models", + required=True, + type=str, + nargs="+", + help="Two to three model names to be merged", +) +parser.add_argument( + "--merged_model_name", + "--destination", + dest="merged_model_name", + type=str, + help="Name of the output model. If not specified, will be the concatenation of the input model names.", +) +parser.add_argument( + "--alpha", + type=float, + default=0.5, + help="The interpolation parameter, ranging from 0 to 1. It affects the ratio in which the checkpoints are merged. Higher values give more weight to the 2d and 3d models", +) +parser.add_argument( + "--interpolation", + dest="interp", + type=str, + choices=["weighted_sum", "sigmoid", "inv_sigmoid", "add_difference"], + default="weighted_sum", + help='Interpolation method to use. If three models are present, only "add_difference" will work.', +) +parser.add_argument( + "--force", + action="store_true", + help="Try to merge models even if they are incompatible with each other", +) +parser.add_argument( + "--clobber", + "--overwrite", + dest='clobber', + action="store_true", + help="Overwrite the merged model if --merged_model_name already exists", +) + +args = parser.parse_args() +global_set_root(args.root_dir) + +assert args.alpha >= 0 and args.alpha <= 1.0, "alpha must be between 0 and 1" +assert len(args.models) >= 1 and len(args.models) <= 3, "provide 2 or 3 models to merge" + +if not args.merged_model_name: + args.merged_model_name = "+".join(args.models) + print( + f'>> No --merged_model_name provided. Defaulting to "{args.merged_model_name}"' + ) + +model_manager = ModelManager(OmegaConf.load(global_config_file())) +assert (args.clobber or args.merged_model_name not in model_manager.model_names()), f'A model named "{args.merged_model_name}" already exists. Use --clobber to overwrite.' + +# It seems that the merge pipeline is not honoring cache_dir, so we set the +# HF_HOME environment variable here *before* we load diffusers. +cache_dir = str(global_cache_dir("diffusers")) +os.environ["HF_HOME"] = cache_dir +from ldm.invoke.merge_diffusers import merge_diffusion_models + +try: + merge_diffusion_models(**vars(args)) + print(f'>> Models merged into new model: "{args.merged_model_name}".') +except Exception as e: + print(f"** An error occurred while merging the pipelines: {str(e)}") + print("** DETAILS:") + print(traceback.format_exc()) + sys.exit(-1) diff --git a/scripts/merge_fe.py b/scripts/merge_models_fe.py similarity index 100% rename from scripts/merge_fe.py rename to scripts/merge_models_fe.py diff --git a/scripts/merge_embeddings.py b/scripts/orig_scripts/merge_embeddings.py similarity index 100% rename from scripts/merge_embeddings.py rename to scripts/orig_scripts/merge_embeddings.py From ffcc5ad79582575fb145c69173226a808999e43b Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Mon, 23 Jan 2023 00:35:16 -0500 Subject: [PATCH 19/24] conversion script uses invokeai models cache by default --- ldm/invoke/ckpt_to_diffuser.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/ldm/invoke/ckpt_to_diffuser.py b/ldm/invoke/ckpt_to_diffuser.py index 86281623a6..9b1735f831 100644 --- a/ldm/invoke/ckpt_to_diffuser.py +++ b/ldm/invoke/ckpt_to_diffuser.py @@ -21,7 +21,7 @@ import os import re import torch from pathlib import Path -from ldm.invoke.globals import Globals +from ldm.invoke.globals import Globals, global_cache_dir from safetensors.torch import load_file try: @@ -637,7 +637,7 @@ def convert_ldm_bert_checkpoint(checkpoint, config): def convert_ldm_clip_checkpoint(checkpoint): - text_model = CLIPTextModel.from_pretrained("openai/clip-vit-large-patch14") + text_model = CLIPTextModel.from_pretrained("openai/clip-vit-large-patch14",cache_dir=global_cache_dir('hub')) keys = list(checkpoint.keys()) @@ -677,7 +677,8 @@ textenc_pattern = re.compile("|".join(protected.keys())) def convert_paint_by_example_checkpoint(checkpoint): - config = CLIPVisionConfig.from_pretrained("openai/clip-vit-large-patch14") + cache_dir = global_cache_dir('hub') + config = CLIPVisionConfig.from_pretrained("openai/clip-vit-large-patch14",cache_dir=cache_dir) model = PaintByExampleImageEncoder(config) keys = list(checkpoint.keys()) @@ -744,7 +745,8 @@ def convert_paint_by_example_checkpoint(checkpoint): def convert_open_clip_checkpoint(checkpoint): - text_model = CLIPTextModel.from_pretrained("stabilityai/stable-diffusion-2", subfolder="text_encoder") + cache_dir=global_cache_dir('hub') + text_model = CLIPTextModel.from_pretrained("stabilityai/stable-diffusion-2", subfolder="text_encoder", cache_dir=cache_dir) keys = list(checkpoint.keys()) @@ -795,6 +797,7 @@ def convert_ckpt_to_diffuser(checkpoint_path:str, ): checkpoint = load_file(checkpoint_path) if Path(checkpoint_path).suffix == '.safetensors' else torch.load(checkpoint_path) + cache_dir = global_cache_dir('hub') # Sometimes models don't have the global_step item if "global_step" in checkpoint: @@ -904,7 +907,7 @@ def convert_ckpt_to_diffuser(checkpoint_path:str, if model_type == "FrozenOpenCLIPEmbedder": text_model = convert_open_clip_checkpoint(checkpoint) - tokenizer = CLIPTokenizer.from_pretrained("stabilityai/stable-diffusion-2", subfolder="tokenizer") + tokenizer = CLIPTokenizer.from_pretrained("stabilityai/stable-diffusion-2", subfolder="tokenizer",cache_dir=global_cache_dir('diffusers')) pipe = StableDiffusionPipeline( vae=vae, text_encoder=text_model, @@ -917,8 +920,8 @@ def convert_ckpt_to_diffuser(checkpoint_path:str, ) elif model_type == "PaintByExample": vision_model = convert_paint_by_example_checkpoint(checkpoint) - tokenizer = CLIPTokenizer.from_pretrained("openai/clip-vit-large-patch14") - feature_extractor = AutoFeatureExtractor.from_pretrained("CompVis/stable-diffusion-safety-checker") + tokenizer = CLIPTokenizer.from_pretrained("openai/clip-vit-large-patch14",cache_dir=cache_dir) + feature_extractor = AutoFeatureExtractor.from_pretrained("CompVis/stable-diffusion-safety-checker",cache_dir=cache_dir) pipe = PaintByExamplePipeline( vae=vae, image_encoder=vision_model, @@ -929,9 +932,9 @@ def convert_ckpt_to_diffuser(checkpoint_path:str, ) elif model_type in ['FrozenCLIPEmbedder','WeightedFrozenCLIPEmbedder']: text_model = convert_ldm_clip_checkpoint(checkpoint) - tokenizer = CLIPTokenizer.from_pretrained("openai/clip-vit-large-patch14") - safety_checker = StableDiffusionSafetyChecker.from_pretrained("CompVis/stable-diffusion-safety-checker") - feature_extractor = AutoFeatureExtractor.from_pretrained("CompVis/stable-diffusion-safety-checker") + tokenizer = CLIPTokenizer.from_pretrained("openai/clip-vit-large-patch14",cache_dir=cache_dir) + safety_checker = StableDiffusionSafetyChecker.from_pretrained("CompVis/stable-diffusion-safety-checker",cache_dir=cache_dir) + feature_extractor = AutoFeatureExtractor.from_pretrained("CompVis/stable-diffusion-safety-checker",cache_dir=cache_dir) pipe = StableDiffusionPipeline( vae=vae, text_encoder=text_model, @@ -944,7 +947,7 @@ def convert_ckpt_to_diffuser(checkpoint_path:str, else: text_config = create_ldm_bert_config(original_config) text_model = convert_ldm_bert_checkpoint(checkpoint, text_config) - tokenizer = BertTokenizerFast.from_pretrained("bert-base-uncased") + tokenizer = BertTokenizerFast.from_pretrained("bert-base-uncased",cache_dir=cache_dir) pipe = LDMTextToImagePipeline(vqvae=vae, bert=text_model, tokenizer=tokenizer, unet=unet, scheduler=scheduler) pipe.save_pretrained( From 7dead7696c55370050125ae60f010d2e4856859d Mon Sep 17 00:00:00 2001 From: Lincoln Stein Date: Mon, 23 Jan 2023 00:43:15 -0500 Subject: [PATCH 20/24] fixed setup.py to install the new scripts --- setup.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index afec71b967..c9809c0c92 100644 --- a/setup.py +++ b/setup.py @@ -92,8 +92,9 @@ setup( 'Topic :: Scientific/Engineering :: Image Processing', ], scripts = ['scripts/invoke.py','scripts/configure_invokeai.py', 'scripts/sd-metadata.py', - 'scripts/preload_models.py', 'scripts/images2prompt.py','scripts/merge_embeddings.py', - 'scripts/textual_inversion_fe.py','scripts/textual_inversion.py' + 'scripts/preload_models.py', 'scripts/images2prompt.py', + 'scripts/textual_inversion_fe.py','scripts/textual_inversion.py', + 'scripts/merge_models_fe.py', 'scripts/merge_models.py', ], data_files=FRONTEND_FILES, ) From 1eee08a07085386f7b05948a2bc777f626e74017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=90=E6=BE=A4=20=E5=85=8B=E5=B9=B8?= Date: Mon, 23 Jan 2023 18:32:48 +0900 Subject: [PATCH 21/24] add Japanese Translation --- frontend/public/locales/common/ja.json | 60 +++++++++++++++++ frontend/public/locales/gallery/ja.json | 17 +++++ frontend/public/locales/modelmanager/ja.json | 68 ++++++++++++++++++++ frontend/public/locales/settings/ja.json | 14 ++++ frontend/public/locales/tooltip/ja.json | 16 +++++ 5 files changed, 175 insertions(+) create mode 100644 frontend/public/locales/common/ja.json create mode 100644 frontend/public/locales/gallery/ja.json create mode 100644 frontend/public/locales/modelmanager/ja.json create mode 100644 frontend/public/locales/settings/ja.json create mode 100644 frontend/public/locales/tooltip/ja.json diff --git a/frontend/public/locales/common/ja.json b/frontend/public/locales/common/ja.json new file mode 100644 index 0000000000..be225e9d34 --- /dev/null +++ b/frontend/public/locales/common/ja.json @@ -0,0 +1,60 @@ +{ + "hotkeysLabel": "Hotkeys", + "themeLabel": "テーマ", + "languagePickerLabel": "言語選択", + "reportBugLabel": "バグ報告", + "githubLabel": "Github", + "discordLabel": "Discord", + "settingsLabel": "設定", + "darkTheme": "ダーク", + "lightTheme": "ライト", + "greenTheme": "緑", + "langEnglish": "English", + "langRussian": "Russian", + "langItalian": "Italian", + "langBrPortuguese": "Portuguese (Brazilian)", + "langGerman": "German", + "langPortuguese": "Portuguese", + "langFrench": "French", + "langPolish": "Polish", + "langSimplifiedChinese": "Simplified Chinese", + "langSpanish": "Spanish", + "text2img": "Text To Image", + "img2img": "Image To Image", + "unifiedCanvas": "Unified Canvas", + "nodes": "Nodes", + "nodesDesc": "現在、画像生成のためのノードベースシステムを開発中です。機能についてのアップデートにご期待ください。", + "postProcessing": "後処理", + "postProcessDesc1": "Invoke AIは、多彩な後処理の機能を備えています。アップスケーリングと顔修復は、すでにWebUI上で利用可能です。これらは、[Text To Image]および[Image To Image]タブの[詳細オプション]メニューからアクセスできます。また、現在の画像表示の上やビューア内の画像アクションボタンを使って、画像を直接処理することもできます。", + "postProcessDesc2": "より高度な後処理の機能を実現するための専用UIを近日中にリリース予定です。", + "postProcessDesc3": "Invoke AI CLIでは、この他にもEmbiggenをはじめとする様々な機能を利用することができます。", + "training": "追加学習", + "trainingDesc1": "Textual InversionとDreamboothを使って、WebUIから独自のEmbeddingとチェックポイントを追加学習するための専用ワークフローです。", + "trainingDesc2": "InvokeAIは、すでにメインスクリプトを使ったTextual Inversionによるカスタム埋め込み追加学習にも対応しています。", + "upload": "アップロード", + "close": "閉じる", + "load": "ロード", + "back": "戻る", + "statusConnected": "接続済", + "statusDisconnected": "切断済", + "statusError": "エラー", + "statusPreparing": "準備中", + "statusProcessingCanceled": "処理をキャンセル", + "statusProcessingComplete": "処理完了", + "statusGenerating": "生成中", + "statusGeneratingTextToImage": "Text To Imageで生成中", + "statusGeneratingImageToImage": "Image To Imageで生成中", + "statusGeneratingInpainting": "Generating Inpainting", + "statusGeneratingOutpainting": "Generating Outpainting", + "statusGenerationComplete": "生成完了", + "statusIterationComplete": "Iteration Complete", + "statusSavingImage": "画像を保存", + "statusRestoringFaces": "顔の修復", + "statusRestoringFacesGFPGAN": "顔の修復 (GFPGAN)", + "statusRestoringFacesCodeFormer": "顔の修復 (CodeFormer)", + "statusUpscaling": "アップスケーリング", + "statusUpscalingESRGAN": "アップスケーリング (ESRGAN)", + "statusLoadingModel": "モデルを読み込む", + "statusModelChanged": "モデルを変更" + } + \ No newline at end of file diff --git a/frontend/public/locales/gallery/ja.json b/frontend/public/locales/gallery/ja.json new file mode 100644 index 0000000000..923dab1c8e --- /dev/null +++ b/frontend/public/locales/gallery/ja.json @@ -0,0 +1,17 @@ +{ + "generations": "Generations", + "showGenerations": "Show Generations", + "uploads": "アップロード", + "showUploads": "アップロードした画像を見る", + "galleryImageSize": "画像のサイズ", + "galleryImageResetSize": "サイズをリセット", + "gallerySettings": "ギャラリーの設定", + "maintainAspectRatio": "アスペクト比を維持", + "autoSwitchNewImages": "Auto-Switch to New Images", + "singleColumnLayout": "シングルカラムレイアウト", + "pinGallery": "ギャラリーにピン留め", + "allImagesLoaded": "すべての画像を読み込む", + "loadMore": "さらに読み込む", + "noImagesInGallery": "ギャラリーに画像がありません" + } + \ No newline at end of file diff --git a/frontend/public/locales/modelmanager/ja.json b/frontend/public/locales/modelmanager/ja.json new file mode 100644 index 0000000000..b8a64794c9 --- /dev/null +++ b/frontend/public/locales/modelmanager/ja.json @@ -0,0 +1,68 @@ +{ + "modelManager": "モデルマネージャ", + "model": "モデル", + "allModels": "すべてのモデル", + "checkpointModels": "Checkpoints", + "diffusersModels": "Diffusers", + "safetensorModels": "SafeTensors", + "modelAdded": "モデルを追加", + "modelUpdated": "モデルをアップデート", + "modelEntryDeleted": "Model Entry Deleted", + "cannotUseSpaces": "Cannot Use Spaces", + "addNew": "新規に追加", + "addNewModel": "新規モデル追加", + "addCheckpointModel": "Checkpointを追加 / Safetensorモデル", + "addDiffuserModel": "Diffusersを追加", + "addManually": "手動で追加", + "manual": "手動", + "name": "名前", + "nameValidationMsg": "モデルの名前を入力", + "description": "概要", + "descriptionValidationMsg": "モデルの概要を入力", + "config": "Config", + "configValidationMsg": "モデルの設定ファイルへのパス", + "modelLocation": "モデルの場所", + "modelLocationValidationMsg": "モデルが配置されている場所へのパス。", + "repo_id": "Repo ID", + "repoIDValidationMsg": "モデルのリモートリポジトリ", + "vaeLocation": "VAEの場所", + "vaeLocationValidationMsg": "Vaeが配置されている場所へのパス", + "vaeRepoID": "VAE Repo ID", + "vaeRepoIDValidationMsg": "Vaeのリモートリポジトリ", + "width": "幅", + "widthValidationMsg": "モデルのデフォルトの幅", + "height": "高さ", + "heightValidationMsg": "モデルのデフォルトの高さ", + "addModel": "モデルを追加", + "updateModel": "モデルをアップデート", + "availableModels": "モデルを有効化", + "search": "検索", + "load": "Load", + "active": "active", + "notLoaded": "読み込まれていません", + "cached": "キャッシュ済", + "checkpointFolder": "Checkpointフォルダ", + "clearCheckpointFolder": "Checkpointフォルダ内を削除", + "findModels": "モデルを見つける", + "scanAgain": "再度スキャン", + "modelsFound": "モデルを発見", + "selectFolder": "フォルダを選択", + "selected": "選択済", + "selectAll": "すべて選択", + "deselectAll": "すべて選択解除", + "showExisting": "既存を表示", + "addSelected": "選択済を追加", + "modelExists": "モデルの有無", + "selectAndAdd": "以下のモデルを選択し、追加できます。", + "noModelsFound": "モデルが見つかりません。", + "delete": "削除", + "deleteModel": "モデルを削除", + "deleteConfig": "設定を削除", + "deleteMsg1": "InvokeAIからこのモデルエントリーを削除してよろしいですか?", + "deleteMsg2": "これは、ドライブからモデルのCheckpointファイルを削除するものではありません。必要であればそれらを読み込むことができます。", + "formMessageDiffusersModelLocation": "Diffusersモデルの場所", + "formMessageDiffusersModelLocationDesc": "最低でも1つは入力してください。", + "formMessageDiffusersVAELocation": "VAEの場所s", + "formMessageDiffusersVAELocationDesc": "指定しない場合、InvokeAIは上記のモデルの場所にあるVAEファイルを探します。" + } + \ No newline at end of file diff --git a/frontend/public/locales/settings/ja.json b/frontend/public/locales/settings/ja.json new file mode 100644 index 0000000000..0af09521b2 --- /dev/null +++ b/frontend/public/locales/settings/ja.json @@ -0,0 +1,14 @@ +{ + "models": "モデル", + "displayInProgress": "生成中の画像を表示する", + "saveSteps": "nステップごとに画像を保存", + "confirmOnDelete": "削除時に確認", + "displayHelpIcons": "ヘルプアイコンを表示", + "useCanvasBeta": "キャンバスレイアウト(Beta)を使用する", + "enableImageDebugging": "画像のデバッグを有効化", + "resetWebUI": "WebUIをリセット", + "resetWebUIDesc1": "WebUIのリセットは、画像と保存された設定のキャッシュをリセットするだけです。画像を削除するわけではありません。", + "resetWebUIDesc2": "もしギャラリーに画像が表示されないなど、何か問題が発生した場合はGitHubにissueを提出する前にリセットを試してください。", + "resetComplete": "WebUIはリセットされました。F5を押して再読み込みしてください。" + } + \ No newline at end of file diff --git a/frontend/public/locales/tooltip/ja.json b/frontend/public/locales/tooltip/ja.json new file mode 100644 index 0000000000..7f3eaaa53b --- /dev/null +++ b/frontend/public/locales/tooltip/ja.json @@ -0,0 +1,16 @@ +{ + "feature": { + "prompt": "これはプロンプトフィールドです。プロンプトには生成オブジェクトや文法用語が含まれます。プロンプトにも重み(Tokenの重要度)を付けることができますが、CLIコマンドやパラメータは機能しません。", + "gallery": "ギャラリーは、出力先フォルダから生成物を表示します。設定はファイル内に保存され、コンテキストメニューからアクセスできます。.", + "other": "These options will enable alternative processing modes for Invoke. 'Seamless tiling' will create repeating patterns in the output. 'High resolution' is generation in two steps with img2img: use this setting when you want a larger and more coherent image without artifacts. It will take longer that usual txt2img.", + "seed": "シード値は、画像が形成される際の初期ノイズに影響します。以前の画像から既に存在するシードを使用することができます。ノイズしきい値は高いCFG値でのアーティファクトを軽減するために使用され、Perlinは生成中にPerlinノイズを追加します(0-10の範囲を試してみてください): どちらも出力にバリエーションを追加するのに役立ちます。", + "variations": "0.1から1.0の間の値で試し、付与されたシードに対する結果を変えてみてください。面白いバリュエーションは0.1〜0.3の間です。", + "upscale": "生成直後の画像をアップスケールするには、ESRGANを使用します。", + "faceCorrection": "GFPGANまたはCodeformerによる顔の修復: 画像内の顔を検出し不具合を修正するアルゴリズムです。高い値を設定すると画像がより変化し、より魅力的な顔になります。Codeformerは顔の修復を犠牲にして、元の画像をできる限り保持します。", + "imageToImage": "Image To Imageは任意の画像を初期値として読み込み、プロンプトとともに新しい画像を生成するために使用されます。値が高いほど結果画像はより変化します。0.0から1.0までの値が可能で、推奨範囲は0.25から0.75です。", + "boundingBox": "バウンディングボックスは、Text To ImageまたはImage To Imageの幅/高さの設定と同じです。ボックス内の領域のみが処理されます。", + "seamCorrection": "キャンバス上の生成された画像間に発生する可視可能な境界の処理を制御します。", + "infillAndScaling": "Manage infill methods (used on masked or erased areas of the canvas) and scaling (useful for small bounding box sizes)." + } + } + \ No newline at end of file From b9c9b947cdb65f2204742e1a7c484fa188dc8ce2 Mon Sep 17 00:00:00 2001 From: Katsuyuki-Karasawa <4ranci0ne@gmail.com> Date: Tue, 24 Jan 2023 03:25:29 +0900 Subject: [PATCH 22/24] update japanese translation --- frontend/public/locales/hotkeys/ja.json | 208 ++++++++++++++++++ frontend/public/locales/options/ja.json | 63 ++++++ frontend/public/locales/toast/ja.json | 32 +++ frontend/public/locales/unifiedcanvas/ja.json | 60 +++++ 4 files changed, 363 insertions(+) create mode 100644 frontend/public/locales/hotkeys/ja.json create mode 100644 frontend/public/locales/options/ja.json create mode 100644 frontend/public/locales/toast/ja.json create mode 100644 frontend/public/locales/unifiedcanvas/ja.json diff --git a/frontend/public/locales/hotkeys/ja.json b/frontend/public/locales/hotkeys/ja.json new file mode 100644 index 0000000000..d5e448246f --- /dev/null +++ b/frontend/public/locales/hotkeys/ja.json @@ -0,0 +1,208 @@ +{ + "keyboardShortcuts": "キーボードショートカット", + "appHotkeys": "アプリのホットキー", + "generalHotkeys": "Generalのホットキー", + "galleryHotkeys": "ギャラリーのホットキー", + "unifiedCanvasHotkeys": "Unified Canvasのホットキー", + "invoke": { + "title": "Invoke", + "desc": "画像を生成" + }, + "cancel": { + "title": "キャンセル", + "desc": "画像の生成をキャンセル" + }, + "focusPrompt": { + "title": "Focus Prompt", + "desc": "プロンプトテキストボックスにフォーカス" + }, + "toggleOptions": { + "title": "オプションパネルのトグル", + "desc": "オプションパネルの開閉" + }, + "pinOptions": { + "title": "ピン", + "desc": "オプションパネルを固定" + }, + "toggleViewer": { + "title": "ビュワーのトグル", + "desc": "ビュワーを開閉" + }, + "toggleGallery": { + "title": "ギャラリーのトグル", + "desc": "ギャラリードロワーの開閉" + }, + "maximizeWorkSpace": { + "title": "作業領域の最大化", + "desc": "パネルを閉じて、作業領域を最大に" + }, + "changeTabs": { + "title": "タブの切替", + "desc": "他の作業領域と切替" + }, + "consoleToggle": { + "title": "コンソールのトグル", + "desc": "コンソールの開閉" + }, + "setPrompt": { + "title": "プロンプトをセット", + "desc": "現在の画像のプロンプトを使用" + }, + "setSeed": { + "title": "シード値をセット", + "desc": "現在の画像のシード値を使用" + }, + "setParameters": { + "title": "パラメータをセット", + "desc": "現在の画像のすべてのパラメータを使用" + }, + "restoreFaces": { + "title": "顔の修復", + "desc": "現在の画像を修復" + }, + "upscale": { + "title": "アップスケール", + "desc": "現在の画像をアップスケール" + }, + "showInfo": { + "title": "情報を見る", + "desc": "現在の画像のメタデータ情報を表示" + }, + "sendToImageToImage": { + "title": "Image To Imageに転送", + "desc": "現在の画像をImage to Imageに転送" + }, + "deleteImage": { + "title": "画像を削除", + "desc": "現在の画像を削除" + }, + "closePanels": { + "title": "パネルを閉じる", + "desc": "開いているパネルを閉じる" + }, + "previousImage": { + "title": "前の画像", + "desc": "ギャラリー内の1つ前の画像を表示" + }, + "nextImage": { + "title": "次の画像", + "desc": "ギャラリー内の1つ後の画像を表示" + }, + "toggleGalleryPin": { + "title": "ギャラリードロワーの固定", + "desc": "ギャラリーをUIにピン留め/解除" + }, + "increaseGalleryThumbSize": { + "title": "ギャラリーの画像を拡大", + "desc": "ギャラリーのサムネイル画像を拡大" + }, + "decreaseGalleryThumbSize": { + "title": "ギャラリーの画像サイズを縮小", + "desc": "ギャラリーのサムネイル画像を縮小" + }, + "selectBrush": { + "title": "ブラシを選択", + "desc": "ブラシを選択" + }, + "selectEraser": { + "title": "消しゴムを選択", + "desc": "消しゴムを選択" + }, + "decreaseBrushSize": { + "title": "ブラシサイズを縮小", + "desc": "ブラシ/消しゴムのサイズを縮小" + }, + "increaseBrushSize": { + "title": "ブラシサイズを拡大", + "desc": "ブラシ/消しゴムのサイズを拡大" + }, + "decreaseBrushOpacity": { + "title": "ブラシの不透明度を下げる", + "desc": "キャンバスブラシの不透明度を下げる" + }, + "increaseBrushOpacity": { + "title": "ブラシの不透明度を上げる", + "desc": "キャンバスブラシの不透明度を上げる" + }, + "moveTool": { + "title": "Move Tool", + "desc": "Allows canvas navigation" + }, + "fillBoundingBox": { + "title": "バウンディングボックスを塗りつぶす", + "desc": "ブラシの色でバウンディングボックス領域を塗りつぶす" + }, + "eraseBoundingBox": { + "title": "バウンディングボックスを消す", + "desc": "バウンディングボックス領域を消す" + }, + "colorPicker": { + "title": "カラーピッカーを選択", + "desc": "カラーピッカーを選択" + }, + "toggleSnap": { + "title": "Toggle Snap", + "desc": "Toggles Snap to Grid" + }, + "quickToggleMove": { + "title": "Quick Toggle Move", + "desc": "Temporarily toggles Move mode" + }, + "toggleLayer": { + "title": "レイヤーを切替", + "desc": "マスク/ベースレイヤの選択を切替" + }, + "clearMask": { + "title": "マスクを消す", + "desc": "マスク全体を消す" + }, + "hideMask": { + "title": "マスクを非表示", + "desc": "マスクを表示/非表示" + }, + "showHideBoundingBox": { + "title": "バウンディングボックスを表示/非表示", + "desc": "バウンディングボックスの表示/非表示を切替" + }, + "mergeVisible": { + "title": "Merge Visible", + "desc": "Merge all visible layers of canvas" + }, + "saveToGallery": { + "title": "ギャラリーに保存", + "desc": "現在のキャンバスをギャラリーに保存" + }, + "copyToClipboard": { + "title": "クリップボードにコピー", + "desc": "現在のキャンバスをクリップボードにコピー" + }, + "downloadImage": { + "title": "画像をダウンロード", + "desc": "現在の画像をダウンロード" + }, + "undoStroke": { + "title": "Undo Stroke", + "desc": "Undo a brush stroke" + }, + "redoStroke": { + "title": "Redo Stroke", + "desc": "Redo a brush stroke" + }, + "resetView": { + "title": "キャンバスをリセット", + "desc": "キャンバスをリセット" + }, + "previousStagingImage": { + "title": "Previous Staging Image", + "desc": "Previous Staging Area Image" + }, + "nextStagingImage": { + "title": "Next Staging Image", + "desc": "Next Staging Area Image" + }, + "acceptStagingImage": { + "title": "Accept Staging Image", + "desc": "Accept Current Staging Area Image" + } + } + \ No newline at end of file diff --git a/frontend/public/locales/options/ja.json b/frontend/public/locales/options/ja.json new file mode 100644 index 0000000000..ffc6dd3f7d --- /dev/null +++ b/frontend/public/locales/options/ja.json @@ -0,0 +1,63 @@ +{ + "images": "画像", + "steps": "ステップ数", + "cfgScale": "CFG Scale", + "width": "幅", + "height": "高さ", + "sampler": "Sampler", + "seed": "シード値", + "randomizeSeed": "ランダムなシード値", + "shuffle": "シャッフル", + "noiseThreshold": "Noise Threshold", + "perlinNoise": "Perlin Noise", + "variations": "Variations", + "variationAmount": "Variation Amount", + "seedWeights": "シード値の重み", + "faceRestoration": "顔の修復", + "restoreFaces": "顔の修復", + "type": "Type", + "strength": "強度", + "upscaling": "アップスケーリング", + "upscale": "アップスケール", + "upscaleImage": "画像をアップスケール", + "scale": "Scale", + "otherOptions": "その他のオプション", + "seamlessTiling": "Seamless Tiling", + "hiresOptim": "High Res Optimization", + "imageFit": "Fit Initial Image To Output Size", + "codeformerFidelity": "Fidelity", + "seamSize": "Seam Size", + "seamBlur": "Seam Blur", + "seamStrength": "Seam Strength", + "seamSteps": "Seam Steps", + "inpaintReplace": "Inpaint Replace", + "scaleBeforeProcessing": "処理前のスケール", + "scaledWidth": "幅のスケール", + "scaledHeight": "高さのスケール", + "infillMethod": "Infill Method", + "tileSize": "Tile Size", + "boundingBoxHeader": "バウンディングボックス", + "seamCorrectionHeader": "Seam Correction", + "infillScalingHeader": "Infill and Scaling", + "img2imgStrength": "Image To Imageの強度", + "toggleLoopback": "Toggle Loopback", + "invoke": "Invoke", + "cancel": "キャンセル", + "promptPlaceholder": "Type prompt here. [negative tokens], (upweight)++, (downweight)--, swap and blend are available (see docs)", + "sendTo": "転送", + "sendToImg2Img": "Image to Imageに転送", + "sendToUnifiedCanvas": "Unified Canvasに転送", + "copyImageToLink": "Copy Image To Link", + "downloadImage": "画像をダウンロード", + "openInViewer": "ビュワーを開く", + "closeViewer": "ビュワーを閉じる", + "usePrompt": "プロンプトを使用", + "useSeed": "シード値を使用", + "useAll": "すべてを使用", + "useInitImg": "Use Initial Image", + "info": "情報", + "deleteImage": "画像を削除", + "initialImage": "Inital Image", + "showOptionsPanel": "オプションパネルを表示" + } + \ No newline at end of file diff --git a/frontend/public/locales/toast/ja.json b/frontend/public/locales/toast/ja.json new file mode 100644 index 0000000000..e43a03a2b5 --- /dev/null +++ b/frontend/public/locales/toast/ja.json @@ -0,0 +1,32 @@ +{ + "tempFoldersEmptied": "Temp Folder Emptied", + "uploadFailed": "アップロード失敗", + "uploadFailedMultipleImagesDesc": "一度にアップロードできる画像は1枚のみです。", + "uploadFailedUnableToLoadDesc": "ファイルを読み込むことができません。", + "downloadImageStarted": "画像ダウンロード開始", + "imageCopied": "画像をコピー", + "imageLinkCopied": "画像のURLをコピー", + "imageNotLoaded": "画像を読み込めません。", + "imageNotLoadedDesc": "Image To Imageに転送する画像が見つかりません。", + "imageSavedToGallery": "画像をギャラリーに保存する", + "canvasMerged": "Canvas Merged", + "sentToImageToImage": "Image To Imageに転送", + "sentToUnifiedCanvas": "Unified Canvasに転送", + "parametersSet": "Parameters Set", + "parametersNotSet": "Parameters Not Set", + "parametersNotSetDesc": "この画像にはメタデータがありません。", + "parametersFailed": "パラメータ読み込みの不具合", + "parametersFailedDesc": "initイメージを読み込めません。", + "seedSet": "Seed Set", + "seedNotSet": "Seed Not Set", + "seedNotSetDesc": "この画像のシード値が見つかりません。", + "promptSet": "Prompt Set", + "promptNotSet": "Prompt Not Set", + "promptNotSetDesc": "この画像のプロンプトが見つかりませんでした。", + "upscalingFailed": "アップスケーリング失敗", + "faceRestoreFailed": "顔の修復に失敗", + "metadataLoadFailed": "メタデータの読み込みに失敗。", + "initialImageSet": "Initial Image Set", + "initialImageNotSet": "Initial Image Not Set", + "initialImageNotSetDesc": "Could not load initial image" + } \ No newline at end of file diff --git a/frontend/public/locales/unifiedcanvas/ja.json b/frontend/public/locales/unifiedcanvas/ja.json new file mode 100644 index 0000000000..2a221519ff --- /dev/null +++ b/frontend/public/locales/unifiedcanvas/ja.json @@ -0,0 +1,60 @@ +{ + "layer": "Layer", + "base": "Base", + "mask": "マスク", + "maskingOptions": "マスクのオプション", + "enableMask": "マスクを有効化", + "preserveMaskedArea": "マスク領域の保存", + "clearMask": "マスクを解除", + "brush": "ブラシ", + "eraser": "消しゴム", + "fillBoundingBox": "バウンディングボックスの塗りつぶし", + "eraseBoundingBox": "バウンディングボックスの消去", + "colorPicker": "カラーピッカー", + "brushOptions": "ブラシオプション", + "brushSize": "サイズ", + "move": "Move", + "resetView": "Reset View", + "mergeVisible": "Merge Visible", + "saveToGallery": "ギャラリーに保存", + "copyToClipboard": "クリップボードにコピー", + "downloadAsImage": "画像としてダウンロード", + "undo": "取り消し", + "redo": "やり直し", + "clearCanvas": "キャンバスを片付ける", + "canvasSettings": "キャンバスの設定", + "showIntermediates": "Show Intermediates", + "showGrid": "グリッドを表示", + "snapToGrid": "Snap to Grid", + "darkenOutsideSelection": "外周を暗くする", + "autoSaveToGallery": "ギャラリーに自動保存", + "saveBoxRegionOnly": "ボックス領域のみ保存", + "limitStrokesToBox": "Limit Strokes to Box", + "showCanvasDebugInfo": "キャンバスのデバッグ情報を表示", + "clearCanvasHistory": "キャンバスの履歴を削除", + "clearHistory": "履歴を削除", + "clearCanvasHistoryMessage": "履歴を消去すると現在のキャンバスは残りますが、取り消しややり直しの履歴は不可逆的に消去されます。", + "clearCanvasHistoryConfirm": "履歴を削除しますか?", + "emptyTempImageFolder": "Empty Temp Image Folde", + "emptyFolder": "空のフォルダ", + "emptyTempImagesFolderMessage": "一時フォルダを空にすると、Unified Canvasも完全にリセットされます。これには、すべての取り消し/やり直しの履歴、ステージング領域の画像、およびキャンバスのベースレイヤーが含まれます。", + "emptyTempImagesFolderConfirm": "一時フォルダを削除しますか?", + "activeLayer": "Active Layer", + "canvasScale": "Canvas Scale", + "boundingBox": "バウンディングボックス", + "scaledBoundingBox": "Scaled Bounding Box", + "boundingBoxPosition": "バウンディングボックスの位置", + "canvasDimensions": "キャンバスの大きさ", + "canvasPosition": "キャンバスの位置", + "cursorPosition": "カーソルの位置", + "previous": "前", + "next": "次", + "accept": "同意", + "showHide": "表示/非表示", + "discardAll": "すべて破棄", + "betaClear": "Clear", + "betaDarkenOutside": "Darken Outside", + "betaLimitToBox": "Limit To Box", + "betaPreserveMasked": "Preserve Masked" + } + \ No newline at end of file From 31a967965bcdb91176d389f65d065e9adc1d463c Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Tue, 24 Jan 2023 08:37:12 +1300 Subject: [PATCH 23/24] Add Japanese Localization --- frontend/public/locales/common/en-US.json | 1 + frontend/public/locales/common/en.json | 1 + frontend/src/features/system/components/LanguagePicker.tsx | 1 + 3 files changed, 3 insertions(+) diff --git a/frontend/public/locales/common/en-US.json b/frontend/public/locales/common/en-US.json index b67799e789..64fbef7c02 100644 --- a/frontend/public/locales/common/en-US.json +++ b/frontend/public/locales/common/en-US.json @@ -19,6 +19,7 @@ "langPolish": "Polish", "langSimplifiedChinese": "Simplified Chinese", "langSpanish": "Spanish", + "langJapanese": "Japanese", "text2img": "Text To Image", "img2img": "Image To Image", "unifiedCanvas": "Unified Canvas", diff --git a/frontend/public/locales/common/en.json b/frontend/public/locales/common/en.json index b67799e789..64fbef7c02 100644 --- a/frontend/public/locales/common/en.json +++ b/frontend/public/locales/common/en.json @@ -19,6 +19,7 @@ "langPolish": "Polish", "langSimplifiedChinese": "Simplified Chinese", "langSpanish": "Spanish", + "langJapanese": "Japanese", "text2img": "Text To Image", "img2img": "Image To Image", "unifiedCanvas": "Unified Canvas", diff --git a/frontend/src/features/system/components/LanguagePicker.tsx b/frontend/src/features/system/components/LanguagePicker.tsx index 29c6f9071a..23d102a236 100644 --- a/frontend/src/features/system/components/LanguagePicker.tsx +++ b/frontend/src/features/system/components/LanguagePicker.tsx @@ -20,6 +20,7 @@ export default function LanguagePicker() { pl: t('common:langPolish'), zh_cn: t('common:langSimplifiedChinese'), es: t('common:langSpanish'), + ja: t('common:langJapanese'), }; const renderLanguagePicker = () => { From 66babb2e81f7de52fe2d93a6c924aebabf89bb72 Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Tue, 24 Jan 2023 08:39:18 +1300 Subject: [PATCH 24/24] Japanese Localization Build --- ...y-474a75fe.js => index-legacy-6edbec57.js} | 12 +- frontend/dist/assets/index.0dadf5d0.css | 1 - frontend/dist/assets/index.1b59e83a.js | 625 ------------------ frontend/dist/assets/index.8badc8b4.css | 1 + frontend/dist/assets/index.dd470915.js | 625 ++++++++++++++++++ frontend/dist/index.html | 6 +- frontend/dist/locales/common/en-US.json | 4 + frontend/dist/locales/common/en.json | 2 + frontend/dist/locales/common/ja.json | 60 ++ frontend/dist/locales/gallery/ja.json | 17 + frontend/dist/locales/hotkeys/ja.json | 208 ++++++ frontend/dist/locales/modelmanager/en-US.json | 19 +- frontend/dist/locales/modelmanager/en.json | 16 +- frontend/dist/locales/modelmanager/ja.json | 68 ++ frontend/dist/locales/options/ja.json | 63 ++ frontend/dist/locales/settings/ja.json | 14 + frontend/dist/locales/toast/ja.json | 32 + frontend/dist/locales/tooltip/it.json | 16 +- frontend/dist/locales/tooltip/ja.json | 16 + frontend/dist/locales/tooltips/it.json | 15 - frontend/dist/locales/unifiedcanvas/ja.json | 60 ++ 21 files changed, 1227 insertions(+), 653 deletions(-) rename frontend/dist/assets/{index-legacy-474a75fe.js => index-legacy-6edbec57.js} (59%) delete mode 100644 frontend/dist/assets/index.0dadf5d0.css delete mode 100644 frontend/dist/assets/index.1b59e83a.js create mode 100644 frontend/dist/assets/index.8badc8b4.css create mode 100644 frontend/dist/assets/index.dd470915.js create mode 100644 frontend/dist/locales/common/ja.json create mode 100644 frontend/dist/locales/gallery/ja.json create mode 100644 frontend/dist/locales/hotkeys/ja.json create mode 100644 frontend/dist/locales/modelmanager/ja.json create mode 100644 frontend/dist/locales/options/ja.json create mode 100644 frontend/dist/locales/settings/ja.json create mode 100644 frontend/dist/locales/toast/ja.json create mode 100644 frontend/dist/locales/tooltip/ja.json delete mode 100644 frontend/dist/locales/tooltips/it.json create mode 100644 frontend/dist/locales/unifiedcanvas/ja.json diff --git a/frontend/dist/assets/index-legacy-474a75fe.js b/frontend/dist/assets/index-legacy-6edbec57.js similarity index 59% rename from frontend/dist/assets/index-legacy-474a75fe.js rename to frontend/dist/assets/index-legacy-6edbec57.js index b48c03f8f8..df48761d1e 100644 --- a/frontend/dist/assets/index-legacy-474a75fe.js +++ b/frontend/dist/assets/index-legacy-6edbec57.js @@ -1,4 +1,4 @@ -!function(){function e(e,t,n){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e;var n=e[Symbol.toPrimitive];if(void 0!==n){var r=n.call(e,t||"default");if("object"!=typeof r)return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:String(t)}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}System.register([],(function(t,n){"use strict";var r=document.createElement("style");return r.textContent="@font-face{font-family:Inter;src:url("+new URL("Inter.b9a8e5e2.ttf",n.meta.url).href+");font-display:swap;font-weight:400;font-style:normal}@font-face{font-family:Inter;src:url("+new URL("Inter-Bold.790c108b.ttf",n.meta.url).href+');font-display:swap;font-weight:600;font-style:normal}@keyframes slideOut{0%{transform:translate(10rem)}to{transform:translate(0)}}@keyframes pulse{0%{transform:scale(1)}50%{transform:scale(1.1)}to{transform:scale(1)}}*{scrollbar-width:thick;scrollbar-color:var(--scrollbar-color) transparent}*::-webkit-scrollbar{width:8px;height:8px}*::-webkit-scrollbar-track{background:transparent}*::-webkit-scrollbar-thumb{background:var(--scrollbar-color);border-radius:8px;border:2px solid var(--scrollbar-color)}*::-webkit-scrollbar-thumb:hover{background:var(--scrollbar-color-hover);border:2px solid var(--scrollbar-color-hover)}::-webkit-scrollbar-button{background:transparent}[data-theme=dark]{--white: rgb(255, 255, 255);--accent-color-dim: rgb(57, 25, 153);--accent-color: rgb(80, 40, 200);--accent-color-bright: rgb(104, 60, 230);--accent-color-hover: var(--accent-color-bright);--root-bg-color: rgb(10, 10, 10);--background-color: rgb(26, 26, 32);--background-color-light: rgb(40, 44, 48);--background-color-secondary: rgb(16, 16, 22);--text-color: rgb(255, 255, 255);--text-color-secondary: rgb(160, 162, 188);--subtext-color: rgb(24, 24, 34);--subtext-color-bright: rgb(48, 48, 64);--border-color: rgb(30, 30, 46);--border-color-light: rgb(60, 60, 76);--svg-color: rgb(255, 255, 255);--invalid: rgb(255, 75, 75);--invalid-secondary: rgb(120, 5, 5);--destructive-color: rgb(185, 55, 55);--destructive-color-hover: rgb(255, 75, 75);--warning-color: rgb(200, 88, 40);--warning-color-hover: rgb(230, 117, 60);--border-color-invalid: rgb(255, 80, 50);--box-shadow-color-invalid: rgb(210, 30, 10);--tab-color: rgb(30, 32, 42);--tab-hover-color: rgb(46, 48, 58);--tab-panel-bg: rgb(36, 38, 48);--tab-list-bg: var(--accent-color);--tab-list-text: rgb(202, 204, 216);--tab-list-text-inactive: rgb(92, 94, 114);--btn-base-color: rgb(30, 32, 42);--btn-base-color-hover: rgb(46, 48, 68);--btn-load-more: rgb(30, 32, 42);--btn-load-more-hover: rgb(54, 56, 66);--btn-svg-color: rgb(255, 255, 255);--btn-delete-image: rgb(182, 46, 46);--btn-checkbox-border-hover: rgb(46, 48, 68);--progress-bar-color: var(--accent-color);--prompt-bg-color: rgb(10, 10, 10);--switch-bg-color: rgb(100, 102, 110);--switch-bg-active-color: var(--accent-color);--slider-color: var(--accent-color-bright);--slider-color: rgb(151, 113, 255);--slider-mark-color: rgb(151, 113, 255);--resizeable-handle-border-color: var(--accent-color);--metadata-bg-color: rgba(0, 0, 0, .7);--metadata-json-bg-color: rgba(255, 255, 255, .1);--status-good-color: rgb(125, 255, 100);--status-good-glow: rgb(40, 215, 40);--status-working-color: rgb(255, 175, 55);--status-working-glow: rgb(255, 160, 55);--status-bad-color: rgb(255, 90, 90);--status-bad-glow: rgb(255, 40, 40);--notice-color: rgb(130, 71, 19);--settings-modal-bg: rgb(30, 32, 42);--input-checkbox-bg: rgb(60, 64, 68);--input-checkbox-checked-bg: var(--accent-color);--input-checkbox-checked-tick: rgb(0, 0, 0);--input-border-color: var(--accent-color-bright);--input-box-shadow-color: var(--accent-color);--error-level-info: rgb(200, 202, 224);--error-level-warning: rgb(255, 225, 105);--error-level-error: rgb(255, 81, 46);--console-bg-color: rgb(30, 30, 36);--console-icon-button-bg-color: rgb(50, 53, 64);--console-icon-button-bg-color-hover: rgb(70, 73, 84);--img2img-img-bg-color: rgb(30, 32, 42);--context-menu-bg-color: rgb(46, 48, 58);--context-menu-box-shadow: none;--context-menu-bg-color-hover: rgb(30, 32, 42);--floating-button-drop-shadow-color: var(--accent-color);--inpainting-alerts-bg: rgba(20, 20, 26, .75);--inpainting-alerts-icon-color: rgb(255, 255, 255);--inpainting-alerts-bg-active: var(--accent-color);--inpainting-alerts-icon-active: rgb(255, 255, 255);--inpainting-alerts-bg-alert: var(--invalid);--inpainting-alerts-icon-alert: rgb(255, 255, 255);--checkboard-dots-color: rgb(35, 35, 39);--scrollbar-color: var(--accent-color);--scrollbar-color-hover: var(--accent-color-bright)}[data-theme=light]{--white: rgb(255, 255, 255);--accent-color-dim: rgb(186, 146, 0);--accent-color: rgb(235, 185, 5);--accent-color-bright: rgb(255, 200, 0);--accent-color-hover: var(--accent-color-bright);--root-bg-color: rgb(255, 255, 255);--background-color: rgb(220, 222, 224);--background-color-light: rgb(250, 252, 254);--background-color-secondary: rgb(208, 210, 212);--text-color: rgb(0, 0, 0);--text-color-secondary: rgb(40, 40, 40);--subtext-color: rgb(24, 24, 34);--subtext-color-bright: rgb(142, 144, 146);--border-color: rgb(200, 200, 200);--border-color-light: rgb(147, 147, 147);--svg-color: rgb(50, 50, 50);--invalid: rgb(255, 75, 75);--invalid-secondary: rgb(120, 5, 5);--destructive-color: rgb(237, 51, 51);--destructive-color-hover: rgb(255, 55, 55);--warning-color: rgb(224, 142, 42);--warning-color-hover: rgb(255, 167, 60);--border-color-invalid: rgb(255, 80, 50);--box-shadow-color-invalid: none;--tab-color: rgb(202, 204, 206);--tab-hover-color: rgb(196, 198, 200);--tab-panel-bg: rgb(206, 208, 210);--tab-list-bg: rgb(235, 185, 5);--tab-list-text: rgb(0, 0, 0);--tab-list-text-inactive: rgb(106, 108, 110);--btn-base-color: rgb(184, 186, 188);--btn-base-color-hover: rgb(230, 232, 234);--btn-load-more: rgb(202, 204, 206);--btn-load-more-hover: rgb(178, 180, 182);--btn-svg-color: rgb(0, 0, 0);--btn-delete-image: rgb(213, 49, 49);--btn-checkbox-border-hover: rgb(176, 178, 182);--progress-bar-color: rgb(235, 185, 5);--prompt-bg-color: rgb(225, 227, 229);--switch-bg-color: rgb(178, 180, 182);--switch-bg-active-color: rgb(235, 185, 5);--slider-color: var(--accent-color);--slider-mark-color: rgb(0, 0, 0);--resizeable-handle-border-color: rgb(160, 162, 164);--metadata-bg-color: rgba(230, 230, 230, .9);--metadata-json-bg-color: rgba(0, 0, 0, .1);--status-good-color: rgb(21, 126, 0);--status-good-glow: var(--background-color);--status-working-color: rgb(235, 141, 0);--status-working-glow: var(--background-color);--status-bad-color: rgb(202, 0, 0);--status-bad-glow: var(--background-color);--notice-color: rgb(255, 71, 90);--settings-modal-bg: rgb(202, 204, 206);--input-checkbox-bg: rgb(167, 167, 171);--input-checkbox-checked-bg: rgb(235, 185, 5);--input-checkbox-checked-tick: rgb(0, 0, 0);--input-border-color: rgb(0, 0, 0);--input-box-shadow-color: none;--error-level-info: rgb(42, 42, 42);--error-level-warning: rgb(173, 121, 0);--error-level-error: rgb(145, 14, 0);--console-bg-color: rgb(220, 224, 230);--console-icon-button-bg-color: var(--switch-bg-color);--console-icon-button-bg-color-hover: var(--resizeable-handle-border-color);--img2img-img-bg-color: rgb(180, 182, 184);--context-menu-bg-color: var(--background-color);--context-menu-box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, .35), 0px 10px 20px -15px rgba(22, 23, 24, .2);--context-menu-bg-color-hover: var(--background-color-secondary);--floating-button-drop-shadow-color: rgba(0, 0, 0, .7);--inpainting-alerts-bg: rgba(220, 222, 224, .75);--inpainting-alerts-icon-color: rgb(0, 0, 0);--inpainting-alerts-bg-active: rgb(255, 200, 0);--inpainting-alerts-icon-active: rgb(0, 0, 0);--inpainting-alerts-bg-alert: var(--invalid);--inpainting-alerts-icon-alert: rgb(0, 0, 0);--checkboard-dots-color: rgb(160, 160, 172);--scrollbar-color: rgb(180, 180, 184);--scrollbar-color-hover: rgb(150, 150, 154)}[data-theme=green]{--white: rgb(255, 255, 255);--accent-color-dim: rgb(10, 60, 40);--accent-color: rgb(20, 110, 70);--accent-color-bright: rgb(30, 180, 100);--accent-color-hover: var(--accent-color-bright);--root-bg-color: rgb(10, 10, 14);--background-color: rgb(30, 32, 37);--background-color-light: rgb(40, 44, 48);--background-color-secondary: rgb(22, 24, 28);--text-color: rgb(255, 255, 255);--text-color-secondary: rgb(160, 164, 168);--subtext-color: rgb(24, 24, 28);--subtext-color-bright: rgb(68, 72, 76);--border-color: rgb(40, 44, 48);--border-color-light: rgb(60, 60, 64);--svg-color: rgb(220, 224, 228);--invalid: rgb(255, 75, 75);--invalid-secondary: rgb(120, 5, 5);--destructive-color: rgb(185, 55, 55);--destructive-color-hover: rgb(255, 75, 75);--warning-color: rgb(200, 88, 40);--warning-color-hover: rgb(230, 117, 60);--border-color-invalid: rgb(255, 80, 50);--box-shadow-color-invalid: rgb(210, 30, 10);--tab-color: rgb(40, 44, 48);--tab-hover-color: rgb(48, 52, 56);--tab-panel-bg: rgb(36, 40, 44);--tab-list-bg: var(--accent-color);--tab-list-text: rgb(202, 204, 206);--tab-list-text-inactive: rgb(92, 94, 96);--btn-base-color: rgb(40, 44, 48);--btn-base-color-hover: rgb(56, 60, 64);--btn-load-more: rgb(30, 32, 42);--btn-load-more-hover: rgb(54, 56, 66);--btn-svg-color: rgb(255, 255, 255);--btn-delete-image: rgb(182, 46, 46);--btn-checkbox-border-hover: rgb(46, 48, 68);--progress-bar-color: var(--accent-color);--prompt-bg-color: rgb(10, 10, 14);--switch-bg-color: rgb(100, 102, 110);--switch-bg-active-color: var(--accent-color);--slider-color: var(--accent-color-bright);--slider-mark-color: var(--accent-color-bright);--resizeable-handle-border-color: var(--accent-color);--metadata-bg-color: rgba(0, 0, 0, .7);--metadata-json-bg-color: rgba(255, 255, 255, .1);--status-good-color: rgb(125, 255, 100);--status-good-glow: rgb(40, 215, 40);--status-working-color: rgb(255, 175, 55);--status-working-glow: rgb(255, 160, 55);--status-bad-color: rgb(255, 90, 90);--status-bad-glow: rgb(255, 40, 40);--notice-color: rgb(130, 71, 19);--settings-modal-bg: rgb(30, 32, 42);--input-checkbox-bg: rgb(60, 64, 68);--input-checkbox-checked-bg: var(--accent-color);--input-checkbox-checked-tick: rgb(0, 0, 0);--input-border-color: var(--accent-color-bright);--input-box-shadow-color: var(--accent-color);--error-level-info: rgb(200, 202, 224);--error-level-warning: rgb(255, 225, 105);--error-level-error: rgb(255, 81, 46);--console-bg-color: rgb(30, 30, 36);--console-icon-button-bg-color: rgb(50, 53, 64);--console-icon-button-bg-color-hover: rgb(70, 73, 84);--img2img-img-bg-color: rgb(30, 32, 42);--context-menu-bg-color: rgb(46, 48, 58);--context-menu-box-shadow: none;--context-menu-bg-color-hover: rgb(30, 32, 42);--floating-button-drop-shadow-color: var(--accent-color);--inpainting-alerts-bg: rgba(20, 20, 26, .75);--inpainting-alerts-icon-color: rgb(255, 255, 255);--inpainting-alerts-bg-active: var(--accent-color);--inpainting-alerts-icon-active: rgb(255, 255, 255);--inpainting-alerts-bg-alert: var(--invalid);--inpainting-alerts-icon-alert: rgb(255, 255, 255);--checkboard-dots-color: rgb(35, 35, 39);--scrollbar-color: var(--accent-color);--scrollbar-color-hover: var(--accent-color-bright)}@media (max-width: 600px){#root .app-content{padding:5px}#root .app-content .site-header{position:fixed;display:flex;height:100px;z-index:1}#root .app-content .site-header .site-header-left-side{position:absolute;display:flex;min-width:145px;float:left;padding-left:0}#root .app-content .site-header .site-header-right-side{display:grid;grid-template-columns:1fr 1fr 1fr 1fr 1fr 1fr;grid-template-rows:25px 25px 25px;grid-template-areas:"logoSpace logoSpace logoSpace sampler sampler sampler" "status status status status status status" "btn1 btn2 btn3 btn4 btn5 btn6";row-gap:15px}#root .app-content .site-header .site-header-right-side .chakra-popover__popper{grid-area:logoSpace}#root .app-content .site-header .site-header-right-side>:nth-child(1).chakra-text{grid-area:status;width:100%;display:flex;justify-content:center}#root .app-content .site-header .site-header-right-side>:nth-child(2){grid-area:sampler;display:flex;justify-content:center;align-items:center}#root .app-content .site-header .site-header-right-side>:nth-child(2) select{width:185px;margin-top:10px}#root .app-content .site-header .site-header-right-side>:nth-child(2) .chakra-select__icon-wrapper{right:10px}#root .app-content .site-header .site-header-right-side>:nth-child(2) .chakra-select__icon-wrapper svg{margin-top:10px}#root .app-content .site-header .site-header-right-side>:nth-child(3){grid-area:btn1}#root .app-content .site-header .site-header-right-side>:nth-child(4){grid-area:btn2}#root .app-content .site-header .site-header-right-side>:nth-child(6){grid-area:btn3}#root .app-content .site-header .site-header-right-side>:nth-child(7){grid-area:btn4}#root .app-content .site-header .site-header-right-side>:nth-child(8){grid-area:btn5}#root .app-content .site-header .site-header-right-side>:nth-child(9){grid-area:btn6}#root .app-content .app-tabs{position:fixed;display:flex;flex-direction:column;row-gap:15px;max-width:100%;overflow:hidden;margin-top:120px}#root .app-content .app-tabs .app-tabs-list{display:flex;justify-content:space-between}#root .app-content .app-tabs .app-tabs-panels{overflow:hidden;overflow-y:scroll}#root .app-content .app-tabs .app-tabs-panels .workarea-main{display:grid;grid-template-areas:"workarea" "options" "gallery";row-gap:15px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .options-panel-wrapper{grid-area:options;width:100%;max-width:100%;height:inherit;overflow:inherit;padding:0 10px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .options-panel-wrapper .main-options-row,#root .app-content .app-tabs .app-tabs-panels .workarea-main .options-panel-wrapper .advanced-settings-item{max-width:100%}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper{grid-area:workarea}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .workarea-split-view{display:flex;flex-direction:column}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .current-image-options{column-gap:3px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .text-to-image-area{padding:0}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .current-image-preview{height:430px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .image-upload-button{row-gap:10px;padding:5px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .image-upload-button svg{width:2rem;height:2rem;margin-top:10px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .inpainting-settings{display:flex;flex-wrap:wrap;row-gap:10px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .inpainting-canvas-area .konvajs-content{height:400px!important}#root .app-content .app-tabs .app-tabs-panels .workarea-main .image-gallery-wrapper{grid-area:gallery;min-height:400px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .image-gallery-wrapper .image-gallery-popup{width:100%!important;max-width:100%!important}}svg{fill:var(--svg-color)}.App{display:grid;width:100vw;height:100vh;background-color:var(--background-color)}.app-content{display:grid;row-gap:1rem;padding:1rem;grid-auto-rows:min-content auto;width:calc(100vw + -0px);height:calc(100vh - .3rem)}.site-header{display:grid;grid-template-columns:auto max-content}.site-header-left-side{display:flex;align-items:center;column-gap:.7rem;padding-left:.5rem}.site-header-left-side img{width:32px;height:32px}.site-header-left-side h1{font-size:1.4rem}.site-header-right-side{display:flex;align-items:center;column-gap:.5rem}.site-header-right-side .lang-select-btn[data-selected=true],.site-header-right-side .lang-select-btn[data-selected=true]:hover{background-color:var(--accent-color)}.status{font-size:.8rem;font-weight:700}.status-good{color:var(--status-good-color);text-shadow:0 0 10px var(--status-good-glow)}.status-bad{color:var(--status-bad-color);text-shadow:0 0 10px var(--status-bad-glow)}.status-working{color:var(--status-working-color);text-shadow:0 0 10px var(--status-working-glow)}.settings-modal{max-height:36rem;font-family:Inter}.settings-modal .settings-modal-content{display:grid;row-gap:2rem;overflow-y:scroll}.settings-modal .settings-modal-header{font-weight:700}.settings-modal .settings-modal-items{display:grid;row-gap:.5rem}.settings-modal .settings-modal-items .settings-modal-item{display:grid;grid-auto-flow:column;background-color:var(--background-color);padding:.4rem 1rem;border-radius:.5rem;align-items:center;width:100%}.settings-modal .settings-modal-reset{display:grid;row-gap:1rem}.settings-modal .settings-modal-reset button{min-width:100%;min-height:100%;background-color:var(--destructive-color)!important}.settings-modal .settings-modal-reset button:hover{background-color:var(--destructive-color-hover)}.settings-modal .settings-modal-reset button:disabled{background-color:var(--btn-base-color)}.settings-modal .settings-modal-reset button:disabled:hover{background-color:var(--btn-base-color)}.settings-modal .settings-modal-reset button svg{width:20px;height:20px;color:var(--btn-svg-color)}.add-model-modal{display:flex}.add-model-modal-body{display:flex;flex-direction:column;row-gap:1rem;padding-bottom:2rem}.add-model-form{display:flex;flex-direction:column;row-gap:.5rem}.hotkeys-modal{width:36rem;max-width:36rem;display:grid;padding:1rem;row-gap:1rem;font-family:Inter}.hotkeys-modal h1{font-size:1.2rem;font-weight:700}.hotkeys-modal h2{font-weight:700}.hotkeys-modal-button{display:flex;align-items:center;justify-content:space-between}.hotkeys-modal-items{max-height:36rem;overflow-y:scroll;-ms-overflow-style:none;scrollbar-width:none}.hotkeys-modal-items::-webkit-scrollbar{display:none}.hotkeys-modal-items .chakra-accordion{display:grid;row-gap:.5rem}.hotkeys-modal-items .chakra-accordion__item{border:none;border-radius:.3rem;background-color:var(--tab-hover-color)}.hotkeys-modal-items button{border-radius:.3rem}.hotkeys-modal-items button[aria-expanded=true]{background-color:var(--tab-hover-color);border-radius:.3rem}.hotkey-modal-category{display:grid;row-gap:.5rem}.hotkey-modal-item{display:grid;grid-template-columns:auto max-content;justify-content:space-between;align-items:center;background-color:var(--background-color);padding:.5rem 1rem;border-radius:.3rem}.hotkey-modal-item .hotkey-info{display:grid}.hotkey-modal-item .hotkey-info .hotkey-title{font-weight:700}.hotkey-modal-item .hotkey-info .hotkey-description{font-size:.9rem;color:var(--text-color-secondary)}.hotkey-modal-item .hotkey-key{font-size:.8rem;font-weight:700;background-color:var(--background-color-light);padding:.2rem .5rem;border-radius:.3rem}.console{width:100vw;display:flex;flex-direction:column;background:var(--console-bg-color);overflow:auto;direction:column;font-family:monospace;padding:0 1rem 1rem 3rem;border-top-width:.3rem;border-color:var(--resizeable-handle-border-color)}.console .console-info-color{color:var(--error-level-info)}.console .console-warning-color{color:var(--error-level-warning)}.console .console-error-color{color:var(--status-bad-color)}.console .console-entry{display:flex;column-gap:.5rem}.console .console-entry .console-timestamp{font-weight:semibold}.console .console-entry .console-message{word-break:break-all}.console-toggle-icon-button{background:var(--console-icon-button-bg-color);position:fixed;left:.5rem;bottom:.5rem;z-index:10000}.console-toggle-icon-button:hover{background:var(--console-icon-button-bg-color-hover)}.console-toggle-icon-button[data-error-seen=true],.console-toggle-icon-button[data-error-seen=true]:hover{background:var(--status-bad-color)}.console-autoscroll-icon-button{background:var(--console-icon-button-bg-color);position:fixed;left:.5rem;bottom:3rem;z-index:10000}.console-autoscroll-icon-button:hover{background:var(--console-icon-button-bg-color-hover)}.console-autoscroll-icon-button[data-autoscroll-enabled=true]{background:var(--accent-color)}.console-autoscroll-icon-button[data-autoscroll-enabled=true]:hover{background:var(--accent-color-hover)}.prompt-bar{display:grid;row-gap:1rem}.prompt-bar input,.prompt-bar textarea{background-color:var(--prompt-bg-color);font-size:1rem;border:2px solid var(--border-color)}.prompt-bar input:hover,.prompt-bar textarea:hover{border:2px solid var(--border-color-light)}.prompt-bar input:focus-visible,.prompt-bar textarea:focus-visible{border:2px solid var(--input-border-color);box-shadow:0 0 10px 0 var(--input-box-shadow-color)}.prompt-bar input[aria-invalid=true],.prompt-bar textarea[aria-invalid=true]{border:2px solid var(--border-color-invalid);box-shadow:0 0 10px 0 var(--box-shadow-color-invalid)}.prompt-bar input:disabled,.prompt-bar textarea:disabled{border:2px solid var(--border-color);box-shadow:none}.prompt-bar textarea{min-height:10rem}.process-buttons{display:flex;column-gap:.5rem}.invoke-btn{flex-grow:1;width:100%;min-width:100%;min-height:100%;background-color:var(--accent-color)!important}.invoke-btn:hover{background-color:var(--accent-color-hover)}.invoke-btn:disabled{background-color:var(--btn-base-color)}.invoke-btn:disabled:hover{background-color:var(--btn-base-color)}.invoke-btn svg{width:16px;height:16px;color:var(--btn-svg-color)}.cancel-btn{min-width:3rem;min-height:100%;background-color:var(--destructive-color)!important}.cancel-btn:hover{background-color:var(--destructive-color-hover)}.cancel-btn:disabled{background-color:var(--btn-base-color)}.cancel-btn:disabled:hover{background-color:var(--btn-base-color)}.cancel-btn svg{width:20px;height:20px;color:var(--btn-svg-color)}.loopback-btn[data-as-checkbox=true]{background-color:var(--btn-btn-base-color);border:3px solid var(--btn-btn-base-color)}.loopback-btn[data-as-checkbox=true] svg{fill:var(--text-color)}.loopback-btn[data-as-checkbox=true]:hover{background-color:var(--btn-btn-base-color);border-color:var(--btn-checkbox-border-hover)}.loopback-btn[data-as-checkbox=true]:hover svg{fill:var(--text-color)}.loopback-btn[data-as-checkbox=true][data-selected=true]{border-color:var(--accent-color);background-color:var(--btn-btn-base-color)}.loopback-btn[data-as-checkbox=true][data-selected=true] svg{fill:var(--text-color)}.loopback-btn[data-as-checkbox=true][data-selected=true]:hover{border-color:var(--accent-color);background-color:var(--btn-btn-base-color)}.loopback-btn[data-as-checkbox=true][data-selected=true]:hover svg{fill:var(--text-color)}.main-options,.main-options-list{display:grid;row-gap:1rem}.main-options-row{display:grid;grid-template-columns:repeat(3,auto);column-gap:.5rem;max-width:22.5rem}.main-option-block{border-radius:.5rem;display:grid!important;grid-template-columns:auto!important;row-gap:.5rem}.main-option-block .invokeai__number-input-form-label,.main-option-block .invokeai__select-label{font-weight:700;font-size:.9rem!important}.main-option-block .invokeai__select-label{margin:0}.advanced-options-checkbox{background-color:var(--background-color-secondary);padding:.5rem 1rem;border-radius:.4rem;font-weight:700}.advanced-settings{padding-top:.5rem;display:grid;row-gap:.5rem}.advanced-settings-item{display:grid;max-width:22.5rem;border:none;border-top:0px;border-radius:.4rem;background-color:var(--tab-panel-bg)}.advanced-settings-item[aria-expanded=true]{background-color:var(--tab-hover-color);border-radius:0 0 .4rem .4rem}.advanced-settings-panel{background-color:var(--tab-panel-bg);border-radius:0 0 .4rem .4rem;padding:1rem}.advanced-settings-panel button{background-color:var(--btn-base-color)}.advanced-settings-panel button:hover{background-color:var(--btn-base-color-hover)}.advanced-settings-panel button:disabled:hover{background-color:var(--btn-base-color)}.advanced-settings-header{border-radius:.4rem;font-weight:700}.advanced-settings-header[aria-expanded=true]{background-color:var(--tab-hover-color);border-radius:.4rem .4rem 0 0}.advanced-settings-header:hover{background-color:var(--tab-hover-color)}.upscale-options{display:grid;grid-template-columns:auto 1fr;column-gap:1rem}.inpainting-bounding-box-settings{display:flex;flex-direction:column;border-radius:.4rem;border:2px solid var(--tab-color)}.inpainting-bounding-box-header{background-color:var(--tab-color);display:flex;flex-direction:row;justify-content:space-between;padding:.5rem 1rem;border-radius:.3rem .3rem 0 0;align-items:center}.inpainting-bounding-box-header button{width:.5rem;height:1.2rem;background:none}.inpainting-bounding-box-header button:hover{background:none}.inpainting-bounding-box-settings-items{padding:1rem;display:flex;flex-direction:column;row-gap:1rem}.inpainting-bounding-box-settings-items .inpainting-bounding-box-reset-icon-btn{background-color:var(--btn-base-color)}.inpainting-bounding-box-settings-items .inpainting-bounding-box-reset-icon-btn:hover{background-color:var(--btn-base-color-hover)}.inpainting-bounding-box-dimensions-slider-numberinput{display:grid;grid-template-columns:repeat(3,auto);column-gap:1rem}.inpainting-bounding-box-darken{width:max-content}.progress-bar{background-color:var(--root-bg-color);height:.3rem;z-index:99}.progress-bar div{background-color:var(--progress-bar-color)}.progress-bar div[data-indeterminate]{background-color:unset;background-image:linear-gradient(to right,transparent 0%,var(--progress-bar-color) 50%,transparent 100%)}.current-image-area{display:flex;flex-direction:column;height:100%;row-gap:1rem;background-color:var(--background-color-secondary);border-radius:.5rem}.current-image-preview{position:relative;justify-content:center;align-items:center;display:flex;width:100%;height:100%}.current-image-preview img{border-radius:.5rem;object-fit:contain;max-width:100%;max-height:100%;height:auto;position:absolute}.current-image-metadata{grid-area:current-image-preview}.current-image-next-prev-buttons{grid-area:current-image-content;display:flex;justify-content:space-between;z-index:1;height:100%;width:100%;pointer-events:none}.next-prev-button-trigger-area{width:7rem;height:100%;width:15%;display:grid;align-items:center;pointer-events:auto}.next-prev-button-trigger-area.prev-button-trigger-area{justify-content:flex-start}.next-prev-button-trigger-area.next-button-trigger-area{justify-content:flex-end}.next-prev-button{font-size:4rem;fill:var(--white);filter:drop-shadow(0 0 1rem var(--text-color-secondary));opacity:70%}.current-image-display-placeholder{background-color:var(--background-color-secondary);display:grid;display:flex;align-items:center;justify-content:center;width:100%;height:100%;border-radius:.5rem}.current-image-display-placeholder svg{width:10rem;height:10rem;color:var(--svg-color)}.current-image-options{width:100%;display:flex;justify-content:center;align-items:center;column-gap:.5em}.current-image-options .current-image-send-to-popover,.current-image-options .current-image-postprocessing-popover{display:flex;flex-direction:column;row-gap:.5rem;max-width:25rem}.current-image-options .current-image-send-to-popover .invokeai__button{place-content:start}.current-image-options .chakra-popover__popper{z-index:11}.current-image-options .delete-image-btn{background-color:var(--btn-base-color)}.current-image-options .delete-image-btn svg{fill:var(--btn-delete-image)}.image-gallery-wrapper-enter{transform:translate(150%)}.image-gallery-wrapper-enter-active{transform:translate(0);transition:all .12s ease-out}.image-gallery-wrapper-exit{transform:translate(0)}.image-gallery-wrapper-exit-active{transform:translate(150%);transition:all .12s ease-out}.image-gallery-wrapper[data-pinned=false]{position:fixed;height:100vh;top:0;right:0}.image-gallery-wrapper[data-pinned=false] .image-gallery-popup{border-radius:0;box-shadow:0 0 1rem var(--text-color-a3)}.image-gallery-wrapper[data-pinned=false] .image-gallery-popup .image-gallery-container{max-height:calc(100vh + 4.7rem)}.image-gallery-wrapper .image-gallery-popup{background-color:var(--background-color-secondary);padding:1rem;display:flex;flex-direction:column;row-gap:1rem;border-radius:.5rem;border-left-width:.3rem;border-color:var(--tab-list-text-inactive)}.image-gallery-wrapper .image-gallery-popup[data-resize-alert=true]{border-color:var(--status-bad-color)}.image-gallery-wrapper .image-gallery-popup .image-gallery-header{display:flex;align-items:center;column-gap:.5rem;justify-content:space-between}.image-gallery-wrapper .image-gallery-popup .image-gallery-header .image-gallery-header-right-icons{display:flex;flex-direction:row;column-gap:.5rem}.image-gallery-wrapper .image-gallery-popup .image-gallery-header .image-gallery-icon-btn{background-color:var(--btn-load-more)}.image-gallery-wrapper .image-gallery-popup .image-gallery-header .image-gallery-icon-btn:hover{background-color:var(--btn-load-more-hover)}.image-gallery-wrapper .image-gallery-popup .image-gallery-header .image-gallery-settings-popover{display:flex;flex-direction:column;row-gap:.5rem}.image-gallery-wrapper .image-gallery-popup .image-gallery-header .image-gallery-settings-popover div{display:flex;column-gap:.5rem;align-items:center;justify-content:space-between}.image-gallery-wrapper .image-gallery-popup .image-gallery-header h1{font-weight:700}.image-gallery-wrapper .image-gallery-popup .image-gallery-container{display:flex;flex-direction:column;max-height:calc(100vh - (70px + 7rem));overflow-y:scroll;-ms-overflow-style:none;scrollbar-width:none}.image-gallery-wrapper .image-gallery-popup .image-gallery-container::-webkit-scrollbar{display:none}.image-gallery-wrapper .image-gallery-popup .image-gallery-container .image-gallery-container-placeholder{display:flex;flex-direction:column;row-gap:.5rem;background-color:var(--background-color);border-radius:.5rem;place-items:center;padding:2rem;text-align:center}.image-gallery-wrapper .image-gallery-popup .image-gallery-container .image-gallery-container-placeholder p{color:var(--subtext-color-bright);font-family:Inter}.image-gallery-wrapper .image-gallery-popup .image-gallery-container .image-gallery-container-placeholder svg{width:4rem;height:4rem;color:var(--svg-color)}.image-gallery-wrapper .image-gallery-popup .image-gallery-container .image-gallery-load-more-btn{background-color:var(--btn-load-more);font-size:.85rem;padding:.5rem;margin-top:1rem}.image-gallery-wrapper .image-gallery-popup .image-gallery-container .image-gallery-load-more-btn:disabled:hover{background-color:var(--btn-load-more)}.image-gallery-wrapper .image-gallery-popup .image-gallery-container .image-gallery-load-more-btn:hover{background-color:var(--btn-load-more-hover)}.image-gallery-category-btn-group{width:max-content;column-gap:0;justify-content:stretch}.image-gallery-category-btn-group button{background-color:var(--btn-base-color);flex-grow:1}.image-gallery-category-btn-group button:hover{background-color:var(--btn-base-color-hover)}.image-gallery-category-btn-group button[data-selected=true]{background-color:var(--accent-color)}.image-gallery-category-btn-group button[data-selected=true]:hover{background-color:var(--accent-color-hover)}.image-gallery{display:grid;grid-gap:.5rem}.image-gallery .hoverable-image{padding:.5rem;position:relative}.image-gallery .hoverable-image:before{content:"";display:block;padding-bottom:100%}.image-gallery .hoverable-image .hoverable-image-image{position:absolute;max-width:100%;top:50%;left:50%;transform:translate(-50%,-50%)}.hoverable-image{display:flex;justify-content:center;transition:transform .2s ease-out}.hoverable-image:hover{cursor:pointer;border-radius:.5rem;z-index:2}.hoverable-image .hoverable-image-image{width:100%;height:100%;max-width:100%;max-height:100%}.hoverable-image .hoverable-image-delete-button{position:absolute;top:.25rem;right:.25rem}.hoverable-image .hoverable-image-content{display:flex;position:absolute;top:0;left:0;width:100%;height:100%;align-items:center;justify-content:center}.hoverable-image .hoverable-image-content .hoverable-image-check{fill:var(--status-good-color)}.hoverable-image .hoverable-image-icons{position:absolute;bottom:-2rem;display:grid;width:min-content;grid-template-columns:repeat(2,max-content);border-radius:.4rem;background-color:var(--background-color-secondary);padding:.2rem;gap:.2rem;grid-auto-rows:max-content}.hoverable-image .hoverable-image-icons button{width:12px;height:12px;border-radius:.2rem;padding:10px 0;flex-shrink:2}.hoverable-image .hoverable-image-icons button svg{width:12px;height:12px}.hoverable-image-context-menu{z-index:15;padding:.4rem;border-radius:.25rem;background-color:var(--context-menu-bg-color);box-shadow:var(--context-menu-box-shadow)}.hoverable-image-context-menu [role=menuitem]{font-size:.8rem;line-height:1rem;border-radius:3px;display:flex;align-items:center;height:1.75rem;padding:0 .5rem;position:relative;user-select:none;cursor:pointer;outline:none}.hoverable-image-context-menu [role=menuitem][data-disabled]{color:gray;pointer-events:none;cursor:not-allowed}.hoverable-image-context-menu [role=menuitem][data-warning]{color:var(--status-bad-color)}.hoverable-image-context-menu [role=menuitem][data-highlighted]{background-color:var(--context-menu-bg-color-hover)}.image-metadata-viewer{position:absolute;top:0;width:100%;border-radius:.5rem;padding:1rem;background-color:var(--metadata-bg-color);overflow:scroll;max-height:calc(100vh - (70px + 5.4rem));height:100%;z-index:10}.image-json-viewer{border-radius:.5rem;margin:0 .5rem 1rem;padding:1rem;overflow-x:scroll;word-break:break-all;background-color:var(--metadata-json-bg-color)}.lightbox-container{width:100%;height:100%;color:var(--text-color);overflow:hidden;position:absolute;left:0;top:0;background-color:var(--background-color-secondary);z-index:30;animation:popIn .3s ease-in}.lightbox-container .image-gallery-wrapper{max-height:100%!important}.lightbox-container .image-gallery-wrapper .image-gallery-container{max-height:calc(100vh - 5rem)}.lightbox-container .current-image-options{z-index:2;position:absolute;top:1rem}.lightbox-container .image-metadata-viewer{left:0;max-height:100%}.lightbox-close-btn{z-index:3;position:absolute;left:1rem;top:1rem;background-color:var(--btn-base-color)}.lightbox-close-btn:hover{background-color:var(--btn-base-color-hover)}.lightbox-close-btn:disabled:hover{background-color:var(--btn-base-color)}.lightbox-display-container{display:flex;flex-direction:row}.lightbox-preview-wrapper{overflow:hidden;background-color:var(--background-color-secondary);display:grid;grid-template-columns:auto max-content;place-items:center;width:100vw;height:100vh}.lightbox-preview-wrapper .current-image-next-prev-buttons{position:absolute}.lightbox-preview-wrapper .lightbox-image{grid-area:lightbox-content;border-radius:.5rem}.lightbox-preview-wrapper .lightbox-image-options{position:absolute;z-index:2;left:1rem;top:4.5rem;user-select:none;border-radius:.5rem;display:flex;flex-direction:column;row-gap:.5rem}@keyframes popIn{0%{opacity:0;filter:blur(100)}to{opacity:1;filter:blur(0)}}.app-tabs{display:grid;grid-template-columns:min-content auto;column-gap:1rem;height:calc(100vh - (70px + 1rem))}.app-tabs-list{display:grid;row-gap:.3rem;grid-auto-rows:min-content;color:var(--tab-list-text-inactive)}.app-tabs-list button{font-size:.85rem;padding:.5rem}.app-tabs-list button:hover{background-color:var(--tab-hover-color);border-radius:.3rem}.app-tabs-list button svg{width:26px;height:26px}.app-tabs-list button[aria-selected=true]{background-color:var(--tab-list-bg);color:var(--tab-list-text);font-weight:700;border-radius:.3rem;border:none}.app-tabs-panels .app-tabs-panel{padding:0;height:100%}.workarea-wrapper{position:relative;width:100%;height:100%}.workarea-wrapper .workarea-main{display:flex;column-gap:1rem;height:100%}.workarea-wrapper .workarea-main .workarea-children-wrapper{position:relative;width:100%;height:100%}.workarea-wrapper .workarea-main .workarea-split-view{width:100%;height:100%;display:grid;grid-template-columns:1fr 1fr;background-color:var(--background-color-secondary);border-radius:.5rem}.workarea-wrapper .workarea-main .workarea-split-view .workarea-split-view-left{padding-right:.5rem}.workarea-wrapper .workarea-main .workarea-split-view .workarea-split-view-right{padding-left:.5rem}.workarea-wrapper .workarea-main .workarea-single-view{width:100%;height:100%;background-color:var(--background-color-secondary);border-radius:.5rem}.workarea-wrapper .workarea-main .workarea-split-view-left,.workarea-wrapper .workarea-main .workarea-split-view-right{display:flex;flex-direction:column;height:100%;width:100%;row-gap:1rem;background-color:var(--background-color-secondary);border-radius:.5rem;padding:1rem}.workarea-split-button{position:absolute;cursor:pointer;padding:.5rem;top:0;right:0}.workarea-split-button[data-selected=true]{top:0;right:0}.workarea-split-button[data-selected=true] svg{opacity:1}.workarea-split-button svg{opacity:.5}.options-panel-wrapper-enter{transform:translate(-150%)}.options-panel-wrapper-enter-active{transform:translate(0);transition:all .12s ease-out}.options-panel-wrapper-exit{transform:translate(0)}.options-panel-wrapper-exit-active{transform:translate(-150%);transition:all .12s ease-out}.options-panel-wrapper{background-color:var(--background-color);height:calc(100vh - (70px + 1rem));width:22.5rem;max-width:22.5rem;flex-shrink:0;position:relative;overflow-y:scroll;-ms-overflow-style:none;scrollbar-width:none}.options-panel-wrapper::-webkit-scrollbar{display:none}.options-panel-wrapper .options-panel{display:flex;flex-direction:column;row-gap:1rem;height:100%;-ms-overflow-style:none;scrollbar-width:none;background-color:var(--background-color)}.options-panel-wrapper .options-panel::-webkit-scrollbar{display:none}.options-panel-wrapper[data-pinned=false]{z-index:20;position:fixed;top:0;left:0;filter:var(--floating-panel-drop-shadow);width:24.5rem;max-width:24.5rem;height:100%}.options-panel-wrapper[data-pinned=false] .options-panel-margin{margin:1rem}.options-panel-wrapper .options-panel-pin-button{position:absolute;cursor:pointer;padding:.5rem;top:1rem;right:1rem;z-index:20}.options-panel-wrapper .options-panel-pin-button[data-selected=true]{top:0;right:0}.options-panel-wrapper .options-panel-pin-button svg{opacity:.5}.invoke-ai-logo-wrapper{display:flex;align-items:center;column-gap:.7rem;padding-left:.5rem;padding-top:.3rem}.invoke-ai-logo-wrapper img{width:32px;height:32px}.invoke-ai-logo-wrapper h1{font-size:1.4rem}.text-to-image-area{padding:1rem;height:100%}.image-to-image-area{display:flex;flex-direction:column;row-gap:1rem;width:100%;height:100%}.image-to-image-strength-main-option{display:flex;row-gap:.5rem!important}.image-to-image-strength-main-option .invokeai__slider-component-label{color:var(--text-color-secondary);font-size:.9rem!important}.init-image-preview-header{display:flex;align-items:center;justify-content:space-between;width:100%}.init-image-preview-header h2{font-weight:700;font-size:.9rem}.init-image-preview{position:relative;height:100%;width:100%;display:flex;align-items:center;justify-content:center}.init-image-preview img{border-radius:.5rem;object-fit:contain;position:absolute}.image-to-image-current-image-display{position:relative}.floating-show-hide-button{position:absolute;top:50%;transform:translateY(-50%);z-index:20;padding:0;background-color:red!important;min-width:2rem;min-height:12rem;background-color:var(--btn-btn-base-color)!important}.floating-show-hide-button.left{left:0;border-radius:0 .5rem .5rem 0}.floating-show-hide-button.right{right:0;border-radius:.5rem 0 0 .5rem}.floating-show-hide-button:hover{background-color:var(--btn-btn-base-color-hover)}.floating-show-hide-button:disabled{background-color:var(--btn-base-color)}.floating-show-hide-button:disabled:hover{background-color:var(--btn-base-color)}.floating-show-hide-button svg{width:20px;height:20px;color:var(--btn-svg-color)}.show-hide-button-options{position:absolute;transform:translateY(-50%);z-index:20;min-width:2rem;top:50%;left:calc(42px + 2rem);border-radius:0 .5rem .5rem 0;display:flex;flex-direction:column;row-gap:.5rem}.show-hide-button-options button{border-radius:0 .3rem .3rem 0}.show-hide-button-gallery{padding-left:.75rem;padding-right:.75rem;background-color:var(--background-color)!important}.inpainting-main-area{display:flex;flex-direction:column;align-items:center;row-gap:1rem;width:100%;height:100%}.inpainting-main-area .inpainting-settings{display:flex;align-items:center;column-gap:.5rem}.inpainting-main-area .inpainting-settings svg{transform:scale(.9)}.inpainting-main-area .inpainting-settings .inpainting-buttons-group{display:flex;align-items:center;column-gap:.5rem}.inpainting-main-area .inpainting-settings .inpainting-button-dropdown{display:flex;flex-direction:column;row-gap:.5rem}.inpainting-main-area .inpainting-settings .inpainting-color-picker{margin-left:1rem}.inpainting-main-area .inpainting-settings .inpainting-brush-options{display:flex;align-items:center;column-gap:1rem}.inpainting-canvas-area{display:flex;flex-direction:column;align-items:center;justify-content:center;row-gap:1rem;width:100%;height:100%}.inpainting-canvas-spiner{display:flex;align-items:center;width:100%;height:100%}.inpainting-canvas-container{display:flex;position:relative;height:100%;width:100%;border-radius:.5rem}.inpainting-canvas-wrapper{position:relative}.inpainting-canvas-stage{outline:none;border-radius:.5rem;box-shadow:0 0 0 1px var(--border-color-light);overflow:hidden}.inpainting-canvas-stage canvas{outline:none;border-radius:.5rem}.inpainting-options-btn{min-height:2rem}.canvas-status-text{position:absolute;top:0;left:0;background-color:var(--background-color);opacity:.65;display:flex;flex-direction:column;font-size:.8rem;padding:.25rem;min-width:12rem;border-radius:.25rem;margin:.25rem;pointer-events:none}.invokeai__number-input-form-control{display:flex;align-items:center;column-gap:1rem}.invokeai__number-input-form-control .invokeai__number-input-form-label{color:var(--text-color-secondary)}.invokeai__number-input-form-control .invokeai__number-input-form-label[data-focus]+.invokeai__number-input-root{outline:none;border:2px solid var(--input-border-color);box-shadow:0 0 10px 0 var(--input-box-shadow-color)}.invokeai__number-input-form-control .invokeai__number-input-form-label[aria-invalid=true]+.invokeai__number-input-root{outline:none;border:2px solid var(--border-color-invalid);box-shadow:0 0 10px 0 var(--box-shadow-color-invalid)}.invokeai__number-input-form-control .invokeai__number-input-root{height:2rem;display:grid;grid-template-columns:auto max-content;column-gap:.5rem;align-items:center;background-color:var(--background-color-secondary);border:2px solid var(--border-color);border-radius:.3rem}.invokeai__number-input-form-control .invokeai__number-input-field{border:none;font-weight:700;width:100%;height:auto;font-size:.9rem;padding:0 .5rem}.invokeai__number-input-form-control .invokeai__number-input-field:focus{outline:none;box-shadow:none}.invokeai__number-input-form-control .invokeai__number-input-field:disabled{opacity:.2}.invokeai__number-input-form-control .invokeai__number-input-stepper{display:grid;padding-right:.5rem}.invokeai__number-input-form-control .invokeai__number-input-stepper .invokeai__number-input-stepper-button{border:none;padding:0 .5rem;margin:0 -.5rem}.invokeai__number-input-form-control .invokeai__number-input-stepper .invokeai__number-input-stepper-button svg{width:10px;height:10px}.input{display:grid;grid-template-columns:max-content auto;column-gap:1rem;align-items:center}.input .input-label{color:var(--text-color-secondary)}.input .input-entry{background-color:var(--background-color-secondary);border:2px solid var(--border-color);border-radius:.2rem;font-weight:700}.input .input-entry:focus{outline:none;border:2px solid var(--input-border-color);box-shadow:0 0 10px 0 var(--input-box-shadow-color)}.input .input-entry:disabled{opacity:.2}.input .input-entry[aria-invalid=true]{outline:none;border:2px solid var(--border-color-invalid);box-shadow:0 0 10px 0 var(--box-shadow-color-invalid)}.invokeai__icon-button{background:var(--btn-base-color);cursor:pointer}.invokeai__icon-button:hover{background-color:var(--btn-base-color-hover)}.invokeai__icon-button[data-selected=true]{background-color:var(--accent-color)}.invokeai__icon-button[data-selected=true]:hover{background-color:var(--accent-color-hover)}.invokeai__icon-button[disabled]{cursor:not-allowed}.invokeai__icon-button[data-variant=link],.invokeai__icon-button[data-variant=link]:hover{background:none}.invokeai__icon-button[data-as-checkbox=true]{background-color:var(--btn-base-color);border:3px solid var(--btn-base-color)}.invokeai__icon-button[data-as-checkbox=true] svg{fill:var(--text-color)}.invokeai__icon-button[data-as-checkbox=true]:hover{background-color:var(--btn-base-color);border-color:var(--btn-checkbox-border-hover)}.invokeai__icon-button[data-as-checkbox=true]:hover svg{fill:var(--text-color)}.invokeai__icon-button[data-as-checkbox=true][data-selected=true]{border-color:var(--accent-color)}.invokeai__icon-button[data-as-checkbox=true][data-selected=true] svg{fill:var(--accent-color-hover)}.invokeai__icon-button[data-as-checkbox=true][data-selected=true]:hover svg{fill:var(--accent-color-hover)}.invokeai__icon-button[data-alert=true]{animation-name:pulseColor;animation-duration:1s;animation-timing-function:ease-in-out;animation-iteration-count:infinite}.invokeai__icon-button[data-alert=true]:hover{animation:none;background-color:var(--accent-color-hover)}@keyframes pulseColor{0%{background-color:var(--accent-color)}50%{background-color:var(--accent-color-dim)}to{background-color:var(--accent-color)}}.invokeai__button{background-color:var(--btn-base-color);place-content:center}.invokeai__button:hover{background-color:var(--btn-base-color-hover)}.invokeai__switch-form-control .invokeai__switch-form-label{color:var(--text-color-secondary)}.invokeai__switch-form-control .invokeai__switch-root span{background-color:var(--switch-bg-color)}.invokeai__switch-form-control .invokeai__switch-root span span{background-color:var(--white)}.invokeai__switch-form-control .invokeai__switch-root[data-checked] span{background:var(--switch-bg-active-color)}.invokeai__switch-form-control .invokeai__switch-root[data-checked] span span{background-color:var(--white)}.invokeai__select{display:flex;column-gap:1rem;align-items:center}.invokeai__select .invokeai__select-label{color:var(--text-color-secondary)}.invokeai__select .invokeai__select-picker{border:2px solid var(--border-color);background-color:var(--background-color-secondary);font-weight:700;font-size:.9rem;height:2rem;border-radius:.2rem}.invokeai__select .invokeai__select-picker:focus{outline:none;border:2px solid var(--input-border-color);box-shadow:0 0 10px 0 var(--input-box-shadow-color)}.invokeai__select .invokeai__select-option{background-color:var(--background-color-secondary);color:var(--text-color-secondary)}.invokeai__slider-component{padding-bottom:.5rem;border-radius:.5rem}.invokeai__slider-component .invokeai__slider-component-label{min-width:max-content;margin:0;font-weight:700;font-size:.9rem;color:var(--text-color-secondary)}.invokeai__slider-component .invokeai__slider_track{background-color:var(--tab-color)}.invokeai__slider-component .invokeai__slider_track-filled{background-color:var(--slider-color)}.invokeai__slider-component .invokeai__slider-thumb{width:4px}.invokeai__slider-component .invokeai__slider-mark{font-size:.75rem;font-weight:700;color:var(--slider-mark-color);margin-top:.3rem}.invokeai__slider-component .invokeai__slider-number-input{border:none;font-size:.9rem;font-weight:700;height:2rem;background-color:var(--background-color-secondary);border:2px solid var(--border-color)}.invokeai__slider-component .invokeai__slider-number-input:focus{outline:none;box-shadow:none;border:2px solid var(--input-border-color);box-shadow:0 0 10px 0 var(--input-box-shadow-color)}.invokeai__slider-component .invokeai__slider-number-input:disabled{opacity:.2}.invokeai__slider-component .invokeai__slider-number-stepper{border:none}.invokeai__slider-component[data-markers=true] .invokeai__slider_container{margin-top:-1rem}.invokeai__checkbox .chakra-checkbox__label{margin-top:1px;color:var(--text-color-secondary);font-size:.9rem}.invokeai__checkbox .chakra-checkbox__control{width:1rem;height:1rem;border:none;border-radius:.2rem;background-color:var(--input-checkbox-bg)}.invokeai__checkbox .chakra-checkbox__control svg{width:.6rem;height:.6rem;stroke-width:3px}.invokeai__checkbox .chakra-checkbox__control[data-checked]{color:var(--text-color);background-color:var(--input-checkbox-checked-bg)}.invokeai__popover-content{min-width:unset;width:unset;padding:1rem;border-radius:.5rem;background-color:var(--background-color);border:2px solid var(--border-color)}.invokeai__popover-content .invokeai__popover-arrow{background-color:var(--background-color)!important}.invokeai__color-picker .react-colorful__hue-pointer,.invokeai__color-picker .react-colorful__saturation-pointer{width:1.5rem;height:1.5rem;border-color:var(--white)}.dropzone-container{position:absolute;top:0;left:0;width:100vw;height:100vh;z-index:999;backdrop-filter:blur(20px)}.dropzone-container .dropzone-overlay{opacity:.5;width:100%;height:100%;display:flex;flex-direction:column;row-gap:1rem;align-items:center;justify-content:center;background-color:var(--background-color)}.dropzone-container .dropzone-overlay.is-drag-accept{box-shadow:inset 0 0 20rem 1rem var(--accent-color)}.dropzone-container .dropzone-overlay.is-drag-reject{box-shadow:inset 0 0 20rem 1rem var(--status-bad-color)}.dropzone-container .dropzone-overlay.is-handling-upload{box-shadow:inset 0 0 20rem 1rem var(--status-working-color)}.image-uploader-button-outer{width:100%;height:100%;display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:.5rem;color:var(--tab-list-text-inactive);background-color:var(--background-color)}.image-uploader-button-outer:hover{background-color:var(--background-color-light)}.image-upload-button-inner{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.image-upload-button{display:flex;flex-direction:column;row-gap:2rem;align-items:center;justify-content:center;text-align:center}.image-upload-button svg{width:4rem;height:4rem}.image-upload-button h2{font-size:1.2rem}.work-in-progress{display:grid;width:100%;height:calc(100vh - (70px + 1rem));grid-auto-rows:max-content;background-color:var(--background-color-secondary);border-radius:.4rem;place-content:center;place-items:center;row-gap:1rem}.work-in-progress h1{font-size:2rem;font-weight:700}.work-in-progress p{text-align:center;max-width:50rem;color:var(--subtext-color-bright)}.guide-popover-arrow{background-color:var(--tab-panel-bg);box-shadow:none}.guide-popover-content{background-color:var(--background-color-secondary);border:none}.guide-popover-guide-content{background:var(--tab-panel-bg);border:2px solid var(--tab-hover-color);border-radius:.4rem;padding:.75rem 1rem;display:grid;grid-template-rows:repeat(auto-fill,1fr);grid-row-gap:.5rem;justify-content:space-between}.modal{background-color:var(--background-color-secondary);color:var(--text-color)}.modal-close-btn{background-color:var(--btn-base-color)}.modal-close-btn:hover{background-color:var(--btn-base-color-hover)}.modal-close-btn:disabled:hover{background-color:var(--btn-base-color)}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html,body{-ms-overflow-style:none;scrollbar-width:none;background-color:var(--root-bg-color);overflow:hidden}html::-webkit-scrollbar,body::-webkit-scrollbar{display:none}#root{background-color:var(--root-bg-color);color:var(--text-color);font-family:Inter,Arial,Helvetica,sans-serif}\n',document.head.appendChild(r),{execute:function(){function r(e,t){for(var n=0;nr[t]})}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}var o="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function i(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var a={exports:{}},s={},l=Symbol.for("react.element"),c=Symbol.for("react.portal"),u=Symbol.for("react.fragment"),d=Symbol.for("react.strict_mode"),h=Symbol.for("react.profiler"),f=Symbol.for("react.provider"),p=Symbol.for("react.context"),g=Symbol.for("react.forward_ref"),m=Symbol.for("react.suspense"),v=Symbol.for("react.memo"),y=Symbol.for("react.lazy"),b=Symbol.iterator;var x={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},w=Object.assign,k={};function S(e,t,n){this.props=e,this.context=t,this.refs=k,this.updater=n||x}function C(){}function _(e,t,n){this.props=e,this.context=t,this.refs=k,this.updater=n||x}S.prototype.isReactComponent={},S.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")},S.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},C.prototype=S.prototype;var E=_.prototype=new C;E.constructor=_,w(E,S.prototype),E.isPureReactComponent=!0;var P=Array.isArray,L=Object.prototype.hasOwnProperty,O={current:null},M={key:!0,ref:!0,__self:!0,__source:!0};function T(e,t,n){var r,o={},i=null,a=null;if(null!=t)for(r in void 0!==t.ref&&(a=t.ref),void 0!==t.key&&(i=""+t.key),t)L.call(t,r)&&!M.hasOwnProperty(r)&&(o[r]=t[r]);var s=arguments.length-2;if(1===s)o.children=n;else if(1:nth-child(1).chakra-text{grid-area:status;width:100%;display:flex;justify-content:center}#root .app-content .site-header .site-header-right-side>:nth-child(2){grid-area:sampler;display:flex;justify-content:center;align-items:center}#root .app-content .site-header .site-header-right-side>:nth-child(2) select{width:185px;margin-top:10px}#root .app-content .site-header .site-header-right-side>:nth-child(2) .chakra-select__icon-wrapper{right:10px}#root .app-content .site-header .site-header-right-side>:nth-child(2) .chakra-select__icon-wrapper svg{margin-top:10px}#root .app-content .site-header .site-header-right-side>:nth-child(3){grid-area:btn1}#root .app-content .site-header .site-header-right-side>:nth-child(4){grid-area:btn2}#root .app-content .site-header .site-header-right-side>:nth-child(6){grid-area:btn3}#root .app-content .site-header .site-header-right-side>:nth-child(7){grid-area:btn4}#root .app-content .site-header .site-header-right-side>:nth-child(8){grid-area:btn5}#root .app-content .site-header .site-header-right-side>:nth-child(9){grid-area:btn6}#root .app-content .app-tabs{position:fixed;display:flex;flex-direction:column;row-gap:15px;max-width:100%;overflow:hidden;margin-top:120px}#root .app-content .app-tabs .app-tabs-list{display:flex;justify-content:space-between}#root .app-content .app-tabs .app-tabs-panels{overflow:hidden;overflow-y:scroll}#root .app-content .app-tabs .app-tabs-panels .workarea-main{display:grid;grid-template-areas:"workarea" "options" "gallery";row-gap:15px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .options-panel-wrapper{grid-area:options;width:100%;max-width:100%;height:inherit;overflow:inherit;padding:0 10px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .options-panel-wrapper .main-options-row,#root .app-content .app-tabs .app-tabs-panels .workarea-main .options-panel-wrapper .advanced-settings-item{max-width:100%}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper{grid-area:workarea}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .workarea-split-view{display:flex;flex-direction:column}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .current-image-options{column-gap:3px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .text-to-image-area{padding:0}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .current-image-preview{height:430px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .image-upload-button{row-gap:10px;padding:5px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .image-upload-button svg{width:2rem;height:2rem;margin-top:10px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .inpainting-settings{display:flex;flex-wrap:wrap;row-gap:10px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .workarea-children-wrapper .inpainting-canvas-area .konvajs-content{height:400px!important}#root .app-content .app-tabs .app-tabs-panels .workarea-main .image-gallery-wrapper{grid-area:gallery;min-height:400px}#root .app-content .app-tabs .app-tabs-panels .workarea-main .image-gallery-wrapper .image-gallery-popup{width:100%!important;max-width:100%!important}}svg{fill:var(--svg-color)}.App{display:grid;width:100vw;height:100vh;background-color:var(--background-color)}.app-content{display:grid;row-gap:1rem;padding:1rem;grid-auto-rows:min-content auto;width:calc(100vw + -0px);height:calc(100vh - .3rem)}.site-header{display:grid;grid-template-columns:auto max-content}.site-header-left-side{display:flex;align-items:center;column-gap:.7rem;padding-left:.5rem}.site-header-left-side img{width:32px;height:32px}.site-header-right-side{display:flex;align-items:center;column-gap:.5rem}.site-header-right-side .lang-select-btn[data-selected=true],.site-header-right-side .lang-select-btn[data-selected=true]:hover{background-color:var(--accent-color)}.status{font-size:.8rem;font-weight:700}.status-good{color:var(--status-good-color);text-shadow:0 0 10px var(--status-good-glow)}.status-bad{color:var(--status-bad-color);text-shadow:0 0 10px var(--status-bad-glow)}.status-working{color:var(--status-working-color);text-shadow:0 0 10px var(--status-working-glow)}.settings-modal{max-height:36rem;font-family:Inter}.settings-modal .settings-modal-content{display:grid;row-gap:2rem;overflow-y:scroll}.settings-modal .settings-modal-header{font-weight:700}.settings-modal .settings-modal-items{display:grid;row-gap:.5rem}.settings-modal .settings-modal-items .settings-modal-item{display:grid;grid-auto-flow:column;background-color:var(--background-color);padding:.4rem 1rem;border-radius:.5rem;align-items:center;width:100%}.settings-modal .settings-modal-reset{display:grid;row-gap:1rem}.settings-modal .settings-modal-reset button{min-width:100%;min-height:100%;background-color:var(--destructive-color)!important}.settings-modal .settings-modal-reset button:hover{background-color:var(--destructive-color-hover)}.settings-modal .settings-modal-reset button:disabled{background-color:var(--btn-base-color)}.settings-modal .settings-modal-reset button:disabled:hover{background-color:var(--btn-base-color)}.settings-modal .settings-modal-reset button svg{width:20px;height:20px;color:var(--btn-svg-color)}.add-model-modal{display:flex}.add-model-modal-body{display:flex;flex-direction:column;row-gap:1rem;padding-bottom:2rem}.add-model-form{display:flex;flex-direction:column;row-gap:.5rem}.hotkeys-modal{width:36rem;max-width:36rem;display:grid;padding:1rem;row-gap:1rem;font-family:Inter}.hotkeys-modal h1{font-size:1.2rem;font-weight:700}.hotkeys-modal h2{font-weight:700}.hotkeys-modal-button{display:flex;align-items:center;justify-content:space-between}.hotkeys-modal-items{max-height:36rem;overflow-y:scroll;-ms-overflow-style:none;scrollbar-width:none}.hotkeys-modal-items::-webkit-scrollbar{display:none}.hotkeys-modal-items .chakra-accordion{display:grid;row-gap:.5rem}.hotkeys-modal-items .chakra-accordion__item{border:none;border-radius:.3rem;background-color:var(--tab-hover-color)}.hotkeys-modal-items button{border-radius:.3rem}.hotkeys-modal-items button[aria-expanded=true]{background-color:var(--tab-hover-color);border-radius:.3rem}.hotkey-modal-category{display:grid;row-gap:.5rem}.hotkey-modal-item{display:grid;grid-template-columns:auto max-content;justify-content:space-between;align-items:center;background-color:var(--background-color);padding:.5rem 1rem;border-radius:.3rem}.hotkey-modal-item .hotkey-info{display:grid}.hotkey-modal-item .hotkey-info .hotkey-title{font-weight:700}.hotkey-modal-item .hotkey-info .hotkey-description{font-size:.9rem;color:var(--text-color-secondary)}.hotkey-modal-item .hotkey-key{font-size:.8rem;font-weight:700;background-color:var(--background-color-light);padding:.2rem .5rem;border-radius:.3rem}.console{width:100vw;display:flex;flex-direction:column;background:var(--console-bg-color);overflow:auto;direction:column;font-family:monospace;padding:0 1rem 1rem 3rem;border-top-width:.3rem;border-color:var(--resizeable-handle-border-color)}.console .console-info-color{color:var(--error-level-info)}.console .console-warning-color{color:var(--error-level-warning)}.console .console-error-color{color:var(--status-bad-color)}.console .console-entry{display:flex;column-gap:.5rem}.console .console-entry .console-timestamp{font-weight:semibold}.console .console-entry .console-message{word-break:break-all}.console-toggle-icon-button{background:var(--console-icon-button-bg-color);position:fixed;left:.5rem;bottom:.5rem;z-index:10000}.console-toggle-icon-button:hover{background:var(--console-icon-button-bg-color-hover)}.console-toggle-icon-button[data-error-seen=true],.console-toggle-icon-button[data-error-seen=true]:hover{background:var(--status-bad-color)}.console-autoscroll-icon-button{background:var(--console-icon-button-bg-color);position:fixed;left:.5rem;bottom:3rem;z-index:10000}.console-autoscroll-icon-button:hover{background:var(--console-icon-button-bg-color-hover)}.console-autoscroll-icon-button[data-autoscroll-enabled=true]{background:var(--accent-color)}.console-autoscroll-icon-button[data-autoscroll-enabled=true]:hover{background:var(--accent-color-hover)}.prompt-bar{display:grid;row-gap:1rem}.prompt-bar input,.prompt-bar textarea{background-color:var(--prompt-bg-color);font-size:1rem;border:2px solid var(--border-color)}.prompt-bar input:hover,.prompt-bar textarea:hover{border:2px solid var(--border-color-light)}.prompt-bar input:focus-visible,.prompt-bar textarea:focus-visible{border:2px solid var(--input-border-color);box-shadow:0 0 10px 0 var(--input-box-shadow-color)}.prompt-bar input[aria-invalid=true],.prompt-bar textarea[aria-invalid=true]{border:2px solid var(--border-color-invalid);box-shadow:0 0 10px 0 var(--box-shadow-color-invalid)}.prompt-bar input:disabled,.prompt-bar textarea:disabled{border:2px solid var(--border-color);box-shadow:none}.prompt-bar textarea{min-height:10rem}.process-buttons{display:flex;column-gap:.5rem}.invoke-btn{flex-grow:1;width:100%;min-width:100%;min-height:100%;background-color:var(--accent-color)!important}.invoke-btn:hover{background-color:var(--accent-color-hover)}.invoke-btn:disabled{background-color:var(--btn-base-color)}.invoke-btn:disabled:hover{background-color:var(--btn-base-color)}.invoke-btn svg{width:16px;height:16px;color:var(--btn-svg-color)}.cancel-btn{min-width:3rem;min-height:100%;background-color:var(--destructive-color)!important}.cancel-btn:hover{background-color:var(--destructive-color-hover)}.cancel-btn:disabled{background-color:var(--btn-base-color)}.cancel-btn:disabled:hover{background-color:var(--btn-base-color)}.cancel-btn svg{width:20px;height:20px;color:var(--btn-svg-color)}.loopback-btn[data-as-checkbox=true]{background-color:var(--btn-btn-base-color);border:3px solid var(--btn-btn-base-color)}.loopback-btn[data-as-checkbox=true] svg{fill:var(--text-color)}.loopback-btn[data-as-checkbox=true]:hover{background-color:var(--btn-btn-base-color);border-color:var(--btn-checkbox-border-hover)}.loopback-btn[data-as-checkbox=true]:hover svg{fill:var(--text-color)}.loopback-btn[data-as-checkbox=true][data-selected=true]{border-color:var(--accent-color);background-color:var(--btn-btn-base-color)}.loopback-btn[data-as-checkbox=true][data-selected=true] svg{fill:var(--text-color)}.loopback-btn[data-as-checkbox=true][data-selected=true]:hover{border-color:var(--accent-color);background-color:var(--btn-btn-base-color)}.loopback-btn[data-as-checkbox=true][data-selected=true]:hover svg{fill:var(--text-color)}.main-options,.main-options-list{display:grid;row-gap:1rem}.main-options-row{display:grid;grid-template-columns:repeat(3,auto);column-gap:.5rem;max-width:22.5rem}.main-option-block{border-radius:.5rem;display:grid!important;grid-template-columns:auto!important;row-gap:.5rem}.main-option-block .invokeai__number-input-form-label,.main-option-block .invokeai__select-label{font-weight:700;font-size:.9rem!important}.main-option-block .invokeai__select-label{margin:0}.advanced-options-checkbox{background-color:var(--background-color-secondary);padding:.5rem 1rem;border-radius:.4rem;font-weight:700}.advanced-settings{padding-top:.5rem;display:grid;row-gap:.5rem}.advanced-settings-item{display:grid;max-width:22.5rem;border:none;border-top:0px;border-radius:.4rem;background-color:var(--tab-panel-bg)}.advanced-settings-item[aria-expanded=true]{background-color:var(--tab-hover-color);border-radius:0 0 .4rem .4rem}.advanced-settings-panel{background-color:var(--tab-panel-bg);border-radius:0 0 .4rem .4rem;padding:1rem}.advanced-settings-panel button{background-color:var(--btn-base-color)}.advanced-settings-panel button:hover{background-color:var(--btn-base-color-hover)}.advanced-settings-panel button:disabled:hover{background-color:var(--btn-base-color)}.advanced-settings-header{border-radius:.4rem;font-weight:700}.advanced-settings-header[aria-expanded=true]{background-color:var(--tab-hover-color);border-radius:.4rem .4rem 0 0}.advanced-settings-header:hover{background-color:var(--tab-hover-color)}.upscale-options{display:grid;grid-template-columns:auto 1fr;column-gap:1rem}.inpainting-bounding-box-settings{display:flex;flex-direction:column;border-radius:.4rem;border:2px solid var(--tab-color)}.inpainting-bounding-box-header{background-color:var(--tab-color);display:flex;flex-direction:row;justify-content:space-between;padding:.5rem 1rem;border-radius:.3rem .3rem 0 0;align-items:center}.inpainting-bounding-box-header button{width:.5rem;height:1.2rem;background:none}.inpainting-bounding-box-header button:hover{background:none}.inpainting-bounding-box-settings-items{padding:1rem;display:flex;flex-direction:column;row-gap:1rem}.inpainting-bounding-box-settings-items .inpainting-bounding-box-reset-icon-btn{background-color:var(--btn-base-color)}.inpainting-bounding-box-settings-items .inpainting-bounding-box-reset-icon-btn:hover{background-color:var(--btn-base-color-hover)}.inpainting-bounding-box-dimensions-slider-numberinput{display:grid;grid-template-columns:repeat(3,auto);column-gap:1rem}.inpainting-bounding-box-darken{width:max-content}.progress-bar{background-color:var(--root-bg-color);height:.3rem;z-index:99}.progress-bar div{background-color:var(--progress-bar-color)}.progress-bar div[data-indeterminate]{background-color:unset;background-image:linear-gradient(to right,transparent 0%,var(--progress-bar-color) 50%,transparent 100%)}.current-image-area{display:flex;flex-direction:column;height:100%;row-gap:1rem;background-color:var(--background-color-secondary);border-radius:.5rem}.current-image-preview{position:relative;justify-content:center;align-items:center;display:flex;width:100%;height:100%}.current-image-preview img{border-radius:.5rem;object-fit:contain;max-width:100%;max-height:100%;height:auto;position:absolute}.current-image-metadata{grid-area:current-image-preview}.current-image-next-prev-buttons{grid-area:current-image-content;display:flex;justify-content:space-between;z-index:1;height:100%;width:100%;pointer-events:none}.next-prev-button-trigger-area{width:7rem;height:100%;width:15%;display:grid;align-items:center;pointer-events:auto}.next-prev-button-trigger-area.prev-button-trigger-area{justify-content:flex-start}.next-prev-button-trigger-area.next-button-trigger-area{justify-content:flex-end}.next-prev-button{font-size:4rem;fill:var(--white);filter:drop-shadow(0 0 1rem var(--text-color-secondary));opacity:70%}.current-image-display-placeholder{background-color:var(--background-color-secondary);display:grid;display:flex;align-items:center;justify-content:center;width:100%;height:100%;border-radius:.5rem}.current-image-display-placeholder svg{width:10rem;height:10rem;color:var(--svg-color)}.current-image-options{width:100%;display:flex;justify-content:center;align-items:center;column-gap:.5em}.current-image-options .current-image-send-to-popover,.current-image-options .current-image-postprocessing-popover{display:flex;flex-direction:column;row-gap:.5rem;max-width:25rem}.current-image-options .current-image-send-to-popover .invokeai__button{place-content:start}.current-image-options .chakra-popover__popper{z-index:11}.current-image-options .delete-image-btn{background-color:var(--btn-base-color)}.current-image-options .delete-image-btn svg{fill:var(--btn-delete-image)}.image-gallery-wrapper-enter{transform:translate(150%)}.image-gallery-wrapper-enter-active{transform:translate(0);transition:all .12s ease-out}.image-gallery-wrapper-exit{transform:translate(0)}.image-gallery-wrapper-exit-active{transform:translate(150%);transition:all .12s ease-out}.image-gallery-wrapper[data-pinned=false]{position:fixed;height:100vh;top:0;right:0}.image-gallery-wrapper[data-pinned=false] .image-gallery-popup{border-radius:0;box-shadow:0 0 1rem var(--text-color-a3)}.image-gallery-wrapper[data-pinned=false] .image-gallery-popup .image-gallery-container{max-height:calc(100vh + 4.7rem)}.image-gallery-wrapper .image-gallery-popup{background-color:var(--background-color-secondary);padding:1rem;display:flex;flex-direction:column;row-gap:1rem;border-radius:.5rem;border-left-width:.3rem;border-color:var(--tab-list-text-inactive)}.image-gallery-wrapper .image-gallery-popup[data-resize-alert=true]{border-color:var(--status-bad-color)}.image-gallery-wrapper .image-gallery-popup .image-gallery-header{display:flex;align-items:center;column-gap:.5rem;justify-content:space-between}.image-gallery-wrapper .image-gallery-popup .image-gallery-header .image-gallery-header-right-icons{display:flex;flex-direction:row;column-gap:.5rem}.image-gallery-wrapper .image-gallery-popup .image-gallery-header .image-gallery-icon-btn{background-color:var(--btn-load-more)}.image-gallery-wrapper .image-gallery-popup .image-gallery-header .image-gallery-icon-btn:hover{background-color:var(--btn-load-more-hover)}.image-gallery-wrapper .image-gallery-popup .image-gallery-header .image-gallery-settings-popover{display:flex;flex-direction:column;row-gap:.5rem}.image-gallery-wrapper .image-gallery-popup .image-gallery-header .image-gallery-settings-popover div{display:flex;column-gap:.5rem;align-items:center;justify-content:space-between}.image-gallery-wrapper .image-gallery-popup .image-gallery-header h1{font-weight:700}.image-gallery-wrapper .image-gallery-popup .image-gallery-container{display:flex;flex-direction:column;max-height:calc(100vh - (70px + 7rem));overflow-y:scroll;-ms-overflow-style:none;scrollbar-width:none}.image-gallery-wrapper .image-gallery-popup .image-gallery-container::-webkit-scrollbar{display:none}.image-gallery-wrapper .image-gallery-popup .image-gallery-container .image-gallery-container-placeholder{display:flex;flex-direction:column;row-gap:.5rem;background-color:var(--background-color);border-radius:.5rem;place-items:center;padding:2rem;text-align:center}.image-gallery-wrapper .image-gallery-popup .image-gallery-container .image-gallery-container-placeholder p{color:var(--subtext-color-bright);font-family:Inter}.image-gallery-wrapper .image-gallery-popup .image-gallery-container .image-gallery-container-placeholder svg{width:4rem;height:4rem;color:var(--svg-color)}.image-gallery-wrapper .image-gallery-popup .image-gallery-container .image-gallery-load-more-btn{background-color:var(--btn-load-more);font-size:.85rem;padding:.5rem;margin-top:1rem}.image-gallery-wrapper .image-gallery-popup .image-gallery-container .image-gallery-load-more-btn:disabled:hover{background-color:var(--btn-load-more)}.image-gallery-wrapper .image-gallery-popup .image-gallery-container .image-gallery-load-more-btn:hover{background-color:var(--btn-load-more-hover)}.image-gallery-category-btn-group{width:max-content;column-gap:0;justify-content:stretch}.image-gallery-category-btn-group button{background-color:var(--btn-base-color);flex-grow:1}.image-gallery-category-btn-group button:hover{background-color:var(--btn-base-color-hover)}.image-gallery-category-btn-group button[data-selected=true]{background-color:var(--accent-color)}.image-gallery-category-btn-group button[data-selected=true]:hover{background-color:var(--accent-color-hover)}.image-gallery{display:grid;grid-gap:.5rem}.image-gallery .hoverable-image{padding:.5rem;position:relative}.image-gallery .hoverable-image:before{content:"";display:block;padding-bottom:100%}.image-gallery .hoverable-image .hoverable-image-image{position:absolute;max-width:100%;top:50%;left:50%;transform:translate(-50%,-50%)}.hoverable-image{display:flex;justify-content:center;transition:transform .2s ease-out}.hoverable-image:hover{cursor:pointer;border-radius:.5rem;z-index:2}.hoverable-image .hoverable-image-image{width:100%;height:100%;max-width:100%;max-height:100%}.hoverable-image .hoverable-image-delete-button{position:absolute;top:.25rem;right:.25rem}.hoverable-image .hoverable-image-content{display:flex;position:absolute;top:0;left:0;width:100%;height:100%;align-items:center;justify-content:center}.hoverable-image .hoverable-image-content .hoverable-image-check{fill:var(--status-good-color)}.hoverable-image .hoverable-image-icons{position:absolute;bottom:-2rem;display:grid;width:min-content;grid-template-columns:repeat(2,max-content);border-radius:.4rem;background-color:var(--background-color-secondary);padding:.2rem;gap:.2rem;grid-auto-rows:max-content}.hoverable-image .hoverable-image-icons button{width:12px;height:12px;border-radius:.2rem;padding:10px 0;flex-shrink:2}.hoverable-image .hoverable-image-icons button svg{width:12px;height:12px}.hoverable-image-context-menu{z-index:15;padding:.4rem;border-radius:.25rem;background-color:var(--context-menu-bg-color);box-shadow:var(--context-menu-box-shadow)}.hoverable-image-context-menu [role=menuitem]{font-size:.8rem;line-height:1rem;border-radius:3px;display:flex;align-items:center;height:1.75rem;padding:0 .5rem;position:relative;user-select:none;cursor:pointer;outline:none}.hoverable-image-context-menu [role=menuitem][data-disabled]{color:gray;pointer-events:none;cursor:not-allowed}.hoverable-image-context-menu [role=menuitem][data-warning]{color:var(--status-bad-color)}.hoverable-image-context-menu [role=menuitem][data-highlighted]{background-color:var(--context-menu-bg-color-hover)}.image-metadata-viewer{position:absolute;top:0;width:100%;border-radius:.5rem;padding:1rem;background-color:var(--metadata-bg-color);overflow:scroll;max-height:calc(100vh - (70px + 5.4rem));height:100%;z-index:10}.image-json-viewer{border-radius:.5rem;margin:0 .5rem 1rem;padding:1rem;overflow-x:scroll;word-break:break-all;background-color:var(--metadata-json-bg-color)}.lightbox-container{width:100%;height:100%;color:var(--text-color);overflow:hidden;position:absolute;left:0;top:0;background-color:var(--background-color-secondary);z-index:30;animation:popIn .3s ease-in}.lightbox-container .image-gallery-wrapper{max-height:100%!important}.lightbox-container .image-gallery-wrapper .image-gallery-container{max-height:calc(100vh - 5rem)}.lightbox-container .current-image-options{z-index:2;position:absolute;top:1rem}.lightbox-container .image-metadata-viewer{left:0;max-height:100%}.lightbox-close-btn{z-index:3;position:absolute;left:1rem;top:1rem;background-color:var(--btn-base-color)}.lightbox-close-btn:hover{background-color:var(--btn-base-color-hover)}.lightbox-close-btn:disabled:hover{background-color:var(--btn-base-color)}.lightbox-display-container{display:flex;flex-direction:row}.lightbox-preview-wrapper{overflow:hidden;background-color:var(--background-color-secondary);display:grid;grid-template-columns:auto max-content;place-items:center;width:100vw;height:100vh}.lightbox-preview-wrapper .current-image-next-prev-buttons{position:absolute}.lightbox-preview-wrapper .lightbox-image{grid-area:lightbox-content;border-radius:.5rem}.lightbox-preview-wrapper .lightbox-image-options{position:absolute;z-index:2;left:1rem;top:4.5rem;user-select:none;border-radius:.5rem;display:flex;flex-direction:column;row-gap:.5rem}@keyframes popIn{0%{opacity:0;filter:blur(100)}to{opacity:1;filter:blur(0)}}.app-tabs{display:grid;grid-template-columns:min-content auto;column-gap:1rem;height:calc(100vh - (70px + 1rem))}.app-tabs-list{display:grid;row-gap:.3rem;grid-auto-rows:min-content;color:var(--tab-list-text-inactive)}.app-tabs-list button{font-size:.85rem;padding:.5rem}.app-tabs-list button:hover{background-color:var(--tab-hover-color);border-radius:.3rem}.app-tabs-list button svg{width:26px;height:26px}.app-tabs-list button[aria-selected=true]{background-color:var(--tab-list-bg);color:var(--tab-list-text);font-weight:700;border-radius:.3rem;border:none}.app-tabs-panels .app-tabs-panel{padding:0;height:100%}.workarea-wrapper{position:relative;width:100%;height:100%}.workarea-wrapper .workarea-main{display:flex;column-gap:1rem;height:100%}.workarea-wrapper .workarea-main .workarea-children-wrapper{position:relative;width:100%;height:100%}.workarea-wrapper .workarea-main .workarea-split-view{width:100%;height:100%;display:grid;grid-template-columns:1fr 1fr;background-color:var(--background-color-secondary);border-radius:.5rem}.workarea-wrapper .workarea-main .workarea-split-view .workarea-split-view-left{padding-right:.5rem}.workarea-wrapper .workarea-main .workarea-split-view .workarea-split-view-right{padding-left:.5rem}.workarea-wrapper .workarea-main .workarea-single-view{width:100%;height:100%;background-color:var(--background-color-secondary);border-radius:.5rem}.workarea-wrapper .workarea-main .workarea-split-view-left,.workarea-wrapper .workarea-main .workarea-split-view-right{display:flex;flex-direction:column;height:100%;width:100%;row-gap:1rem;background-color:var(--background-color-secondary);border-radius:.5rem;padding:1rem}.workarea-split-button{position:absolute;cursor:pointer;padding:.5rem;top:0;right:0}.workarea-split-button[data-selected=true]{top:0;right:0}.workarea-split-button[data-selected=true] svg{opacity:1}.workarea-split-button svg{opacity:.5}.options-panel-wrapper-enter{transform:translate(-150%)}.options-panel-wrapper-enter-active{transform:translate(0);transition:all .12s ease-out}.options-panel-wrapper-exit{transform:translate(0)}.options-panel-wrapper-exit-active{transform:translate(-150%);transition:all .12s ease-out}.options-panel-wrapper{background-color:var(--background-color);height:calc(100vh - (70px + 1rem));width:22.5rem;max-width:22.5rem;flex-shrink:0;position:relative;overflow-y:scroll;-ms-overflow-style:none;scrollbar-width:none}.options-panel-wrapper::-webkit-scrollbar{display:none}.options-panel-wrapper .options-panel{display:flex;flex-direction:column;row-gap:1rem;height:100%;-ms-overflow-style:none;scrollbar-width:none;background-color:var(--background-color)}.options-panel-wrapper .options-panel::-webkit-scrollbar{display:none}.options-panel-wrapper[data-pinned=false]{z-index:20;position:fixed;top:0;left:0;filter:var(--floating-panel-drop-shadow);width:24.5rem;max-width:24.5rem;height:100%}.options-panel-wrapper[data-pinned=false] .options-panel-margin{margin:1rem}.options-panel-wrapper .options-panel-pin-button{position:absolute;cursor:pointer;padding:.5rem;top:1rem;right:1rem;z-index:20}.options-panel-wrapper .options-panel-pin-button[data-selected=true]{top:0;right:0}.options-panel-wrapper .options-panel-pin-button svg{opacity:.5}.invoke-ai-logo-wrapper{display:flex;align-items:center;column-gap:.7rem;padding-left:.5rem;padding-top:.3rem}.invoke-ai-logo-wrapper img{width:32px;height:32px}.invoke-ai-logo-wrapper h1{font-size:1.4rem}.text-to-image-area{padding:1rem;height:100%}.image-to-image-area{display:flex;flex-direction:column;row-gap:1rem;width:100%;height:100%}.image-to-image-strength-main-option{display:flex;row-gap:.5rem!important}.image-to-image-strength-main-option .invokeai__slider-component-label{color:var(--text-color-secondary);font-size:.9rem!important}.init-image-preview-header{display:flex;align-items:center;justify-content:space-between;width:100%}.init-image-preview-header h2{font-weight:700;font-size:.9rem}.init-image-preview{position:relative;height:100%;width:100%;display:flex;align-items:center;justify-content:center}.init-image-preview img{border-radius:.5rem;object-fit:contain;position:absolute}.image-to-image-current-image-display{position:relative}.floating-show-hide-button{position:absolute;top:50%;transform:translateY(-50%);z-index:20;padding:0;background-color:red!important;min-width:2rem;min-height:12rem;background-color:var(--btn-btn-base-color)!important}.floating-show-hide-button.left{left:0;border-radius:0 .5rem .5rem 0}.floating-show-hide-button.right{right:0;border-radius:.5rem 0 0 .5rem}.floating-show-hide-button:hover{background-color:var(--btn-btn-base-color-hover)}.floating-show-hide-button:disabled{background-color:var(--btn-base-color)}.floating-show-hide-button:disabled:hover{background-color:var(--btn-base-color)}.floating-show-hide-button svg{width:20px;height:20px;color:var(--btn-svg-color)}.show-hide-button-options{position:absolute;transform:translateY(-50%);z-index:20;min-width:2rem;top:50%;left:calc(42px + 2rem);border-radius:0 .5rem .5rem 0;display:flex;flex-direction:column;row-gap:.5rem}.show-hide-button-options button{border-radius:0 .3rem .3rem 0}.show-hide-button-gallery{padding-left:.75rem;padding-right:.75rem;background-color:var(--background-color)!important}.inpainting-main-area{display:flex;flex-direction:column;align-items:center;row-gap:1rem;width:100%;height:100%}.inpainting-main-area .inpainting-settings{display:flex;align-items:center;column-gap:.5rem}.inpainting-main-area .inpainting-settings svg{transform:scale(.9)}.inpainting-main-area .inpainting-settings .inpainting-buttons-group{display:flex;align-items:center;column-gap:.5rem}.inpainting-main-area .inpainting-settings .inpainting-button-dropdown{display:flex;flex-direction:column;row-gap:.5rem}.inpainting-main-area .inpainting-settings .inpainting-color-picker{margin-left:1rem}.inpainting-main-area .inpainting-settings .inpainting-brush-options{display:flex;align-items:center;column-gap:1rem}.inpainting-canvas-area{display:flex;flex-direction:column;align-items:center;justify-content:center;row-gap:1rem;width:100%;height:100%}.inpainting-canvas-spiner{display:flex;align-items:center;width:100%;height:100%}.inpainting-canvas-container{display:flex;position:relative;height:100%;width:100%;border-radius:.5rem}.inpainting-canvas-wrapper{position:relative}.inpainting-canvas-stage{outline:none;border-radius:.5rem;box-shadow:0 0 0 1px var(--border-color-light);overflow:hidden}.inpainting-canvas-stage canvas{outline:none;border-radius:.5rem}.inpainting-options-btn{min-height:2rem}.canvas-status-text{position:absolute;top:0;left:0;background-color:var(--background-color);opacity:.65;display:flex;flex-direction:column;font-size:.8rem;padding:.25rem;min-width:12rem;border-radius:.25rem;margin:.25rem;pointer-events:none}.invokeai__number-input-form-control{display:flex;align-items:center;column-gap:1rem}.invokeai__number-input-form-control .invokeai__number-input-form-label{color:var(--text-color-secondary)}.invokeai__number-input-form-control .invokeai__number-input-form-label[data-focus]+.invokeai__number-input-root{outline:none;border:2px solid var(--input-border-color);box-shadow:0 0 10px 0 var(--input-box-shadow-color)}.invokeai__number-input-form-control .invokeai__number-input-form-label[aria-invalid=true]+.invokeai__number-input-root{outline:none;border:2px solid var(--border-color-invalid);box-shadow:0 0 10px 0 var(--box-shadow-color-invalid)}.invokeai__number-input-form-control .invokeai__number-input-root{height:2rem;display:grid;grid-template-columns:auto max-content;column-gap:.5rem;align-items:center;background-color:var(--background-color-secondary);border:2px solid var(--border-color);border-radius:.3rem}.invokeai__number-input-form-control .invokeai__number-input-field{border:none;font-weight:700;width:100%;height:auto;font-size:.9rem;padding:0 .5rem}.invokeai__number-input-form-control .invokeai__number-input-field:focus{outline:none;box-shadow:none}.invokeai__number-input-form-control .invokeai__number-input-field:disabled{opacity:.2}.invokeai__number-input-form-control .invokeai__number-input-stepper{display:grid;padding-right:.5rem}.invokeai__number-input-form-control .invokeai__number-input-stepper .invokeai__number-input-stepper-button{border:none;padding:0 .5rem;margin:0 -.5rem}.invokeai__number-input-form-control .invokeai__number-input-stepper .invokeai__number-input-stepper-button svg{width:10px;height:10px}.input{display:grid;grid-template-columns:max-content auto;column-gap:1rem;align-items:center}.input .input-label{color:var(--text-color-secondary)}.input .input-entry{background-color:var(--background-color-secondary);border:2px solid var(--border-color);border-radius:.2rem;font-weight:700}.input .input-entry:focus{outline:none;border:2px solid var(--input-border-color);box-shadow:0 0 10px 0 var(--input-box-shadow-color)}.input .input-entry:disabled{opacity:.2}.input .input-entry[aria-invalid=true]{outline:none;border:2px solid var(--border-color-invalid);box-shadow:0 0 10px 0 var(--box-shadow-color-invalid)}.invokeai__icon-button{background:var(--btn-base-color);cursor:pointer}.invokeai__icon-button:hover{background-color:var(--btn-base-color-hover)}.invokeai__icon-button[data-selected=true]{background-color:var(--accent-color)}.invokeai__icon-button[data-selected=true]:hover{background-color:var(--accent-color-hover)}.invokeai__icon-button[disabled]{cursor:not-allowed}.invokeai__icon-button[data-variant=link],.invokeai__icon-button[data-variant=link]:hover{background:none}.invokeai__icon-button[data-as-checkbox=true]{background-color:var(--btn-base-color);border:3px solid var(--btn-base-color)}.invokeai__icon-button[data-as-checkbox=true] svg{fill:var(--text-color)}.invokeai__icon-button[data-as-checkbox=true]:hover{background-color:var(--btn-base-color);border-color:var(--btn-checkbox-border-hover)}.invokeai__icon-button[data-as-checkbox=true]:hover svg{fill:var(--text-color)}.invokeai__icon-button[data-as-checkbox=true][data-selected=true]{border-color:var(--accent-color)}.invokeai__icon-button[data-as-checkbox=true][data-selected=true] svg{fill:var(--accent-color-hover)}.invokeai__icon-button[data-as-checkbox=true][data-selected=true]:hover svg{fill:var(--accent-color-hover)}.invokeai__icon-button[data-alert=true]{animation-name:pulseColor;animation-duration:1s;animation-timing-function:ease-in-out;animation-iteration-count:infinite}.invokeai__icon-button[data-alert=true]:hover{animation:none;background-color:var(--accent-color-hover)}@keyframes pulseColor{0%{background-color:var(--accent-color)}50%{background-color:var(--accent-color-dim)}to{background-color:var(--accent-color)}}.invokeai__button{background-color:var(--btn-base-color);place-content:center}.invokeai__button:hover{background-color:var(--btn-base-color-hover)}.invokeai__switch-form-control .invokeai__switch-form-label{color:var(--text-color-secondary)}.invokeai__switch-form-control .invokeai__switch-root span{background-color:var(--switch-bg-color)}.invokeai__switch-form-control .invokeai__switch-root span span{background-color:var(--white)}.invokeai__switch-form-control .invokeai__switch-root[data-checked] span{background:var(--switch-bg-active-color)}.invokeai__switch-form-control .invokeai__switch-root[data-checked] span span{background-color:var(--white)}.invokeai__select{display:flex;column-gap:1rem;align-items:center}.invokeai__select .invokeai__select-label{color:var(--text-color-secondary)}.invokeai__select .invokeai__select-picker{border:2px solid var(--border-color);background-color:var(--background-color-secondary);font-weight:700;font-size:.9rem;height:2rem;border-radius:.2rem}.invokeai__select .invokeai__select-picker:focus{outline:none;border:2px solid var(--input-border-color);box-shadow:0 0 10px 0 var(--input-box-shadow-color)}.invokeai__select .invokeai__select-option{background-color:var(--background-color-secondary);color:var(--text-color-secondary)}.invokeai__slider-component{padding-bottom:.5rem;border-radius:.5rem}.invokeai__slider-component .invokeai__slider-component-label{min-width:max-content;margin:0;font-weight:700;font-size:.9rem;color:var(--text-color-secondary)}.invokeai__slider-component .invokeai__slider_track{background-color:var(--tab-color)}.invokeai__slider-component .invokeai__slider_track-filled{background-color:var(--slider-color)}.invokeai__slider-component .invokeai__slider-thumb{width:4px}.invokeai__slider-component .invokeai__slider-mark{font-size:.75rem;font-weight:700;color:var(--slider-mark-color);margin-top:.3rem}.invokeai__slider-component .invokeai__slider-number-input{border:none;font-size:.9rem;font-weight:700;height:2rem;background-color:var(--background-color-secondary);border:2px solid var(--border-color)}.invokeai__slider-component .invokeai__slider-number-input:focus{outline:none;box-shadow:none;border:2px solid var(--input-border-color);box-shadow:0 0 10px 0 var(--input-box-shadow-color)}.invokeai__slider-component .invokeai__slider-number-input:disabled{opacity:.2}.invokeai__slider-component .invokeai__slider-number-stepper{border:none}.invokeai__slider-component[data-markers=true] .invokeai__slider_container{margin-top:-1rem}.invokeai__checkbox .chakra-checkbox__label{margin-top:1px;color:var(--text-color-secondary);font-size:.9rem}.invokeai__checkbox .chakra-checkbox__control{width:1rem;height:1rem;border:none;border-radius:.2rem;background-color:var(--input-checkbox-bg)}.invokeai__checkbox .chakra-checkbox__control svg{width:.6rem;height:.6rem;stroke-width:3px}.invokeai__checkbox .chakra-checkbox__control[data-checked]{color:var(--text-color);background-color:var(--input-checkbox-checked-bg)}.invokeai__popover-content{min-width:unset;width:unset;padding:1rem;border-radius:.5rem;background-color:var(--background-color);border:2px solid var(--border-color)}.invokeai__popover-content .invokeai__popover-arrow{background-color:var(--background-color)!important}.invokeai__color-picker .react-colorful__hue-pointer,.invokeai__color-picker .react-colorful__saturation-pointer{width:1.5rem;height:1.5rem;border-color:var(--white)}.dropzone-container{position:absolute;top:0;left:0;width:100vw;height:100vh;z-index:999;backdrop-filter:blur(20px)}.dropzone-container .dropzone-overlay{opacity:.5;width:100%;height:100%;display:flex;flex-direction:column;row-gap:1rem;align-items:center;justify-content:center;background-color:var(--background-color)}.dropzone-container .dropzone-overlay.is-drag-accept{box-shadow:inset 0 0 20rem 1rem var(--accent-color)}.dropzone-container .dropzone-overlay.is-drag-reject{box-shadow:inset 0 0 20rem 1rem var(--status-bad-color)}.dropzone-container .dropzone-overlay.is-handling-upload{box-shadow:inset 0 0 20rem 1rem var(--status-working-color)}.image-uploader-button-outer{width:100%;height:100%;display:flex;align-items:center;justify-content:center;cursor:pointer;border-radius:.5rem;color:var(--tab-list-text-inactive);background-color:var(--background-color)}.image-uploader-button-outer:hover{background-color:var(--background-color-light)}.image-upload-button-inner{width:100%;height:100%;display:flex;align-items:center;justify-content:center}.image-upload-button{display:flex;flex-direction:column;row-gap:2rem;align-items:center;justify-content:center;text-align:center}.image-upload-button svg{width:4rem;height:4rem}.image-upload-button h2{font-size:1.2rem}.work-in-progress{display:grid;width:100%;height:calc(100vh - (70px + 1rem));grid-auto-rows:max-content;background-color:var(--background-color-secondary);border-radius:.4rem;place-content:center;place-items:center;row-gap:1rem}.work-in-progress h1{font-size:2rem;font-weight:700}.work-in-progress p{text-align:center;max-width:50rem;color:var(--subtext-color-bright)}.guide-popover-arrow{background-color:var(--tab-panel-bg);box-shadow:none}.guide-popover-content{background-color:var(--background-color-secondary);border:none}.guide-popover-guide-content{background:var(--tab-panel-bg);border:2px solid var(--tab-hover-color);border-radius:.4rem;padding:.75rem 1rem;display:grid;grid-template-rows:repeat(auto-fill,1fr);grid-row-gap:.5rem;justify-content:space-between}.modal{background-color:var(--background-color-secondary);color:var(--text-color);font-family:Inter}.modal-close-btn{background-color:var(--btn-base-color)}.modal-close-btn:hover{background-color:var(--btn-base-color-hover)}.modal-close-btn:disabled:hover{background-color:var(--btn-base-color)}*,*:before,*:after{box-sizing:border-box;margin:0;padding:0}html,body{-ms-overflow-style:none;scrollbar-width:none;background-color:var(--root-bg-color);overflow:hidden}html::-webkit-scrollbar,body::-webkit-scrollbar{display:none}#root{background-color:var(--root-bg-color);color:var(--text-color);font-family:Inter,Arial,Helvetica,sans-serif}\n',document.head.appendChild(r),{execute:function(){function r(e,t){for(var n=0;nr[t]})}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}var o="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function i(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var a={exports:{}},s={},l=Symbol.for("react.element"),c=Symbol.for("react.portal"),u=Symbol.for("react.fragment"),d=Symbol.for("react.strict_mode"),h=Symbol.for("react.profiler"),f=Symbol.for("react.provider"),p=Symbol.for("react.context"),g=Symbol.for("react.forward_ref"),m=Symbol.for("react.suspense"),v=Symbol.for("react.memo"),y=Symbol.for("react.lazy"),b=Symbol.iterator;var x={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},w=Object.assign,k={};function S(e,t,n){this.props=e,this.context=t,this.refs=k,this.updater=n||x}function C(){}function _(e,t,n){this.props=e,this.context=t,this.refs=k,this.updater=n||x}S.prototype.isReactComponent={},S.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")},S.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},C.prototype=S.prototype;var E=_.prototype=new C;E.constructor=_,w(E,S.prototype),E.isPureReactComponent=!0;var L=Array.isArray,P=Object.prototype.hasOwnProperty,O={current:null},M={key:!0,ref:!0,__self:!0,__source:!0};function T(e,t,n){var r,o={},i=null,a=null;if(null!=t)for(r in void 0!==t.ref&&(a=t.ref),void 0!==t.key&&(i=""+t.key),t)P.call(t,r)&&!M.hasOwnProperty(r)&&(o[r]=t[r]);var s=arguments.length-2;if(1===s)o.children=n;else if(1>>1,i=e[r];if(!(0>>1;ro(l,n))co(u,l)?(e[r]=u,e[c]=n,r=c):(e[r]=l,e[s]=n,r=s);else{if(!(co(u,n)))break e;e[r]=u,e[c]=n,r=c}}}return t}function o(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}if("object"==typeof performance&&"function"==typeof performance.now){var i=performance;e.unstable_now=function(){return i.now()}}else{var a=Date,s=a.now();e.unstable_now=function(){return a.now()-s}}var l=[],c=[],u=1,d=null,h=3,f=!1,p=!1,g=!1,m="function"==typeof setTimeout?setTimeout:null,v="function"==typeof clearTimeout?clearTimeout:null,y="undefined"!=typeof setImmediate?setImmediate:null;function b(e){for(var o=n(c);null!==o;){if(null===o.callback)r(c);else{if(!(o.startTime<=e))break;r(c),o.sortIndex=o.expirationTime,t(l,o)}o=n(c)}}function x(e){if(g=!1,b(e),!p)if(null!==n(l))p=!0,A(w);else{var t=n(c);null!==t&&I(x,t.startTime-e)}}function w(t,o){p=!1,g&&(g=!1,v(_),_=-1),f=!0;var i=h;try{for(b(o),d=n(l);null!==d&&(!(d.expirationTime>o)||t&&!L());){var a=d.callback;if("function"==typeof a){d.callback=null,h=d.priorityLevel;var s=a(d.expirationTime<=o);o=e.unstable_now(),"function"==typeof s?d.callback=s:d===n(l)&&r(l),b(o)}else r(l);d=n(l)}if(null!==d)var u=!0;else{var m=n(c);null!==m&&I(x,m.startTime-o),u=!1}return u}finally{d=null,h=i,f=!1}}"undefined"!=typeof navigator&&void 0!==navigator.scheduling&&void 0!==navigator.scheduling.isInputPending&&navigator.scheduling.isInputPending.bind(navigator.scheduling);var k,S=!1,C=null,_=-1,E=5,P=-1;function L(){return!(e.unstable_now()-Pe||125a?(r.sortIndex=i,t(c,r),null===n(l)&&r===n(c)&&(g?(v(_),_=-1):g=!0,I(x,i-a))):(r.sortIndex=s,t(l,r),p||f||(p=!0,A(w))),r},e.unstable_shouldYield=L,e.unstable_wrapCallback=function(e){var t=h;return function(){var n=h;h=t;try{return e.apply(this,arguments)}finally{h=n}}}}(q),function(e){e.exports=q}(G); +!function(e){function t(e,t){var n=e.length;e.push(t);e:for(;0>>1,i=e[r];if(!(0>>1;ro(l,n))co(u,l)?(e[r]=u,e[c]=n,r=c):(e[r]=l,e[s]=n,r=s);else{if(!(co(u,n)))break e;e[r]=u,e[c]=n,r=c}}}return t}function o(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}if("object"==typeof performance&&"function"==typeof performance.now){var i=performance;e.unstable_now=function(){return i.now()}}else{var a=Date,s=a.now();e.unstable_now=function(){return a.now()-s}}var l=[],c=[],u=1,d=null,h=3,f=!1,p=!1,g=!1,m="function"==typeof setTimeout?setTimeout:null,v="function"==typeof clearTimeout?clearTimeout:null,y="undefined"!=typeof setImmediate?setImmediate:null;function b(e){for(var o=n(c);null!==o;){if(null===o.callback)r(c);else{if(!(o.startTime<=e))break;r(c),o.sortIndex=o.expirationTime,t(l,o)}o=n(c)}}function x(e){if(g=!1,b(e),!p)if(null!==n(l))p=!0,A(w);else{var t=n(c);null!==t&&I(x,t.startTime-e)}}function w(t,o){p=!1,g&&(g=!1,v(_),_=-1),f=!0;var i=h;try{for(b(o),d=n(l);null!==d&&(!(d.expirationTime>o)||t&&!P());){var a=d.callback;if("function"==typeof a){d.callback=null,h=d.priorityLevel;var s=a(d.expirationTime<=o);o=e.unstable_now(),"function"==typeof s?d.callback=s:d===n(l)&&r(l),b(o)}else r(l);d=n(l)}if(null!==d)var u=!0;else{var m=n(c);null!==m&&I(x,m.startTime-o),u=!1}return u}finally{d=null,h=i,f=!1}}"undefined"!=typeof navigator&&void 0!==navigator.scheduling&&void 0!==navigator.scheduling.isInputPending&&navigator.scheduling.isInputPending.bind(navigator.scheduling);var k,S=!1,C=null,_=-1,E=5,L=-1;function P(){return!(e.unstable_now()-Le||125a?(r.sortIndex=i,t(c,r),null===n(l)&&r===n(c)&&(g?(v(_),_=-1):g=!0,I(x,i-a))):(r.sortIndex=s,t(l,r),p||f||(p=!0,A(w))),r},e.unstable_shouldYield=P,e.unstable_wrapCallback=function(e){var t=h;return function(){var n=h;h=t;try{return e.apply(this,arguments)}finally{h=n}}}}(q),function(e){e.exports=q}(G); /** * @license React * react-dom.production.min.js @@ -18,7 +18,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -var Y=a.exports,Z=G.exports;function X(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n