Merge branch 'easydiffusion:beta' into beta

Update Branch
This commit is contained in:
ManInDark 2024-07-12 18:54:47 +02:00 committed by GitHub
commit ab547d10bf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 181 additions and 8 deletions

View File

@ -17,6 +17,8 @@
- **Major rewrite of the code** - We've switched to using diffusers under-the-hood, which allows us to release new features faster, and focus on making the UI and installer even easier to use.
### Detailed changelog
* 3.0.9 - 28 May 2024 - Slider for controlling the strength of controlnets.
* 3.0.8 - 27 May 2024 - SDXL ControlNets for Img2Img and Inpainting.
* 3.0.7 - 11 Dec 2023 - Setting to enable/disable VAE tiling (in the Image Settings panel). Sometimes VAE tiling reduces the quality of the image, so this setting will help control that.
* 3.0.6 - 18 Sep 2023 - Add thumbnails to embeddings from the UI, using the new `Upload Thumbnail` button in the Embeddings popup. Thanks @JeLuf.
* 3.0.6 - 15 Sep 2023 - Fix broken embeddings dialog when LoRA information couldn't be fetched.

View File

@ -15,13 +15,16 @@ import traceback
import shutil
from pathlib import Path
from pprint import pprint
import re
os_name = platform.system()
modules_to_check = {
"torch": ("1.11.0", "1.13.1", "2.0.0", "2.0.1"),
"torchvision": ("0.12.0", "0.14.1", "0.15.1", "0.15.2"),
"sdkit": "2.0.15",
"setuptools": "69.5.1",
# "sdkit": "2.0.15.6", # checked later
# "diffusers": "0.21.4", # checked later
"stable-diffusion-sdkit": "2.1.5",
"rich": "12.6.0",
"uvicorn": "0.19.0",
@ -32,7 +35,7 @@ modules_to_check = {
"python-multipart": "0.0.6",
# "xformers": "0.0.16",
}
modules_to_log = ["torch", "torchvision", "sdkit", "stable-diffusion-sdkit"]
modules_to_log = ["torch", "torchvision", "sdkit", "stable-diffusion-sdkit", "diffusers"]
def version(module_name: str) -> str:
@ -91,6 +94,14 @@ def update_modules():
allowed_versions, latest_version = get_allowed_versions(module_name, allowed_versions)
if module_name == "setuptools":
if os_name == "Windows":
allowed_versions = ("59.8.0",)
latest_version = "59.8.0"
else:
allowed_versions = ("69.0.0",)
latest_version = "69.0.0"
requires_install = False
if module_name in ("torch", "torchvision"):
if version(module_name) is None: # allow any torch version
@ -114,8 +125,110 @@ def update_modules():
f"WARNING! Tried to install {module_name}=={latest_version}, but the version is still {version(module_name)}!"
)
if module_name in modules_to_log:
print(f"{module_name}: {version(module_name)}")
# different sdkit versions, with the corresponding diffusers
# if sdkit is 2.0.15.x (or lower), then diffusers should be restricted to 0.21.4 (see below for the reason)
# otherwise use the current sdkit version (with the corresponding diffusers version)
expected_sdkit_version_str = "2.0.20.4"
expected_diffusers_version_str = "0.28.2"
legacy_sdkit_version_str = "2.0.15.7"
legacy_diffusers_version_str = "0.21.4"
sdkit_version_str = version("sdkit")
if sdkit_version_str is None: # first install
_install("sdkit", expected_sdkit_version_str)
_install("diffusers", expected_diffusers_version_str)
else:
sdkit_version = version_str_to_tuple(sdkit_version_str)
legacy_sdkit_version = version_str_to_tuple(legacy_sdkit_version_str)
if sdkit_version[:3] <= legacy_sdkit_version[:3]: # and torch_version < (0, 13):
# stick to diffusers 0.21.4, since it preserves torch 0.11+ compatibility.
# upgrading beyond this will result in a 2+ GB download of torch on older installations
# and a time-consuming chain of small package updates due to huggingface_hub upgrade.
# for now, the user will need to explicitly upgrade to a newer sdkit, to break this ceiling.
install_pkg_if_necessary("sdkit", legacy_sdkit_version_str)
install_pkg_if_necessary("diffusers", legacy_diffusers_version_str)
else:
torch_version = version_str_to_tuple(version("torch"))
if torch_version < (1, 13):
# install the gpu-compatible torch (if necessary), instead of the default CPU-only one
# from the diffusers dependency chain
install("torch", modules_to_check["torch"][-1])
install("torchvision", modules_to_check["torchvision"][-1])
install_pkg_if_necessary("sdkit", expected_sdkit_version_str)
install_pkg_if_necessary("diffusers", expected_diffusers_version_str)
# hotfix accelerate
accelerate_version = version("accelerate")
if accelerate_version is None:
install("accelerate", "0.23.0")
else:
accelerate_version = accelerate_version.split(".")
accelerate_version = tuple(map(int, accelerate_version))
if accelerate_version < (0, 23):
install("accelerate", "0.23.0")
# hotfix - 29 May 2024. sdkit has stopped pulling its dependencies for some reason
# temporarily dumping sdkit's requirements here:
if os_name != "Windows":
sdkit_deps = [
"gfpgan",
"piexif",
"realesrgan",
"requests",
"picklescan",
"safetensors==0.3.3",
"k-diffusion==0.0.12",
"compel==2.0.1",
"controlnet-aux==0.0.6",
"invisible-watermark==0.2.0", # required for SD XL
]
for mod in sdkit_deps:
mod_name = mod
mod_force_version_str = None
if "==" in mod:
mod_name, mod_force_version_str = mod.split("==")
curr_mod_version_str = version(mod_name)
if curr_mod_version_str is None:
_install(mod_name, mod_force_version_str)
elif mod_force_version_str is not None:
curr_mod_version = version_str_to_tuple(curr_mod_version_str)
mod_force_version = version_str_to_tuple(mod_force_version_str)
if curr_mod_version != mod_force_version:
_install(mod_name, mod_force_version_str)
for module_name in modules_to_log:
print(f"{module_name}: {version(module_name)}")
def _install(module_name, module_version=None):
if module_version is None:
install_cmd = f"python -m pip install {module_name}"
else:
install_cmd = f"python -m pip install --upgrade {module_name}=={module_version}"
print(">", install_cmd)
os.system(install_cmd)
def install_pkg_if_necessary(pkg_name, required_version):
pkg_version = version(pkg_name)
if pkg_version != required_version:
_install(pkg_name, required_version)
def version_str_to_tuple(ver_str):
ver_str = ver_str.split("+")[0]
ver_str = re.sub("[^0-9.]", "", ver_str)
ver = ver_str.split(".")
return tuple(map(int, ver))
### utilities
@ -302,8 +415,16 @@ def launch_uvicorn():
setup_amd_environment()
print("\nLaunching uvicorn\n")
os.system(
f'python -m uvicorn main:server_api --app-dir "{os.environ["SD_UI_PATH"]}" --port {listen_port} --host {bind_ip} --log-level error'
import uvicorn
uvicorn.run(
"main:server_api",
port=listen_port,
log_level="error",
app_dir=os.environ["SD_UI_PATH"],
host=bind_ip,
access_log=False,
)

View File

@ -243,7 +243,8 @@ def get_processor_name():
if platform.system() == "Windows":
return platform.processor()
elif platform.system() == "Darwin":
os.environ["PATH"] = os.environ["PATH"] + os.pathsep + "/usr/sbin"
if "/usr/sbin" not in os.environ["PATH"].split(os.pathsep):
os.environ["PATH"] = os.environ["PATH"] + os.pathsep + "/usr/sbin"
command = "sysctl -n machdep.cpu.brand_string"
return subprocess.check_output(command, shell=True).decode().strip()
elif platform.system() == "Linux":

View File

@ -31,6 +31,7 @@ TASK_TEXT_MAPPING = {
"clip_skip": "Clip Skip",
"use_controlnet_model": "ControlNet model",
"control_filter_to_apply": "ControlNet Filter",
"control_alpha": "ControlNet Strength",
"use_vae_model": "VAE model",
"sampler_name": "Sampler",
"width": "Width",

View File

@ -36,7 +36,7 @@
<h1>
<img id="logo_img" src="/media/images/icon-512x512.png" >
Easy Diffusion
<small><span id="version">v3.0.7</span> <span id="updateBranchLabel"></span></small>
<small><span id="version">v3.0.9</span> <span id="updateBranchLabel"></span></small>
</h1>
</div>
<div id="server-status">
@ -239,6 +239,8 @@
<label for="controlnet_model"><small>Model:</small></label> <input id="controlnet_model" type="text" spellcheck="false" autocomplete="off" class="model-filter" data-path="" />
<br/>
<label><small>Will download the necessary models, the first time.</small></label>
<br/>
<label for="controlnet_alpha_slider"><small>Strength:</small></label> <input id="controlnet_alpha_slider" name="controlnet_alpha_slider" class="editor-slider" value="10" type="range" min="0" max="10"> <input id="controlnet_alpha" name="controlnet_alpha" size="4" pattern="^[0-9\.]+$" onkeypress="preventNonNumericalInput(event)" inputmode="decimal">
</div>
</td>
</tr>

View File

@ -59,6 +59,7 @@ const SETTINGS_IDS_LIST = [
"embedding-card-size-selector",
"lora_model",
"enable_vae_tiling",
"controlnet_alpha",
]
const IGNORE_BY_DEFAULT = ["prompt"]

View File

@ -309,10 +309,21 @@ const TASK_MAPPING = {
readUI: () => controlImageFilterField.value,
parse: (val) => val,
},
control_alpha: {
name: "ControlNet Strength",
setUI: (control_alpha) => {
control_alpha = control_alpha || 1.0
controlAlphaField.value = control_alpha
updateControlAlphaSlider()
},
readUI: () => parseFloat(controlAlphaField.value),
parse: (val) => val === null ? 1.0 : parseFloat(val),
},
use_lora_model: {
name: "LoRA model",
setUI: (use_lora_model) => {
let modelPaths = []
use_lora_model = use_lora_model === null ? "" : use_lora_model
use_lora_model = Array.isArray(use_lora_model) ? use_lora_model : [use_lora_model]
use_lora_model.forEach((m) => {
if (m.includes("models\\lora\\")) {
@ -529,6 +540,11 @@ function restoreTaskToUI(task, fieldsToSkip) {
// listen for inpainter loading event, which happens AFTER the main image loads (which reloads the inpai
controlImagePreview.src = task.reqBody.control_image
}
if ("use_controlnet_model" in task.reqBody && task.reqBody.use_controlnet_model && !("control_alpha" in task.reqBody)) {
controlAlphaField.value = 1.0
updateControlAlphaSlider()
}
}
function readUI() {
const reqBody = {}
@ -587,6 +603,7 @@ const TASK_TEXT_MAPPING = {
lora_alpha: "LoRA Strength",
use_controlnet_model: "ControlNet model",
control_filter_to_apply: "ControlNet Filter",
control_alpha: "ControlNet Strength",
tiling: "Seamless Tiling",
}
function parseTaskFromText(str) {

View File

@ -51,6 +51,10 @@ const taskConfigSetup = {
preserve_init_image_color_profile: "Preserve Color Profile",
strict_mask_border: "Strict Mask Border",
use_controlnet_model: "ControlNet Model",
control_alpha: {
label: "ControlNet Strength",
visible: ({ reqBody }) => !!reqBody?.use_controlnet_model,
},
},
pluginTaskConfig: {},
getCSSKey: (key) =>
@ -99,6 +103,8 @@ let controlImagePreview = document.querySelector("#control_image_preview")
let controlImageClearBtn = document.querySelector(".control_image_clear")
let controlImageContainer = document.querySelector("#control_image_wrapper")
let controlImageFilterField = document.querySelector("#control_image_filter")
let controlAlphaSlider = document.querySelector("#controlnet_alpha_slider")
let controlAlphaField = document.querySelector("#controlnet_alpha")
let applyColorCorrectionField = document.querySelector("#apply_color_correction")
let strictMaskBorderField = document.querySelector("#strict_mask_border")
let colorCorrectionSetting = document.querySelector("#apply_color_correction_setting")
@ -1753,6 +1759,7 @@ function getCurrentUserRequest() {
if (controlnetModelField.value !== "" && IMAGE_REGEX.test(controlImagePreview.src)) {
newTask.reqBody.use_controlnet_model = controlnetModelField.value
newTask.reqBody.control_image = controlImagePreview.src
newTask.reqBody.control_alpha = parseFloat(controlAlphaField.value)
if (controlImageFilterField.value !== "") {
newTask.reqBody.control_filter_to_apply = controlImageFilterField.value
}
@ -2374,6 +2381,27 @@ function updateHypernetworkStrengthContainer() {
hypernetworkModelField.addEventListener("change", updateHypernetworkStrengthContainer)
updateHypernetworkStrengthContainer()
/********************* Controlnet Alpha **************************/
function updateControlAlpha() {
controlAlphaField.value = controlAlphaSlider.value / 10
controlAlphaField.dispatchEvent(new Event("change"))
}
function updateControlAlphaSlider() {
if (controlAlphaField.value < 0) {
controlAlphaField.value = 0
} else if (controlAlphaField.value > 10) {
controlAlphaField.value = 10
}
controlAlphaSlider.value = controlAlphaField.value * 10
controlAlphaSlider.dispatchEvent(new Event("change"))
}
controlAlphaSlider.addEventListener("input", updateControlAlpha)
controlAlphaField.addEventListener("input", updateControlAlphaSlider)
updateControlAlpha()
/********************* JPEG/WEBP Quality **********************/
function updateOutputQuality() {
outputQualityField.value = 0 | outputQualitySlider.value