mirror of
https://github.com/easydiffusion/easydiffusion.git
synced 2025-08-13 17:57:20 +02:00
Compare commits
102 Commits
v2.5.30
...
revert-119
Author | SHA1 | Date | |
---|---|---|---|
6fbb24ae3d | |||
943776dd14 | |||
bb607927d0 | |||
1f4e4d8d82 | |||
4ef10222e1 | |||
d7b91db204 | |||
5acf5949a6 | |||
3d740555c3 | |||
f7235cf82c | |||
eb16296873 | |||
1967299417 | |||
1864921d1d | |||
0b19adba75 | |||
2e84a421f3 | |||
fea77e97a0 | |||
e1b6cc2a86 | |||
0921573644 | |||
526fc989c1 | |||
023b78d1c9 | |||
670410b539 | |||
76e379d7e1 | |||
cde57109e4 | |||
bc142c9ecd | |||
6c148f1791 | |||
534bb2dd84 | |||
d0f4476ba5 | |||
6287bcd00a | |||
fcbcb7d471 | |||
cb527919a2 | |||
83c34ea52f | |||
35c75115de | |||
7c75a61700 | |||
34ea49147c | |||
c1e8637a9f | |||
becbef4fac | |||
f22ecc454a | |||
bf3df097b8 | |||
7fc2ed28b1 | |||
30a133bad9 | |||
d8d44c579c | |||
80384e6ee1 | |||
0898f98355 | |||
e7dc41e271 | |||
0f0f475241 | |||
127ee68486 | |||
b204b02b05 | |||
893b6d985c | |||
44824fb5f9 | |||
dc21cbe59d | |||
e16d9f4742 | |||
f2b5843e6c | |||
16229caa8e | |||
0c0525e11b | |||
1ba3a139d9 | |||
80bcfabc48 | |||
4192f87d6b | |||
03c8a0fca5 | |||
a3d2c71ed6 | |||
8ba0b34853 | |||
424ec40fa5 | |||
210429a259 | |||
df806d5dfa | |||
b07046f6a2 | |||
4cdb8a7d2a | |||
2f83f2bd48 | |||
8a6cf3cfae | |||
514e40569e | |||
f30f98abd8 | |||
c611d26306 | |||
9ee38d0b70 | |||
5e45f37232 | |||
4f2df2d188 | |||
0f4b62cb97 | |||
4c7b4c7592 | |||
9e244f758c | |||
e7c0b9bd76 | |||
d7317e8252 | |||
a6ec401440 | |||
37082ad430 | |||
c571521e87 | |||
c438cd47b9 | |||
3ce6c3dc61 | |||
17f60d3c7f | |||
7d4d85284b | |||
c115a9aa3d | |||
6529240808 | |||
0d570b3fae | |||
0778078350 | |||
888dc05cde | |||
687da5b64a | |||
5b00d54c76 | |||
38b4a7856e | |||
4f899bd83d | |||
7f80f7c46b | |||
88d415d3f9 | |||
ec0b08e4d0 | |||
6aa048e3ad | |||
bc711414a8 | |||
07b467e4bc | |||
afc18619db | |||
fe635db3ab | |||
7e53eb658c |
@ -21,6 +21,14 @@
|
||||
Our focus continues to remain on an easy installation experience, and an easy user-interface. While still remaining pretty powerful, in terms of features and speed.
|
||||
|
||||
### Detailed changelog
|
||||
* 2.5.34 - 22 Apr 2023 - Nothing, just keeping this line warm.
|
||||
* 2.5.33 - 21 Apr 2023 - Install PyTorch 2.0 on new installations (on Windows and Linux).
|
||||
* 2.5.32 - 19 Apr 2023 - Automatically check for black images, and set full-precision if necessary (for attn). This means custom models based on Stable Diffusion v2.1 will just work, without needing special command-line arguments or editing of yaml config files.
|
||||
* 2.5.32 - 18 Apr 2023 - Automatic support for AMD graphics cards on Linux. Thanks @DianaNites and @JeLuf.
|
||||
* 2.5.31 - 10 Apr 2023 - Reduce VRAM usage while upscaling.
|
||||
* 2.5.31 - 6 Apr 2023 - Allow seeds upto `4,294,967,295`. Thanks @ogmaresca.
|
||||
* 2.5.31 - 6 Apr 2023 - Buttons to show the previous/next image in the image popup. Thanks @ogmaresca.
|
||||
* 2.5.30 - 5 Apr 2023 - Fix a bug where the JPEG image quality wasn't being respected when embedding the metadata into it. Thanks @JeLuf.
|
||||
* 2.5.30 - 1 Apr 2023 - (beta-only) Slider to control the strength of the LoRA model.
|
||||
* 2.5.30 - 28 Mar 2023 - Refactor task entry config to use a generating method. Added ability for plugins to easily add to this. Removed confusing sentence from `contributing.md`
|
||||
* 2.5.30 - 28 Mar 2023 - Allow the user to undo the deletion of tasks or images, instead of showing a pop-up each time. The new `Undo` button will be present at the top of the UI. Thanks @JeLuf.
|
||||
|
@ -235,7 +235,7 @@ Section "MainSection" SEC01
|
||||
NScurl::http get "https://huggingface.co/CompVis/stable-diffusion-v-1-4-original/resolve/main/sd-v1-4.ckpt" "$INSTDIR\models\stable-diffusion\sd-v1-4.ckpt" /CANCEL /INSIST /END
|
||||
|
||||
DetailPrint 'Downloading the GFPGAN model...'
|
||||
NScurl::http get "https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth" "$INSTDIR\models\gfpgan\GFPGANv1.3.pth" /CANCEL /INSIST /END
|
||||
NScurl::http get "https://github.com/TencentARC/GFPGAN/releases/download/v1.3.4/GFPGANv1.4.pth" "$INSTDIR\models\gfpgan\GFPGANv1.4.pth" /CANCEL /INSIST /END
|
||||
|
||||
DetailPrint 'Downloading the RealESRGAN_x4plus model...'
|
||||
NScurl::http get "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth" "$INSTDIR\models\realesrgan\RealESRGAN_x4plus.pth" /CANCEL /INSIST /END
|
||||
|
101
scripts/check_models.py
Normal file
101
scripts/check_models.py
Normal file
@ -0,0 +1,101 @@
|
||||
# this script runs inside the legacy "stable-diffusion" folder
|
||||
|
||||
from sdkit.models import download_model, get_model_info_from_db
|
||||
from sdkit.utils import hash_file_quick
|
||||
|
||||
import os
|
||||
import shutil
|
||||
from glob import glob
|
||||
import traceback
|
||||
|
||||
models_base_dir = os.path.abspath(os.path.join("..", "models"))
|
||||
|
||||
models_to_check = {
|
||||
"stable-diffusion": [
|
||||
{"file_name": "sd-v1-4.ckpt", "model_id": "1.4"},
|
||||
],
|
||||
"gfpgan": [
|
||||
{"file_name": "GFPGANv1.4.pth", "model_id": "1.4"},
|
||||
],
|
||||
"realesrgan": [
|
||||
{"file_name": "RealESRGAN_x4plus.pth", "model_id": "x4plus"},
|
||||
{"file_name": "RealESRGAN_x4plus_anime_6B.pth", "model_id": "x4plus_anime_6"},
|
||||
],
|
||||
"vae": [
|
||||
{"file_name": "vae-ft-mse-840000-ema-pruned.ckpt", "model_id": "vae-ft-mse-840000-ema-pruned"},
|
||||
],
|
||||
}
|
||||
MODEL_EXTENSIONS = { # copied from easydiffusion/model_manager.py
|
||||
"stable-diffusion": [".ckpt", ".safetensors"],
|
||||
"vae": [".vae.pt", ".ckpt", ".safetensors"],
|
||||
"hypernetwork": [".pt", ".safetensors"],
|
||||
"gfpgan": [".pth"],
|
||||
"realesrgan": [".pth"],
|
||||
"lora": [".ckpt", ".safetensors"],
|
||||
}
|
||||
|
||||
|
||||
def download_if_necessary(model_type: str, file_name: str, model_id: str):
|
||||
model_path = os.path.join(models_base_dir, model_type, file_name)
|
||||
expected_hash = get_model_info_from_db(model_type=model_type, model_id=model_id)["quick_hash"]
|
||||
|
||||
other_models_exist = any_model_exists(model_type)
|
||||
known_model_exists = os.path.exists(model_path)
|
||||
known_model_is_corrupt = known_model_exists and hash_file_quick(model_path) != expected_hash
|
||||
|
||||
if known_model_is_corrupt or (not other_models_exist and not known_model_exists):
|
||||
print("> download", model_type, model_id)
|
||||
download_model(model_type, model_id, download_base_dir=models_base_dir)
|
||||
|
||||
|
||||
def init():
|
||||
migrate_legacy_model_location()
|
||||
|
||||
for model_type, models in models_to_check.items():
|
||||
for model in models:
|
||||
try:
|
||||
download_if_necessary(model_type, model["file_name"], model["model_id"])
|
||||
except:
|
||||
traceback.print_exc()
|
||||
fail(model_type)
|
||||
|
||||
print(model_type, "model(s) found.")
|
||||
|
||||
|
||||
### utilities
|
||||
def any_model_exists(model_type: str) -> bool:
|
||||
extensions = MODEL_EXTENSIONS.get(model_type, [])
|
||||
for ext in extensions:
|
||||
if any(glob(f"{models_base_dir}/{model_type}/**/*{ext}", recursive=True)):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def migrate_legacy_model_location():
|
||||
'Move the models inside the legacy "stable-diffusion" folder, to their respective folders'
|
||||
|
||||
for model_type, models in models_to_check.items():
|
||||
for model in models:
|
||||
file_name = model["file_name"]
|
||||
if os.path.exists(file_name):
|
||||
dest_dir = os.path.join(models_base_dir, model_type)
|
||||
os.makedirs(dest_dir, exist_ok=True)
|
||||
shutil.move(file_name, os.path.join(dest_dir, file_name))
|
||||
|
||||
|
||||
def fail(model_name):
|
||||
print(
|
||||
f"""Error downloading the {model_name} model. Sorry about that, please try to:
|
||||
1. Run this installer again.
|
||||
2. If that doesn't fix it, please try to download the file manually. The address to download from, and the destination to save to are printed above this message.
|
||||
3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB
|
||||
4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues
|
||||
Thanks!"""
|
||||
)
|
||||
exit(1)
|
||||
|
||||
|
||||
### start
|
||||
|
||||
init()
|
@ -1,13 +1,155 @@
|
||||
'''
|
||||
This script checks if the given modules exist
|
||||
'''
|
||||
"""
|
||||
This script checks and installs the required modules.
|
||||
|
||||
import sys
|
||||
import pkgutil
|
||||
This script runs inside the legacy "stable-diffusion" folder
|
||||
|
||||
modules = sys.argv[1:]
|
||||
missing_modules = []
|
||||
for m in modules:
|
||||
if pkgutil.find_loader(m) is None:
|
||||
print('module', m, 'not found')
|
||||
exit(1)
|
||||
TODO - Maybe replace the bulk of this script with a call to `pip install -f requirements.txt`, with
|
||||
a custom index URL depending on the platform.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
from importlib.metadata import version as pkg_version
|
||||
import platform
|
||||
import traceback
|
||||
|
||||
os_name = platform.system()
|
||||
|
||||
modules_to_check = {
|
||||
"torch": ("1.11.0", "1.13.1", "2.0.0"),
|
||||
"torchvision": ("0.12.0", "0.14.1", "0.15.1"),
|
||||
"sdkit": "1.0.81",
|
||||
"stable-diffusion-sdkit": "2.1.4",
|
||||
"rich": "12.6.0",
|
||||
"uvicorn": "0.19.0",
|
||||
"fastapi": "0.85.1",
|
||||
# "xformers": "0.0.16",
|
||||
}
|
||||
|
||||
|
||||
def version(module_name: str) -> str:
|
||||
try:
|
||||
return pkg_version(module_name)
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def install(module_name: str, module_version: str):
|
||||
if module_name == "xformers" and (os_name == "Darwin" or is_amd_on_linux()):
|
||||
return
|
||||
|
||||
index_url = None
|
||||
if module_name in ("torch", "torchvision"):
|
||||
module_version, index_url = apply_torch_install_overrides(module_version)
|
||||
|
||||
if is_amd_on_linux(): # hack until AMD works properly on torch 2.0 (avoids black images on some cards)
|
||||
if module_name == "torch":
|
||||
module_version = "1.13.1+rocm5.2"
|
||||
elif module_name == "torchvision":
|
||||
module_version = "0.14.1+rocm5.2"
|
||||
elif os_name == "Darwin":
|
||||
if module_name == "torch":
|
||||
module_version = "1.13.1"
|
||||
elif module_name == "torchvision":
|
||||
module_version = "0.14.1"
|
||||
|
||||
install_cmd = f"python -m pip install --upgrade {module_name}=={module_version}"
|
||||
if index_url:
|
||||
install_cmd += f" --index-url {index_url}"
|
||||
if module_name == "sdkit" and version("sdkit") is not None:
|
||||
install_cmd += " -q"
|
||||
|
||||
print(">", install_cmd)
|
||||
os.system(install_cmd)
|
||||
|
||||
|
||||
def init():
|
||||
for module_name, allowed_versions in modules_to_check.items():
|
||||
if os.path.exists(f"../src/{module_name}"):
|
||||
print(f"Skipping {module_name} update, since it's in developer/editable mode")
|
||||
continue
|
||||
|
||||
allowed_versions, latest_version = get_allowed_versions(module_name, allowed_versions)
|
||||
|
||||
requires_install = False
|
||||
if module_name in ("torch", "torchvision"):
|
||||
if version(module_name) is None: # allow any torch version
|
||||
requires_install = True
|
||||
elif os_name == "Darwin" and ( # force mac to downgrade from torch 2.0
|
||||
version("torch").startswith("2.") or version("torchvision").startswith("0.15.")
|
||||
):
|
||||
requires_install = True
|
||||
elif version(module_name) not in allowed_versions:
|
||||
requires_install = True
|
||||
|
||||
if requires_install:
|
||||
try:
|
||||
install(module_name, latest_version)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
fail(module_name)
|
||||
|
||||
print(f"{module_name}: {version(module_name)}")
|
||||
|
||||
|
||||
### utilities
|
||||
|
||||
|
||||
def get_allowed_versions(module_name: str, allowed_versions: tuple):
|
||||
allowed_versions = (allowed_versions,) if isinstance(allowed_versions, str) else allowed_versions
|
||||
latest_version = allowed_versions[-1]
|
||||
|
||||
if module_name in ("torch", "torchvision"):
|
||||
allowed_versions = include_cuda_versions(allowed_versions)
|
||||
|
||||
return allowed_versions, latest_version
|
||||
|
||||
|
||||
def apply_torch_install_overrides(module_version: str):
|
||||
index_url = None
|
||||
if os_name == "Windows":
|
||||
module_version += "+cu117"
|
||||
index_url = "https://download.pytorch.org/whl/cu117"
|
||||
elif is_amd_on_linux():
|
||||
index_url = "https://download.pytorch.org/whl/rocm5.2"
|
||||
|
||||
return module_version, index_url
|
||||
|
||||
|
||||
def include_cuda_versions(module_versions: tuple) -> tuple:
|
||||
"Adds CUDA-specific versions to the list of allowed version numbers"
|
||||
|
||||
allowed_versions = tuple(module_versions)
|
||||
allowed_versions += tuple(f"{v}+cu116" for v in module_versions)
|
||||
allowed_versions += tuple(f"{v}+cu117" for v in module_versions)
|
||||
allowed_versions += tuple(f"{v}+rocm5.2" for v in module_versions)
|
||||
allowed_versions += tuple(f"{v}+rocm5.4.2" for v in module_versions)
|
||||
|
||||
return allowed_versions
|
||||
|
||||
|
||||
def is_amd_on_linux():
|
||||
if os_name == "Linux":
|
||||
with open("/proc/bus/pci/devices", "r") as f:
|
||||
device_info = f.read()
|
||||
if "amdgpu" in device_info and "nvidia" not in device_info:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def fail(module_name):
|
||||
print(
|
||||
f"""Error installing {module_name}. Sorry about that, please try to:
|
||||
1. Run this installer again.
|
||||
2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting
|
||||
3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB
|
||||
4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues
|
||||
Thanks!"""
|
||||
)
|
||||
exit(1)
|
||||
|
||||
|
||||
### start
|
||||
|
||||
init()
|
||||
|
@ -8,6 +8,10 @@ if exist "scripts\config.bat" (
|
||||
@call scripts\config.bat
|
||||
)
|
||||
|
||||
if exist "scripts\user_config.bat" (
|
||||
@call scripts\user_config.bat
|
||||
)
|
||||
|
||||
if "%update_branch%"=="" (
|
||||
set update_branch=main
|
||||
)
|
||||
@ -53,6 +57,7 @@ if "%update_branch%"=="" (
|
||||
@xcopy sd-ui-files\ui ui /s /i /Y /q
|
||||
@copy sd-ui-files\scripts\on_sd_start.bat scripts\ /Y
|
||||
@copy sd-ui-files\scripts\check_modules.py scripts\ /Y
|
||||
@copy sd-ui-files\scripts\check_models.py scripts\ /Y
|
||||
@copy "sd-ui-files\scripts\Start Stable Diffusion UI.cmd" . /Y
|
||||
@copy "sd-ui-files\scripts\Developer Console.cmd" . /Y
|
||||
|
||||
|
@ -8,6 +8,11 @@ if [ -f "scripts/config.sh" ]; then
|
||||
source scripts/config.sh
|
||||
fi
|
||||
|
||||
if [ -f "scripts/user_config.sh" ]; then
|
||||
source scripts/user_config.sh
|
||||
fi
|
||||
|
||||
|
||||
if [ "$update_branch" == "" ]; then
|
||||
export update_branch="main"
|
||||
fi
|
||||
@ -38,6 +43,7 @@ cp -Rf sd-ui-files/ui .
|
||||
cp sd-ui-files/scripts/on_sd_start.sh scripts/
|
||||
cp sd-ui-files/scripts/bootstrap.sh scripts/
|
||||
cp sd-ui-files/scripts/check_modules.py scripts/
|
||||
cp sd-ui-files/scripts/check_models.py scripts/
|
||||
cp sd-ui-files/scripts/start.sh .
|
||||
cp sd-ui-files/scripts/developer_console.sh .
|
||||
cp sd-ui-files/scripts/functions.sh scripts/
|
||||
|
@ -4,8 +4,8 @@
|
||||
@REM Note to self: Please rewrite this in Python. For the sake of your own sanity.
|
||||
|
||||
@copy sd-ui-files\scripts\on_env_start.bat scripts\ /Y
|
||||
@copy sd-ui-files\scripts\bootstrap.bat scripts\ /Y
|
||||
@copy sd-ui-files\scripts\check_modules.py scripts\ /Y
|
||||
@copy sd-ui-files\scripts\check_models.py scripts\ /Y
|
||||
|
||||
if exist "%cd%\profile" (
|
||||
set USERPROFILE=%cd%\profile
|
||||
@ -34,8 +34,6 @@ call conda activate
|
||||
@REM remove the old version of the dev console script, if it's still present
|
||||
if exist "Open Developer Console.cmd" del "Open Developer Console.cmd"
|
||||
|
||||
@call python -c "import os; import shutil; frm = 'sd-ui-files\\ui\\hotfix\\9c24e6cd9f499d02c4f21a033736dabd365962dc80fe3aeb57a8f85ea45a20a3.26fead7ea4f0f843f6eb4055dfd25693f1a71f3c6871b184042d4b126244e142'; dst = os.path.join(os.path.expanduser('~'), '.cache', 'huggingface', 'transformers', '9c24e6cd9f499d02c4f21a033736dabd365962dc80fe3aeb57a8f85ea45a20a3.26fead7ea4f0f843f6eb4055dfd25693f1a71f3c6871b184042d4b126244e142'); shutil.copyfile(frm, dst) if os.path.exists(dst) else print(''); print('Hotfixed broken JSON file from OpenAI');"
|
||||
|
||||
@rem create the stable-diffusion folder, to work with legacy installations
|
||||
if not exist "stable-diffusion" mkdir stable-diffusion
|
||||
cd stable-diffusion
|
||||
@ -49,111 +47,22 @@ if exist "env" (
|
||||
if exist src rename src src-old
|
||||
if exist ldm rename ldm ldm-old
|
||||
|
||||
if not exist "..\models\stable-diffusion" mkdir "..\models\stable-diffusion"
|
||||
if not exist "..\models\gfpgan" mkdir "..\models\gfpgan"
|
||||
if not exist "..\models\realesrgan" mkdir "..\models\realesrgan"
|
||||
if not exist "..\models\vae" mkdir "..\models\vae"
|
||||
|
||||
@rem migrate the legacy models to the correct path (if already downloaded)
|
||||
if exist "sd-v1-4.ckpt" move sd-v1-4.ckpt ..\models\stable-diffusion\
|
||||
if exist "custom-model.ckpt" move custom-model.ckpt ..\models\stable-diffusion\
|
||||
if exist "GFPGANv1.3.pth" move GFPGANv1.3.pth ..\models\gfpgan\
|
||||
if exist "RealESRGAN_x4plus.pth" move RealESRGAN_x4plus.pth ..\models\realesrgan\
|
||||
if exist "RealESRGAN_x4plus_anime_6B.pth" move RealESRGAN_x4plus_anime_6B.pth ..\models\realesrgan\
|
||||
|
||||
if not exist "%INSTALL_ENV_DIR%\DLLs\libssl-1_1-x64.dll" copy "%INSTALL_ENV_DIR%\Library\bin\libssl-1_1-x64.dll" "%INSTALL_ENV_DIR%\DLLs\"
|
||||
if not exist "%INSTALL_ENV_DIR%\DLLs\libcrypto-1_1-x64.dll" copy "%INSTALL_ENV_DIR%\Library\bin\libcrypto-1_1-x64.dll" "%INSTALL_ENV_DIR%\DLLs\"
|
||||
|
||||
@rem install torch and torchvision
|
||||
call python ..\scripts\check_modules.py torch torchvision
|
||||
if "%ERRORLEVEL%" EQU "0" (
|
||||
echo "torch and torchvision have already been installed."
|
||||
) else (
|
||||
echo "Installing torch and torchvision.."
|
||||
|
||||
@REM prevent from using packages from the user's home directory, to avoid conflicts
|
||||
set PYTHONNOUSERSITE=1
|
||||
set PYTHONPATH=%INSTALL_ENV_DIR%\lib\site-packages
|
||||
|
||||
call python -m pip install --upgrade torch==1.13.1+cu116 torchvision==0.14.1+cu116 --extra-index-url https://download.pytorch.org/whl/cu116 || (
|
||||
echo "Error installing torch. Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!"
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
|
||||
@rem install or upgrade the required modules
|
||||
set PATH=C:\Windows\System32;%PATH%
|
||||
|
||||
@rem install/upgrade sdkit
|
||||
call python ..\scripts\check_modules.py sdkit sdkit.models ldm transformers numpy antlr4 gfpgan realesrgan
|
||||
if "%ERRORLEVEL%" EQU "0" (
|
||||
echo "sdkit is already installed."
|
||||
@REM prevent from using packages from the user's home directory, to avoid conflicts
|
||||
set PYTHONNOUSERSITE=1
|
||||
set PYTHONPATH=%INSTALL_ENV_DIR%\lib\site-packages
|
||||
|
||||
@rem skip sdkit upgrade if in developer-mode
|
||||
if not exist "..\src\sdkit" (
|
||||
@REM prevent from using packages from the user's home directory, to avoid conflicts
|
||||
set PYTHONNOUSERSITE=1
|
||||
set PYTHONPATH=%INSTALL_ENV_DIR%\lib\site-packages
|
||||
|
||||
call python -m pip install --upgrade sdkit==1.0.64 -q || (
|
||||
echo "Error updating sdkit"
|
||||
)
|
||||
)
|
||||
) else (
|
||||
echo "Installing sdkit: https://pypi.org/project/sdkit/"
|
||||
|
||||
@REM prevent from using packages from the user's home directory, to avoid conflicts
|
||||
set PYTHONNOUSERSITE=1
|
||||
set PYTHONPATH=%INSTALL_ENV_DIR%\lib\site-packages
|
||||
|
||||
call python -m pip install sdkit==1.0.64 || (
|
||||
echo "Error installing sdkit. Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!"
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
|
||||
call python -c "from importlib.metadata import version; print('sdkit version:', version('sdkit'))"
|
||||
|
||||
@rem upgrade stable-diffusion-sdkit
|
||||
call python -m pip install --upgrade stable-diffusion-sdkit==2.1.4 -q || (
|
||||
echo "Error updating stable-diffusion-sdkit"
|
||||
)
|
||||
call python -c "from importlib.metadata import version; print('stable-diffusion version:', version('stable-diffusion-sdkit'))"
|
||||
|
||||
@rem install rich
|
||||
call python ..\scripts\check_modules.py rich
|
||||
if "%ERRORLEVEL%" EQU "0" (
|
||||
echo "rich has already been installed."
|
||||
) else (
|
||||
echo "Installing rich.."
|
||||
|
||||
set PYTHONNOUSERSITE=1
|
||||
set PYTHONPATH=%INSTALL_ENV_DIR%\lib\site-packages
|
||||
|
||||
call python -m pip install rich || (
|
||||
echo "Error installing rich. Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!"
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
|
||||
set PATH=C:\Windows\System32;%PATH%
|
||||
|
||||
call python ..\scripts\check_modules.py uvicorn fastapi
|
||||
@if "%ERRORLEVEL%" EQU "0" (
|
||||
echo "Packages necessary for Easy Diffusion were already installed"
|
||||
) else (
|
||||
@echo. & echo "Downloading packages necessary for Easy Diffusion..." & echo.
|
||||
|
||||
set PYTHONNOUSERSITE=1
|
||||
set PYTHONPATH=%INSTALL_ENV_DIR%\lib\site-packages
|
||||
|
||||
@call conda install -c conda-forge -y uvicorn fastapi || (
|
||||
echo "Error installing the packages necessary for Easy Diffusion. Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!"
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
@rem Download the required packages
|
||||
call python ..\scripts\check_modules.py
|
||||
if "%ERRORLEVEL%" NEQ "0" (
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
call WHERE uvicorn > .tmp
|
||||
@ -169,160 +78,11 @@ call WHERE uvicorn > .tmp
|
||||
@echo conda_sd_ui_deps_installed >> ..\scripts\install_status.txt
|
||||
)
|
||||
|
||||
@if exist "..\models\stable-diffusion\sd-v1-4.ckpt" (
|
||||
for %%I in ("..\models\stable-diffusion\sd-v1-4.ckpt") do if "%%~zI" EQU "4265380512" (
|
||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded. Using the HuggingFace 4 GB Model."
|
||||
) else (
|
||||
for %%J in ("..\models\stable-diffusion\sd-v1-4.ckpt") do if "%%~zJ" EQU "7703807346" (
|
||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded. Using the HuggingFace 7 GB Model."
|
||||
) else (
|
||||
for %%K in ("..\models\stable-diffusion\sd-v1-4.ckpt") do if "%%~zK" EQU "7703810927" (
|
||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded. Using the Waifu Model."
|
||||
) else (
|
||||
echo. & echo "The model file present at models\stable-diffusion\sd-v1-4.ckpt is invalid. It is only %%~zK bytes in size. Re-downloading.." & echo.
|
||||
del "..\models\stable-diffusion\sd-v1-4.ckpt"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@if not exist "..\models\stable-diffusion\sd-v1-4.ckpt" (
|
||||
@echo. & echo "Downloading data files (weights) for Stable Diffusion.." & echo.
|
||||
|
||||
@call curl -L -k https://huggingface.co/CompVis/stable-diffusion-v-1-4-original/resolve/main/sd-v1-4.ckpt > ..\models\stable-diffusion\sd-v1-4.ckpt
|
||||
|
||||
@if exist "..\models\stable-diffusion\sd-v1-4.ckpt" (
|
||||
for %%I in ("..\models\stable-diffusion\sd-v1-4.ckpt") do if "%%~zI" NEQ "4265380512" (
|
||||
echo. & echo "Error: The downloaded model file was invalid! Bytes downloaded: %%~zI" & echo.
|
||||
echo. & echo "Error downloading the data files (weights) for Stable Diffusion. Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
) else (
|
||||
@echo. & echo "Error downloading the data files (weights) for Stable Diffusion. Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@if exist "..\models\gfpgan\GFPGANv1.3.pth" (
|
||||
for %%I in ("..\models\gfpgan\GFPGANv1.3.pth") do if "%%~zI" EQU "348632874" (
|
||||
echo "Data files (weights) necessary for GFPGAN (Face Correction) were already downloaded"
|
||||
) else (
|
||||
echo. & echo "The GFPGAN model file present at models\gfpgan\GFPGANv1.3.pth is invalid. It is only %%~zI bytes in size. Re-downloading.." & echo.
|
||||
del "..\models\gfpgan\GFPGANv1.3.pth"
|
||||
)
|
||||
)
|
||||
|
||||
@if not exist "..\models\gfpgan\GFPGANv1.3.pth" (
|
||||
@echo. & echo "Downloading data files (weights) for GFPGAN (Face Correction).." & echo.
|
||||
|
||||
@call curl -L -k https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth > ..\models\gfpgan\GFPGANv1.3.pth
|
||||
|
||||
@if exist "..\models\gfpgan\GFPGANv1.3.pth" (
|
||||
for %%I in ("..\models\gfpgan\GFPGANv1.3.pth") do if "%%~zI" NEQ "348632874" (
|
||||
echo. & echo "Error: The downloaded GFPGAN model file was invalid! Bytes downloaded: %%~zI" & echo.
|
||||
echo. & echo "Error downloading the data files (weights) for GFPGAN (Face Correction). Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
) else (
|
||||
@echo. & echo "Error downloading the data files (weights) for GFPGAN (Face Correction). Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@if exist "..\models\realesrgan\RealESRGAN_x4plus.pth" (
|
||||
for %%I in ("..\models\realesrgan\RealESRGAN_x4plus.pth") do if "%%~zI" EQU "67040989" (
|
||||
echo "Data files (weights) necessary for ESRGAN (Resolution Upscaling) x4plus were already downloaded"
|
||||
) else (
|
||||
echo. & echo "The RealESRGAN model file present at models\realesrgan\RealESRGAN_x4plus.pth is invalid. It is only %%~zI bytes in size. Re-downloading.." & echo.
|
||||
del "..\models\realesrgan\RealESRGAN_x4plus.pth"
|
||||
)
|
||||
)
|
||||
|
||||
@if not exist "..\models\realesrgan\RealESRGAN_x4plus.pth" (
|
||||
@echo. & echo "Downloading data files (weights) for ESRGAN (Resolution Upscaling) x4plus.." & echo.
|
||||
|
||||
@call curl -L -k https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth > ..\models\realesrgan\RealESRGAN_x4plus.pth
|
||||
|
||||
@if exist "..\models\realesrgan\RealESRGAN_x4plus.pth" (
|
||||
for %%I in ("..\models\realesrgan\RealESRGAN_x4plus.pth") do if "%%~zI" NEQ "67040989" (
|
||||
echo. & echo "Error: The downloaded ESRGAN x4plus model file was invalid! Bytes downloaded: %%~zI" & echo.
|
||||
echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus. Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
) else (
|
||||
@echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus. Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@if exist "..\models\realesrgan\RealESRGAN_x4plus_anime_6B.pth" (
|
||||
for %%I in ("..\models\realesrgan\RealESRGAN_x4plus_anime_6B.pth") do if "%%~zI" EQU "17938799" (
|
||||
echo "Data files (weights) necessary for ESRGAN (Resolution Upscaling) x4plus_anime were already downloaded"
|
||||
) else (
|
||||
echo. & echo "The RealESRGAN model file present at models\realesrgan\RealESRGAN_x4plus_anime_6B.pth is invalid. It is only %%~zI bytes in size. Re-downloading.." & echo.
|
||||
del "..\models\realesrgan\RealESRGAN_x4plus_anime_6B.pth"
|
||||
)
|
||||
)
|
||||
|
||||
@if not exist "..\models\realesrgan\RealESRGAN_x4plus_anime_6B.pth" (
|
||||
@echo. & echo "Downloading data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime.." & echo.
|
||||
|
||||
@call curl -L -k https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth > ..\models\realesrgan\RealESRGAN_x4plus_anime_6B.pth
|
||||
|
||||
@if exist "..\models\realesrgan\RealESRGAN_x4plus_anime_6B.pth" (
|
||||
for %%I in ("..\models\realesrgan\RealESRGAN_x4plus_anime_6B.pth") do if "%%~zI" NEQ "17938799" (
|
||||
echo. & echo "Error: The downloaded ESRGAN x4plus_anime model file was invalid! Bytes downloaded: %%~zI" & echo.
|
||||
echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime. Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
) else (
|
||||
@echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime. Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@if exist "..\models\vae\vae-ft-mse-840000-ema-pruned.ckpt" (
|
||||
for %%I in ("..\models\vae\vae-ft-mse-840000-ema-pruned.ckpt") do if "%%~zI" EQU "334695179" (
|
||||
echo "Data files (weights) necessary for the default VAE (sd-vae-ft-mse-original) were already downloaded"
|
||||
) else (
|
||||
echo. & echo "The default VAE (sd-vae-ft-mse-original) file present at models\vae\vae-ft-mse-840000-ema-pruned.ckpt is invalid. It is only %%~zI bytes in size. Re-downloading.." & echo.
|
||||
del "..\models\vae\vae-ft-mse-840000-ema-pruned.ckpt"
|
||||
)
|
||||
)
|
||||
|
||||
@if not exist "..\models\vae\vae-ft-mse-840000-ema-pruned.ckpt" (
|
||||
@echo. & echo "Downloading data files (weights) for the default VAE (sd-vae-ft-mse-original).." & echo.
|
||||
|
||||
@call curl -L -k https://huggingface.co/stabilityai/sd-vae-ft-mse-original/resolve/main/vae-ft-mse-840000-ema-pruned.ckpt > ..\models\vae\vae-ft-mse-840000-ema-pruned.ckpt
|
||||
|
||||
@if exist "..\models\vae\vae-ft-mse-840000-ema-pruned.ckpt" (
|
||||
for %%I in ("..\models\vae\vae-ft-mse-840000-ema-pruned.ckpt") do if "%%~zI" NEQ "334695179" (
|
||||
echo. & echo "Error: The downloaded default VAE (sd-vae-ft-mse-original) file was invalid! Bytes downloaded: %%~zI" & echo.
|
||||
echo. & echo "Error downloading the data files (weights) for the default VAE (sd-vae-ft-mse-original). Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
) else (
|
||||
@echo. & echo "Error downloading the data files (weights) for the default VAE (sd-vae-ft-mse-original). Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!" & echo.
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
@rem Download the required models
|
||||
call python ..\scripts\check_models.py
|
||||
if "%ERRORLEVEL%" NEQ "0" (
|
||||
pause
|
||||
exit /b
|
||||
)
|
||||
|
||||
@>nul findstr /m "sd_install_complete" ..\scripts\install_status.txt
|
||||
|
@ -4,6 +4,7 @@ cp sd-ui-files/scripts/functions.sh scripts/
|
||||
cp sd-ui-files/scripts/on_env_start.sh scripts/
|
||||
cp sd-ui-files/scripts/bootstrap.sh scripts/
|
||||
cp sd-ui-files/scripts/check_modules.py scripts/
|
||||
cp sd-ui-files/scripts/check_models.py scripts/
|
||||
|
||||
source ./scripts/functions.sh
|
||||
|
||||
@ -18,11 +19,6 @@ if [ -e "open_dev_console.sh" ]; then
|
||||
rm "open_dev_console.sh"
|
||||
fi
|
||||
|
||||
python -c "import os; import shutil; frm = 'sd-ui-files/ui/hotfix/9c24e6cd9f499d02c4f21a033736dabd365962dc80fe3aeb57a8f85ea45a20a3.26fead7ea4f0f843f6eb4055dfd25693f1a71f3c6871b184042d4b126244e142'; dst = os.path.join(os.path.expanduser('~'), '.cache', 'huggingface', 'transformers', '9c24e6cd9f499d02c4f21a033736dabd365962dc80fe3aeb57a8f85ea45a20a3.26fead7ea4f0f843f6eb4055dfd25693f1a71f3c6871b184042d4b126244e142'); shutil.copyfile(frm, dst) if os.path.exists(dst) else print(''); print('Hotfixed broken JSON file from OpenAI');"
|
||||
|
||||
# Caution, this file will make your eyes and brain bleed. It's such an unholy mess.
|
||||
# Note to self: Please rewrite this in Python. For the sake of your own sanity.
|
||||
|
||||
# set the correct installer path (current vs legacy)
|
||||
if [ -e "installer_files/env" ]; then
|
||||
export INSTALL_ENV_DIR="$(pwd)/installer_files/env"
|
||||
@ -44,258 +40,20 @@ fi
|
||||
if [ -e "src" ]; then mv src src-old; fi
|
||||
if [ -e "ldm" ]; then mv ldm ldm-old; fi
|
||||
|
||||
mkdir -p "../models/stable-diffusion"
|
||||
mkdir -p "../models/gfpgan"
|
||||
mkdir -p "../models/realesrgan"
|
||||
mkdir -p "../models/vae"
|
||||
|
||||
# migrate the legacy models to the correct path (if already downloaded)
|
||||
if [ -e "sd-v1-4.ckpt" ]; then mv sd-v1-4.ckpt ../models/stable-diffusion/; fi
|
||||
if [ -e "custom-model.ckpt" ]; then mv custom-model.ckpt ../models/stable-diffusion/; fi
|
||||
if [ -e "GFPGANv1.3.pth" ]; then mv GFPGANv1.3.pth ../models/gfpgan/; fi
|
||||
if [ -e "RealESRGAN_x4plus.pth" ]; then mv RealESRGAN_x4plus.pth ../models/realesrgan/; fi
|
||||
if [ -e "RealESRGAN_x4plus_anime_6B.pth" ]; then mv RealESRGAN_x4plus_anime_6B.pth ../models/realesrgan/; fi
|
||||
|
||||
OS_NAME=$(uname -s)
|
||||
case "${OS_NAME}" in
|
||||
Linux*) OS_NAME="linux";;
|
||||
Darwin*) OS_NAME="macos";;
|
||||
*) echo "Unknown OS: $OS_NAME! This script runs only on Linux or Mac" && exit
|
||||
esac
|
||||
|
||||
# install torch and torchvision
|
||||
if python ../scripts/check_modules.py torch torchvision; then
|
||||
# temp fix for installations that installed torch 2.0 by mistake
|
||||
if [ "$OS_NAME" == "linux" ]; then
|
||||
python -m pip install --upgrade torch==1.13.1+cu116 torchvision==0.14.1+cu116 --extra-index-url https://download.pytorch.org/whl/cu116 -q
|
||||
elif [ "$OS_NAME" == "macos" ]; then
|
||||
python -m pip install --upgrade torch==1.13.1 torchvision==0.14.1 -q
|
||||
fi
|
||||
|
||||
echo "torch and torchvision have already been installed."
|
||||
else
|
||||
echo "Installing torch and torchvision.."
|
||||
|
||||
export PYTHONNOUSERSITE=1
|
||||
export PYTHONPATH="$INSTALL_ENV_DIR/lib/python3.8/site-packages"
|
||||
|
||||
if [ "$OS_NAME" == "linux" ]; then
|
||||
if python -m pip install --upgrade torch==1.13.1+cu116 torchvision==0.14.1+cu116 --extra-index-url https://download.pytorch.org/whl/cu116 ; then
|
||||
echo "Installed."
|
||||
else
|
||||
fail "torch install failed"
|
||||
fi
|
||||
elif [ "$OS_NAME" == "macos" ]; then
|
||||
if python -m pip install --upgrade torch==1.13.1 torchvision==0.14.1 ; then
|
||||
echo "Installed."
|
||||
else
|
||||
fail "torch install failed"
|
||||
fi
|
||||
fi
|
||||
# Download the required packages
|
||||
if ! python ../scripts/check_modules.py; then
|
||||
read -p "Press any key to continue"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# install/upgrade sdkit
|
||||
if python ../scripts/check_modules.py sdkit sdkit.models ldm transformers numpy antlr4 gfpgan realesrgan ; then
|
||||
echo "sdkit is already installed."
|
||||
|
||||
# skip sdkit upgrade if in developer-mode
|
||||
if [ ! -e "../src/sdkit" ]; then
|
||||
export PYTHONNOUSERSITE=1
|
||||
export PYTHONPATH="$INSTALL_ENV_DIR/lib/python3.8/site-packages"
|
||||
|
||||
python -m pip install --upgrade sdkit==1.0.64 -q
|
||||
fi
|
||||
else
|
||||
echo "Installing sdkit: https://pypi.org/project/sdkit/"
|
||||
|
||||
export PYTHONNOUSERSITE=1
|
||||
export PYTHONPATH="$INSTALL_ENV_DIR/lib/python3.8/site-packages"
|
||||
|
||||
if python -m pip install sdkit==1.0.64 ; then
|
||||
echo "Installed."
|
||||
else
|
||||
fail "sdkit install failed"
|
||||
fi
|
||||
if ! command -v uvicorn &> /dev/null; then
|
||||
fail "UI packages not found!"
|
||||
fi
|
||||
|
||||
python -c "from importlib.metadata import version; print('sdkit version:', version('sdkit'))"
|
||||
|
||||
# upgrade stable-diffusion-sdkit
|
||||
python -m pip install --upgrade stable-diffusion-sdkit==2.1.4 -q
|
||||
python -c "from importlib.metadata import version; print('stable-diffusion version:', version('stable-diffusion-sdkit'))"
|
||||
|
||||
# install rich
|
||||
if python ../scripts/check_modules.py rich; then
|
||||
echo "rich has already been installed."
|
||||
else
|
||||
echo "Installing rich.."
|
||||
|
||||
export PYTHONNOUSERSITE=1
|
||||
export PYTHONPATH="$INSTALL_ENV_DIR/lib/python3.8/site-packages"
|
||||
|
||||
if python -m pip install rich ; then
|
||||
echo "Installed."
|
||||
else
|
||||
fail "Install failed for rich"
|
||||
fi
|
||||
fi
|
||||
|
||||
if python ../scripts/check_modules.py uvicorn fastapi ; then
|
||||
echo "Packages necessary for Easy Diffusion were already installed"
|
||||
else
|
||||
printf "\n\nDownloading packages necessary for Easy Diffusion..\n\n"
|
||||
|
||||
export PYTHONNOUSERSITE=1
|
||||
export PYTHONPATH="$INSTALL_ENV_DIR/lib/python3.8/site-packages"
|
||||
|
||||
if conda install -c conda-forge -y uvicorn fastapi ; then
|
||||
echo "Installed. Testing.."
|
||||
else
|
||||
fail "'conda install uvicorn' failed"
|
||||
fi
|
||||
|
||||
if ! command -v uvicorn &> /dev/null; then
|
||||
fail "UI packages not found!"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -f "../models/stable-diffusion/sd-v1-4.ckpt" ]; then
|
||||
model_size=`filesize "../models/stable-diffusion/sd-v1-4.ckpt"`
|
||||
|
||||
if [ "$model_size" -eq "4265380512" ] || [ "$model_size" -eq "7703807346" ] || [ "$model_size" -eq "7703810927" ]; then
|
||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded"
|
||||
else
|
||||
printf "\n\nThe model file present at models/stable-diffusion/sd-v1-4.ckpt is invalid. It is only $model_size bytes in size. Re-downloading.."
|
||||
rm ../models/stable-diffusion/sd-v1-4.ckpt
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "../models/stable-diffusion/sd-v1-4.ckpt" ]; then
|
||||
echo "Downloading data files (weights) for Stable Diffusion.."
|
||||
|
||||
curl -L -k https://huggingface.co/CompVis/stable-diffusion-v-1-4-original/resolve/main/sd-v1-4.ckpt > ../models/stable-diffusion/sd-v1-4.ckpt
|
||||
|
||||
if [ -f "../models/stable-diffusion/sd-v1-4.ckpt" ]; then
|
||||
model_size=`filesize "../models/stable-diffusion/sd-v1-4.ckpt"`
|
||||
if [ ! "$model_size" == "4265380512" ]; then
|
||||
fail "The downloaded model file was invalid! Bytes downloaded: $model_size"
|
||||
fi
|
||||
else
|
||||
fail "Error downloading the data files (weights) for Stable Diffusion"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ -f "../models/gfpgan/GFPGANv1.3.pth" ]; then
|
||||
model_size=`filesize "../models/gfpgan/GFPGANv1.3.pth"`
|
||||
|
||||
if [ "$model_size" -eq "348632874" ]; then
|
||||
echo "Data files (weights) necessary for GFPGAN (Face Correction) were already downloaded"
|
||||
else
|
||||
printf "\n\nThe model file present at models/gfpgan/GFPGANv1.3.pth is invalid. It is only $model_size bytes in size. Re-downloading.."
|
||||
rm ../models/gfpgan/GFPGANv1.3.pth
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "../models/gfpgan/GFPGANv1.3.pth" ]; then
|
||||
echo "Downloading data files (weights) for GFPGAN (Face Correction).."
|
||||
|
||||
curl -L -k https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth > ../models/gfpgan/GFPGANv1.3.pth
|
||||
|
||||
if [ -f "../models/gfpgan/GFPGANv1.3.pth" ]; then
|
||||
model_size=`filesize "../models/gfpgan/GFPGANv1.3.pth"`
|
||||
if [ ! "$model_size" -eq "348632874" ]; then
|
||||
fail "The downloaded GFPGAN model file was invalid! Bytes downloaded: $model_size"
|
||||
fi
|
||||
else
|
||||
fail "Error downloading the data files (weights) for GFPGAN (Face Correction)."
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ -f "../models/realesrgan/RealESRGAN_x4plus.pth" ]; then
|
||||
model_size=`filesize "../models/realesrgan/RealESRGAN_x4plus.pth"`
|
||||
|
||||
if [ "$model_size" -eq "67040989" ]; then
|
||||
echo "Data files (weights) necessary for ESRGAN (Resolution Upscaling) x4plus were already downloaded"
|
||||
else
|
||||
printf "\n\nThe model file present at models/realesrgan/RealESRGAN_x4plus.pth is invalid. It is only $model_size bytes in size. Re-downloading.."
|
||||
rm ../models/realesrgan/RealESRGAN_x4plus.pth
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "../models/realesrgan/RealESRGAN_x4plus.pth" ]; then
|
||||
echo "Downloading data files (weights) for ESRGAN (Resolution Upscaling) x4plus.."
|
||||
|
||||
curl -L -k https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth > ../models/realesrgan/RealESRGAN_x4plus.pth
|
||||
|
||||
if [ -f "../models/realesrgan/RealESRGAN_x4plus.pth" ]; then
|
||||
model_size=`filesize "../models/realesrgan/RealESRGAN_x4plus.pth"`
|
||||
if [ ! "$model_size" -eq "67040989" ]; then
|
||||
fail "The downloaded ESRGAN x4plus model file was invalid! Bytes downloaded: $model_size"
|
||||
fi
|
||||
else
|
||||
fail "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ -f "../models/realesrgan/RealESRGAN_x4plus_anime_6B.pth" ]; then
|
||||
model_size=`filesize "../models/realesrgan/RealESRGAN_x4plus_anime_6B.pth"`
|
||||
|
||||
if [ "$model_size" -eq "17938799" ]; then
|
||||
echo "Data files (weights) necessary for ESRGAN (Resolution Upscaling) x4plus_anime were already downloaded"
|
||||
else
|
||||
printf "\n\nThe model file present at models/realesrgan/RealESRGAN_x4plus_anime_6B.pth is invalid. It is only $model_size bytes in size. Re-downloading.."
|
||||
rm ../models/realesrgan/RealESRGAN_x4plus_anime_6B.pth
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "../models/realesrgan/RealESRGAN_x4plus_anime_6B.pth" ]; then
|
||||
echo "Downloading data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime.."
|
||||
|
||||
curl -L -k https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth > ../models/realesrgan/RealESRGAN_x4plus_anime_6B.pth
|
||||
|
||||
if [ -f "../models/realesrgan/RealESRGAN_x4plus_anime_6B.pth" ]; then
|
||||
model_size=`filesize "../models/realesrgan/RealESRGAN_x4plus_anime_6B.pth"`
|
||||
if [ ! "$model_size" -eq "17938799" ]; then
|
||||
fail "The downloaded ESRGAN x4plus_anime model file was invalid! Bytes downloaded: $model_size"
|
||||
fi
|
||||
else
|
||||
fail "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime."
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
if [ -f "../models/vae/vae-ft-mse-840000-ema-pruned.ckpt" ]; then
|
||||
model_size=`filesize "../models/vae/vae-ft-mse-840000-ema-pruned.ckpt"`
|
||||
|
||||
if [ "$model_size" -eq "334695179" ]; then
|
||||
echo "Data files (weights) necessary for the default VAE (sd-vae-ft-mse-original) were already downloaded"
|
||||
else
|
||||
printf "\n\nThe model file present at models/vae/vae-ft-mse-840000-ema-pruned.ckpt is invalid. It is only $model_size bytes in size. Re-downloading.."
|
||||
rm ../models/vae/vae-ft-mse-840000-ema-pruned.ckpt
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -f "../models/vae/vae-ft-mse-840000-ema-pruned.ckpt" ]; then
|
||||
echo "Downloading data files (weights) for the default VAE (sd-vae-ft-mse-original).."
|
||||
|
||||
curl -L -k https://huggingface.co/stabilityai/sd-vae-ft-mse-original/resolve/main/vae-ft-mse-840000-ema-pruned.ckpt > ../models/vae/vae-ft-mse-840000-ema-pruned.ckpt
|
||||
|
||||
if [ -f "../models/vae/vae-ft-mse-840000-ema-pruned.ckpt" ]; then
|
||||
model_size=`filesize "../models/vae/vae-ft-mse-840000-ema-pruned.ckpt"`
|
||||
if [ ! "$model_size" -eq "334695179" ]; then
|
||||
printf "\n\nError: The downloaded default VAE (sd-vae-ft-mse-original) file was invalid! Bytes downloaded: $model_size\n\n"
|
||||
printf "\n\nError downloading the data files (weights) for the default VAE (sd-vae-ft-mse-original). Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting\n 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
else
|
||||
printf "\n\nError downloading the data files (weights) for the default VAE (sd-vae-ft-mse-original). Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting\n 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
|
||||
read -p "Press any key to continue"
|
||||
exit
|
||||
fi
|
||||
# Download the required models
|
||||
if ! python ../scripts/check_models.py; then
|
||||
read -p "Press any key to continue"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ `grep -c sd_install_complete ../scripts/install_status.txt` -gt "0" ]; then
|
||||
|
@ -41,12 +41,15 @@ def load_default_models(context: Context):
|
||||
for model_type in MODELS_TO_LOAD_ON_START:
|
||||
context.model_paths[model_type] = resolve_model_to_use(model_type=model_type)
|
||||
try:
|
||||
load_model(context, model_type)
|
||||
load_model(
|
||||
context,
|
||||
model_type,
|
||||
scan_model = context.model_paths[model_type] != None and not context.model_paths[model_type].endswith('.safetensors')
|
||||
)
|
||||
except Exception as e:
|
||||
log.error(f"[red]Error while loading {model_type} model: {context.model_paths[model_type]}[/red]")
|
||||
log.error(f"[red]Error: {e}[/red]")
|
||||
log.error(f"[red]Consider removing the model from the model folder.[red]")
|
||||
|
||||
log.exception(e)
|
||||
del context.model_paths[model_type]
|
||||
|
||||
def unload_all(context: Context):
|
||||
for model_type in KNOWN_MODEL_TYPES:
|
||||
@ -243,6 +246,7 @@ def getModels():
|
||||
except MaliciousModelException as e:
|
||||
models["scan-error"] = e
|
||||
|
||||
log.info(f"[green]Scanning all model folders for models...[/]")
|
||||
# custom models
|
||||
listModels(model_type="stable-diffusion")
|
||||
listModels(model_type="vae")
|
||||
|
@ -10,7 +10,13 @@ from easydiffusion.utils import get_printable_request, save_images_to_disk, log
|
||||
from sdkit import Context
|
||||
from sdkit.generate import generate_images
|
||||
from sdkit.filter import apply_filters
|
||||
from sdkit.utils import img_to_buffer, img_to_base64_str, latent_samples_to_images, diffusers_latent_samples_to_images
|
||||
from sdkit.utils import (
|
||||
img_to_buffer,
|
||||
img_to_base64_str,
|
||||
latent_samples_to_images,
|
||||
diffusers_latent_samples_to_images,
|
||||
gc,
|
||||
)
|
||||
|
||||
context = Context() # thread-local
|
||||
"""
|
||||
@ -62,7 +68,6 @@ def print_task_info(req: GenerateImageRequest, task_data: TaskData):
|
||||
def make_images_internal(
|
||||
req: GenerateImageRequest, task_data: TaskData, data_queue: queue.Queue, task_temp_images: list, step_callback
|
||||
):
|
||||
|
||||
images, user_stopped = generate_images_internal(
|
||||
req,
|
||||
task_data,
|
||||
@ -72,6 +77,7 @@ def make_images_internal(
|
||||
task_data.stream_image_progress,
|
||||
task_data.stream_image_progress_interval,
|
||||
)
|
||||
gc(context)
|
||||
filtered_images = filter_images(task_data, images, user_stopped)
|
||||
|
||||
if task_data.save_to_disk_path is not None:
|
||||
|
@ -10,7 +10,7 @@ from typing import List, Union
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from starlette.responses import FileResponse, JSONResponse, StreamingResponse
|
||||
from pydantic import BaseModel
|
||||
from pydantic import BaseModel, Extra
|
||||
|
||||
from easydiffusion import app, model_manager, task_manager
|
||||
from easydiffusion.types import TaskData, GenerateImageRequest, MergeRequest
|
||||
@ -44,7 +44,7 @@ class NoCacheStaticFiles(StaticFiles):
|
||||
return super().is_not_modified(response_headers, request_headers)
|
||||
|
||||
|
||||
class SetAppConfigRequest(BaseModel):
|
||||
class SetAppConfigRequest(BaseModel, extra=Extra.allow):
|
||||
update_branch: str = None
|
||||
render_devices: Union[List[str], List[int], str, int] = None
|
||||
model_vae: str = None
|
||||
@ -136,6 +136,10 @@ def set_app_config_internal(req: SetAppConfigRequest):
|
||||
|
||||
config["test_diffusers"] = req.test_diffusers
|
||||
|
||||
for property, property_value in req.dict().items():
|
||||
if property_value is not None and property not in req.__fields__:
|
||||
config[property] = property_value
|
||||
|
||||
try:
|
||||
app.setConfig(config)
|
||||
|
||||
|
@ -317,6 +317,9 @@ def thread_render(device):
|
||||
def step_callback():
|
||||
global current_state_error
|
||||
|
||||
task_cache.keep(id(task), TASK_TTL)
|
||||
session_cache.keep(task.task_data.session_id, TASK_TTL)
|
||||
|
||||
if (
|
||||
isinstance(current_state_error, SystemExit)
|
||||
or isinstance(current_state_error, StopAsyncIteration)
|
||||
|
@ -2,12 +2,16 @@ import os
|
||||
import time
|
||||
import re
|
||||
|
||||
from easydiffusion import app
|
||||
from easydiffusion.types import TaskData, GenerateImageRequest
|
||||
from functools import reduce
|
||||
from datetime import datetime
|
||||
|
||||
from sdkit.utils import save_images, save_dicts
|
||||
from numpy import base_repr
|
||||
|
||||
filename_regex = re.compile("[^a-zA-Z0-9._-]")
|
||||
img_number_regex = re.compile("([0-9]{5,})")
|
||||
|
||||
# keep in sync with `ui/media/js/dnd.js`
|
||||
TASK_TEXT_MAPPING = {
|
||||
@ -28,15 +32,89 @@ TASK_TEXT_MAPPING = {
|
||||
"use_hypernetwork_model": "Hypernetwork model",
|
||||
"hypernetwork_strength": "Hypernetwork Strength",
|
||||
"use_lora_model": "LoRA model",
|
||||
# "lora_alpha": "LoRA Strength",
|
||||
"lora_alpha": "LoRA Strength",
|
||||
}
|
||||
|
||||
time_placeholders = {
|
||||
"$yyyy": "%Y",
|
||||
"$MM": "%m",
|
||||
"$dd": "%d",
|
||||
"$HH": "%H",
|
||||
"$mm": "%M",
|
||||
"$ss": "%S",
|
||||
}
|
||||
|
||||
other_placeholders = {
|
||||
"$id": lambda req, task_data: filename_regex.sub("_", task_data.session_id),
|
||||
"$p": lambda req, task_data: filename_regex.sub("_", req.prompt)[:50],
|
||||
"$s": lambda req, task_data: str(req.seed),
|
||||
}
|
||||
|
||||
class ImageNumber:
|
||||
_factory = None
|
||||
_evaluated = False
|
||||
|
||||
def __init__(self, factory):
|
||||
self._factory = factory
|
||||
self._evaluated = None
|
||||
def __call__(self) -> int:
|
||||
if self._evaluated is None:
|
||||
self._evaluated = self._factory()
|
||||
return self._evaluated
|
||||
|
||||
def format_placeholders(format: str, req: GenerateImageRequest, task_data: TaskData, now = None):
|
||||
if now is None:
|
||||
now = time.time()
|
||||
|
||||
for placeholder, time_format in time_placeholders.items():
|
||||
if placeholder in format:
|
||||
format = format.replace(placeholder, datetime.fromtimestamp(now).strftime(time_format))
|
||||
for placeholder, replace_func in other_placeholders.items():
|
||||
if placeholder in format:
|
||||
format = format.replace(placeholder, replace_func(req, task_data))
|
||||
|
||||
return format
|
||||
|
||||
def format_folder_name(format: str, req: GenerateImageRequest, task_data: TaskData):
|
||||
format = format_placeholders(format, req, task_data)
|
||||
return filename_regex.sub("_", format)
|
||||
|
||||
def format_file_name(
|
||||
format: str,
|
||||
req: GenerateImageRequest,
|
||||
task_data: TaskData,
|
||||
now: float,
|
||||
batch_file_number: int,
|
||||
folder_img_number: ImageNumber,
|
||||
):
|
||||
format = format_placeholders(format, req, task_data, now)
|
||||
|
||||
if "$n" in format:
|
||||
format = format.replace("$n", f"{folder_img_number():05}")
|
||||
|
||||
if "$tsb64" in format:
|
||||
img_id = base_repr(int(now * 10000), 36)[-7:] + base_repr(int(batch_file_number), 36) # Base 36 conversion, 0-9, A-Z
|
||||
format = format.replace("$tsb64", img_id)
|
||||
|
||||
if "$ts" in format:
|
||||
format = format.replace("$ts", str(int(now * 1000) + batch_file_number))
|
||||
|
||||
return filename_regex.sub("_", format)
|
||||
|
||||
def save_images_to_disk(images: list, filtered_images: list, req: GenerateImageRequest, task_data: TaskData):
|
||||
now = time.time()
|
||||
save_dir_path = os.path.join(task_data.save_to_disk_path, filename_regex.sub("_", task_data.session_id))
|
||||
app_config = app.getConfig()
|
||||
folder_format = app_config.get("folder_format", "$id")
|
||||
save_dir_path = os.path.join(task_data.save_to_disk_path, format_folder_name(folder_format, req, task_data))
|
||||
metadata_entries = get_metadata_entries_for_request(req, task_data)
|
||||
make_filename = make_filename_callback(req, now=now)
|
||||
file_number = calculate_img_number(save_dir_path, task_data)
|
||||
make_filename = make_filename_callback(
|
||||
app_config.get("filename_format", "$p_$tsb64"),
|
||||
req,
|
||||
task_data,
|
||||
file_number,
|
||||
now=now,
|
||||
)
|
||||
|
||||
if task_data.show_only_filtered_image or filtered_images is images:
|
||||
save_images(
|
||||
@ -58,7 +136,13 @@ def save_images_to_disk(images: list, filtered_images: list, req: GenerateImageR
|
||||
file_format=task_data.output_format,
|
||||
)
|
||||
else:
|
||||
make_filter_filename = make_filename_callback(req, now=now, suffix="filtered")
|
||||
make_filter_filename = make_filename_callback(
|
||||
app_config.get("filename_format", "$p_$tsb64"),
|
||||
req,
|
||||
task_data,
|
||||
file_number,
|
||||
now=now,
|
||||
suffix="filtered")
|
||||
|
||||
save_images(
|
||||
images,
|
||||
@ -105,9 +189,6 @@ def get_metadata_entries_for_request(req: GenerateImageRequest, task_data: TaskD
|
||||
if task_data.use_lora_model is None:
|
||||
if "lora_alpha" in metadata:
|
||||
del metadata["lora_alpha"]
|
||||
|
||||
from easydiffusion import app
|
||||
|
||||
app_config = app.getConfig()
|
||||
if not app_config.get("test_diffusers", False) and "use_lora_model" in metadata:
|
||||
del metadata["use_lora_model"]
|
||||
@ -133,16 +214,66 @@ def get_printable_request(req: GenerateImageRequest):
|
||||
return metadata
|
||||
|
||||
|
||||
def make_filename_callback(req: GenerateImageRequest, suffix=None, now=None):
|
||||
def make_filename_callback(
|
||||
filename_format: str,
|
||||
req: GenerateImageRequest,
|
||||
task_data: TaskData,
|
||||
folder_img_number: int,
|
||||
suffix=None,
|
||||
now=None,
|
||||
):
|
||||
if now is None:
|
||||
now = time.time()
|
||||
|
||||
def make_filename(i):
|
||||
img_id = base_repr(int(now * 10000), 36)[-7:] + base_repr(int(i),36) # Base 36 conversion, 0-9, A-Z
|
||||
|
||||
prompt_flattened = filename_regex.sub("_", req.prompt)[:50]
|
||||
name = f"{prompt_flattened}_{img_id}"
|
||||
name = format_file_name(filename_format, req, task_data, now, i, folder_img_number)
|
||||
name = name if suffix is None else f"{name}_{suffix}"
|
||||
|
||||
return name
|
||||
|
||||
return make_filename
|
||||
|
||||
def _calculate_img_number(save_dir_path: str, task_data: TaskData):
|
||||
def get_highest_img_number(accumulator: int, file: os.DirEntry) -> int:
|
||||
if not file.is_file:
|
||||
return accumulator
|
||||
|
||||
if len(list(filter(lambda e: file.name.endswith(e), app.IMAGE_EXTENSIONS))) == 0:
|
||||
return accumulator
|
||||
|
||||
get_highest_img_number.number_of_images = get_highest_img_number.number_of_images + 1
|
||||
|
||||
number_match = img_number_regex.match(file.name)
|
||||
if not number_match:
|
||||
return accumulator
|
||||
|
||||
file_number = number_match.group().lstrip('0')
|
||||
|
||||
# Handle 00000
|
||||
return int(file_number) if file_number else 0
|
||||
|
||||
get_highest_img_number.number_of_images = 0
|
||||
|
||||
highest_file_number = -1
|
||||
|
||||
if os.path.isdir(save_dir_path):
|
||||
existing_files = list(os.scandir(save_dir_path))
|
||||
highest_file_number = reduce(get_highest_img_number, existing_files, -1)
|
||||
|
||||
calculated_img_number = max(highest_file_number, get_highest_img_number.number_of_images - 1)
|
||||
|
||||
if task_data.session_id in _calculate_img_number.session_img_numbers:
|
||||
calculated_img_number = max(
|
||||
_calculate_img_number.session_img_numbers[task_data.session_id],
|
||||
calculated_img_number,
|
||||
)
|
||||
|
||||
calculated_img_number = calculated_img_number + 1
|
||||
|
||||
_calculate_img_number.session_img_numbers[task_data.session_id] = calculated_img_number
|
||||
return calculated_img_number
|
||||
|
||||
_calculate_img_number.session_img_numbers = {}
|
||||
|
||||
def calculate_img_number(save_dir_path: str, task_data: TaskData):
|
||||
return ImageNumber(lambda: _calculate_img_number(save_dir_path, task_data))
|
||||
|
@ -1,171 +0,0 @@
|
||||
{
|
||||
"_name_or_path": "clip-vit-large-patch14/",
|
||||
"architectures": [
|
||||
"CLIPModel"
|
||||
],
|
||||
"initializer_factor": 1.0,
|
||||
"logit_scale_init_value": 2.6592,
|
||||
"model_type": "clip",
|
||||
"projection_dim": 768,
|
||||
"text_config": {
|
||||
"_name_or_path": "",
|
||||
"add_cross_attention": false,
|
||||
"architectures": null,
|
||||
"attention_dropout": 0.0,
|
||||
"bad_words_ids": null,
|
||||
"bos_token_id": 0,
|
||||
"chunk_size_feed_forward": 0,
|
||||
"cross_attention_hidden_size": null,
|
||||
"decoder_start_token_id": null,
|
||||
"diversity_penalty": 0.0,
|
||||
"do_sample": false,
|
||||
"dropout": 0.0,
|
||||
"early_stopping": false,
|
||||
"encoder_no_repeat_ngram_size": 0,
|
||||
"eos_token_id": 2,
|
||||
"finetuning_task": null,
|
||||
"forced_bos_token_id": null,
|
||||
"forced_eos_token_id": null,
|
||||
"hidden_act": "quick_gelu",
|
||||
"hidden_size": 768,
|
||||
"id2label": {
|
||||
"0": "LABEL_0",
|
||||
"1": "LABEL_1"
|
||||
},
|
||||
"initializer_factor": 1.0,
|
||||
"initializer_range": 0.02,
|
||||
"intermediate_size": 3072,
|
||||
"is_decoder": false,
|
||||
"is_encoder_decoder": false,
|
||||
"label2id": {
|
||||
"LABEL_0": 0,
|
||||
"LABEL_1": 1
|
||||
},
|
||||
"layer_norm_eps": 1e-05,
|
||||
"length_penalty": 1.0,
|
||||
"max_length": 20,
|
||||
"max_position_embeddings": 77,
|
||||
"min_length": 0,
|
||||
"model_type": "clip_text_model",
|
||||
"no_repeat_ngram_size": 0,
|
||||
"num_attention_heads": 12,
|
||||
"num_beam_groups": 1,
|
||||
"num_beams": 1,
|
||||
"num_hidden_layers": 12,
|
||||
"num_return_sequences": 1,
|
||||
"output_attentions": false,
|
||||
"output_hidden_states": false,
|
||||
"output_scores": false,
|
||||
"pad_token_id": 1,
|
||||
"prefix": null,
|
||||
"problem_type": null,
|
||||
"projection_dim" : 768,
|
||||
"pruned_heads": {},
|
||||
"remove_invalid_values": false,
|
||||
"repetition_penalty": 1.0,
|
||||
"return_dict": true,
|
||||
"return_dict_in_generate": false,
|
||||
"sep_token_id": null,
|
||||
"task_specific_params": null,
|
||||
"temperature": 1.0,
|
||||
"tie_encoder_decoder": false,
|
||||
"tie_word_embeddings": true,
|
||||
"tokenizer_class": null,
|
||||
"top_k": 50,
|
||||
"top_p": 1.0,
|
||||
"torch_dtype": null,
|
||||
"torchscript": false,
|
||||
"transformers_version": "4.16.0.dev0",
|
||||
"use_bfloat16": false,
|
||||
"vocab_size": 49408
|
||||
},
|
||||
"text_config_dict": {
|
||||
"hidden_size": 768,
|
||||
"intermediate_size": 3072,
|
||||
"num_attention_heads": 12,
|
||||
"num_hidden_layers": 12,
|
||||
"projection_dim": 768
|
||||
},
|
||||
"torch_dtype": "float32",
|
||||
"transformers_version": null,
|
||||
"vision_config": {
|
||||
"_name_or_path": "",
|
||||
"add_cross_attention": false,
|
||||
"architectures": null,
|
||||
"attention_dropout": 0.0,
|
||||
"bad_words_ids": null,
|
||||
"bos_token_id": null,
|
||||
"chunk_size_feed_forward": 0,
|
||||
"cross_attention_hidden_size": null,
|
||||
"decoder_start_token_id": null,
|
||||
"diversity_penalty": 0.0,
|
||||
"do_sample": false,
|
||||
"dropout": 0.0,
|
||||
"early_stopping": false,
|
||||
"encoder_no_repeat_ngram_size": 0,
|
||||
"eos_token_id": null,
|
||||
"finetuning_task": null,
|
||||
"forced_bos_token_id": null,
|
||||
"forced_eos_token_id": null,
|
||||
"hidden_act": "quick_gelu",
|
||||
"hidden_size": 1024,
|
||||
"id2label": {
|
||||
"0": "LABEL_0",
|
||||
"1": "LABEL_1"
|
||||
},
|
||||
"image_size": 224,
|
||||
"initializer_factor": 1.0,
|
||||
"initializer_range": 0.02,
|
||||
"intermediate_size": 4096,
|
||||
"is_decoder": false,
|
||||
"is_encoder_decoder": false,
|
||||
"label2id": {
|
||||
"LABEL_0": 0,
|
||||
"LABEL_1": 1
|
||||
},
|
||||
"layer_norm_eps": 1e-05,
|
||||
"length_penalty": 1.0,
|
||||
"max_length": 20,
|
||||
"min_length": 0,
|
||||
"model_type": "clip_vision_model",
|
||||
"no_repeat_ngram_size": 0,
|
||||
"num_attention_heads": 16,
|
||||
"num_beam_groups": 1,
|
||||
"num_beams": 1,
|
||||
"num_hidden_layers": 24,
|
||||
"num_return_sequences": 1,
|
||||
"output_attentions": false,
|
||||
"output_hidden_states": false,
|
||||
"output_scores": false,
|
||||
"pad_token_id": null,
|
||||
"patch_size": 14,
|
||||
"prefix": null,
|
||||
"problem_type": null,
|
||||
"projection_dim" : 768,
|
||||
"pruned_heads": {},
|
||||
"remove_invalid_values": false,
|
||||
"repetition_penalty": 1.0,
|
||||
"return_dict": true,
|
||||
"return_dict_in_generate": false,
|
||||
"sep_token_id": null,
|
||||
"task_specific_params": null,
|
||||
"temperature": 1.0,
|
||||
"tie_encoder_decoder": false,
|
||||
"tie_word_embeddings": true,
|
||||
"tokenizer_class": null,
|
||||
"top_k": 50,
|
||||
"top_p": 1.0,
|
||||
"torch_dtype": null,
|
||||
"torchscript": false,
|
||||
"transformers_version": "4.16.0.dev0",
|
||||
"use_bfloat16": false
|
||||
},
|
||||
"vision_config_dict": {
|
||||
"hidden_size": 1024,
|
||||
"intermediate_size": 4096,
|
||||
"num_attention_heads": 16,
|
||||
"num_hidden_layers": 24,
|
||||
"patch_size": 14,
|
||||
"projection_dim": 768
|
||||
}
|
||||
}
|
@ -30,7 +30,7 @@
|
||||
<h1>
|
||||
<img id="logo_img" src="/media/images/icon-512x512.png" >
|
||||
Easy Diffusion
|
||||
<small>v2.5.30 <span id="updateBranchLabel"></span></small>
|
||||
<small>v2.5.34 <span id="updateBranchLabel"></span></small>
|
||||
</h1>
|
||||
</div>
|
||||
<div id="server-status">
|
||||
@ -221,7 +221,7 @@
|
||||
<input id="lora_model" type="text" spellcheck="false" autocomplete="off" class="model-filter" data-path="" />
|
||||
</td></tr>
|
||||
<tr id="lora_alpha_container" class="pl-5">
|
||||
<td><label for="lora_alpha_slider">LoRA strength:</label></td>
|
||||
<td><label for="lora_alpha_slider">LoRA Strength:</label></td>
|
||||
<td> <input id="lora_alpha_slider" name="lora_alpha_slider" class="editor-slider" value="50" type="range" min="0" max="100"> <input id="lora_alpha" name="lora_alpha" size="4" pattern="^[0-9\.]+$" onkeypress="preventNonNumericalInput(event)"><br/></td>
|
||||
</tr>
|
||||
<tr class="pl-5"><td><label for="hypernetwork_model">Hypernetwork:</i></label></td><td>
|
||||
@ -293,6 +293,12 @@
|
||||
|
||||
<div id="preview" class="col-free">
|
||||
|
||||
<div id="initial-text">
|
||||
Type a prompt and press the "Make Image" button.<br/><br/>You can set an "Initial Image" if you want to guide the AI.<br/><br/>
|
||||
You can also add modifiers like "Realistic", "Pencil Sketch", "ArtStation" etc by browsing through the "Image Modifiers" section
|
||||
and selecting the desired modifiers.<br/><br/>
|
||||
Click "Image Settings" for additional settings like seed, image size, number of images to generate etc.<br/><br/>Enjoy! :)
|
||||
</div>
|
||||
<div id="preview-content">
|
||||
<div id="preview-tools" class="displayNone">
|
||||
<button id="clear-all-previews" class="secondaryButton"><i class="fa-solid fa-trash-can icon"></i> Clear All</button>
|
||||
@ -326,12 +332,6 @@
|
||||
<div class="clearfix" style="clear: both;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="initial-text">
|
||||
Type a prompt and press the "Make Image" button.<br/><br/>You can set an "Initial Image" if you want to guide the AI.<br/><br/>
|
||||
You can also add modifiers like "Realistic", "Pencil Sketch", "ArtStation" etc by browsing through the "Image Modifiers" section
|
||||
and selecting the desired modifiers.<br/><br/>
|
||||
Click "Image Settings" for additional settings like seed, image size, number of images to generate etc.<br/><br/>Enjoy! :)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -520,7 +520,7 @@ async function init() {
|
||||
}
|
||||
})
|
||||
|
||||
playSound()
|
||||
// playSound()
|
||||
}
|
||||
|
||||
init()
|
||||
|
@ -3,7 +3,7 @@
|
||||
font-family: 'Work Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local(''),
|
||||
src: local('Work Sans'),
|
||||
url('/media/fonts/work-sans-v18-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('/media/fonts/work-sans-v18-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
@ -13,7 +13,7 @@
|
||||
font-family: 'Work Sans';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
src: local(''),
|
||||
src: local('Work Sans'),
|
||||
url('/media/fonts/work-sans-v18-latin-600.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('/media/fonts/work-sans-v18-latin-600.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
@ -23,7 +23,7 @@
|
||||
font-family: 'Work Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local(''),
|
||||
src: local('Work Sans'),
|
||||
url('/media/fonts/work-sans-v18-latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('/media/fonts/work-sans-v18-latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
@ -33,8 +33,8 @@
|
||||
font-family: 'Work Sans';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
src: local(''),
|
||||
src: local('Work Sans'),
|
||||
url('/media/fonts/work-sans-v18-latin-800.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||
url('/media/fonts/work-sans-v18-latin-800.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||
}
|
||||
|
||||
|
||||
|
@ -238,6 +238,10 @@ code {
|
||||
#stopImage:hover {
|
||||
background: rgb(177, 27, 0);
|
||||
}
|
||||
#undo {
|
||||
float: right;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
div#render-buttons {
|
||||
gap: 3px;
|
||||
|
@ -153,6 +153,10 @@
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
}
|
||||
.modifier-card-overlay:hover ~ .modifier-card-container .modifier-card-label.tooltip .tooltip-text {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
.modifier-card:hover > .modifier-card-image-container .modifier-card-image-overlay {
|
||||
opacity: 1;
|
||||
}
|
||||
@ -220,4 +224,4 @@
|
||||
#modifier-settings-config textarea {
|
||||
width: 90%;
|
||||
height: 150px;
|
||||
}
|
||||
}
|
||||
|
@ -245,6 +245,14 @@ const TASK_MAPPING = {
|
||||
readUI: () => loraModelField.value,
|
||||
parse: (val) => val
|
||||
},
|
||||
lora_alpha: { name: 'LoRA Strength',
|
||||
setUI: (lora_alpha) => {
|
||||
loraAlphaField.value = lora_alpha
|
||||
updateLoraAlphaSlider()
|
||||
},
|
||||
readUI: () => parseFloat(loraAlphaField.value),
|
||||
parse: (val) => parseFloat(val)
|
||||
},
|
||||
use_hypernetwork_model: { name: 'Hypernetwork model',
|
||||
setUI: (use_hypernetwork_model) => {
|
||||
const oldVal = hypernetworkModelField.value
|
||||
@ -340,7 +348,12 @@ function restoreTaskToUI(task, fieldsToSkip) {
|
||||
hypernetworkModelField.value = ""
|
||||
hypernetworkModelField.dispatchEvent(new Event("change"))
|
||||
}
|
||||
|
||||
|
||||
if (!('use_lora_model' in task.reqBody)) {
|
||||
loraModelField.value = ""
|
||||
loraModelField.dispatchEvent(new Event("change"))
|
||||
}
|
||||
|
||||
// restore the original prompt if provided (e.g. use settings), fallback to prompt as needed (e.g. copy/paste or d&d)
|
||||
promptField.value = task.reqBody.original_prompt
|
||||
if (!('original_prompt' in task.reqBody)) {
|
||||
@ -595,7 +608,7 @@ document.addEventListener('paste', async (event) => {
|
||||
}
|
||||
const paste = (event.clipboardData || window.clipboardData).getData('text')
|
||||
const selection = window.getSelection()
|
||||
if (selection.toString().trim().length <= 0 && await parseContent(paste)) {
|
||||
if (paste != "" && selection.toString().trim().length <= 0 && await parseContent(paste)) {
|
||||
event.preventDefault()
|
||||
return
|
||||
}
|
||||
|
@ -1,6 +1,28 @@
|
||||
"use strict"
|
||||
|
||||
/**
|
||||
* @typedef {object} ImageModalRequest
|
||||
* @property {string} src
|
||||
* @property {ImageModalRequest | () => ImageModalRequest | undefined} previous
|
||||
* @property {ImageModalRequest | () => ImageModalRequest | undefined} next
|
||||
*/
|
||||
|
||||
/**
|
||||
* @type {(() => (string | ImageModalRequest) | string | ImageModalRequest) => {}}
|
||||
*/
|
||||
const imageModal = (function() {
|
||||
const backElem = createElement(
|
||||
'i',
|
||||
undefined,
|
||||
['fa-solid', 'fa-arrow-left', 'tertiaryButton'],
|
||||
)
|
||||
|
||||
const forwardElem = createElement(
|
||||
'i',
|
||||
undefined,
|
||||
['fa-solid', 'fa-arrow-right', 'tertiaryButton'],
|
||||
)
|
||||
|
||||
const zoomElem = createElement(
|
||||
'i',
|
||||
undefined,
|
||||
@ -13,7 +35,7 @@ const imageModal = (function() {
|
||||
['fa-solid', 'fa-xmark', 'tertiaryButton'],
|
||||
)
|
||||
|
||||
const menuBarElem = createElement('div', undefined, 'menu-bar', [zoomElem, closeElem])
|
||||
const menuBarElem = createElement('div', undefined, 'menu-bar', [backElem, forwardElem, zoomElem, closeElem])
|
||||
|
||||
const imageContainer = createElement('div', undefined, 'image-wrapper')
|
||||
|
||||
@ -63,15 +85,87 @@ const imageModal = (function() {
|
||||
() => setZoomLevel(imageContainer.querySelector('img')?.classList?.contains('natural-zoom')),
|
||||
)
|
||||
|
||||
const close = () => {
|
||||
const state = {
|
||||
previous: undefined,
|
||||
next: undefined,
|
||||
}
|
||||
|
||||
const clear = () => {
|
||||
imageContainer.innerHTML = ''
|
||||
|
||||
Object.keys(state).forEach(key => delete state[key])
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
clear()
|
||||
modalElem.classList.remove('active')
|
||||
document.body.style.overflow = 'initial'
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape' && modalElem.classList.contains('active')) {
|
||||
/**
|
||||
* @param {() => (string | ImageModalRequest) | string | ImageModalRequest} optionsFactory
|
||||
*/
|
||||
function init(optionsFactory) {
|
||||
if (!optionsFactory) {
|
||||
close()
|
||||
return
|
||||
}
|
||||
|
||||
clear()
|
||||
|
||||
const options = typeof optionsFactory === 'function' ? optionsFactory() : optionsFactory
|
||||
const src = typeof options === 'string' ? options : options.src
|
||||
|
||||
const imgElem = createElement('img', { src }, 'natural-zoom')
|
||||
imageContainer.appendChild(imgElem)
|
||||
modalElem.classList.add('active')
|
||||
document.body.style.overflow = 'hidden'
|
||||
setZoomLevel(false)
|
||||
|
||||
if (typeof options === 'object' && options.previous) {
|
||||
state.previous = options.previous
|
||||
backElem.style.display = 'unset'
|
||||
} else {
|
||||
backElem.style.display = 'none'
|
||||
}
|
||||
|
||||
if (typeof options === 'object' && options.next) {
|
||||
state.next = options.next
|
||||
forwardElem.style.display = 'unset'
|
||||
} else {
|
||||
forwardElem.style.display = 'none'
|
||||
}
|
||||
}
|
||||
|
||||
const back = () => {
|
||||
if (state.previous) {
|
||||
init(state.previous)
|
||||
} else {
|
||||
backElem.style.display = 'none'
|
||||
}
|
||||
}
|
||||
|
||||
const forward = () => {
|
||||
if (state.next) {
|
||||
init(state.next)
|
||||
} else {
|
||||
forwardElem.style.display = 'none'
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', (e) => {
|
||||
if (modalElem.classList.contains('active')) {
|
||||
switch (e.key) {
|
||||
case 'Escape':
|
||||
close()
|
||||
break
|
||||
case 'ArrowLeft':
|
||||
back()
|
||||
break
|
||||
case 'ArrowRight':
|
||||
forward()
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
window.addEventListener('click', (e) => {
|
||||
@ -86,15 +180,12 @@ const imageModal = (function() {
|
||||
}
|
||||
})
|
||||
|
||||
return (optionsFactory) => {
|
||||
const options = typeof optionsFactory === 'function' ? optionsFactory() : optionsFactory
|
||||
const src = typeof options === 'string' ? options : options.src
|
||||
backElem.addEventListener('click', back)
|
||||
|
||||
// TODO center it if < window size
|
||||
const imgElem = createElement('img', { src }, 'natural-zoom')
|
||||
imageContainer.appendChild(imgElem)
|
||||
modalElem.classList.add('active')
|
||||
document.body.style.overflow = 'hidden'
|
||||
setZoomLevel(false)
|
||||
}
|
||||
forwardElem.addEventListener('click', forward)
|
||||
|
||||
/**
|
||||
* @param {() => (string | ImageModalRequest) | string | ImageModalRequest} optionsFactory
|
||||
*/
|
||||
return (optionsFactory) => init(optionsFactory)
|
||||
})()
|
||||
|
@ -230,7 +230,7 @@ function refreshInactiveTags(inactiveTags) {
|
||||
// update cards
|
||||
let overlays = document.querySelector('#editor-inputs-tags-list').querySelectorAll('.modifier-card-overlay')
|
||||
overlays.forEach (i => {
|
||||
let modifierName = i.parentElement.getElementsByClassName('modifier-card-label')[0].getElementsByTagName("p")[0].innerText
|
||||
let modifierName = i.parentElement.getElementsByClassName('modifier-card-label')[0].getElementsByTagName("p")[0].dataset.fullName
|
||||
if (inactiveTags?.find(element => element === modifierName) !== undefined) {
|
||||
i.parentElement.classList.add('modifier-toggle-inactive')
|
||||
}
|
||||
|
@ -398,7 +398,30 @@ function showImages(reqBody, res, outputContainer, livePreview) {
|
||||
if ('seed' in result && !imageElem.hasAttribute('data-seed')) {
|
||||
const imageExpandBtn = imageItemElem.querySelector('.imgExpandBtn')
|
||||
imageExpandBtn.addEventListener('click', function() {
|
||||
imageModal(imageElem.src)
|
||||
function previousImage(img) {
|
||||
const allImages = Array.from(outputContainer.parentNode.querySelectorAll('.imgItem img'))
|
||||
const index = allImages.indexOf(img)
|
||||
return allImages.slice(0, index).reverse()[0]
|
||||
}
|
||||
|
||||
function nextImage(img) {
|
||||
const allImages = Array.from(outputContainer.parentNode.querySelectorAll('.imgItem img'))
|
||||
const index = allImages.indexOf(img)
|
||||
return allImages.slice(index + 1)[0]
|
||||
}
|
||||
|
||||
function imageModalParameter(img) {
|
||||
const previousImg = previousImage(img)
|
||||
const nextImg = nextImage(img)
|
||||
|
||||
return {
|
||||
src: img.src,
|
||||
previous: previousImg ? () => imageModalParameter(previousImg) : undefined,
|
||||
next: nextImg ? () => imageModalParameter(nextImg) : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
imageModal(imageModalParameter(imageElem))
|
||||
})
|
||||
|
||||
const req = Object.assign({}, reqBody, {
|
||||
@ -1099,7 +1122,7 @@ function createTask(task) {
|
||||
function getCurrentUserRequest() {
|
||||
const numOutputsTotal = parseInt(numOutputsTotalField.value)
|
||||
const numOutputsParallel = parseInt(numOutputsParallelField.value)
|
||||
const seed = (randomSeedField.checked ? Math.floor(Math.random() * 10000000) : parseInt(seedField.value))
|
||||
const seed = (randomSeedField.checked ? Math.floor(Math.random() * (2**32 - 1)) : parseInt(seedField.value))
|
||||
|
||||
const newTask = {
|
||||
batchesDone: 0,
|
||||
@ -1287,13 +1310,15 @@ async function stopAllTasks() {
|
||||
|
||||
function updateInitialText() {
|
||||
if (document.querySelector('.imageTaskContainer') === null) {
|
||||
if (undoBuffer.length == 0) {
|
||||
previewTools.classList.add('displayNone')
|
||||
if (undoBuffer.length > 0) {
|
||||
initialText.prepend(undoButton)
|
||||
}
|
||||
previewTools.classList.add('displayNone')
|
||||
initialText.classList.remove('displayNone')
|
||||
} else {
|
||||
initialText.classList.add('displayNone')
|
||||
previewTools.classList.remove('displayNone')
|
||||
document.querySelector('div.display-settings').prepend(undoButton)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* @readonly
|
||||
* @enum {string}
|
||||
*/
|
||||
var ParameterType = {
|
||||
var ParameterType = {
|
||||
checkbox: "checkbox",
|
||||
select: "select",
|
||||
select_multiple: "select_multiple",
|
||||
@ -15,10 +15,13 @@
|
||||
* JSDoc style
|
||||
* @typedef {object} Parameter
|
||||
* @property {string} id
|
||||
* @property {ParameterType} type
|
||||
* @property {string} label
|
||||
* @property {?string} note
|
||||
* @property {keyof ParameterType} type
|
||||
* @property {string | (parameter: Parameter) => (HTMLElement | string)} label
|
||||
* @property {string | (parameter: Parameter) => (HTMLElement | string) | undefined} note
|
||||
* @property {(parameter: Parameter) => (HTMLElement | string) | undefined} render
|
||||
* @property {string | undefined} icon
|
||||
* @property {number|boolean|string} default
|
||||
* @property {boolean?} saveInAppConfig
|
||||
*/
|
||||
|
||||
|
||||
@ -118,6 +121,7 @@ var PARAMETERS = [
|
||||
note: "starts the default browser on startup",
|
||||
icon: "fa-window-restore",
|
||||
default: true,
|
||||
saveInAppConfig: true,
|
||||
},
|
||||
{
|
||||
id: "vram_usage_level",
|
||||
@ -179,6 +183,7 @@ var PARAMETERS = [
|
||||
note: "Other devices on your network can access this web page",
|
||||
icon: "fa-network-wired",
|
||||
default: true,
|
||||
saveInAppConfig: true,
|
||||
},
|
||||
{
|
||||
id: "listen_port",
|
||||
@ -188,7 +193,8 @@ var PARAMETERS = [
|
||||
icon: "fa-anchor",
|
||||
render: (parameter) => {
|
||||
return `<input id="${parameter.id}" name="${parameter.id}" size="6" value="9000" onkeypress="preventNonNumericalInput(event)">`
|
||||
}
|
||||
},
|
||||
saveInAppConfig: true,
|
||||
},
|
||||
{
|
||||
id: "use_beta_channel",
|
||||
@ -205,6 +211,7 @@ var PARAMETERS = [
|
||||
note: "<b>Experimental! Can have bugs!</b> Use upcoming features (like LoRA) in our new engine. Please press Save, then restart the program after changing this.",
|
||||
icon: "fa-bolt",
|
||||
default: false,
|
||||
saveInAppConfig: true,
|
||||
},
|
||||
];
|
||||
|
||||
@ -228,6 +235,10 @@ function sliderUpdate(event) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Parameter} parameter
|
||||
* @returns {string | HTMLElement}
|
||||
*/
|
||||
function getParameterElement(parameter) {
|
||||
switch (parameter.type) {
|
||||
case ParameterType.checkbox:
|
||||
@ -243,29 +254,74 @@ function getParameterElement(parameter) {
|
||||
case ParameterType.custom:
|
||||
return parameter.render(parameter)
|
||||
default:
|
||||
console.error(`Invalid type for parameter ${parameter.id}`);
|
||||
console.error(`Invalid type ${parameter.type} for parameter ${parameter.id}`);
|
||||
return "ERROR: Invalid Type"
|
||||
}
|
||||
}
|
||||
|
||||
let parametersTable = document.querySelector("#system-settings .parameters-table")
|
||||
/* fill in the system settings popup table */
|
||||
function initParameters() {
|
||||
PARAMETERS.forEach(parameter => {
|
||||
var element = getParameterElement(parameter)
|
||||
var note = parameter.note ? `<small>${parameter.note}</small>` : "";
|
||||
var icon = parameter.icon ? `<i class="fa ${parameter.icon}"></i>` : "";
|
||||
var newrow = document.createElement('div')
|
||||
newrow.innerHTML = `
|
||||
<div>${icon}</div>
|
||||
<div><label for="${parameter.id}">${parameter.label}</label>${note}</div>
|
||||
<div>${element}</div>`
|
||||
/**
|
||||
* fill in the system settings popup table
|
||||
* @param {Array<Parameter> | undefined} parameters
|
||||
* */
|
||||
function initParameters(parameters) {
|
||||
parameters.forEach(parameter => {
|
||||
const element = getParameterElement(parameter)
|
||||
const elementWrapper = createElement('div')
|
||||
if (element instanceof Node) {
|
||||
elementWrapper.appendChild(element)
|
||||
} else {
|
||||
elementWrapper.innerHTML = element
|
||||
}
|
||||
|
||||
const note = typeof parameter.note === 'function' ? parameter.note(parameter) : parameter.note
|
||||
const noteElements = []
|
||||
if (note) {
|
||||
const noteElement = createElement('small')
|
||||
if (note instanceof Node) {
|
||||
noteElement.appendChild(note)
|
||||
} else {
|
||||
noteElement.innerHTML = note || ''
|
||||
}
|
||||
noteElements.push(noteElement)
|
||||
}
|
||||
|
||||
const icon = parameter.icon ? [createElement('i', undefined, ['fa', parameter.icon])] : []
|
||||
|
||||
const label = typeof parameter.label === 'function' ? parameter.label(parameter) : parameter.label
|
||||
const labelElement = createElement('label', { for: parameter.id })
|
||||
if (label instanceof Node) {
|
||||
labelElement.appendChild(label)
|
||||
} else {
|
||||
labelElement.innerHTML = label
|
||||
}
|
||||
|
||||
const newrow = createElement(
|
||||
'div',
|
||||
{ 'data-setting-id': parameter.id, 'data-save-in-app-config': parameter.saveInAppConfig },
|
||||
undefined,
|
||||
[
|
||||
createElement('div', undefined, undefined, icon),
|
||||
createElement('div', undefined, undefined, [labelElement, ...noteElements]),
|
||||
elementWrapper,
|
||||
]
|
||||
)
|
||||
parametersTable.appendChild(newrow)
|
||||
parameter.settingsEntry = newrow
|
||||
})
|
||||
}
|
||||
|
||||
initParameters()
|
||||
initParameters(PARAMETERS)
|
||||
|
||||
// listen to parameters from plugins
|
||||
PARAMETERS.addEventListener('push', (...items) => {
|
||||
initParameters(items)
|
||||
|
||||
if (items.find(item => item.saveInAppConfig)) {
|
||||
console.log('Reloading app config for new parameters', items.map(p => p.id))
|
||||
getAppConfig()
|
||||
}
|
||||
})
|
||||
|
||||
let vramUsageLevelField = document.querySelector('#vram_usage_level')
|
||||
let useCPUField = document.querySelector('#use_cpu')
|
||||
@ -306,6 +362,9 @@ async function getAppConfig() {
|
||||
let res = await fetch('/get/app_config')
|
||||
const config = await res.json()
|
||||
|
||||
applySettingsFromConfig(config)
|
||||
|
||||
// custom overrides
|
||||
if (config.update_branch === 'beta') {
|
||||
useBetaChannelField.checked = true
|
||||
document.querySelector("#updateBranchLabel").innerText = "(beta)"
|
||||
@ -322,6 +381,7 @@ async function getAppConfig() {
|
||||
listenPortField.value = config.net.listen_port
|
||||
}
|
||||
if (config.test_diffusers === undefined || config.update_branch === 'main') {
|
||||
testDiffusers.checked = false
|
||||
document.querySelector("#lora_model_container").style.display = 'none'
|
||||
document.querySelector("#lora_alpha_container").style.display = 'none'
|
||||
} else {
|
||||
@ -331,11 +391,48 @@ async function getAppConfig() {
|
||||
}
|
||||
|
||||
console.log('get config status response', config)
|
||||
|
||||
return config
|
||||
} catch (e) {
|
||||
console.log('get config status error', e)
|
||||
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
function applySettingsFromConfig(config) {
|
||||
Array.from(parametersTable.children).forEach(parameterRow => {
|
||||
if (parameterRow.dataset.settingId in config && parameterRow.dataset.saveInAppConfig === 'true') {
|
||||
const configValue = config[parameterRow.dataset.settingId]
|
||||
const parameterElement = document.getElementById(parameterRow.dataset.settingId) ||
|
||||
parameterRow.querySelector('input') || parameterRow.querySelector('select')
|
||||
|
||||
switch (parameterElement?.tagName) {
|
||||
case 'INPUT':
|
||||
if (parameterElement.type === 'checkbox') {
|
||||
parameterElement.checked = configValue
|
||||
} else {
|
||||
parameterElement.value = configValue
|
||||
}
|
||||
parameterElement.dispatchEvent(new Event('change'))
|
||||
break
|
||||
case 'SELECT':
|
||||
if (Array.isArray(configValue)) {
|
||||
Array.from(parameterElement.options).forEach(option => {
|
||||
if (configValue.includes(option.value || option.text)) {
|
||||
option.selected = true
|
||||
}
|
||||
})
|
||||
} else {
|
||||
parameterElement.value = configValue
|
||||
}
|
||||
parameterElement.dispatchEvent(new Event('change'))
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
saveToDiskField.addEventListener('change', function(e) {
|
||||
diskPathField.disabled = !this.checked
|
||||
metadataOutputFormatField.disabled = !this.checked
|
||||
@ -492,16 +589,43 @@ saveSettingsBtn.addEventListener('click', function() {
|
||||
alert('The network port must be a number from 1 to 65535')
|
||||
return
|
||||
}
|
||||
let updateBranch = (useBetaChannelField.checked ? 'beta' : 'main')
|
||||
changeAppConfig({
|
||||
const updateBranch = (useBetaChannelField.checked ? 'beta' : 'main')
|
||||
|
||||
const updateAppConfigRequest = {
|
||||
'render_devices': getCurrentRenderDeviceSelection(),
|
||||
'update_branch': updateBranch,
|
||||
'ui_open_browser_on_start': uiOpenBrowserOnStartField.checked,
|
||||
'listen_to_network': listenToNetworkField.checked,
|
||||
'listen_port': listenPortField.value,
|
||||
'test_diffusers': testDiffusers.checked
|
||||
})
|
||||
saveSettingsBtn.classList.add('active')
|
||||
asyncDelay(300).then(() => saveSettingsBtn.classList.remove('active'))
|
||||
})
|
||||
}
|
||||
|
||||
Array.from(parametersTable.children).forEach(parameterRow => {
|
||||
if (parameterRow.dataset.saveInAppConfig === 'true') {
|
||||
const parameterElement = document.getElementById(parameterRow.dataset.settingId) ||
|
||||
parameterRow.querySelector('input') || parameterRow.querySelector('select')
|
||||
|
||||
switch (parameterElement?.tagName) {
|
||||
case 'INPUT':
|
||||
if (parameterElement.type === 'checkbox') {
|
||||
updateAppConfigRequest[parameterRow.dataset.settingId] = parameterElement.checked
|
||||
} else {
|
||||
updateAppConfigRequest[parameterRow.dataset.settingId] = parameterElement.value
|
||||
}
|
||||
break
|
||||
case 'SELECT':
|
||||
if (parameterElement.multiple) {
|
||||
updateAppConfigRequest[parameterRow.dataset.settingId] = Array.from(parameterElement.options)
|
||||
.filter(option => option.selected)
|
||||
.map(option => option.value || option.text)
|
||||
} else {
|
||||
updateAppConfigRequest[parameterRow.dataset.settingId] = parameterElement.value
|
||||
}
|
||||
break
|
||||
default:
|
||||
console.error(`Setting parameter ${parameterRow.dataset.settingId} couldn't be saved to app.config - element #${parameter.id} is a <${parameterElement?.tagName} /> instead of a <input /> or a <select />!`)
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const savePromise = changeAppConfig(updateAppConfigRequest)
|
||||
saveSettingsBtn.classList.add('active')
|
||||
Promise.all([savePromise, asyncDelay(300)]).then(() => saveSettingsBtn.classList.remove('active'))
|
||||
})
|
||||
|
@ -683,14 +683,16 @@ class ServiceContainer {
|
||||
* @param {string} tag
|
||||
* @param {object} attributes
|
||||
* @param {string | Array<string>} classes
|
||||
* @param {string | HTMLElement | Array<string | HTMLElement>}
|
||||
* @param {string | Node | Array<string | Node>}
|
||||
* @returns {HTMLElement}
|
||||
*/
|
||||
function createElement(tagName, attributes, classes, textOrElements) {
|
||||
const element = document.createElement(tagName)
|
||||
if (attributes) {
|
||||
Object.entries(attributes).forEach(([key, value]) => {
|
||||
element.setAttribute(key, value)
|
||||
if (value !== undefined && value !== null) {
|
||||
element.setAttribute(key, value)
|
||||
}
|
||||
});
|
||||
}
|
||||
if (classes) {
|
||||
@ -699,7 +701,7 @@ function createElement(tagName, attributes, classes, textOrElements) {
|
||||
if (textOrElements) {
|
||||
const children = Array.isArray(textOrElements) ? textOrElements : [textOrElements]
|
||||
children.forEach(textOrElem => {
|
||||
if (textOrElem instanceof HTMLElement) {
|
||||
if (textOrElem instanceof Node) {
|
||||
element.appendChild(textOrElem)
|
||||
} else {
|
||||
element.appendChild(document.createTextNode(textOrElem))
|
||||
@ -708,3 +710,19 @@ function createElement(tagName, attributes, classes, textOrElements) {
|
||||
}
|
||||
return element
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener for arrays
|
||||
* @param {keyof Array} method
|
||||
* @param {(args) => {}} callback
|
||||
*/
|
||||
Array.prototype.addEventListener = function(method, callback) {
|
||||
const originalFunction = this[method]
|
||||
if (originalFunction) {
|
||||
this[method] = function() {
|
||||
console.log(`Array.${method}()`, arguments)
|
||||
originalFunction.apply(this, arguments)
|
||||
callback.apply(this, arguments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user