From e33d093fa8772c0d94089dd39925b14acde9cd61 Mon Sep 17 00:00:00 2001 From: Divided by Zer0 Date: Tue, 4 Oct 2022 12:07:09 +0200 Subject: [PATCH] Added batch/shell script to explicitly start the stable horde bridge (#1413) So that people can start it from the file browser/explorer --- horde_bridge.cmd | 106 +++++++++++++++++++++++++++++ horde_bridge.sh | 169 +++++++++++++++++++++++++++++++++++++++++++++++ scripts/webui.py | 16 ++--- 3 files changed, 283 insertions(+), 8 deletions(-) create mode 100644 horde_bridge.cmd create mode 100644 horde_bridge.sh diff --git a/horde_bridge.cmd b/horde_bridge.cmd new file mode 100644 index 0000000..d592393 --- /dev/null +++ b/horde_bridge.cmd @@ -0,0 +1,106 @@ +@echo off +:: This file is part of stable-diffusion-webui (https://github.com/sd-webui/stable-diffusion-webui/). + +:: Copyright 2022 sd-webui team. +:: This program is free software: you can redistribute it and/or modify +:: it under the terms of the GNU Affero General Public License as published by +:: the Free Software Foundation, either version 3 of the License, or +:: (at your option) any later version. + +:: This program is distributed in the hope that it will be useful, +:: but WITHOUT ANY WARRANTY; without even the implied warranty of +:: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +:: GNU Affero General Public License for more details. + +:: You should have received a copy of the GNU Affero General Public License +:: along with this program. If not, see . +:: Run all commands using this script's directory as the working directory +cd %~dp0 + +:: copy over the first line from environment.yaml, e.g. name: ldm, and take the second word after splitting by ":" delimiter +for /F "tokens=2 delims=: " %%i in (environment.yaml) DO ( + set v_conda_env_name=%%i + goto EOL +) +:EOL + +echo Environment name is set as %v_conda_env_name% as per environment.yaml + +:: Put the path to conda directory in a file called "custom-conda-path.txt" if it's installed at non-standard path +IF EXIST custom-conda-path.txt ( + FOR /F %%i IN (custom-conda-path.txt) DO set v_custom_path=%%i +) + +set v_paths=%ProgramData%\miniconda3 +set v_paths=%v_paths%;%USERPROFILE%\miniconda3 +set v_paths=%v_paths%;%ProgramData%\anaconda3 +set v_paths=%v_paths%;%USERPROFILE%\anaconda3 + +for %%a in (%v_paths%) do ( + IF NOT "%v_custom_path%"=="" ( + set v_paths=%v_custom_path%;%v_paths% + ) +) + +for %%a in (%v_paths%) do ( + if EXIST "%%a\Scripts\activate.bat" ( + SET v_conda_path=%%a + echo anaconda3/miniconda3 detected in %%a + goto :CONDA_FOUND + ) +) + +IF "%v_conda_path%"=="" ( + echo anaconda3/miniconda3 not found. Install from here https://docs.conda.io/en/latest/miniconda.html + pause + exit /b 1 +) + +:CONDA_FOUND +echo Stashing local changes and pulling latest update... +call git stash +call git pull +set /P restore="Do you want to restore changes you made before updating? (Y/N): " +IF /I "%restore%" == "N" ( + echo Removing changes please wait... + call git stash drop + echo Changes removed, press any key to continue... + pause >nul +) ELSE IF /I "%restore%" == "Y" ( + echo Restoring changes, please wait... + call git stash pop --quiet + echo Changes restored, press any key to continue... + pause >nul +) +call "%v_conda_path%\Scripts\activate.bat" + +for /f "delims=" %%a in ('git log -1 --format^="%%H" -- environment.yaml') DO set v_cur_hash=%%a +set /p "v_last_hash="<"z_version_env.tmp" +echo %v_cur_hash%>z_version_env.tmp + +echo Current environment.yaml hash: %v_cur_hash% +echo Previous environment.yaml hash: %v_last_hash% + +if "%v_last_hash%" == "%v_cur_hash%" ( + echo environment.yaml unchanged. dependencies should be up to date. + echo if you still have unresolved dependencies, delete "z_version_env.tmp" +) else ( + echo environment.yaml changed. updating dependencies + call conda env create --name "%v_conda_env_name%" -f environment.yaml + call conda env update --name "%v_conda_env_name%" -f environment.yaml +) + + +call "%v_conda_path%\Scripts\activate.bat" "%v_conda_env_name%" + +:PROMPT +set SETUPTOOLS_USE_DISTUTILS=stdlib +IF EXIST "models\ldm\stable-diffusion-v1\model.ckpt" ( + set "PYTHONPATH=%~dp0" + python scripts\relauncher.py --bridge -v %* +) ELSE ( + echo Your model file does not exist! Place it in 'models\ldm\stable-diffusion-v1' with the name 'model.ckpt'. + pause +) + +::cmd /k diff --git a/horde_bridge.sh b/horde_bridge.sh new file mode 100644 index 0000000..7d77b77 --- /dev/null +++ b/horde_bridge.sh @@ -0,0 +1,169 @@ +#!/bin/bash -i +# This file is part of stable-diffusion-webui (https://github.com/sd-webui/stable-diffusion-webui/). + +# Copyright 2022 sd-webui team. +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# Start the Stable Diffusion WebUI for Linux Users + +DIRECTORY="." +ENV_FILE="environment.yaml" +ENV_NAME="ldm" +ENV_MODIFIED=$(date -r $ENV_FILE "+%s") +ENV_MODIFED_FILE=".env_updated" +ENV_UPDATED=0 + +# Models used for upscaling +GFPGAN_MODEL="https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3.pth" +LATENT_DIFFUSION_REPO="https://github.com/devilismyfriend/latent-diffusion.git" +LSDR_CONFIG="https://heibox.uni-heidelberg.de/f/31a76b13ea27482981b4/?dl=1" +LSDR_MODEL="https://heibox.uni-heidelberg.de/f/578df07c8fc04ffbadf3/?dl=1" +REALESRGAN_MODEL="https://github.com/xinntao/Real-ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth" +REALESRGAN_ANIME_MODEL="https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth" +SD_CONCEPT_REPO="https://github.com/sd-webui/sd-concepts-library/archive/refs/heads/main.zip" + + +if [[ -f $ENV_MODIFED_FILE ]]; then + ENV_MODIFIED_CACHED=$(<${ENV_MODIFED_FILE}) +else + ENV_MODIFIED_CACHED=0 +fi + +# Setup the Conda env for the project. This will also handle updating the env as needed too. +conda_env_setup () { + # Set conda path if it is not already in default environment + CUSTOM_CONDA_PATH= + + # Allow setting custom path via file to allow updates of this script without undoing custom path + if [ -f custom-conda-path.txt ]; then + CUSTOM_CONDA_PATH=$(cat custom-conda-path.txt) + fi + + # If custom path is set above, try to setup conda environment + if [ -f "${CUSTOM_CONDA_PATH}/etc/profile.d/conda.sh" ]; then + . "${CUSTOM_CONDA_PATH}/etc/profile.d/conda.sh" + elif [ -n "${CUSTOM_CONDA_PATH}" ] && [ -f "${CUSTOM_CONDA_PATH}/bin" ]; then + export PATH="${CUSTOM_CONDA_PATH}/bin:$PATH" + fi + + if ! command -v conda >/dev/null; then + printf "Anaconda3 not found. Install from here https://www.anaconda.com/products/distribution\n" + exit 1 + fi + + # Create/update conda env if needed + if ! conda env list | grep ".*${ENV_NAME}.*" >/dev/null 2>&1; then + printf "Could not find conda env: ${ENV_NAME} ... creating ... \n\n" + conda env create -f $ENV_FILE + ENV_UPDATED=1 + elif [[ ! -z $CONDA_FORCE_UPDATE && $CONDA_FORCE_UPDATE == "true" ]] || (( $ENV_MODIFIED > $ENV_MODIFIED_CACHED )); then + printf "Updating conda env: ${ENV_NAME} ...\n\n" + PIP_EXISTS_ACTION=w conda env update --file $ENV_FILE --prune + ENV_UPDATED=1 + fi + + # Clear artifacts from conda after create/update + if (( $ENV_UPDATED > 0 )); then + conda clean --all + echo -n $ENV_MODIFIED > $ENV_MODIFED_FILE + fi +} + +# Activate conda environment +conda_env_activation () { + conda activate $ENV_NAME + conda info | grep active +} + +# Check to see if the SD model already exists, if not then it creates it and prompts the user to add the SD AI models to the repo directory +sd_model_loading () { + if [ -f "$DIRECTORY/models/ldm/stable-diffusion-v1/model.ckpt" ]; then + printf "AI Model already in place. Continuing...\n\n" + else + printf "\n\n########## MOVE MODEL FILE ##########\n\n" + printf "Please download the 1.4 AI Model from Huggingface (or another source) and place it inside of the stable-diffusion-webui folder\n\n" + read -p "Once you have sd-v1-4.ckpt in the project root, Press Enter...\n\n" + + # Check to make sure checksum of models is the original one from HuggingFace and not a fake model set + printf "fe4efff1e174c627256e44ec2991ba279b3816e364b49f9be2abc0b3ff3f8556 sd-v1-4.ckpt" | sha256sum --check || exit 1 + mv sd-v1-4.ckpt $DIRECTORY/models/ldm/stable-diffusion-v1/model.ckpt + rm -r ./Models + fi +} + +# Checks to see if the upscaling models exist in their correct locations. If they do not they will be downloaded as required +post_processor_model_loading () { + # Check to see if GFPGAN has been added yet, if not it will download it and place it in the proper directory + if [ -f "$DIRECTORY/src/gfpgan/experiments/pretrained_models/GFPGANv1.3.pth" ]; then + printf "GFPGAN already exists. Continuing...\n\n" + else + printf "Downloading GFPGAN model. Please wait...\n" + wget $GFPGAN_MODEL -P $DIRECTORY/src/gfpgan/experiments/pretrained_models + fi + + # Check to see if realESRGAN has been added yet, if not it will download it and place it in the proper directory + if [ -f "$DIRECTORY/src/realesrgan/experiments/pretrained_models/RealESRGAN_x4plus.pth" ]; then + printf "realESRGAN already exists. Continuing...\n\n" + else + printf "Downloading realESRGAN model. Please wait...\n" + wget $REALESRGAN_MODEL -P $DIRECTORY/src/realesrgan/experiments/pretrained_models + wget $REALESRGAN_ANIME_MODEL -P $DIRECTORY/src/realesrgan/experiments/pretrained_models + fi + + # Check to see if LDSR has been added yet, if not it will be cloned and its models downloaded to the correct directory + if [ -f "$DIRECTORY/src/latent-diffusion/experiments/pretrained_models/model.ckpt" ]; then + printf "LDSR already exists. Continuing...\n\n" + else + printf "Cloning LDSR and downloading model. Please wait...\n" + git clone $LATENT_DIFFUSION_REPO + mv latent-diffusion $DIRECTORY/src/latent-diffusion + mkdir $DIRECTORY/src/latent-diffusion/experiments + mkdir $DIRECTORY/src/latent-diffusion/experiments/pretrained_models + wget $LSDR_CONFIG -P $DIRECTORY/src/latent-diffusion/experiments/pretrained_models + mv $DIRECTORY/src/latent-diffusion/experiments/pretrained_models/index.html?dl=1 $DIRECTORY/src/latent-diffusion/experiments/pretrained_models/project.yaml + wget $LSDR_MODEL -P $DIRECTORY/src/latent-diffusion/experiments/pretrained_models + mv $DIRECTORY/src/latent-diffusion/experiments/pretrained_models/index.html?dl=1 $DIRECTORY/src/latent-diffusion/experiments/pretrained_models/model.ckpt + fi + + # Check to see if SD Concepts has been added yet, if not it will download it and place it in the proper directory + if [ -d "$DIRECTORY/models/custom/sd-concepts-library" ]; then + printf "SD Concepts Library already exists. Continuing...\n\n" + else + printf "Downloading and Extracting SD Concepts Library model. Please wait...\n" + mkdir $DIRECTORY/models/custom + wget $SD_CONCEPT_REPO + if ! command -v unzip &> /dev/null + then + printf "Warning: unzip could not be found. \nPlease install 'unzip' from your package manager and rerun this program.\n" + exit 1 + fi + unzip main.zip + mv sd-concepts-library-main/sd-concepts-library $DIRECTORY/models/custom + fi +} + +# Function to initialize the other functions +start_initialization () { + conda_env_setup + sd_model_loading + post_processor_model_loading + conda_env_activation + if [ ! -e "models/ldm/stable-diffusion-v1/model.ckpt" ]; then + echo "Your model file does not exist! Place it in 'models/ldm/stable-diffusion-v1' with the name 'model.ckpt'." + exit 1 + fi + printf "\nStarting Stable Horde Bridg: Please Wait...\n"; python scripts/relauncher.py --bridge -v "$@"; break;; + +} + +start_initialization "$@" \ No newline at end of file diff --git a/scripts/webui.py b/scripts/webui.py index c090180..8e3f56f 100644 --- a/scripts/webui.py +++ b/scripts/webui.py @@ -2654,6 +2654,14 @@ def run_bridge(interval, api_key, horde_name, horde_url, priority_usernames, hor current_payload = None loop_retry = 0 while True: + if loop_retry > 10 and current_id: + logger.error(f"Exceeded retry count {loop_retry} for generation id {current_id}. Aborting generation!") + current_id = None + current_payload = None + current_generation = None + loop_retry = 0 + elif current_id: + logger.debug(f"Retrying ({loop_retry}/10) for generation id {current_id}...") gen_dict = { "name": horde_name, "max_pixels": horde_max_pixels, @@ -2754,14 +2762,6 @@ def run_bridge(interval, api_key, horde_name, horde_url, priority_usernames, hor logger.warning(f"Server {horde_url} unavailable during submit. Waiting 10 seconds... (Retry {loop_retry}/10)") time.sleep(10) continue - if loop_retry > 10 and current_id: - logger.error(f"Exceeded retry count {loop_retry} for generation id {current_id}. Aborting generation!") - current_id = None - current_payload = None - current_generation = None - loop_retry = 0 - elif current_id: - logger.debug(f"Retrying ({loop_retry}/10) for generation id {current_id}...") time.sleep(interval)