Merge branch 'main' into chore/accessability_various-additions

This commit is contained in:
Elrik 2023-03-07 17:44:55 -06:00 committed by GitHub
commit 6b41127421
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 1122 additions and 1381 deletions

1
.git-blame-ignore-revs Normal file
View File

@ -0,0 +1 @@
b3dccfaeb636599c02effc377cdd8a87d658256c

View File

@ -4,9 +4,17 @@ on:
pull_request:
paths:
- 'invokeai/frontend/web/**'
types:
- 'ready_for_review'
- 'opened'
- 'synchronize'
push:
branches:
- 'main'
paths:
- 'invokeai/frontend/web/**'
merge_group:
workflow_dispatch:
defaults:
run:

View File

@ -6,7 +6,7 @@ on:
- 'invokeai/**'
- 'invokeai/backend/**'
- 'invokeai/configs/**'
- 'invokeai/frontend/dist/**'
- 'invokeai/frontend/web/dist/**'
merge_group:
workflow_dispatch:

View File

@ -8,14 +8,14 @@ on:
- 'invokeai/**'
- 'invokeai/backend/**'
- 'invokeai/configs/**'
- 'invokeai/frontend/dist/**'
- 'invokeai/frontend/web/dist/**'
pull_request:
paths:
- 'pyproject.toml'
- 'invokeai/**'
- 'invokeai/backend/**'
- 'invokeai/configs/**'
- 'invokeai/frontend/dist/**'
- 'invokeai/frontend/web/dist/**'
types:
- 'ready_for_review'
- 'opened'

View File

View File

@ -0,0 +1,202 @@
# Copyright (c) 2023 Kyle Schouviller (https://github.com/kyle0654)
from abc import ABC, abstractmethod
import argparse
from typing import Any, Callable, Iterable, Literal, get_args, get_origin, get_type_hints
from pydantic import BaseModel, Field
from ..invocations.image import ImageField
from ..services.graph import GraphExecutionState
from ..services.invoker import Invoker
def add_parsers(
subparsers,
commands: list[type],
command_field: str = "type",
exclude_fields: list[str] = ["id", "type"],
add_arguments: Callable[[argparse.ArgumentParser], None]|None = None
):
"""Adds parsers for each command to the subparsers"""
# Create subparsers for each command
for command in commands:
hints = get_type_hints(command)
cmd_name = get_args(hints[command_field])[0]
command_parser = subparsers.add_parser(cmd_name, help=command.__doc__)
if add_arguments is not None:
add_arguments(command_parser)
# Convert all fields to arguments
fields = command.__fields__ # type: ignore
for name, field in fields.items():
if name in exclude_fields:
continue
if get_origin(field.type_) == Literal:
allowed_values = get_args(field.type_)
allowed_types = set()
for val in allowed_values:
allowed_types.add(type(val))
allowed_types_list = list(allowed_types)
field_type = allowed_types_list[0] if len(allowed_types) == 1 else Union[allowed_types_list] # type: ignore
command_parser.add_argument(
f"--{name}",
dest=name,
type=field_type,
default=field.default,
choices=allowed_values,
help=field.field_info.description,
)
else:
command_parser.add_argument(
f"--{name}",
dest=name,
type=field.type_,
default=field.default,
help=field.field_info.description,
)
class CliContext:
invoker: Invoker
session: GraphExecutionState
parser: argparse.ArgumentParser
defaults: dict[str, Any]
def __init__(self, invoker: Invoker, session: GraphExecutionState, parser: argparse.ArgumentParser):
self.invoker = invoker
self.session = session
self.parser = parser
self.defaults = dict()
def get_session(self):
self.session = self.invoker.services.graph_execution_manager.get(self.session.id)
return self.session
class ExitCli(Exception):
"""Exception to exit the CLI"""
pass
class BaseCommand(ABC, BaseModel):
"""A CLI command"""
# All commands must include a type name like this:
# type: Literal['your_command_name'] = 'your_command_name'
@classmethod
def get_all_subclasses(cls):
subclasses = []
toprocess = [cls]
while len(toprocess) > 0:
next = toprocess.pop(0)
next_subclasses = next.__subclasses__()
subclasses.extend(next_subclasses)
toprocess.extend(next_subclasses)
return subclasses
@classmethod
def get_commands(cls):
return tuple(BaseCommand.get_all_subclasses())
@classmethod
def get_commands_map(cls):
# Get the type strings out of the literals and into a dictionary
return dict(map(lambda t: (get_args(get_type_hints(t)['type'])[0], t),BaseCommand.get_all_subclasses()))
@abstractmethod
def run(self, context: CliContext) -> None:
"""Run the command. Raise ExitCli to exit."""
pass
class ExitCommand(BaseCommand):
"""Exits the CLI"""
type: Literal['exit'] = 'exit'
def run(self, context: CliContext) -> None:
raise ExitCli()
class HelpCommand(BaseCommand):
"""Shows help"""
type: Literal['help'] = 'help'
def run(self, context: CliContext) -> None:
context.parser.print_help()
def get_graph_execution_history(
graph_execution_state: GraphExecutionState,
) -> Iterable[str]:
"""Gets the history of fully-executed invocations for a graph execution"""
return (
n
for n in reversed(graph_execution_state.executed_history)
if n in graph_execution_state.graph.nodes
)
def get_invocation_command(invocation) -> str:
fields = invocation.__fields__.items()
type_hints = get_type_hints(type(invocation))
command = [invocation.type]
for name, field in fields:
if name in ["id", "type"]:
continue
# TODO: add links
# Skip image fields when serializing command
type_hint = type_hints.get(name) or None
if type_hint is ImageField or ImageField in get_args(type_hint):
continue
field_value = getattr(invocation, name)
field_default = field.default
if field_value != field_default:
if type_hint is str or str in get_args(type_hint):
command.append(f'--{name} "{field_value}"')
else:
command.append(f"--{name} {field_value}")
return " ".join(command)
class HistoryCommand(BaseCommand):
"""Shows the invocation history"""
type: Literal['history'] = 'history'
# Inputs
# fmt: off
count: int = Field(default=5, gt=0, description="The number of history entries to show")
# fmt: on
def run(self, context: CliContext) -> None:
history = list(get_graph_execution_history(context.get_session()))
for i in range(min(self.count, len(history))):
entry_id = history[-1 - i]
entry = context.get_session().graph.get_node(entry_id)
print(f"{entry_id}: {get_invocation_command(entry)}")
class SetDefaultCommand(BaseCommand):
"""Sets a default value for a field"""
type: Literal['default'] = 'default'
# Inputs
# fmt: off
field: str = Field(description="The field to set the default for")
value: str = Field(description="The value to set the default to, or None to clear the default")
# fmt: on
def run(self, context: CliContext) -> None:
if self.value is None:
if self.field in context.defaults:
del context.defaults[self.field]
else:
context.defaults[self.field] = self.value

View File

@ -5,13 +5,7 @@ import os
import shlex
import time
from typing import (
Any,
Dict,
Iterable,
Literal,
Union,
get_args,
get_origin,
get_type_hints,
)
@ -19,9 +13,9 @@ from pydantic import BaseModel
from pydantic.fields import Field
from ..backend import Args
from .cli.commands import BaseCommand, CliContext, ExitCli, add_parsers, get_graph_execution_history
from .invocations import *
from .invocations.baseinvocation import BaseInvocation
from .invocations.image import ImageField
from .services.events import EventServiceBase
from .services.generate_initializer import get_generate
from .services.graph import EdgeConnection, GraphExecutionState
@ -33,15 +27,33 @@ from .services.processor import DefaultInvocationProcessor
from .services.sqlite import SqliteItemStorage
class InvocationCommand(BaseModel):
invocation: Union[BaseInvocation.get_invocations()] = Field(discriminator="type") # type: ignore
class CliCommand(BaseModel):
command: Union[BaseCommand.get_commands() + BaseInvocation.get_invocations()] = Field(discriminator="type") # type: ignore
class InvalidArgs(Exception):
pass
def get_invocation_parser() -> argparse.ArgumentParser:
def add_invocation_args(command_parser):
# Add linking capability
command_parser.add_argument(
"--link",
"-l",
action="append",
nargs=3,
help="A link in the format 'dest_field source_node source_field'. source_node can be relative to history (e.g. -1)",
)
command_parser.add_argument(
"--link_node",
"-ln",
action="append",
help="A link from all fields in the specified node. Node can be relative to history (e.g. -1)",
)
def get_command_parser() -> argparse.ArgumentParser:
# Create invocation parser
parser = argparse.ArgumentParser()
@ -49,129 +61,19 @@ def get_invocation_parser() -> argparse.ArgumentParser:
raise InvalidArgs
parser.exit = exit
subparsers = parser.add_subparsers(dest="type")
invocation_parsers = dict()
# Add history parser
history_parser = subparsers.add_parser(
"history", help="Shows the invocation history"
)
history_parser.add_argument(
"count",
nargs="?",
default=5,
type=int,
help="The number of history entries to show",
)
# Add default parser
default_parser = subparsers.add_parser(
"default", help="Define a default value for all inputs with a specified name"
)
default_parser.add_argument("input", type=str, help="The input field")
default_parser.add_argument("value", help="The default value")
default_parser = subparsers.add_parser(
"reset_default", help="Resets a default value"
)
default_parser.add_argument("input", type=str, help="The input field")
# Create subparsers for each invocation
invocations = BaseInvocation.get_all_subclasses()
for invocation in invocations:
hints = get_type_hints(invocation)
cmd_name = get_args(hints["type"])[0]
command_parser = subparsers.add_parser(cmd_name, help=invocation.__doc__)
invocation_parsers[cmd_name] = command_parser
add_parsers(subparsers, invocations, add_arguments=add_invocation_args)
# Add linking capability
command_parser.add_argument(
"--link",
"-l",
action="append",
nargs=3,
help="A link in the format 'dest_field source_node source_field'. source_node can be relative to history (e.g. -1)",
)
command_parser.add_argument(
"--link_node",
"-ln",
action="append",
help="A link from all fields in the specified node. Node can be relative to history (e.g. -1)",
)
# Convert all fields to arguments
fields = invocation.__fields__
for name, field in fields.items():
if name in ["id", "type"]:
continue
if get_origin(field.type_) == Literal:
allowed_values = get_args(field.type_)
allowed_types = set()
for val in allowed_values:
allowed_types.add(type(val))
allowed_types_list = list(allowed_types)
field_type = allowed_types_list[0] if len(allowed_types) == 1 else Union[allowed_types_list] # type: ignore
command_parser.add_argument(
f"--{name}",
dest=name,
type=field_type,
default=field.default,
choices=allowed_values,
help=field.field_info.description,
)
else:
command_parser.add_argument(
f"--{name}",
dest=name,
type=field.type_,
default=field.default,
help=field.field_info.description,
)
# Create subparsers for each command
commands = BaseCommand.get_all_subclasses()
add_parsers(subparsers, commands, exclude_fields=["type"])
return parser
def get_invocation_command(invocation) -> str:
fields = invocation.__fields__.items()
type_hints = get_type_hints(type(invocation))
command = [invocation.type]
for name, field in fields:
if name in ["id", "type"]:
continue
# TODO: add links
# Skip image fields when serializing command
type_hint = type_hints.get(name) or None
if type_hint is ImageField or ImageField in get_args(type_hint):
continue
field_value = getattr(invocation, name)
field_default = field.default
if field_value != field_default:
if type_hint is str or str in get_args(type_hint):
command.append(f'--{name} "{field_value}"')
else:
command.append(f"--{name} {field_value}")
return " ".join(command)
def get_graph_execution_history(
graph_execution_state: GraphExecutionState,
) -> Iterable[str]:
"""Gets the history of fully-executed invocations for a graph execution"""
return (
n
for n in reversed(graph_execution_state.executed_history)
if n in graph_execution_state.graph.nodes
)
def generate_matching_edges(
a: BaseInvocation, b: BaseInvocation
) -> list[tuple[EdgeConnection, EdgeConnection]]:
@ -233,13 +135,12 @@ def invoke_cli():
invoker = Invoker(services)
session: GraphExecutionState = invoker.create_execution_state()
parser = get_invocation_parser()
parser = get_command_parser()
# Uncomment to print out previous sessions at startup
# print(services.session_manager.list())
# Defaults storage
defaults: Dict[str, Any] = dict()
context = CliContext(invoker, session, parser)
while True:
try:
@ -248,13 +149,6 @@ def invoke_cli():
# Ctrl-c exits
break
if cmd_input in ["exit", "q"]:
break
if cmd_input in ["--help", "help", "h", "?"]:
parser.print_help()
continue
try:
# Refresh the state of the session
session = invoker.services.graph_execution_manager.get(session.id)
@ -272,35 +166,23 @@ def invoke_cli():
# Parse args to create invocation
args = vars(parser.parse_args(shlex.split(cmd.strip())))
# Check for special commands
# TODO: These might be better as Pydantic models, similar to the invocations
if args["type"] == "history":
history_count = args["count"] or 5
for i in range(min(history_count, len(history))):
entry_id = history[-1 - i]
entry = session.graph.get_node(entry_id)
print(f"{entry_id}: {get_invocation_command(entry.invocation)}")
continue
if args["type"] == "reset_default":
if args["input"] in defaults:
del defaults[args["input"]]
continue
if args["type"] == "default":
field = args["input"]
field_value = args["value"]
defaults[field] = field_value
continue
# Override defaults
for field_name, field_default in defaults.items():
for field_name, field_default in context.defaults.items():
if field_name in args:
args[field_name] = field_default
# Parse invocation
args["id"] = current_id
command = InvocationCommand(invocation=args)
command = CliCommand(command=args)
# Run any CLI commands immediately
# TODO: this won't behave as expected if piping and using e.g. history,
# since invocations are gathered and then run together at the end.
# This is more efficient if the CLI is running against a distributed
# backend, so it's preferable not to change that behavior.
if isinstance(command.command, BaseCommand):
command.command.run(context)
continue
# Pipe previous command output (if there was a previous command)
edges = []
@ -314,7 +196,7 @@ def invoke_cli():
else session.graph.get_node(from_id)
)
matching_edges = generate_matching_edges(
from_node, command.invocation
from_node, command.command
)
edges.extend(matching_edges)
@ -323,22 +205,25 @@ def invoke_cli():
for link in args["link_node"]:
link_node = session.graph.get_node(link)
matching_edges = generate_matching_edges(
link_node, command.invocation
link_node, command.command
)
matching_destinations = [e[1] for e in matching_edges]
edges = [e for e in edges if e[1] not in matching_destinations]
edges.extend(matching_edges)
if "link" in args and args["link"]:
for link in args["link"]:
edges = [e for e in edges if e[1].node_id != command.command.id and e[1].field != link[2]]
edges.append(
(
EdgeConnection(node_id=link[1], field=link[0]),
EdgeConnection(
node_id=command.invocation.id, field=link[2]
node_id=command.command.id, field=link[2]
),
)
)
new_invocations.append((command.invocation, edges))
new_invocations.append((command.command, edges))
current_id = current_id + 1
@ -347,13 +232,14 @@ def invoke_cli():
for invocation in new_invocations:
session.add_node(invocation[0])
for edge in invocation[1]:
print(edge)
session.add_edge(edge)
# Execute all available invocations
invoker.invoke(session, invoke_all=True)
while not session.is_complete():
# Wait some time
session = invoker.services.graph_execution_manager.get(session.id)
session = context.get_session()
time.sleep(0.1)
# Print any errors
@ -366,11 +252,15 @@ def invoke_cli():
# Start a new session
print("Creating a new session")
session = invoker.create_execution_state()
context.session = session
except InvalidArgs:
print('Invalid command, use "help" to list commands')
continue
except ExitCli:
break
except SystemExit:
continue

View File

@ -295,7 +295,7 @@ def download_vaes():
# first the diffusers version
repo_id = "stabilityai/sd-vae-ft-mse"
args = dict(
cache_dir=global_cache_dir("diffusers"),
cache_dir=global_cache_dir("hub"),
)
if not AutoencoderKL.from_pretrained(repo_id, **args):
raise Exception(f"download of {repo_id} failed")

View File

@ -270,7 +270,6 @@ def _download_diffusion_weights(
path = download_from_hf(
model_class,
repo_id,
cache_subdir="diffusers",
safety_checker=None,
**extra_args,
)

View File

@ -98,16 +98,13 @@ def global_cache_dir(subdir: Union[str, Path] = "") -> Path:
"""
Returns Path to the model cache directory. If a subdirectory
is provided, it will be appended to the end of the path, allowing
for huggingface-style conventions:
global_cache_dir('diffusers')
for Hugging Face-style conventions. Currently, Hugging Face has
moved all models into the "hub" subfolder, so for any pretrained
HF model, use:
global_cache_dir('hub')
Current HuggingFace documentation (mid-Jan 2023) indicates that
transformers models will be cached into a "transformers" subdirectory,
but in practice they seem to go into "hub". But if needed:
global_cache_dir('transformers')
One other caveat is that HuggingFace is moving some diffusers models
into the "hub" subdirectory as well, so this will need to be revisited
from time to time.
The legacy location for transformers used to be global_cache_dir('transformers')
and global_cache_dir('diffusers') for diffusers.
"""
home: str = os.getenv("HF_HOME")
@ -115,7 +112,7 @@ def global_cache_dir(subdir: Union[str, Path] = "") -> Path:
home = os.getenv("XDG_CACHE_HOME")
if home is not None:
# Set `home` to $XDG_CACHE_HOME/huggingface, which is the default location mentioned in HuggingFace Hub Client Library.
# Set `home` to $XDG_CACHE_HOME/huggingface, which is the default location mentioned in Hugging Face Hub Client Library.
# See: https://huggingface.co/docs/huggingface_hub/main/en/package_reference/environment_variables#xdgcachehome
home += os.sep + "huggingface"

View File

@ -6,5 +6,4 @@ from .convert_ckpt_to_diffusers import (
load_pipeline_from_original_stable_diffusion_ckpt,
)
from .model_manager import ModelManager
from invokeai.frontend.merge import merge_diffusion_models

View File

@ -1101,14 +1101,17 @@ def load_pipeline_from_original_stable_diffusion_ckpt(
if original_config_file is None:
model_type = ModelManager.probe_model_type(checkpoint)
if model_type == SDLegacyType.V2:
if model_type == SDLegacyType.V2_v:
original_config_file = (
global_config_dir() / "stable-diffusion" / "v2-inference-v.yaml"
)
if global_step == 110000:
# v2.1 needs to upcast attention
upcast_attention = True
elif model_type == SDLegacyType.V2_e:
original_config_file = (
global_config_dir() / "stable-diffusion" / "v2-inference.yaml"
)
elif model_type == SDLegacyType.V1_INPAINT:
original_config_file = (
global_config_dir()

View File

@ -40,16 +40,16 @@ from ..util import CPU_DEVICE, ask_user, download_with_resume
class SDLegacyType(Enum):
V1 = 1
V1_INPAINT = 2
V2 = 3
V2 = 3
V2_e = 4
V2_v = 5
UNKNOWN = 99
DEFAULT_MAX_MODELS = 2
VAE_TO_REPO_ID = { # hack, see note in convert_and_import()
"vae-ft-mse-840000-ema-pruned": "stabilityai/sd-vae-ft-mse",
}
class ModelManager(object):
def __init__(
self,
@ -335,10 +335,23 @@ class ModelManager(object):
tic = time.time()
with warnings.catch_warnings():
warnings.simplefilter("ignore")
model, width, height, model_hash = self._load_diffusers_model(mconfig)
# this does the work
model_format = mconfig.get("format", "ckpt")
if model_format == "ckpt":
weights = mconfig.weights
print(f">> Loading {model_name} from {weights}")
model, width, height, model_hash = self._load_ckpt_model(
model_name, mconfig
)
elif model_format == "diffusers":
with warnings.catch_warnings():
warnings.simplefilter("ignore")
model, width, height, model_hash = self._load_diffusers_model(mconfig)
else:
raise NotImplementedError(
f"Unknown model format {model_name}: {model_format}"
)
# usage statistics
toc = time.time()
print(">> Model loaded in", "%4.2fs" % (toc - tic))
@ -369,7 +382,7 @@ class ModelManager(object):
if vae := self._load_vae(mconfig["vae"]):
pipeline_args.update(vae=vae)
if not isinstance(name_or_path, Path):
pipeline_args.update(cache_dir=global_cache_dir("diffusers"))
pipeline_args.update(cache_dir=global_cache_dir("hub"))
if using_fp16:
pipeline_args.update(torch_dtype=torch.float16)
fp_args_list = [{"revision": "fp16"}, {}]
@ -527,7 +540,7 @@ class ModelManager(object):
self,
repo_or_path: Union[str, Path],
model_name: str = None,
model_description: str = None,
description: str = None,
vae: dict = None,
commit_to_conf: Path = None,
) -> bool:
@ -569,15 +582,24 @@ class ModelManager(object):
format. Valid return values include:
SDLegacyType.V1
SDLegacyType.V1_INPAINT
SDLegacyType.V2
SDLegacyType.V2 (V2 prediction type unknown)
SDLegacyType.V2_e (V2 using 'epsilon' prediction type)
SDLegacyType.V2_v (V2 using 'v_prediction' prediction type)
SDLegacyType.UNKNOWN
"""
key_name = "model.diffusion_model.input_blocks.2.1.transformer_blocks.0.attn2.to_k.weight"
if key_name in checkpoint and checkpoint[key_name].shape[-1] == 1024:
return SDLegacyType.V2
global_step = checkpoint.get('global_step')
state_dict = checkpoint.get("state_dict") or checkpoint
try:
state_dict = checkpoint.get("state_dict") or checkpoint
key_name = "model.diffusion_model.input_blocks.2.1.transformer_blocks.0.attn2.to_k.weight"
if key_name in state_dict and state_dict[key_name].shape[-1] == 1024:
if global_step == 220000:
return SDLegacyType.V2_e
elif global_step == 110000:
return SDLegacyType.V2_v
else:
return SDLegacyType.V2
# otherwise we assume a V1 file
in_channels = state_dict[
"model.diffusion_model.input_blocks.0.0.weight"
].shape[1]
@ -591,12 +613,13 @@ class ModelManager(object):
return SDLegacyType.UNKNOWN
def heuristic_import(
self,
path_url_or_repo: str,
convert: bool = True,
model_name: str = None,
description: str = None,
commit_to_conf: Path = None,
self,
path_url_or_repo: str,
convert: bool = True,
model_name: str = None,
description: str = None,
model_config_file: Path = None,
commit_to_conf: Path = None,
) -> str:
"""
Accept a string which could be:
@ -693,7 +716,7 @@ class ModelManager(object):
if model_path.stem in self.config: # already imported
print(" | Already imported. Skipping")
return
return model_path.stem
# another round of heuristics to guess the correct config file.
checkpoint = (
@ -701,32 +724,46 @@ class ModelManager(object):
if model_path.suffix == ".safetensors"
else torch.load(model_path)
)
model_type = self.probe_model_type(checkpoint)
model_config_file = None
if model_type == SDLegacyType.V1:
print(" | SD-v1 model detected")
model_config_file = Path(
Globals.root, "configs/stable-diffusion/v1-inference.yaml"
)
elif model_type == SDLegacyType.V1_INPAINT:
print(" | SD-v1 inpainting model detected")
model_config_file = Path(
Globals.root, "configs/stable-diffusion/v1-inpainting-inference.yaml"
)
elif model_type == SDLegacyType.V2:
print(
" | SD-v2 model detected; model will be converted to diffusers format"
)
model_config_file = Path(
Globals.root, "configs/stable-diffusion/v2-inference-v.yaml"
)
convert = True
else:
print(
f"** {thing} is a legacy checkpoint file but not in a known Stable Diffusion model. Skipping import"
)
return
# additional probing needed if no config file provided
if model_config_file is None:
model_type = self.probe_model_type(checkpoint)
if model_type == SDLegacyType.V1:
print(" | SD-v1 model detected")
model_config_file = Path(
Globals.root, "configs/stable-diffusion/v1-inference.yaml"
)
elif model_type == SDLegacyType.V1_INPAINT:
print(" | SD-v1 inpainting model detected")
model_config_file = Path(
Globals.root, "configs/stable-diffusion/v1-inpainting-inference.yaml"
)
elif model_type == SDLegacyType.V2_v:
print(
" | SD-v2-v model detected; model will be converted to diffusers format"
)
model_config_file = Path(
Globals.root, "configs/stable-diffusion/v2-inference-v.yaml"
)
convert = True
elif model_type == SDLegacyType.V2_e:
print(
" | SD-v2-e model detected; model will be converted to diffusers format"
)
model_config_file = Path(
Globals.root, "configs/stable-diffusion/v2-inference.yaml"
)
convert = True
elif model_type == SDLegacyType.V2:
print(
f"** {thing} is a V2 checkpoint file, but its parameterization cannot be determined. Please provide configuration file path."
)
return
else:
print(
f"** {thing} is a legacy checkpoint file but not a known Stable Diffusion model. Please provide configuration file path."
)
return
diffuser_path = Path(
Globals.root, "models", Globals.converted_ckpts_dir, model_path.stem
@ -916,27 +953,40 @@ class ModelManager(object):
to the 2.3.0 "diffusers" version. This should be a one-time operation, called at
script startup time.
"""
# Three transformer models to check: bert, clip and safety checker
# Three transformer models to check: bert, clip and safety checker, and
# the diffusers as well
models_dir = Path(Globals.root, "models")
legacy_locations = [
Path(
models_dir,
"CompVis/stable-diffusion-safety-checker/models--CompVis--stable-diffusion-safety-checker"
),
Path("bert-base-uncased/models--bert-base-uncased"),
Path(models_dir, "bert-base-uncased/models--bert-base-uncased"),
Path(
models_dir,
"openai/clip-vit-large-patch14/models--openai--clip-vit-large-patch14"
),
]
models_dir = Path(Globals.root, "models")
legacy_locations.extend(list(global_cache_dir("diffusers").glob('*')))
legacy_layout = False
for model in legacy_locations:
legacy_layout = legacy_layout or Path(models_dir, model).exists()
legacy_layout = legacy_layout or model.exists()
if not legacy_layout:
return
print(
"** Legacy version <= 2.2.5 model directory layout detected. Reorganizing."
"""
>> ALERT:
>> The location of your previously-installed diffusers models needs to move from
>> invokeai/models/diffusers to invokeai/models/hub due to a change introduced by
>> diffusers version 0.14. InvokeAI will now move all models from the "diffusers" directory
>> into "hub" and then remove the diffusers directory. This is a quick, safe, one-time
>> operation. However if you have customized either of these directories and need to
>> make adjustments, please press ctrl-C now to abort and relaunch InvokeAI when you are ready.
>> Otherwise press <enter> to continue."""
)
print("** This is a quick one-time operation.")
input('continue> ')
# transformer files get moved into the hub directory
if cls._is_huggingface_hub_directory_present():
@ -948,33 +998,20 @@ class ModelManager(object):
for model in legacy_locations:
source = models_dir / model
dest = hub / model.stem
if dest.exists() and not source.exists():
continue
print(f"** {source} => {dest}")
if source.exists():
if dest.exists():
rmtree(source)
if dest.is_symlink():
print(f"** Found symlink at {dest.name}. Not migrating.")
elif dest.exists():
if source.is_dir():
rmtree(source)
else:
source.unlink()
else:
move(source, dest)
# anything else gets moved into the diffusers directory
if cls._is_huggingface_hub_directory_present():
diffusers = global_cache_dir("diffusers")
else:
diffusers = models_dir / "diffusers"
os.makedirs(diffusers, exist_ok=True)
for root, dirs, _ in os.walk(models_dir, topdown=False):
for dir in dirs:
full_path = Path(root, dir)
if full_path.is_relative_to(hub) or full_path.is_relative_to(diffusers):
continue
if Path(dir).match("models--*--*"):
dest = diffusers / dir
print(f"** {full_path} => {dest}")
if dest.exists():
rmtree(full_path)
else:
move(full_path, dest)
# now clean up by removing any empty directories
empty = [
root
@ -1072,7 +1109,7 @@ class ModelManager(object):
path = name_or_path
else:
owner, repo = name_or_path.split("/")
path = Path(global_cache_dir("diffusers") / f"models--{owner}--{repo}")
path = Path(global_cache_dir("hub") / f"models--{owner}--{repo}")
if not path.exists():
return None
hashpath = path / "checksum.sha256"
@ -1133,7 +1170,7 @@ class ModelManager(object):
using_fp16 = self.precision == "float16"
vae_args.update(
cache_dir=global_cache_dir("diffusers"),
cache_dir=global_cache_dir("hub"),
local_files_only=not Globals.internet_available,
)
@ -1172,7 +1209,7 @@ class ModelManager(object):
@staticmethod
def _delete_model_from_cache(repo_id):
cache_info = scan_cache_dir(global_cache_dir("diffusers"))
cache_info = scan_cache_dir(global_cache_dir("hub"))
# I'm sure there is a way to do this with comprehensions
# but the code quickly became incomprehensible!

View File

@ -640,7 +640,7 @@ def do_textual_inversion_training(
assert (
pretrained_model_name_or_path
), f"models.yaml error: neither 'repo_id' nor 'path' is defined for {model}"
pipeline_args = dict(cache_dir=global_cache_dir("diffusers"))
pipeline_args = dict(cache_dir=global_cache_dir("hub"))
# Load tokenizer
if tokenizer_name:

View File

@ -26,7 +26,7 @@ from ..args import APP_ID, APP_VERSION, Args, calculate_init_img_hash
from ..generator import infill_methods
from ..globals import Globals, global_converted_ckpts_dir, global_models_dir
from ..image_util import PngWriter, retrieve_metadata
from ..model_management import merge_diffusion_models
from ...frontend.merge.merge_diffusers import merge_diffusion_models
from ..prompting import (
get_prompt_structure,
get_tokenizer,

View File

@ -20,7 +20,7 @@ stable-diffusion-2.1:
recommended: True
sd-inpainting-2.0:
description: Stable Diffusion version 2.0 inpainting model (5.21 GB)
repo_id: stabilityai/stable-diffusion-2-1
repo_id: stabilityai/stable-diffusion-2-inpainting
format: diffusers
recommended: False
analog-diffusion-1.0:

View File

@ -1,6 +1,6 @@
model:
base_learning_rate: 1.0e-4
target: invokeai.backend.models.diffusion.ddpm.LatentDiffusion
target: invokeai.backend.stable_diffusion.diffusion.ddpm.LatentDiffusion
params:
parameterization: "v"
linear_start: 0.00085

View File

@ -0,0 +1,67 @@
model:
base_learning_rate: 1.0e-4
target: invokeai.backend.stable_diffusion.diffusion.ddpm.LatentDiffusion
params:
linear_start: 0.00085
linear_end: 0.0120
num_timesteps_cond: 1
log_every_t: 200
timesteps: 1000
first_stage_key: "jpg"
cond_stage_key: "txt"
image_size: 64
channels: 4
cond_stage_trainable: false
conditioning_key: crossattn
monitor: val/loss_simple_ema
scale_factor: 0.18215
use_ema: False # we set this to false because this is an inference only config
unet_config:
target: invokeai.backend.stable_diffusion.diffusionmodules.openaimodel.UNetModel
params:
use_checkpoint: True
use_fp16: True
image_size: 32 # unused
in_channels: 4
out_channels: 4
model_channels: 320
attention_resolutions: [ 4, 2, 1 ]
num_res_blocks: 2
channel_mult: [ 1, 2, 4, 4 ]
num_head_channels: 64 # need to fix for flash-attn
use_spatial_transformer: True
use_linear_in_transformer: True
transformer_depth: 1
context_dim: 1024
legacy: False
first_stage_config:
target: invokeai.backend.stable_diffusion.autoencoder.AutoencoderKL
params:
embed_dim: 4
monitor: val/rec_loss
ddconfig:
#attn_type: "vanilla-xformers"
double_z: true
z_channels: 4
resolution: 256
in_channels: 3
out_ch: 3
ch: 128
ch_mult:
- 1
- 2
- 4
- 4
num_res_blocks: 2
attn_resolutions: []
dropout: 0.0
lossconfig:
target: torch.nn.Identity
cond_stage_config:
target: invokeai.backend.stable_diffusion.encoders.modules.FrozenOpenCLIPEmbedder
params:
freeze: True
layer: "penultimate"

View File

@ -19,7 +19,7 @@ import invokeai.version as invokeai
from ...backend import Generate, ModelManager
from ...backend.args import Args, dream_cmd_from_png, metadata_dumps, metadata_from_png
from ...backend.globals import Globals
from ...backend.globals import Globals, global_config_dir
from ...backend.image_util import (
PngWriter,
make_grid,
@ -66,6 +66,9 @@ def main():
Globals.sequential_guidance = args.sequential_guidance
Globals.ckpt_convert = True # always true now
# run any post-install patches needed
run_patches()
print(f">> Internet connectivity is {Globals.internet_available}")
if not args.conf:
@ -658,7 +661,16 @@ def import_model(model_path: str, gen, opt, completer, convert=False):
)
if not imported_name:
print("** Import failed or was skipped")
if config_file := _pick_configuration_file(completer):
imported_name = gen.model_manager.heuristic_import(
model_path,
model_name=model_name,
description=model_desc,
convert=convert,
model_config_file=config_file,
)
if not imported_name:
print("** Aborting import.")
return
if not _verify_load(imported_name, gen):
@ -672,6 +684,46 @@ def import_model(model_path: str, gen, opt, completer, convert=False):
completer.update_models(gen.model_manager.list_models())
print(f">> {imported_name} successfully installed")
def _pick_configuration_file(completer)->Path:
print(
"""
Please select the type of this model:
[1] A Stable Diffusion v1.x ckpt/safetensors model
[2] A Stable Diffusion v1.x inpainting ckpt/safetensors model
[3] A Stable Diffusion v2.x base model (512 pixels)
[4] A Stable Diffusion v2.x v-predictive model (768 pixels)
[5] Other (you will be prompted to enter the config file path)
[Q] I have no idea! Skip the import.
""")
choices = [
global_config_dir() / 'stable-diffusion' / x
for x in [
'v1-inference.yaml',
'v1-inpainting-inference.yaml',
'v2-inference.yaml',
'v2-inference-v.yaml',
]
]
ok = False
while not ok:
try:
choice = input('select 0-5, Q > ').strip()
if choice.startswith(('q','Q')):
return
if choice == '5':
completer.complete_extensions(('.yaml'))
choice = Path(input('Select config file for this model> ').strip()).absolute()
completer.complete_extensions(None)
ok = choice.exists()
else:
choice = choices[int(choice)-1]
ok = True
except (ValueError, IndexError):
print(f'{choice} is not a valid choice')
except EOFError:
return
return choice
def _verify_load(model_name: str, gen) -> bool:
print(">> Verifying that new model loads...")
@ -1236,6 +1288,21 @@ def check_internet() -> bool:
except:
return False
# This routine performs any patch-ups needed after installation
def run_patches():
# install ckpt configuration files that may have been added to the
# distro after original root directory configuration
import invokeai.configs as conf
from shutil import copyfile
root_configs = Path(global_config_dir(), 'stable-diffusion')
repo_configs = Path(conf.__path__[0], 'stable-diffusion')
if not root_configs.exists():
os.makedirs(root_configs, exist_ok=True)
for src in repo_configs.iterdir():
dest = root_configs / src.name
if not dest.exists():
copyfile(src, dest)
if __name__ == "__main__":
main()

View File

@ -442,7 +442,7 @@ def main():
args = _parse_args()
global_set_root(args.root_dir)
cache_dir = str(global_cache_dir("diffusers"))
cache_dir = str(global_cache_dir("hub"))
os.environ[
"HF_HOME"
] = cache_dir # because not clear the merge pipeline is honoring cache_dir

View File

@ -1,20 +1,43 @@
# InvokeAI UI dev setup
# InvokeAI Web UI
The UI is in `invokeai/frontend`.
The UI is a fairly straightforward Typescript React app. The only really fancy stuff is the Unified Canvas.
## Environment set up
Code in `invokeai/frontend/web/` if you want to have a look.
Install [node](https://nodejs.org/en/download/) (includes npm) and
[yarn](https://yarnpkg.com/getting-started/install).
## Details
From `invokeai/frontend/` run `yarn install --immutable` to get everything set up.
State management is Redux via [Redux Toolkit](https://github.com/reduxjs/redux-toolkit). Communication with server is a mix of HTTP and [socket.io](https://github.com/socketio/socket.io-client) (with a custom redux middleware to help).
## Dev
[Chakra-UI](https://github.com/chakra-ui/chakra-ui) for components and styling.
[Konva](https://github.com/konvajs/react-konva) for the canvas, but we are pushing the limits of what is feasible with it (and HTML canvas in general). We plan to rebuild it with [PixiJS](https://github.com/pixijs/pixijs) to take advantage of WebGL's improved raster handling.
[Vite](https://vitejs.dev/) for bundling.
Localisation is via [i18next](https://github.com/i18next/react-i18next), but translation happens on our [Weblate](https://hosted.weblate.org/engage/invokeai/) project. Only the English source strings should be changed on this repo.
## Contributing
Thanks for your interest in contributing to the InvokeAI Web UI!
We encourage you to ping @psychedelicious and @blessedcoolant on [Discord](https://discord.gg/ZmtBAhwWhy) if you want to contribute, just to touch base and ensure your work doesn't conflict with anything else going on. The project is very active.
### Dev Environment
Install [node](https://nodejs.org/en/download/) and [yarn classic](https://classic.yarnpkg.com/lang/en/).
From `invokeai/frontend/web/` run `yarn install` to get everything set up.
Start everything in dev mode:
1. Start the dev server: `yarn dev`
2. Start the InvokeAI UI per usual: `invokeai --web`
3. Point your browser to the dev server address e.g. `http://localhost:5173/`
To build for dev: `yarn build-dev`
### Production builds
To build for production: `yarn build`
For a number of technical and logistical reasons, we need to commit UI build artefacts to the repo.
If you submit a PR, there is a good chance we will ask you to include a separate commit with a build of the app.
To build for production, run `yarn build`.

View File

@ -0,0 +1,3 @@
'''
Initialization file for invokeai.frontend.web
'''

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -12,7 +12,7 @@
margin: 0;
}
</style>
<script type="module" crossorigin src="./assets/index-bcc89564.js"></script>
<script type="module" crossorigin src="./assets/index-b928084d.js"></script>
<link rel="stylesheet" href="./assets/index-5483945c.css">
</head>

View File

@ -371,7 +371,8 @@
"convertToDiffusersHelpText6": "Do you wish to convert this model?",
"convertToDiffusersSaveLocation": "Save Location",
"v1": "v1",
"v2": "v2",
"v2_base": "v2 (512px)",
"v2_768": "v2 (768px)",
"inpainting": "v1 Inpainting",
"customConfig": "Custom Config",
"pathToCustomConfig": "Path To Custom Config",

View File

@ -4,14 +4,14 @@
"version": "0.0.1",
"scripts": {
"prepare": "cd ../../../ && husky install invokeai/frontend/web/.husky",
"dev": "vite dev",
"build": "npm run lint && vite build",
"dev": "concurrently \"vite dev\" \"yarn run theme:watch\"",
"build": "yarn run lint && vite build",
"preview": "vite preview",
"lint:madge": "madge --circular src/main.tsx",
"lint:eslint": "eslint --max-warnings=0",
"lint:prettier": "prettier --check .",
"lint:tsc": "tsc --noEmit",
"lint": "npm run lint:eslint && npm run lint:prettier && npm run lint:tsc && npm run lint:madge",
"lint": "yarn run lint:eslint && yarn run lint:prettier && yarn run lint:tsc && yarn run lint:madge",
"fix": "eslint --fix . && prettier --loglevel warn --write . && tsc --noEmit",
"lint-staged": "lint-staged",
"postinstall": "patch-package && yarn run theme",
@ -38,6 +38,7 @@
"@chakra-ui/anatomy": "^2.1.1",
"@chakra-ui/icons": "^2.0.17",
"@chakra-ui/react": "^2.5.1",
"@chakra-ui/styled-system": "^2.6.1",
"@chakra-ui/theme-tools": "^2.0.16",
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
@ -82,6 +83,7 @@
"@typescript-eslint/parser": "^5.52.0",
"@vitejs/plugin-react-swc": "^3.2.0",
"babel-plugin-transform-imports": "^2.0.0",
"concurrently": "^7.6.0",
"eslint": "^8.34.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-prettier": "^4.2.1",

View File

@ -371,7 +371,8 @@
"convertToDiffusersHelpText6": "Do you wish to convert this model?",
"convertToDiffusersSaveLocation": "Save Location",
"v1": "v1",
"v2": "v2",
"v2_base": "v2 (512px)",
"v2_768": "v2 (768px)",
"inpainting": "v1 Inpainting",
"customConfig": "Custom Config",
"pathToCustomConfig": "Path To Custom Config",

View File

@ -363,7 +363,6 @@
"convertToDiffusersHelpText6": "¿Desea transformar este modelo?",
"convertToDiffusersSaveLocation": "Guardar ubicación",
"v1": "v1",
"v2": "v2",
"statusConverting": "Adaptar",
"modelConverted": "Modelo adaptado",
"sameFolder": "La misma carpeta",

View File

@ -45,7 +45,9 @@
"statusUpscaling": "Mise à échelle",
"statusUpscalingESRGAN": "Mise à échelle (ESRGAN)",
"statusLoadingModel": "Chargement du modèle",
"statusModelChanged": "Modèle changé"
"statusModelChanged": "Modèle changé",
"discordLabel": "Discord",
"githubLabel": "Github"
},
"gallery": {
"generations": "Générations",

View File

@ -92,7 +92,6 @@
"modelThree": "מודל 3",
"mergedModelName": "שם מודל ממוזג",
"v1": "v1",
"v2": "v2",
"invokeRoot": "תיקיית InvokeAI",
"customConfig": "תצורה מותאמת אישית",
"pathToCustomConfig": "נתיב לתצורה מותאמת אישית",

View File

@ -361,7 +361,6 @@
"convertToDiffusersHelpText5": "Assicurati di avere spazio su disco sufficiente. I modelli generalmente variano tra 4 GB e 7 GB di dimensioni.",
"convertToDiffusersHelpText6": "Vuoi convertire questo modello?",
"convertToDiffusersSaveLocation": "Ubicazione salvataggio",
"v2": "v2",
"inpainting": "v1 Inpainting",
"customConfig": "Configurazione personalizzata",
"statusConverting": "Conversione in corso",

View File

@ -302,7 +302,7 @@
"name": "Naam",
"nameValidationMsg": "Geef een naam voor je model",
"description": "Beschrijving",
"descriptionValidationMsg": "Voeg een beschrijving toe voor je model",
"descriptionValidationMsg": "Voeg een beschrijving toe voor je model.",
"config": "Configuratie",
"configValidationMsg": "Pad naar het configuratiebestand van je model.",
"modelLocation": "Locatie model",
@ -364,7 +364,6 @@
"convertToDiffusersHelpText5": "Zorg ervoor dat je genoeg schijfruimte hebt. Modellen nemen gewoonlijk ongeveer 4 - 7 GB ruimte in beslag.",
"convertToDiffusersSaveLocation": "Bewaarlocatie",
"v1": "v1",
"v2": "v2",
"inpainting": "v1-inpainting",
"customConfig": "Eigen configuratie",
"pathToCustomConfig": "Pad naar eigen configuratie",

View File

@ -358,7 +358,6 @@
"convertToDiffusersHelpText6": "Você deseja converter este modelo?",
"convertToDiffusersSaveLocation": "Local para Salvar",
"v1": "v1",
"v2": "v2",
"inpainting": "v1 Inpainting",
"customConfig": "Configuração personalizada",
"pathToCustomConfig": "Caminho para configuração personalizada",
@ -381,7 +380,19 @@
"allModels": "Todos os Modelos",
"repoIDValidationMsg": "Repositório Online do seu Modelo",
"convert": "Converter",
"convertToDiffusersHelpText2": "Este processo irá substituir sua entrada de Gerenciador de Modelos por uma versão Diffusers do mesmo modelo."
"convertToDiffusersHelpText2": "Este processo irá substituir sua entrada de Gerenciador de Modelos por uma versão Diffusers do mesmo modelo.",
"mergedModelCustomSaveLocation": "Caminho Personalizado",
"mergedModelSaveLocation": "Local de Salvamento",
"interpolationType": "Tipo de Interpolação",
"ignoreMismatch": "Ignorar Divergências entre Modelos Selecionados",
"invokeAIFolder": "Pasta Invoke AI",
"weightedSum": "Soma Ponderada",
"sigmoid": "Sigmóide",
"inverseSigmoid": "Sigmóide Inversa",
"modelMergeHeaderHelp1": "Você pode mesclar até três modelos diferentes para criar uma mistura que atenda às suas necessidades.",
"modelMergeInterpAddDifferenceHelp": "Neste modo, o Modelo 3 é primeiro subtraído do Modelo 2. A versão resultante é mesclada com o Modelo 1 com a taxa alpha definida acima.",
"modelMergeAlphaHelp": "Alpha controla a força da mistura dos modelos. Valores de alpha mais baixos resultam em uma influência menor do segundo modelo.",
"modelMergeHeaderHelp2": "Apenas Diffusers estão disponíveis para mesclagem. Se você deseja mesclar um modelo de checkpoint, por favor, converta-o para Diffusers primeiro."
},
"parameters": {
"images": "Imagems",
@ -441,7 +452,22 @@
"info": "Informações",
"deleteImage": "Apagar Imagem",
"initialImage": "Imagem inicial",
"showOptionsPanel": "Mostrar Painel de Opções"
"showOptionsPanel": "Mostrar Painel de Opções",
"vSymmetryStep": "V Passo de Simetria",
"hSymmetryStep": "H Passo de Simetria",
"symmetry": "Simetria",
"copyImage": "Copiar imagem",
"negativePrompts": "Indicações negativas",
"hiresStrength": "Força da Alta Resolução",
"denoisingStrength": "A força de remoção de ruído",
"imageToImage": "Imagem para Imagem",
"cancel": {
"setType": "Definir tipo de cancelamento",
"isScheduled": "Cancelando",
"schedule": "Cancelar após a iteração atual",
"immediate": "Cancelar imediatamente"
},
"general": "Geral"
},
"settings": {
"models": "Modelos",
@ -454,7 +480,8 @@
"resetWebUI": "Reiniciar Interface",
"resetWebUIDesc1": "Reiniciar a interface apenas reinicia o cache local do broswer para imagens e configurações lembradas. Não apaga nenhuma imagem do disco.",
"resetWebUIDesc2": "Se as imagens não estão aparecendo na galeria ou algo mais não está funcionando, favor tentar reiniciar antes de postar um problema no GitHub.",
"resetComplete": "A interface foi reiniciada. Atualize a página para carregar."
"resetComplete": "A interface foi reiniciada. Atualize a página para carregar.",
"useSlidersForAll": "Usar deslizadores para todas as opções"
},
"toast": {
"tempFoldersEmptied": "Pasta de Arquivos Temporários Esvaziada",
@ -546,5 +573,20 @@
"betaDarkenOutside": "Escurecer Externamente",
"betaLimitToBox": "Limitar Para a Caixa",
"betaPreserveMasked": "Preservar Máscarado"
},
"tooltip": {
"feature": {
"seed": "O valor da semente afeta o ruído inicial a partir do qual a imagem é formada. Você pode usar as sementes já existentes de imagens anteriores. 'Limiar de ruído' é usado para mitigar artefatos em valores CFG altos (experimente a faixa de 0-10), e o Perlin para adicionar ruído Perlin durante a geração: ambos servem para adicionar variação às suas saídas.",
"gallery": "A galeria exibe as gerações da pasta de saída conforme elas são criadas. As configurações são armazenadas em arquivos e acessadas pelo menu de contexto.",
"other": "Essas opções ativam modos alternativos de processamento para o Invoke. 'Seamless tiling' criará padrões repetidos na saída. 'High resolution' é uma geração em duas etapas com img2img: use essa configuração quando desejar uma imagem maior e mais coerente sem artefatos. Levará mais tempo do que o txt2img usual.",
"boundingBox": "A caixa delimitadora é a mesma que as configurações de largura e altura para Texto para Imagem ou Imagem para Imagem. Apenas a área na caixa será processada.",
"upscale": "Use o ESRGAN para ampliar a imagem imediatamente após a geração.",
"seamCorrection": "Controla o tratamento das emendas visíveis que ocorrem entre as imagens geradas no canvas.",
"faceCorrection": "Correção de rosto com GFPGAN ou Codeformer: o algoritmo detecta rostos na imagem e corrige quaisquer defeitos. Um valor alto mudará mais a imagem, resultando em rostos mais atraentes. Codeformer com uma fidelidade maior preserva a imagem original às custas de uma correção de rosto mais forte.",
"prompt": "Este é o campo de prompt. O prompt inclui objetos de geração e termos estilísticos. Você também pode adicionar peso (importância do token) no prompt, mas comandos e parâmetros de CLI não funcionarão.",
"infillAndScaling": "Gerencie os métodos de preenchimento (usados em áreas mascaradas ou apagadas do canvas) e a escala (útil para tamanhos de caixa delimitadora pequenos).",
"imageToImage": "Image to Image carrega qualquer imagem como inicial, que é então usada para gerar uma nova junto com o prompt. Quanto maior o valor, mais a imagem resultante mudará. Valores de 0.0 a 1.0 são possíveis, a faixa recomendada é de 0.25 a 0.75",
"variations": "Experimente uma variação com um valor entre 0,1 e 1,0 para mudar o resultado para uma determinada semente. Variações interessantes da semente estão entre 0,1 e 0,3."
}
}
}

View File

@ -1 +1,24 @@
{}
{
"common": {
"nodes": "節點",
"img2img": "圖片轉圖片",
"langSimplifiedChinese": "簡體中文",
"statusError": "錯誤",
"statusDisconnected": "已中斷連線",
"statusConnected": "已連線",
"back": "返回",
"load": "載入",
"close": "關閉",
"langEnglish": "英語",
"settingsLabel": "設定",
"upload": "上傳",
"langArabic": "阿拉伯語",
"greenTheme": "綠色",
"lightTheme": "淺色",
"darkTheme": "深色",
"discordLabel": "Discord",
"nodesDesc": "使用Node生成圖像的系統正在開發中。敬請期待有關於這項功能的更新。",
"reportBugLabel": "回報錯誤",
"githubLabel": "GitHub"
}
}

View File

@ -163,7 +163,8 @@ export default function SearchModels() {
const configFiles = {
v1: 'configs/stable-diffusion/v1-inference.yaml',
v2: 'configs/stable-diffusion/v2-inference-v.yaml',
v2_base: 'configs/stable-diffusion/v2-inference-v.yaml',
v2_768: 'configs/stable-diffusion/v2-inference-v.yaml',
inpainting: 'configs/stable-diffusion/v1-inpainting-inference.yaml',
custom: pathToConfig,
};
@ -372,8 +373,11 @@ export default function SearchModels() {
<Radio value="v1">
<Text fontSize="sm">{t('modelManager.v1')}</Text>
</Radio>
<Radio value="v2">
<Text fontSize="sm">{t('modelManager.v2')}</Text>
<Radio value="v2_base">
<Text fontSize="sm">{t('modelManager.v2_base')}</Text>
</Radio>
<Radio value="v2_768">
<Text fontSize="sm">{t('modelManager.v2_768')}</Text>
</Radio>
<Radio value="inpainting">
<Text fontSize="sm">{t('modelManager.inpainting')}</Text>

View File

@ -1,40 +0,0 @@
@mixin Button(
$btn-color: rgb(45, 49, 53),
$btn-color-hover: rgb(65, 69, 73),
$btn-width: 100%,
$btn-height: 100%,
$icon-size: 20px
) {
// min-width: $btn-width;
// min-height: $btn-height;
// background-color: $btn-color;
// &:hover {
// background-color: $btn-color-hover;
// }
// &:disabled {
// background-color: var(--btn-base-color);
// &:hover {
// background-color: var(--btn-base-color);
// }
// }
// svg {
// width: $icon-size;
// height: $icon-size;
// color: var(--btn-svg-color);
// }
}
@mixin BaseButton {
// background-color: var(--btn-base-color);
// &:hover {
// background-color: var(--btn-base-color-hover);
// }
// &:disabled {
// &:hover {
// background-color: var(--btn-base-color);
// }
// }
}

View File

@ -1,159 +0,0 @@
// @media (max-width: 600px) {
// #root {
// .app-content {
// padding: 5px;
// .site-header {
// position: fixed;
// display: flex;
// height: 100px;
// z-index: 1;
// .site-header-left-side {
// position: absolute;
// display: flex;
// min-width: 145px;
// float: left;
// padding-left: 0;
// }
// .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;
// .chakra-popover__popper {
// grid-area: logoSpace;
// }
// > :nth-child(1).chakra-text {
// grid-area: status;
// width: 100%;
// display: flex;
// justify-content: center;
// }
// > :nth-child(2) {
// grid-area: sampler;
// display: flex;
// justify-content: center;
// align-items: center;
// select {
// width: 185px;
// margin-top: 10px;
// }
// .chakra-select__icon-wrapper {
// right: 10px;
// svg {
// margin-top: 10px;
// }
// }
// }
// > :nth-child(3) {
// grid-area: btn1;
// }
// > :nth-child(4) {
// grid-area: btn2;
// }
// > :nth-child(6) {
// grid-area: btn3;
// }
// > :nth-child(7) {
// grid-area: btn4;
// }
// > :nth-child(8) {
// grid-area: btn5;
// }
// > :nth-child(9) {
// grid-area: btn6;
// }
// }
// }
// .app-tabs {
// position: fixed;
// display: flex;
// flex-direction: column;
// row-gap: 15px;
// max-width: 100%;
// overflow: hidden;
// margin-top: 120px;
// .app-tabs-list {
// display: flex;
// justify-content: space-between;
// }
// .app-tabs-panels {
// overflow: hidden;
// overflow-y: scroll;
// .workarea-main {
// display: grid;
// grid-template-areas:
// 'workarea'
// 'options'
// 'gallery';
// row-gap: 15px;
// .parameters-panel-wrapper {
// grid-area: options;
// width: 100%;
// max-width: 100%;
// height: inherit;
// overflow: inherit;
// padding: 0 10px;
// .main-settings-row {
// max-width: 100%;
// }
// .advanced-parameters-item {
// max-width: 100%;
// }
// }
// .workarea-children-wrapper {
// grid-area: workarea;
// .workarea-split-view {
// display: flex;
// flex-direction: column;
// }
// .current-image-options {
// column-gap: 3px;
// }
// .text-to-image-area {
// padding: 0;
// }
// .current-image-preview {
// height: 430px;
// }
// //image 2 image
// .image-upload-button {
// row-gap: 10px;
// padding: 5px;
// svg {
// width: 2rem;
// height: 2rem;
// margin-top: 10px;
// }
// }
// //Cavas Painting
// .inpainting-settings {
// display: flex;
// flex-wrap: wrap;
// row-gap: 10px;
// }
// .inpainting-canvas-area {
// .konvajs-content {
// height: 400px !important;
// }
// }
// }
// .image-gallery-wrapper {
// grid-area: gallery;
// min-height: 400px;
// .image-gallery-popup {
// width: 100% !important;
// max-width: 100% !important;
// }
// }
// }
// }
// }
// }
// }
// }

View File

@ -1,7 +0,0 @@
@mixin HideScrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
}

View File

@ -1,20 +0,0 @@
// Calc Values
$app-cutoff: 0px;
$app-content-height-cutoff: calc(70px + 1rem); // default: 7rem
// Usage Variables
// app
$app-padding: 1rem;
$progress-bar-thickness: 0.3rem;
$app-width: calc(100vw - $app-cutoff);
$app-height: calc(100vh - $progress-bar-thickness);
$app-content-height: calc(100vh - $app-content-height-cutoff);
$app-gallery-height: calc(100vh - ($app-content-height-cutoff + 5.5rem));
$app-gallery-popover-height: calc(100vh - ($app-content-height-cutoff + 6rem));
$app-metadata-height: calc(100vh - ($app-content-height-cutoff + 4.4rem));
$app-text-to-image-height: calc(
100vh - 9.4375rem - 1.925rem - 1.15rem
); // do not touch ffs
// option bar
$options-bar-max-width: 22.5rem;

View File

@ -1,4 +0,0 @@
@forward './Shared';
@forward './Buttons';
@forward './Variables';
@forward './Responsive';

View File

@ -1,143 +0,0 @@
[data-theme='asdf'] {
// General Colors
--white: rgb(255, 255, 255);
// Accent Colors
--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);
// App Colors
--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);
// Error status colors
--border-color-invalid: rgb(255, 80, 50);
--box-shadow-color-invalid: rgb(210, 30, 10);
// Tabs
--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);
// Button Colors
--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);
// IAI Button Colors
--btn-checkbox-border-hover: rgb(46, 48, 68);
// Progress Bar Color
--progress-bar-color: var(--accent-color);
// Prompt Box Colors
--prompt-bg-color: rgb(10, 10, 10);
// Switch
--switch-bg-color: rgb(100, 102, 110);
--switch-bg-active-color: var(--accent-color);
// Slider
--slider-color: var(--accent-color-bright);
// Slider
--slider-color: rgb(151, 113, 255);
--slider-mark-color: rgb(151, 113, 255);
// Resizable
--resizeable-handle-border-color: var(--accent-color);
// Metadata Viewer
--metadata-bg-color: rgba(0, 0, 0, 0.7);
--metadata-json-bg-color: rgba(255, 255, 255, 0.1);
// Status Message
--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
--settings-modal-bg: rgb(30, 32, 42);
// Input
--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);
// Console
--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
--img2img-img-bg-color: rgb(30, 32, 42);
// Gallery
// Context Menus
--context-menu-bg-color: rgb(46, 48, 58);
--context-menu-box-shadow: none;
--context-menu-bg-color-hover: rgb(30, 32, 42);
// Shadows
--floating-button-drop-shadow-color: var(--accent-color);
// Canvas
--inpainting-alerts-bg: rgba(20, 20, 26, 0.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);
// Checkerboard
--checkboard-dots-color: rgb(35, 35, 39);
// Scrollbar
--scrollbar-color: var(--accent-color);
--scrollbar-color-hover: var(--accent-color-bright);
// SubHook
--subhook-color: var(--accent-color);
}

View File

@ -1,141 +0,0 @@
[data-theme='green'] {
// General Colors
--white: rgb(255, 255, 255);
// Accent Colors
--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);
// App Colors
--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);
// Error status colors
--border-color-invalid: rgb(255, 80, 50);
--box-shadow-color-invalid: rgb(210, 30, 10);
// Tabs
--tab-color: rgb(40, 44, 48);
--tab-hover-color: rgb(48, 52, 56); //done
--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); //done
// Button Colors
--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);
// IAI Button Colors
--btn-checkbox-border-hover: rgb(46, 48, 68);
// Progress Bar Color
--progress-bar-color: var(--accent-color);
// Prompt Box Colors
--prompt-bg-color: rgb(10, 10, 14);
// Switch
--switch-bg-color: rgb(100, 102, 110);
--switch-bg-active-color: var(--accent-color);
// Slider
--slider-color: var(--accent-color-bright);
--slider-mark-color: var(--accent-color-bright);
// Resizable
--resizeable-handle-border-color: var(--accent-color);
// Metadata Viewer
--metadata-bg-color: rgba(0, 0, 0, 0.7);
--metadata-json-bg-color: rgba(255, 255, 255, 0.1);
// Status Message
--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
--settings-modal-bg: rgb(30, 32, 42);
// Input
--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);
// Console
--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
--img2img-img-bg-color: rgb(30, 32, 42);
// Gallery
// Context Menus
--context-menu-bg-color: rgb(46, 48, 58);
--context-menu-box-shadow: none;
--context-menu-bg-color-hover: rgb(30, 32, 42);
// Shadows
--floating-button-drop-shadow-color: var(--accent-color);
// Canvas
--inpainting-alerts-bg: rgba(20, 20, 26, 0.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);
//Checkerboard
--checkboard-dots-color: rgb(35, 35, 39);
// Scrollbar
--scrollbar-color: var(--accent-color);
--scrollbar-color-hover: var(--accent-color-bright);
// SubHook
--subhook-color: var(--accent-color);
}

View File

@ -1,138 +0,0 @@
// [data-theme='light'] {
// // General Colors
// --white: rgb(255, 255, 255);
// // Accent Colors
// --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);
// // App Colors
// --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);
// // Error status colors
// --border-color-invalid: rgb(255, 80, 50);
// --box-shadow-color-invalid: none;
// // Tabs
// --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);
// // Button Colors
// --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);
// // IAI Button Colors
// --btn-checkbox-border-hover: rgb(176, 178, 182);
// // Progress Bar Color
// --progress-bar-color: rgb(235, 185, 5);
// // Prompt Box Colors
// --prompt-bg-color: rgb(225, 227, 229);
// // Switch
// --switch-bg-color: rgb(178, 180, 182);
// --switch-bg-active-color: rgb(235, 185, 5);
// // Slider
// --slider-color: var(--accent-color);
// --slider-mark-color: rgb(0, 0, 0);
// // Resizable
// --resizeable-handle-border-color: rgb(160, 162, 164);
// // Metadata Viewer
// --metadata-bg-color: rgba(230, 230, 230, 0.9);
// --metadata-json-bg-color: rgba(0, 0, 0, 0.1);
// // Status Message
// --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
// --settings-modal-bg: rgb(202, 204, 206);
// // Input
// --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;
// // Console
// --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
// --img2img-img-bg-color: rgb(180, 182, 184);
// // Gallery
// // Context Menus
// --context-menu-bg-color: var(--background-color);
// --context-menu-box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35),
// 0px 10px 20px -15px rgba(22, 23, 24, 0.2);
// --context-menu-bg-color-hover: var(--background-color-secondary);
// // Shadows
// --floating-button-drop-shadow-color: rgba(0, 0, 0, 0.7);
// // Canvas
// --inpainting-alerts-bg: rgba(220, 222, 224, 0.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);
// // Checkerboard
// --checkboard-dots-color: rgb(160, 160, 172);
// // Scrollbar
// --scrollbar-color: rgb(180, 180, 184);
// --scrollbar-color-hover: rgb(150, 150, 154);
// // SubHook
// --subhook-color: rgb(0, 0, 0);
// }

View File

@ -3,7 +3,6 @@ import {
createMultiStyleConfigHelpers,
defineStyle,
} from '@chakra-ui/styled-system';
import { mode } from '@chakra-ui/theme-tools';
const { definePartsStyle, defineMultiStyleConfig } =
createMultiStyleConfigHelpers(parts.keys);
@ -20,16 +19,16 @@ const invokeAIButton = defineStyle((props) => {
fontSize: 'sm',
border: 'none',
borderRadius: 'base',
bg: mode(`${c}.250`, `${c}.800`)(props),
color: mode('base.900', 'base.100')(props),
bg: `${c}.800`,
color: 'base.100',
_hover: {
bg: mode(`${c}.300`, `${c}.700`)(props),
bg: `${c}.700`,
},
_expanded: {
bg: mode(`${c}.250`, `${c}.750`)(props),
bg: `${c}.750`,
borderBottomRadius: 'none',
_hover: {
bg: mode(`${c}.300`, `${c}.700`)(props),
bg: `${c}.700`,
},
},
};
@ -38,7 +37,7 @@ const invokeAIButton = defineStyle((props) => {
const invokeAIPanel = defineStyle((props) => {
const { colorScheme: c } = props;
return {
bg: mode(`${c}.200`, `${c}.800`)(props),
bg: `${c}.800`,
borderRadius: 'base',
borderTopRadius: 'none',
p: 4,

View File

@ -1,45 +1,44 @@
import { defineStyle, defineStyleConfig } from '@chakra-ui/react';
import { mode } from '@chakra-ui/theme-tools';
const invokeAI = defineStyle((props) => {
const { colorScheme: c } = props;
// must specify `_disabled` colors if we override `_hover`, else hover on disabled has no styles
const _disabled = {
bg: mode(`${c}.200`, `${c}.600`)(props),
color: mode(`${c}.700`, `${c}.100`)(props),
bg: `${c}.600`,
color: `${c}.100`,
svg: {
fill: mode(`${c}.700`, `${c}.100`)(props),
fill: `${c}.100`,
},
};
return {
bg: mode(`${c}.300`, `${c}.700`)(props),
color: mode(`${c}.800`, `${c}.100`)(props),
bg: `${c}.700`,
color: `${c}.100`,
borderRadius: 'base',
svg: {
fill: mode(`${c}.800`, `${c}.100`)(props),
fill: `${c}.100`,
},
_disabled,
_hover: {
bg: mode(`${c}.400`, `${c}.650`)(props),
color: mode(`black`, `${c}.50`)(props),
bg: `${c}.650`,
color: `${c}.50`,
svg: {
fill: mode(`black`, `${c}.50`)(props),
fill: `${c}.50`,
},
_disabled,
},
_checked: {
bg: mode('accent.200', 'accent.700')(props),
color: mode('accent.800', 'accent.100')(props),
bg: 'accent.700',
color: 'accent.100',
svg: {
fill: mode('accent.800', 'accent.100')(props),
fill: 'accent.100',
},
_disabled,
_hover: {
bg: mode('accent.300', 'accent.600')(props),
color: mode('accent.900', 'accent.50')(props),
bg: 'accent.600',
color: 'accent.50',
svg: {
fill: mode('accent.900', 'accent.50')(props),
fill: 'accent.50',
},
_disabled,
},

View File

@ -3,7 +3,6 @@ import {
createMultiStyleConfigHelpers,
defineStyle,
} from '@chakra-ui/styled-system';
import { mode } from '@chakra-ui/theme-tools';
const { definePartsStyle, defineMultiStyleConfig } =
createMultiStyleConfigHelpers(parts.keys);
@ -13,31 +12,31 @@ const invokeAIControl = defineStyle((props) => {
return {
_checked: {
bg: mode(`${c}.500`, `${c}.200`)(props),
borderColor: mode(`${c}.500`, `${c}.200`)(props),
color: mode('white', 'base.900')(props),
bg: `${c}.200`,
borderColor: `${c}.200`,
color: 'base.900',
_hover: {
bg: mode(`${c}.600`, `${c}.300`)(props),
borderColor: mode(`${c}.600`, `${c}.300`)(props),
bg: `${c}.300`,
borderColor: `${c}.300`,
},
_disabled: {
borderColor: mode('base.200', 'transparent')(props),
bg: mode('base.200', 'whiteAlpha.300')(props),
color: mode('base.500', 'whiteAlpha.500')(props),
borderColor: 'transparent',
bg: 'whiteAlpha.300',
color: 'whiteAlpha.500',
},
},
_indeterminate: {
bg: mode(`${c}.500`, `${c}.200`)(props),
borderColor: mode(`${c}.500`, `${c}.200`)(props),
color: mode('white', 'base.900')(props),
bg: `${c}.200`,
borderColor: `${c}.200`,
color: 'base.900',
},
_disabled: {
bg: mode('base.100', 'whiteAlpha.100')(props),
borderColor: mode('base.100', 'transparent')(props),
bg: 'whiteAlpha.100',
borderColor: 'transparent',
},
_focusVisible: {
@ -45,7 +44,7 @@ const invokeAIControl = defineStyle((props) => {
},
_invalid: {
borderColor: mode('red.500', 'red.300')(props),
borderColor: 'red.300',
},
};
});

View File

@ -1,7 +1,6 @@
import { defineStyle, defineStyleConfig } from '@chakra-ui/styled-system';
import { mode } from '@chakra-ui/theme-tools';
const invokeAI = defineStyle((props) => {
const invokeAI = defineStyle((_props) => {
return {
fontSize: 'sm',
marginEnd: 0,
@ -13,7 +12,7 @@ const invokeAI = defineStyle((props) => {
_disabled: {
opacity: 0.4,
},
color: mode('base.600', 'base.300')(props),
color: 'base.300',
};
});

View File

@ -3,7 +3,6 @@ import {
createMultiStyleConfigHelpers,
defineStyle,
} from '@chakra-ui/styled-system';
import { mode } from '@chakra-ui/theme-tools';
const { defineMultiStyleConfig, definePartsStyle } =
createMultiStyleConfigHelpers(parts.keys);
@ -14,18 +13,18 @@ const invokeAIOverlay = defineStyle({
const invokeAIDialogContainer = defineStyle({});
const invokeAIDialog = defineStyle((props) => {
const invokeAIDialog = defineStyle((_props) => {
return {
bg: mode('base.300', 'base.850')(props),
bg: 'base.850',
maxH: '80vh',
};
});
const invokeAIHeader = defineStyle((props) => {
const invokeAIHeader = defineStyle((_props) => {
return {
fontWeight: '600',
fontSize: 'lg',
color: mode('base.700', 'base.200')(props),
color: 'base.200',
};
});

View File

@ -3,7 +3,7 @@ import {
createMultiStyleConfigHelpers,
defineStyle,
} from '@chakra-ui/styled-system';
import { mode } from '@chakra-ui/theme-tools';
import { getInputOutlineStyles } from '../util/getInputOutlineStyles';
const { defineMultiStyleConfig, definePartsStyle } =
@ -33,7 +33,7 @@ const invokeAIStepperGroup = defineStyle((_props) => {
};
});
const invokeAIStepper = defineStyle((props) => {
const invokeAIStepper = defineStyle((_props) => {
return {
border: 'none',
// expand arrow hitbox
@ -43,11 +43,11 @@ const invokeAIStepper = defineStyle((props) => {
my: 0,
svg: {
color: mode('base.600', 'base.300')(props),
color: 'base.300',
width: 2.5,
height: 2.5,
_hover: {
color: mode('base.900', 'base.50')(props),
color: 'base.50',
},
},
};

View File

@ -4,7 +4,6 @@ import {
defineStyle,
} from '@chakra-ui/styled-system';
import { cssVar } from '@chakra-ui/theme-tools';
import { mode } from '@chakra-ui/theme-tools';
const { defineMultiStyleConfig, definePartsStyle } =
createMultiStyleConfigHelpers(parts.keys);
@ -13,7 +12,7 @@ const $popperBg = cssVar('popper-bg');
const $arrowBg = cssVar('popper-arrow-bg');
const $arrowShadowColor = cssVar('popper-arrow-shadow-color');
const invokeAIContent = defineStyle((props) => {
const invokeAIContent = defineStyle((_props) => {
return {
[$arrowBg.variable]: `colors.base.800`,
[$popperBg.variable]: `colors.base.800`,
@ -23,8 +22,8 @@ const invokeAIContent = defineStyle((props) => {
p: 4,
borderWidth: '2px',
borderStyle: 'solid',
borderColor: mode('base.500', 'base.600')(props),
bg: mode('base.200', 'base.800')(props),
borderColor: 'base.600',
bg: 'base.800',
};
});

View File

@ -3,25 +3,22 @@ import {
createMultiStyleConfigHelpers,
defineStyle,
} from '@chakra-ui/styled-system';
import { mode } from '@chakra-ui/theme-tools';
const { defineMultiStyleConfig, definePartsStyle } =
createMultiStyleConfigHelpers(parts.keys);
const invokeAIFilledTrack = defineStyle((props) => ({
bg: mode('accent.400', 'accent.600')(props),
const invokeAIFilledTrack = defineStyle((_props) => ({
bg: 'accent.600',
transition: 'width 0.2s ease-in-out',
_indeterminate: {
bgGradient: `linear(to-r, transparent 0%, ${mode(
'accent.400',
'accent.600'
)(props)} 50%, transparent 100%);`,
bgGradient:
'linear(to-r, transparent 0%, accent.600 50%, transparent 100%);',
},
}));
const invokeAITrack = defineStyle((props) => {
const invokeAITrack = defineStyle((_props) => {
return {
bg: mode('base.300', 'base.800')(props),
bg: 'base.800',
};
});

View File

@ -1,14 +1,13 @@
import { selectAnatomy as parts } from '@chakra-ui/anatomy';
import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react';
import { getInputOutlineStyles } from '../util/getInputOutlineStyles';
import { mode } from '@chakra-ui/theme-tools';
const { definePartsStyle, defineMultiStyleConfig } =
createMultiStyleConfigHelpers(parts.keys);
const invokeAIIcon = defineStyle((props) => {
const invokeAIIcon = defineStyle((_props) => {
return {
color: mode('base.600', 'base.300')(props),
color: 'base.300',
};
});

View File

@ -1,13 +1,12 @@
import { sliderAnatomy as parts } from '@chakra-ui/anatomy';
import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react';
import { mode } from '@chakra-ui/theme-tools';
const { definePartsStyle, defineMultiStyleConfig } =
createMultiStyleConfigHelpers(parts.keys);
const invokeAITrack = defineStyle((props) => {
const invokeAITrack = defineStyle((_props) => {
return {
bg: mode('base.300', 'base.400')(props),
bg: 'base.400',
h: 1.5,
};
});
@ -15,7 +14,7 @@ const invokeAITrack = defineStyle((props) => {
const invokeAIFilledTrack = defineStyle((props) => {
const { colorScheme: c } = props;
return {
bg: mode(`${c}.400`, `${c}.600`)(props),
bg: `${c}.600`,
h: 1.5,
};
});
@ -27,11 +26,11 @@ const invokeAIThumb = defineStyle((_props) => {
};
});
const invokeAIMark = defineStyle((props) => {
const invokeAIMark = defineStyle((_props) => {
return {
fontSize: 'xs',
fontWeight: '500',
color: mode('base.800', 'base.200')(props),
color: 'base.200',
mt: 2,
insetInlineStart: 'unset',
};

View File

@ -3,7 +3,6 @@ import {
createMultiStyleConfigHelpers,
defineStyle,
} from '@chakra-ui/styled-system';
import { mode } from '@chakra-ui/theme-tools';
const { defineMultiStyleConfig, definePartsStyle } =
createMultiStyleConfigHelpers(parts.keys);
@ -12,13 +11,13 @@ const invokeAITrack = defineStyle((props) => {
const { colorScheme: c } = props;
return {
bg: mode(`base.400`, `base.600`)(props),
bg: 'base.600',
_focusVisible: {
boxShadow: 'none',
},
_checked: {
bg: mode(`${c}.400`, `${c}.600`)(props),
bg: `${c}.600`,
},
};
});
@ -27,7 +26,7 @@ const invokeAIThumb = defineStyle((props) => {
const { colorScheme: c } = props;
return {
bg: mode(`${c}.50`, `${c}.50`)(props),
bg: `${c}.50`,
};
});

View File

@ -3,7 +3,6 @@ import {
createMultiStyleConfigHelpers,
defineStyle,
} from '@chakra-ui/styled-system';
import { mode } from '@chakra-ui/theme-tools';
const { defineMultiStyleConfig, definePartsStyle } =
createMultiStyleConfigHelpers(parts.keys);
@ -17,26 +16,26 @@ const invokeAIRoot = defineStyle((_props) => {
const invokeAITab = defineStyle((_props) => ({}));
const invokeAITablist = defineStyle((props) => ({
const invokeAITablist = defineStyle((_props) => ({
display: 'flex',
flexDirection: 'column',
gap: 1,
color: mode('base.500', 'base.700')(props),
color: 'base.700',
button: {
fontSize: 'sm',
padding: 2,
borderRadius: 'base',
_selected: {
bg: mode('accent.200', 'accent.700')(props),
color: mode('accent.800', 'accent.100')(props),
bg: 'accent.700',
color: 'accent.100',
_hover: {
bg: mode('accent.300', 'accent.600')(props),
color: mode('accent.900', 'accent.50')(props),
bg: 'accent.600',
color: 'accent.50',
},
},
_hover: {
bg: mode('base.300', 'base.600')(props),
color: mode('base.900', 'base.50')(props),
bg: 'base.600',
color: 'base.50',
},
},
}));

View File

@ -1,8 +1,7 @@
import { defineStyle, defineStyleConfig } from '@chakra-ui/react';
import { mode } from '@chakra-ui/theme-tools';
const subtext = defineStyle((props) => ({
color: mode('base.700', 'base.400')(props),
const subtext = defineStyle((_props) => ({
color: 'base.400',
}));
export const textTheme = defineStyleConfig({

View File

@ -1,6 +1,6 @@
import { ThemeOverride } from '@chakra-ui/react';
import type { StyleFunctionProps } from '@chakra-ui/styled-system';
import { mode } from '@chakra-ui/theme-tools';
import { invokeAIThemeColors } from './colors/invokeAI';
import { accordionTheme } from './components/accordion';
import { buttonTheme } from './components/button';
@ -22,15 +22,13 @@ import { textareaTheme } from './components/textarea';
export const theme: ThemeOverride = {
config: {
initialColorMode: 'dark',
useSystemColorMode: false,
cssVarPrefix: 'invokeai',
},
styles: {
global: (props: StyleFunctionProps) => ({
global: (_props: StyleFunctionProps) => ({
body: {
bg: mode('base.100', 'base.900')(props),
color: mode('base.800', 'base.50')(props),
bg: 'base.900',
color: 'base.50',
overflow: 'hidden',
},
...scrollbar,

View File

@ -1,40 +1,40 @@
import { mode, StyleFunctionProps } from '@chakra-ui/theme-tools';
import { StyleFunctionProps } from '@chakra-ui/theme-tools';
export const getInputOutlineStyles = (props: StyleFunctionProps) => ({
export const getInputOutlineStyles = (_props: StyleFunctionProps) => ({
outline: 'none',
borderWidth: 2,
borderStyle: 'solid',
borderColor: mode('base.300', 'base.800')(props),
bg: mode('base.200', 'base.900')(props),
borderColor: 'base.800',
bg: 'base.900',
borderRadius: 'base',
color: mode('base.900', 'base.100')(props),
color: 'base.100',
boxShadow: 'none',
_hover: {
borderColor: mode('base.500', 'base.600')(props),
borderColor: 'base.600',
},
_focus: {
borderColor: mode('accent.600', 'accent.700')(props),
borderColor: 'accent.700',
boxShadow: 'none',
_hover: {
borderColor: mode('accent.700', 'accent.600')(props),
borderColor: 'accent.600',
},
},
_invalid: {
borderColor: mode('error.300', 'error.700')(props),
borderColor: 'error.700',
boxShadow: 'none',
_hover: {
borderColor: mode('error.500', 'error.600')(props),
borderColor: 'error.600',
},
},
_disabled: {
borderColor: mode('base.300', 'base.700')(props),
bg: mode('base.400', 'base.700')(props),
color: mode('base.600', 'base.400')(props),
borderColor: 'base.700',
bg: 'base.700',
color: 'base.400',
_hover: {
borderColor: mode('base.300', 'base.700')(props),
borderColor: 'base.700',
},
},
_placeholder: {
color: mode('base.600', 'base.400')(props),
color: 'base.400',
},
});

File diff suppressed because one or more lines are too long

View File

@ -734,7 +734,7 @@
"@chakra-ui/react-context" "2.0.7"
"@chakra-ui/shared-utils" "2.0.5"
"@chakra-ui/styled-system@2.6.1":
"@chakra-ui/styled-system@2.6.1", "@chakra-ui/styled-system@^2.6.1":
version "2.6.1"
resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.6.1.tgz#302d496d34c0b7b30c646a7e3c9b113a2f4588da"
integrity sha512-jy/1dVi1LxjoRCm+Eo5mqBgvPy5SCWMlIcz6GbIZBDpkGeKZwtqrZLjekxxLBCy8ORY+kJlUB0FT6AzVR/1tjw==
@ -2107,6 +2107,21 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
concurrently@^7.6.0:
version "7.6.0"
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-7.6.0.tgz#531a6f5f30cf616f355a4afb8f8fcb2bba65a49a"
integrity sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==
dependencies:
chalk "^4.1.0"
date-fns "^2.29.1"
lodash "^4.17.21"
rxjs "^7.0.0"
shell-quote "^1.7.3"
spawn-command "^0.0.2-1"
supports-color "^8.1.0"
tree-kill "^1.2.2"
yargs "^17.3.1"
configstore@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
@ -2191,6 +2206,11 @@ csstype@^3.0.11, csstype@^3.0.2:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==
date-fns@^2.29.1:
version "2.29.3"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8"
integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==
dateformat@^5.0.3:
version "5.0.3"
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-5.0.3.tgz#fe2223eff3cc70ce716931cb3038b59a9280696e"
@ -4833,7 +4853,7 @@ run-parallel@^1.1.9:
dependencies:
queue-microtask "^1.2.2"
rxjs@^7.8.0:
rxjs@^7.0.0, rxjs@^7.8.0:
version "7.8.0"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4"
integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==
@ -4916,6 +4936,11 @@ shebang-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
shell-quote@^1.7.3:
version "1.8.0"
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.0.tgz#20d078d0eaf71d54f43bd2ba14a1b5b9bfa5c8ba"
integrity sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==
side-channel@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
@ -5012,6 +5037,11 @@ source-map@^0.7.4:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656"
integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==
spawn-command@^0.0.2-1:
version "0.0.2-1"
resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"
integrity sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==
stream-to-array@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353"
@ -5151,6 +5181,13 @@ supports-color@^7.1.0:
dependencies:
has-flag "^4.0.0"
supports-color@^8.1.0:
version "8.1.1"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
dependencies:
has-flag "^4.0.0"
supports-preserve-symlinks-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
@ -5225,6 +5262,11 @@ tr46@~0.0.3:
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
tree-kill@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
ts-graphviz@^1.5.0:
version "1.5.5"
resolved "https://registry.yarnpkg.com/ts-graphviz/-/ts-graphviz-1.5.5.tgz#b5e9079c18289fb36b6b53f3d81da96445c37514"
@ -5628,7 +5670,7 @@ yargs-parser@^21.1.1:
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
yargs@^17.5.1:
yargs@^17.3.1, yargs@^17.5.1:
version "17.7.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967"
integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==