mirror of
https://github.com/easydiffusion/easydiffusion.git
synced 2025-06-21 02:18:24 +02:00
Merge branch 'beta' into bucketlite
This commit is contained in:
commit
c1bb7dc119
@ -5,10 +5,10 @@ If you haven't downloaded Stable Diffusion UI yet, please download from https://
|
|||||||
After downloading, to install please follow these instructions:
|
After downloading, to install please follow these instructions:
|
||||||
|
|
||||||
For Windows:
|
For Windows:
|
||||||
- Please double-click the "Start Stable Diffusion UI.cmd" file inside the "stable-diffusion-ui" folder.
|
- Please double-click the "Easy-Diffusion-Windows.exe" file and follow the instructions.
|
||||||
|
|
||||||
For Linux:
|
For Linux:
|
||||||
- Please open a terminal, and go to the "stable-diffusion-ui" directory. Then run ./start.sh
|
- Please open a terminal, unzip the Easy-Diffusion-Linux.zip file and go to the "easy-diffusion" directory. Then run ./start.sh
|
||||||
|
|
||||||
That file will automatically install everything. After that it will start the Stable Diffusion interface in a web browser.
|
That file will automatically install everything. After that it will start the Stable Diffusion interface in a web browser.
|
||||||
|
|
||||||
@ -21,4 +21,4 @@ If you have any problems, please:
|
|||||||
3. Or, file an issue at https://github.com/easydiffusion/easydiffusion/issues
|
3. Or, file an issue at https://github.com/easydiffusion/easydiffusion/issues
|
||||||
|
|
||||||
Thanks
|
Thanks
|
||||||
cmdr2 (and contributors to the project)
|
cmdr2 (and contributors to the project)
|
||||||
|
16
README.md
16
README.md
@ -11,9 +11,9 @@ Does not require technical knowledge, does not require pre-installed software. 1
|
|||||||
Click the download button for your operating system:
|
Click the download button for your operating system:
|
||||||
|
|
||||||
<p float="left">
|
<p float="left">
|
||||||
<a href="https://github.com/easydiffusion/easydiffusion/releases/download/v2.5.24/Easy-Diffusion-Windows.exe"><img src="https://github.com/easydiffusion/easydiffusion/raw/main/media/download-win.png" width="200" /></a>
|
<a href="https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.5.41a/Easy-Diffusion-Windows.exe"><img src="https://github.com/cmdr2/stable-diffusion-ui/raw/main/media/download-win.png" width="200" /></a>
|
||||||
<a href="https://github.com/easydiffusion/easydiffusion/releases/download/v2.5.24/Easy-Diffusion-Linux.zip"><img src="https://github.com/easydiffusion/easydiffusion/raw/main/media/download-linux.png" width="200" /></a>
|
<a href="https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.5.41a/Easy-Diffusion-Linux.zip"><img src="https://github.com/cmdr2/stable-diffusion-ui/raw/main/media/download-linux.png" width="200" /></a>
|
||||||
<a href="https://github.com/easydiffusion/easydiffusion/releases/download/v2.5.24/Easy-Diffusion-Mac.zip"><img src="https://github.com/easydiffusion/easydiffusion/raw/main/media/download-mac.png" width="200" /></a>
|
<a href="https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.5.41a/Easy-Diffusion-Mac.zip"><img src="https://github.com/cmdr2/stable-diffusion-ui/raw/main/media/download-mac.png" width="200" /></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
**Hardware requirements:**
|
**Hardware requirements:**
|
||||||
@ -23,6 +23,7 @@ Click the download button for your operating system:
|
|||||||
- Minimum 8 GB of system RAM.
|
- Minimum 8 GB of system RAM.
|
||||||
- Atleast 25 GB of space on the hard disk.
|
- Atleast 25 GB of space on the hard disk.
|
||||||
|
|
||||||
|
|
||||||
The installer will take care of whatever is needed. If you face any problems, you can join the friendly [Discord community](https://discord.com/invite/u9yhsFmEkB) and ask for assistance.
|
The installer will take care of whatever is needed. If you face any problems, you can join the friendly [Discord community](https://discord.com/invite/u9yhsFmEkB) and ask for assistance.
|
||||||
|
|
||||||
## On Windows:
|
## On Windows:
|
||||||
@ -132,6 +133,15 @@ We could really use help on these aspects (click to view tasks that need your he
|
|||||||
|
|
||||||
If you have any code contributions in mind, please feel free to say Hi to us on the [discord server](https://discord.com/invite/u9yhsFmEkB). We use the Discord server for development-related discussions, and for helping users.
|
If you have any code contributions in mind, please feel free to say Hi to us on the [discord server](https://discord.com/invite/u9yhsFmEkB). We use the Discord server for development-related discussions, and for helping users.
|
||||||
|
|
||||||
|
# Credits
|
||||||
|
* Stable Diffusion: https://github.com/Stability-AI/stablediffusion
|
||||||
|
* CodeFormer: https://github.com/sczhou/CodeFormer (license: https://github.com/sczhou/CodeFormer/blob/master/LICENSE)
|
||||||
|
* GFPGAN: https://github.com/TencentARC/GFPGAN
|
||||||
|
* RealESRGAN: https://github.com/xinntao/Real-ESRGAN
|
||||||
|
* k-diffusion: https://github.com/crowsonkb/k-diffusion
|
||||||
|
* Code contributors and artists on the cmdr2 UI: https://github.com/cmdr2/stable-diffusion-ui and Discord (https://discord.com/invite/u9yhsFmEkB)
|
||||||
|
* Lots of contributors on the internet
|
||||||
|
|
||||||
# Disclaimer
|
# Disclaimer
|
||||||
The authors of this project are not responsible for any content generated using this interface.
|
The authors of this project are not responsible for any content generated using this interface.
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ os_name = platform.system()
|
|||||||
modules_to_check = {
|
modules_to_check = {
|
||||||
"torch": ("1.11.0", "1.13.1", "2.0.0"),
|
"torch": ("1.11.0", "1.13.1", "2.0.0"),
|
||||||
"torchvision": ("0.12.0", "0.14.1", "0.15.1"),
|
"torchvision": ("0.12.0", "0.14.1", "0.15.1"),
|
||||||
"sdkit": "1.0.156",
|
"sdkit": "1.0.165",
|
||||||
"stable-diffusion-sdkit": "2.1.4",
|
"stable-diffusion-sdkit": "2.1.4",
|
||||||
"rich": "12.6.0",
|
"rich": "12.6.0",
|
||||||
"uvicorn": "0.19.0",
|
"uvicorn": "0.19.0",
|
||||||
|
@ -148,7 +148,7 @@ def reload_models_if_necessary(context: Context, models_data: ModelsData, models
|
|||||||
models_to_reload = {
|
models_to_reload = {
|
||||||
model_type: path
|
model_type: path
|
||||||
for model_type, path in models_data.model_paths.items()
|
for model_type, path in models_data.model_paths.items()
|
||||||
if context.model_paths.get(model_type) != path
|
if context.model_paths.get(model_type) != path or (path is not None and context.models.get(model_type) is None)
|
||||||
}
|
}
|
||||||
|
|
||||||
if models_data.model_paths.get("codeformer"):
|
if models_data.model_paths.get("codeformer"):
|
||||||
|
@ -15,6 +15,7 @@ from sdkit.utils import (
|
|||||||
img_to_base64_str,
|
img_to_base64_str,
|
||||||
img_to_buffer,
|
img_to_buffer,
|
||||||
latent_samples_to_images,
|
latent_samples_to_images,
|
||||||
|
log,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .task import Task
|
from .task import Task
|
||||||
@ -93,15 +94,27 @@ class RenderTask(Task):
|
|||||||
return model["params"].get(param_name) != new_val
|
return model["params"].get(param_name) != new_val
|
||||||
|
|
||||||
def trt_needs_reload(self, context):
|
def trt_needs_reload(self, context):
|
||||||
if not self.has_param_changed(context, "convert_to_tensorrt"):
|
if not context.test_diffusers:
|
||||||
return False
|
return False
|
||||||
|
if "stable-diffusion" not in context.models or "params" not in context.models["stable-diffusion"]:
|
||||||
|
return True
|
||||||
|
|
||||||
model = context.models["stable-diffusion"]
|
model = context.models["stable-diffusion"]
|
||||||
pipe = model["default"]
|
|
||||||
if hasattr(pipe.unet, "_allocate_trt_buffers"): # TRT already loaded
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
# curr_convert_to_trt = model["params"].get("convert_to_tensorrt")
|
||||||
|
new_convert_to_trt = self.models_data.model_params.get("stable-diffusion", {}).get("convert_to_tensorrt", False)
|
||||||
|
|
||||||
|
pipe = model["default"]
|
||||||
|
is_trt_loaded = hasattr(pipe.unet, "_allocate_trt_buffers") or hasattr(
|
||||||
|
pipe.unet, "_allocate_trt_buffers_backup"
|
||||||
|
)
|
||||||
|
if new_convert_to_trt and not is_trt_loaded:
|
||||||
|
return True
|
||||||
|
|
||||||
|
curr_build_config = model["params"].get("trt_build_config")
|
||||||
|
new_build_config = self.models_data.model_params.get("stable-diffusion", {}).get("trt_build_config", {})
|
||||||
|
|
||||||
|
return new_convert_to_trt and curr_build_config != new_build_config
|
||||||
|
|
||||||
|
|
||||||
def make_images(
|
def make_images(
|
||||||
@ -210,17 +223,29 @@ def generate_images_internal(
|
|||||||
if req.init_image is not None and not context.test_diffusers:
|
if req.init_image is not None and not context.test_diffusers:
|
||||||
req.sampler_name = "ddim"
|
req.sampler_name = "ddim"
|
||||||
|
|
||||||
|
req.width, req.height = map(lambda x: x - x % 8, (req.width, req.height)) # clamp to 8
|
||||||
|
|
||||||
if req.control_image and task_data.control_filter_to_apply:
|
if req.control_image and task_data.control_filter_to_apply:
|
||||||
req.control_image = filter_images(context, req.control_image, task_data.control_filter_to_apply)[0]
|
req.control_image = filter_images(context, req.control_image, task_data.control_filter_to_apply)[0]
|
||||||
|
|
||||||
if context.test_diffusers:
|
if context.test_diffusers:
|
||||||
pipe = context.models["stable-diffusion"]["default"]
|
pipe = context.models["stable-diffusion"]["default"]
|
||||||
|
if hasattr(pipe.unet, "_allocate_trt_buffers_backup"):
|
||||||
|
setattr(pipe.unet, "_allocate_trt_buffers", pipe.unet._allocate_trt_buffers_backup)
|
||||||
|
delattr(pipe.unet, "_allocate_trt_buffers_backup")
|
||||||
|
|
||||||
if hasattr(pipe.unet, "_allocate_trt_buffers"):
|
if hasattr(pipe.unet, "_allocate_trt_buffers"):
|
||||||
convert_to_trt = models_data.model_params["stable-diffusion"].get("convert_to_tensorrt", False)
|
convert_to_trt = models_data.model_params["stable-diffusion"].get("convert_to_tensorrt", False)
|
||||||
pipe.unet.forward = pipe.unet._trt_forward if convert_to_trt else pipe.unet._non_trt_forward
|
if convert_to_trt:
|
||||||
# pipe.vae.decoder.forward = (
|
pipe.unet.forward = pipe.unet._trt_forward
|
||||||
# pipe.vae.decoder._trt_forward if convert_to_trt else pipe.vae.decoder._non_trt_forward
|
# pipe.vae.decoder.forward = pipe.vae.decoder._trt_forward
|
||||||
# )
|
log.info(f"Setting unet.forward to TensorRT")
|
||||||
|
else:
|
||||||
|
log.info(f"Not using TensorRT for unet.forward")
|
||||||
|
pipe.unet.forward = pipe.unet._non_trt_forward
|
||||||
|
# pipe.vae.decoder.forward = pipe.vae.decoder._non_trt_forward
|
||||||
|
setattr(pipe.unet, "_allocate_trt_buffers_backup", pipe.unet._allocate_trt_buffers)
|
||||||
|
delattr(pipe.unet, "_allocate_trt_buffers")
|
||||||
|
|
||||||
images = generate_images(context, callback=callback, **req.dict())
|
images = generate_images(context, callback=callback, **req.dict())
|
||||||
user_stopped = False
|
user_stopped = False
|
||||||
|
@ -226,6 +226,9 @@ def convert_legacy_render_req_to_new(old_req: dict):
|
|||||||
model_params["stable-diffusion"] = {
|
model_params["stable-diffusion"] = {
|
||||||
"clip_skip": bool(old_req.get("clip_skip", False)),
|
"clip_skip": bool(old_req.get("clip_skip", False)),
|
||||||
"convert_to_tensorrt": bool(old_req.get("convert_to_tensorrt", False)),
|
"convert_to_tensorrt": bool(old_req.get("convert_to_tensorrt", False)),
|
||||||
|
"trt_build_config": old_req.get(
|
||||||
|
"trt_build_config", {"batch_size_range": (1, 1), "dimensions_range": [(768, 1024)]}
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
# move the filter params
|
# move the filter params
|
||||||
|
@ -21,6 +21,8 @@ TASK_TEXT_MAPPING = {
|
|||||||
"seed": "Seed",
|
"seed": "Seed",
|
||||||
"use_stable_diffusion_model": "Stable Diffusion model",
|
"use_stable_diffusion_model": "Stable Diffusion model",
|
||||||
"clip_skip": "Clip Skip",
|
"clip_skip": "Clip Skip",
|
||||||
|
"use_controlnet_model": "ControlNet model",
|
||||||
|
"control_filter_to_apply": "ControlNet Filter",
|
||||||
"use_vae_model": "VAE model",
|
"use_vae_model": "VAE model",
|
||||||
"sampler_name": "Sampler",
|
"sampler_name": "Sampler",
|
||||||
"width": "Width",
|
"width": "Width",
|
||||||
@ -260,10 +262,12 @@ def get_printable_request(req: GenerateImageRequest, task_data: TaskData, output
|
|||||||
del metadata["lora_alpha"]
|
del metadata["lora_alpha"]
|
||||||
if task_data.use_upscale != "latent_upscaler" and "latent_upscaler_steps" in metadata:
|
if task_data.use_upscale != "latent_upscaler" and "latent_upscaler_steps" in metadata:
|
||||||
del metadata["latent_upscaler_steps"]
|
del metadata["latent_upscaler_steps"]
|
||||||
|
if task_data.use_controlnet_model is None and "control_filter_to_apply" in metadata:
|
||||||
|
del metadata["control_filter_to_apply"]
|
||||||
|
|
||||||
if not using_diffusers:
|
if not using_diffusers:
|
||||||
for key in (
|
for key in (
|
||||||
x for x in ["use_lora_model", "lora_alpha", "clip_skip", "tiling", "latent_upscaler_steps"] if x in metadata
|
x for x in ["use_lora_model", "lora_alpha", "clip_skip", "tiling", "latent_upscaler_steps", "use_controlnet_model", "control_filter_to_apply"] if x in metadata
|
||||||
):
|
):
|
||||||
del metadata[key]
|
del metadata[key]
|
||||||
|
|
||||||
|
113
ui/index.html
113
ui/index.html
@ -163,60 +163,63 @@
|
|||||||
<a href="https://github.com/easydiffusion/easydiffusion/wiki/Clip-Skip" target="_blank"><i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip top-left">Click to learn more about Clip Skip</span></i></a>
|
<a href="https://github.com/easydiffusion/easydiffusion/wiki/Clip-Skip" target="_blank"><i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip top-left">Click to learn more about Clip Skip</span></i></a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr id="controlnet_model_container" class="pl-5"><td><label for="controlnet_model">ControlNet Image:</label></td><td>
|
<tr id="controlnet_model_container" class="pl-5">
|
||||||
<div id="control_image_wrapper" class="preview_image_wrapper">
|
<td><label for="controlnet_model">ControlNet Image:</label></td>
|
||||||
<img id="control_image_preview" class="image_preview" src="" crossorigin="anonymous" />
|
<td class="diffusers-restart-needed">
|
||||||
<span id="control_image_size_box" class="img_bottom_label"></span>
|
<div id="control_image_wrapper" class="preview_image_wrapper">
|
||||||
<button class="control_image_clear image_clear_btn"><i class="fa-solid fa-xmark"></i></button>
|
<img id="control_image_preview" class="image_preview" src="" crossorigin="anonymous" />
|
||||||
</div>
|
<span id="control_image_size_box" class="img_bottom_label"></span>
|
||||||
<input id="control_image" name="control_image" type="file" />
|
<button class="control_image_clear image_clear_btn"><i class="fa-solid fa-xmark"></i></button>
|
||||||
<a href="https://github.com/easydiffusion/easydiffusion/wiki/ControlNet" target="_blank"><i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip top-left">Click to learn more about ControlNets</span></i></a>
|
</div>
|
||||||
<div id="controlnet_config" class="displayNone">
|
<input id="control_image" name="control_image" type="file" />
|
||||||
<label><small>Filter to apply:</small></label>
|
<a href="https://github.com/easydiffusion/easydiffusion/wiki/ControlNet" target="_blank"><i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip top-left">Click to learn more about ControlNets</span></i></a>
|
||||||
<select id="control_image_filter">
|
<div id="controlnet_config" class="displayNone">
|
||||||
<option value="">None</option>
|
<label><small>Filter to apply:</small></label>
|
||||||
<optgroup label="Pose">
|
<select id="control_image_filter">
|
||||||
<option value="openpose">OpenPose (*)</option>
|
<option value="">None</option>
|
||||||
<option value="openpose_face">OpenPose face</option>
|
<optgroup label="Pose">
|
||||||
<option value="openpose_faceonly">OpenPose face-only</option>
|
<option value="openpose">OpenPose (*)</option>
|
||||||
<option value="openpose_hand">OpenPose hand</option>
|
<option value="openpose_face">OpenPose face</option>
|
||||||
<option value="openpose_full">OpenPose full</option>
|
<option value="openpose_faceonly">OpenPose face-only</option>
|
||||||
</optgroup>
|
<option value="openpose_hand">OpenPose hand</option>
|
||||||
<optgroup label="Outline">
|
<option value="openpose_full">OpenPose full</option>
|
||||||
<option value="canny">Canny (*)</option>
|
</optgroup>
|
||||||
<option value="mlsd">Straight lines</option>
|
<optgroup label="Outline">
|
||||||
<option value="scribble_hed">Scribble hed (*)</option>
|
<option value="canny">Canny (*)</option>
|
||||||
<option value="scribble_hedsafe">Scribble hedsafe</option>
|
<option value="mlsd">Straight lines</option>
|
||||||
<option value="scribble_pidinet">Scribble pidinet</option>
|
<option value="scribble_hed">Scribble hed (*)</option>
|
||||||
<option value="scribble_pidsafe">Scribble pidsafe</option>
|
<option value="scribble_hedsafe">Scribble hedsafe</option>
|
||||||
<option value="softedge_hed">Softedge hed</option>
|
<option value="scribble_pidinet">Scribble pidinet</option>
|
||||||
<option value="softedge_hedsafe">Softedge hedsafe</option>
|
<option value="scribble_pidsafe">Scribble pidsafe</option>
|
||||||
<option value="softedge_pidinet">Softedge pidinet</option>
|
<option value="softedge_hed">Softedge hed</option>
|
||||||
<option value="softedge_pidsafe">Softedge pidsafe</option>
|
<option value="softedge_hedsafe">Softedge hedsafe</option>
|
||||||
</optgroup>
|
<option value="softedge_pidinet">Softedge pidinet</option>
|
||||||
<optgroup label="Depth">
|
<option value="softedge_pidsafe">Softedge pidsafe</option>
|
||||||
<option value="normal_bae">Normal bae (*)</option>
|
</optgroup>
|
||||||
<option value="depth_midas">Depth midas</option>
|
<optgroup label="Depth">
|
||||||
<option value="depth_zoe">Depth zoe</option>
|
<option value="normal_bae">Normal bae (*)</option>
|
||||||
<option value="depth_leres">Depth leres</option>
|
<option value="depth_midas">Depth midas</option>
|
||||||
<option value="depth_leres++">Depth leres++</option>
|
<option value="depth_zoe">Depth zoe</option>
|
||||||
</optgroup>
|
<option value="depth_leres">Depth leres</option>
|
||||||
<optgroup label="Line art">
|
<option value="depth_leres++">Depth leres++</option>
|
||||||
<option value="lineart_coarse">Lineart coarse</option>
|
</optgroup>
|
||||||
<option value="lineart_realistic">Lineart realistic</option>
|
<optgroup label="Line art">
|
||||||
<option value="lineart_anime">Lineart anime</option>
|
<option value="lineart_coarse">Lineart coarse</option>
|
||||||
</optgroup>
|
<option value="lineart_realistic">Lineart realistic</option>
|
||||||
<optgroup label="Misc">
|
<option value="lineart_anime">Lineart anime</option>
|
||||||
<option value="shuffle">Shuffle</option>
|
</optgroup>
|
||||||
<option value="segment">Segment</option>
|
<optgroup label="Misc">
|
||||||
</optgroup>
|
<option value="shuffle">Shuffle</option>
|
||||||
</select>
|
<option value="segment">Segment</option>
|
||||||
<br/>
|
</optgroup>
|
||||||
<label for="controlnet_model"><small>Model:</small></label> <input id="controlnet_model" type="text" spellcheck="false" autocomplete="off" class="model-filter" data-path="" />
|
</select>
|
||||||
<br/>
|
<br/>
|
||||||
<label><small>Will download the necessary models, the first time.</small></label>
|
<label for="controlnet_model"><small>Model:</small></label> <input id="controlnet_model" type="text" spellcheck="false" autocomplete="off" class="model-filter" data-path="" />
|
||||||
</div>
|
<br/>
|
||||||
</td></tr>
|
<label><small>Will download the necessary models, the first time.</small></label>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr class="pl-5"><td><label for="vae_model">Custom VAE:</label></td><td>
|
<tr class="pl-5"><td><label for="vae_model">Custom VAE:</label></td><td>
|
||||||
<input id="vae_model" type="text" spellcheck="false" autocomplete="off" class="model-filter" data-path="" />
|
<input id="vae_model" type="text" spellcheck="false" autocomplete="off" class="model-filter" data-path="" />
|
||||||
<a href="https://github.com/easydiffusion/easydiffusion/wiki/VAE-Variational-Auto-Encoder" target="_blank"><i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip top-left">Click to learn more about VAEs</span></i></a>
|
<a href="https://github.com/easydiffusion/easydiffusion/wiki/VAE-Variational-Auto-Encoder" target="_blank"><i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip top-left">Click to learn more about VAEs</span></i></a>
|
||||||
@ -323,7 +326,7 @@
|
|||||||
<button class="add_model_entry"><i class="fa-solid fa-plus"></i> add another LoRA</button>
|
<button class="add_model_entry"><i class="fa-solid fa-plus"></i> add another LoRA</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="pl-5"><td><label for="hypernetwork_model">Hypernetwork:</label></td><td>
|
<tr id="hypernetwork_model_container" class="pl-5"><td><label for="hypernetwork_model">Hypernetwork:</label></td><td>
|
||||||
<input id="hypernetwork_model" type="text" spellcheck="false" autocomplete="off" class="model-filter" data-path="" />
|
<input id="hypernetwork_model" type="text" spellcheck="false" autocomplete="off" class="model-filter" data-path="" />
|
||||||
</td></tr>
|
</td></tr>
|
||||||
<tr id="hypernetwork_strength_container" class="pl-5">
|
<tr id="hypernetwork_strength_container" class="pl-5">
|
||||||
|
@ -1852,4 +1852,9 @@ div#enlarge-buttons {
|
|||||||
}
|
}
|
||||||
#controlnet_model {
|
#controlnet_model {
|
||||||
width: 77%;
|
width: 77%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hack for fixing Image Modifier Improvements plugin */
|
||||||
|
#imageTagPopupContainer {
|
||||||
|
position: absolute;
|
||||||
}
|
}
|
@ -55,6 +55,7 @@ const SETTINGS_IDS_LIST = [
|
|||||||
"zip_toggle",
|
"zip_toggle",
|
||||||
"tree_toggle",
|
"tree_toggle",
|
||||||
"json_toggle",
|
"json_toggle",
|
||||||
|
"extract_lora_from_prompt",
|
||||||
]
|
]
|
||||||
|
|
||||||
const IGNORE_BY_DEFAULT = ["prompt"]
|
const IGNORE_BY_DEFAULT = ["prompt"]
|
||||||
|
@ -186,6 +186,8 @@ let undoBuffer = []
|
|||||||
const UNDO_LIMIT = 20
|
const UNDO_LIMIT = 20
|
||||||
const MAX_IMG_UNDO_ENTRIES = 5
|
const MAX_IMG_UNDO_ENTRIES = 5
|
||||||
|
|
||||||
|
let IMAGE_STEP_SIZE = 64
|
||||||
|
|
||||||
let loraModels = []
|
let loraModels = []
|
||||||
|
|
||||||
imagePreview.addEventListener("drop", function(ev) {
|
imagePreview.addEventListener("drop", function(ev) {
|
||||||
@ -1453,15 +1455,21 @@ function getCurrentUserRequest() {
|
|||||||
let numOutputsParallel = parseInt(numOutputsParallelField.value)
|
let numOutputsParallel = parseInt(numOutputsParallelField.value)
|
||||||
const seed = randomSeedField.checked ? Math.floor(Math.random() * (2 ** 32 - 1)) : parseInt(seedField.value)
|
const seed = randomSeedField.checked ? Math.floor(Math.random() * (2 ** 32 - 1)) : parseInt(seedField.value)
|
||||||
|
|
||||||
if (
|
// if (
|
||||||
testDiffusers.checked &&
|
// testDiffusers.checked &&
|
||||||
document.getElementById("toggle-tensorrt-install").innerHTML == "Uninstall" &&
|
// document.getElementById("toggle-tensorrt-install").innerHTML == "Uninstall" &&
|
||||||
document.querySelector("#convert_to_tensorrt").checked
|
// document.querySelector("#convert_to_tensorrt").checked
|
||||||
) {
|
// ) {
|
||||||
// TRT enabled
|
// // TRT enabled
|
||||||
|
|
||||||
numOutputsParallel = 1 // force 1 parallel
|
// numOutputsParallel = 1 // force 1 parallel
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
// clamp to multiple of 8
|
||||||
|
let width = parseInt(widthField.value)
|
||||||
|
let height = parseInt(heightField.value)
|
||||||
|
width = width - (width % IMAGE_STEP_SIZE)
|
||||||
|
height = height - (height % IMAGE_STEP_SIZE)
|
||||||
|
|
||||||
const newTask = {
|
const newTask = {
|
||||||
batchesDone: 0,
|
batchesDone: 0,
|
||||||
@ -1475,8 +1483,8 @@ function getCurrentUserRequest() {
|
|||||||
num_outputs: numOutputsParallel,
|
num_outputs: numOutputsParallel,
|
||||||
num_inference_steps: parseInt(numInferenceStepsField.value),
|
num_inference_steps: parseInt(numInferenceStepsField.value),
|
||||||
guidance_scale: parseFloat(guidanceScaleField.value),
|
guidance_scale: parseFloat(guidanceScaleField.value),
|
||||||
width: parseInt(widthField.value),
|
width: width,
|
||||||
height: parseInt(heightField.value),
|
height: height,
|
||||||
// allow_nsfw: allowNSFWField.checked,
|
// allow_nsfw: allowNSFWField.checked,
|
||||||
vram_usage_level: vramUsageLevelField.value,
|
vram_usage_level: vramUsageLevelField.value,
|
||||||
sampler_name: samplerField.value,
|
sampler_name: samplerField.value,
|
||||||
@ -1550,6 +1558,22 @@ function getCurrentUserRequest() {
|
|||||||
if (testDiffusers.checked && document.getElementById("toggle-tensorrt-install").innerHTML == "Uninstall") {
|
if (testDiffusers.checked && document.getElementById("toggle-tensorrt-install").innerHTML == "Uninstall") {
|
||||||
// TRT is installed
|
// TRT is installed
|
||||||
newTask.reqBody.convert_to_tensorrt = document.querySelector("#convert_to_tensorrt").checked
|
newTask.reqBody.convert_to_tensorrt = document.querySelector("#convert_to_tensorrt").checked
|
||||||
|
let trtBuildConfig = {
|
||||||
|
batch_size_range: [
|
||||||
|
parseInt(document.querySelector("#trt-build-min-batch").value),
|
||||||
|
parseInt(document.querySelector("#trt-build-max-batch").value),
|
||||||
|
],
|
||||||
|
dimensions_range: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
let sizes = [512, 768, 1024, 1280, 1536]
|
||||||
|
sizes.forEach((i) => {
|
||||||
|
let el = document.querySelector("#trt-build-res-" + i)
|
||||||
|
if (el.checked) {
|
||||||
|
trtBuildConfig["dimensions_range"].push([i, i + 256])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
newTask.reqBody.trt_build_config = trtBuildConfig
|
||||||
}
|
}
|
||||||
if (controlnetModelField.value !== "" && IMAGE_REGEX.test(controlImagePreview.src)) {
|
if (controlnetModelField.value !== "" && IMAGE_REGEX.test(controlImagePreview.src)) {
|
||||||
newTask.reqBody.use_controlnet_model = controlnetModelField.value
|
newTask.reqBody.use_controlnet_model = controlnetModelField.value
|
||||||
@ -2238,6 +2262,7 @@ function checkRandomSeed() {
|
|||||||
randomSeedField.addEventListener("input", checkRandomSeed)
|
randomSeedField.addEventListener("input", checkRandomSeed)
|
||||||
checkRandomSeed()
|
checkRandomSeed()
|
||||||
|
|
||||||
|
// warning: the core plugin `image-editor-improvements.js:172` replaces loadImg2ImgFromFile() with a custom version
|
||||||
function loadImg2ImgFromFile() {
|
function loadImg2ImgFromFile() {
|
||||||
if (initImageSelector.files.length === 0) {
|
if (initImageSelector.files.length === 0) {
|
||||||
return
|
return
|
||||||
@ -2320,6 +2345,9 @@ controlImageSelector.addEventListener("change", loadControlnetImageFromFile)
|
|||||||
function controlImageLoad() {
|
function controlImageLoad() {
|
||||||
let w = controlImagePreview.naturalWidth
|
let w = controlImagePreview.naturalWidth
|
||||||
let h = controlImagePreview.naturalHeight
|
let h = controlImagePreview.naturalHeight
|
||||||
|
w = w - (w % IMAGE_STEP_SIZE)
|
||||||
|
h = h - (h % IMAGE_STEP_SIZE)
|
||||||
|
|
||||||
addImageSizeOption(w)
|
addImageSizeOption(w)
|
||||||
addImageSizeOption(h)
|
addImageSizeOption(h)
|
||||||
|
|
||||||
@ -2481,6 +2509,7 @@ function packagesUpdate(event) {
|
|||||||
|
|
||||||
if (document.getElementById("toggle-tensorrt-install").innerHTML == "Uninstall") {
|
if (document.getElementById("toggle-tensorrt-install").innerHTML == "Uninstall") {
|
||||||
document.querySelector("#enable_trt_config").classList.remove("displayNone")
|
document.querySelector("#enable_trt_config").classList.remove("displayNone")
|
||||||
|
document.querySelector("#trt-build-config").classList.remove("displayNone")
|
||||||
|
|
||||||
if (!trtSettingsForced) {
|
if (!trtSettingsForced) {
|
||||||
// settings for demo
|
// settings for demo
|
||||||
@ -2492,8 +2521,8 @@ function packagesUpdate(event) {
|
|||||||
seedField.disabled = false
|
seedField.disabled = false
|
||||||
stableDiffusionModelField.value = "sd-v1-4"
|
stableDiffusionModelField.value = "sd-v1-4"
|
||||||
|
|
||||||
numOutputsParallelField.classList.add("displayNone")
|
// numOutputsParallelField.classList.add("displayNone")
|
||||||
document.querySelector("#num_outputs_parallel_label").classList.add("displayNone")
|
// document.querySelector("#num_outputs_parallel_label").classList.add("displayNone")
|
||||||
|
|
||||||
trtSettingsForced = true
|
trtSettingsForced = true
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,15 @@ var PARAMETERS = [
|
|||||||
icon: "fa-arrow-down-short-wide",
|
icon: "fa-arrow-down-short-wide",
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "extract_lora_from_prompt",
|
||||||
|
type: ParameterType.checkbox,
|
||||||
|
label: "Extract LoRA tags from the prompt",
|
||||||
|
note:
|
||||||
|
"Automatically extract lora tags like <lora:name:0.4> from the prompt, and apply the correct LoRA (if present)",
|
||||||
|
icon: "fa-code",
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "ui_open_browser_on_start",
|
id: "ui_open_browser_on_start",
|
||||||
type: ParameterType.checkbox,
|
type: ParameterType.checkbox,
|
||||||
@ -258,7 +267,19 @@ var PARAMETERS = [
|
|||||||
label: "NVIDIA TensorRT",
|
label: "NVIDIA TensorRT",
|
||||||
note: `Faster image generation by converting your Stable Diffusion models to the NVIDIA TensorRT format. You can choose the
|
note: `Faster image generation by converting your Stable Diffusion models to the NVIDIA TensorRT format. You can choose the
|
||||||
models to convert. Download size: approximately 2 GB.<br/><br/>
|
models to convert. Download size: approximately 2 GB.<br/><br/>
|
||||||
<b>Early access version:</b> support for LoRA is still under development.`,
|
<b>Early access version:</b> support for LoRA is still under development.
|
||||||
|
<div id="trt-build-config" class="displayNone">
|
||||||
|
<h3>Build Config:</h3>
|
||||||
|
Batch size range:
|
||||||
|
<label>Min:</label> <input id="trt-build-min-batch" type="number" min="1" value="1" style="width: 40pt" />
|
||||||
|
<label>Max:</label> <input id="trt-build-max-batch" type="number" min="1" value="1" style="width: 40pt" /><br/><br/>
|
||||||
|
<b>Build for resolutions</b>:<br/>
|
||||||
|
<input id="trt-build-res-512" type="checkbox" value="1" /> 512x512 to 768x768<br/>
|
||||||
|
<input id="trt-build-res-768" type="checkbox" value="1" checked /> 768x768 to 1024x1024<br/>
|
||||||
|
<input id="trt-build-res-1024" type="checkbox" value="1" /> 1024x1024 to 1280x1280<br/>
|
||||||
|
<input id="trt-build-res-1280" type="checkbox" value="1" /> 1280x1280 to 1536x1536<br/>
|
||||||
|
<input id="trt-build-res-1536" type="checkbox" value="1" /> 1536x1536 to 1792x1792<br/>
|
||||||
|
</div>`,
|
||||||
icon: "fa-angles-up",
|
icon: "fa-angles-up",
|
||||||
render: () => '<button id="toggle-tensorrt-install" class="primaryButton">Install</button>',
|
render: () => '<button id="toggle-tensorrt-install" class="primaryButton">Install</button>',
|
||||||
table: installExtrasTable,
|
table: installExtrasTable,
|
||||||
@ -460,15 +481,22 @@ async function getAppConfig() {
|
|||||||
if (!testDiffusersEnabled) {
|
if (!testDiffusersEnabled) {
|
||||||
document.querySelector("#lora_model_container").style.display = "none"
|
document.querySelector("#lora_model_container").style.display = "none"
|
||||||
document.querySelector("#tiling_container").style.display = "none"
|
document.querySelector("#tiling_container").style.display = "none"
|
||||||
|
document.querySelector("#controlnet_model_container").style.display = "none"
|
||||||
|
document.querySelector("#hypernetwork_model_container").style.display = ""
|
||||||
|
document.querySelector("#hypernetwork_strength_container").style.display = ""
|
||||||
|
|
||||||
document.querySelectorAll("#sampler_name option.diffusers-only").forEach((option) => {
|
document.querySelectorAll("#sampler_name option.diffusers-only").forEach((option) => {
|
||||||
option.style.display = "none"
|
option.style.display = "none"
|
||||||
})
|
})
|
||||||
customWidthField.step=64
|
IMAGE_STEP_SIZE = 64
|
||||||
customHeightField.step=64
|
customWidthField.step = IMAGE_STEP_SIZE
|
||||||
|
customHeightField.step = IMAGE_STEP_SIZE
|
||||||
} else {
|
} else {
|
||||||
document.querySelector("#lora_model_container").style.display = ""
|
document.querySelector("#lora_model_container").style.display = ""
|
||||||
document.querySelector("#tiling_container").style.display = ""
|
document.querySelector("#tiling_container").style.display = ""
|
||||||
|
document.querySelector("#controlnet_model_container").style.display = ""
|
||||||
|
document.querySelector("#hypernetwork_model_container").style.display = "none"
|
||||||
|
document.querySelector("#hypernetwork_strength_container").style.display = "none"
|
||||||
|
|
||||||
document.querySelectorAll("#sampler_name option.k_diffusion-only").forEach((option) => {
|
document.querySelectorAll("#sampler_name option.k_diffusion-only").forEach((option) => {
|
||||||
option.style.display = "none"
|
option.style.display = "none"
|
||||||
@ -476,8 +504,9 @@ async function getAppConfig() {
|
|||||||
document.querySelector("#clip_skip_config").classList.remove("displayNone")
|
document.querySelector("#clip_skip_config").classList.remove("displayNone")
|
||||||
document.querySelector("#embeddings-button").classList.remove("displayNone")
|
document.querySelector("#embeddings-button").classList.remove("displayNone")
|
||||||
document.querySelector("#negative-embeddings-button").classList.remove("displayNone")
|
document.querySelector("#negative-embeddings-button").classList.remove("displayNone")
|
||||||
customWidthField.step=8
|
IMAGE_STEP_SIZE = 8
|
||||||
customHeightField.step=8
|
customWidthField.step = IMAGE_STEP_SIZE
|
||||||
|
customHeightField.step = IMAGE_STEP_SIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("get config status response", config)
|
console.log("get config status response", config)
|
||||||
|
@ -124,35 +124,17 @@
|
|||||||
// Draw the image with centered coordinates
|
// Draw the image with centered coordinates
|
||||||
context.drawImage(imageObj, x, y, this.width, this.height);
|
context.drawImage(imageObj, x, y, this.width, this.height);
|
||||||
|
|
||||||
initImagePreview.src = canvas.toDataURL('image/png');
|
let bestWidth = maxCroppedWidth - maxCroppedWidth % IMAGE_STEP_SIZE
|
||||||
|
let bestHeight = maxCroppedHeight - maxCroppedHeight % IMAGE_STEP_SIZE
|
||||||
|
|
||||||
// Get the options from widthField and heightField
|
addImageSizeOption(bestWidth)
|
||||||
const widthOptions = Array.from(widthField.options).map(option => parseInt(option.value));
|
addImageSizeOption(bestHeight)
|
||||||
const heightOptions = Array.from(heightField.options).map(option => parseInt(option.value));
|
|
||||||
|
|
||||||
// Find the closest aspect ratio and closest to original dimensions
|
|
||||||
let bestWidth = widthOptions[0];
|
|
||||||
let bestHeight = heightOptions[0];
|
|
||||||
let minDifference = Math.abs(maxCroppedWidth / maxCroppedHeight - bestWidth / bestHeight);
|
|
||||||
let minDistance = Math.abs(maxCroppedWidth - bestWidth) + Math.abs(maxCroppedHeight - bestHeight);
|
|
||||||
|
|
||||||
for (const width of widthOptions) {
|
|
||||||
for (const height of heightOptions) {
|
|
||||||
const difference = Math.abs(maxCroppedWidth / maxCroppedHeight - width / height);
|
|
||||||
const distance = Math.abs(maxCroppedWidth - width) + Math.abs(maxCroppedHeight - height);
|
|
||||||
|
|
||||||
if (difference < minDifference || (difference === minDifference && distance < minDistance)) {
|
|
||||||
minDifference = difference;
|
|
||||||
minDistance = distance;
|
|
||||||
bestWidth = width;
|
|
||||||
bestHeight = height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the width and height to the closest aspect ratio and closest to original dimensions
|
// Set the width and height to the closest aspect ratio and closest to original dimensions
|
||||||
widthField.value = bestWidth;
|
widthField.value = bestWidth;
|
||||||
heightField.value = bestHeight;
|
heightField.value = bestHeight;
|
||||||
|
|
||||||
|
initImagePreview.src = canvas.toDataURL('image/png');
|
||||||
};
|
};
|
||||||
|
|
||||||
function handlePaste(e) {
|
function handlePaste(e) {
|
||||||
|
119
ui/plugins/ui/lora-prompt-parser.plugin.js
Normal file
119
ui/plugins/ui/lora-prompt-parser.plugin.js
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
LoRA Prompt Parser 1.0
|
||||||
|
by Patrice
|
||||||
|
|
||||||
|
Copying and pasting a prompt with a LoRA tag will automatically select the corresponding option in the Easy Diffusion dropdown and remove the LoRA tag from the prompt. The LoRA must be already available in the corresponding Easy Diffusion dropdown (this is not a LoRA downloader).
|
||||||
|
*/
|
||||||
|
(function() {
|
||||||
|
"use strict"
|
||||||
|
|
||||||
|
promptField.addEventListener('input', function(e) {
|
||||||
|
let loraExtractSetting = document.getElementById("extract_lora_from_prompt")
|
||||||
|
if (!loraExtractSetting.checked) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const { LoRA, prompt } = extractLoraTags(e.target.value);
|
||||||
|
//console.log('e.target: ' + JSON.stringify(LoRA));
|
||||||
|
|
||||||
|
if (LoRA !== null && LoRA.length > 0) {
|
||||||
|
promptField.value = prompt.replace(/,+$/, ''); // remove any trailing ,
|
||||||
|
|
||||||
|
if (testDiffusers?.checked === false) {
|
||||||
|
showToast("LoRA's are only supported with diffusers. Just stripping the LoRA tag from the prompt.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LoRA !== null && LoRA.length > 0 && testDiffusers?.checked) {
|
||||||
|
for (let i = 0; i < LoRA.length; i++) {
|
||||||
|
//if (loraModelField.value !== LoRA[0].lora_model) {
|
||||||
|
// Set the new LoRA value
|
||||||
|
//console.log("Loading info");
|
||||||
|
//console.log(LoRA[0].lora_model_0);
|
||||||
|
//console.log(JSON.stringify(LoRa));
|
||||||
|
|
||||||
|
let lora = `lora_model_${i}`;
|
||||||
|
let alpha = `lora_alpha_${i}`;
|
||||||
|
let loramodel = document.getElementById(lora);
|
||||||
|
let alphavalue = document.getElementById(alpha);
|
||||||
|
loramodel.setAttribute("data-path", LoRA[i].lora_model_0);
|
||||||
|
loramodel.value = LoRA[i].lora_model_0;
|
||||||
|
alphavalue.value = LoRA[i].lora_alpha_0;
|
||||||
|
if (i != LoRA.length - 1)
|
||||||
|
createLoraEntry();
|
||||||
|
}
|
||||||
|
//loraAlphaSlider.value = loraAlphaField.value * 100;
|
||||||
|
//TBD.value = LoRA[0].blockweights; // block weights not supported by ED at this time
|
||||||
|
//}
|
||||||
|
showToast("Prompt successfully processed", LoRA[0].lora_model_0);
|
||||||
|
//console.log('LoRa: ' + LoRA[0].lora_model_0);
|
||||||
|
//showToast("Prompt successfully processed", lora_model_0.value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//promptField.dispatchEvent(new Event('change'));
|
||||||
|
});
|
||||||
|
|
||||||
|
function isModelAvailable(array, searchString) {
|
||||||
|
const foundItem = array.find(function(item) {
|
||||||
|
item = item.toString().toLowerCase();
|
||||||
|
return item === searchString.toLowerCase()
|
||||||
|
});
|
||||||
|
|
||||||
|
return foundItem || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract LoRA tags from strings
|
||||||
|
function extractLoraTags(prompt) {
|
||||||
|
// Define the regular expression for the tags
|
||||||
|
const regex = /<(?:lora|lyco):([^:>]+)(?::([^:>]*))?(?::([^:>]*))?>/gi
|
||||||
|
|
||||||
|
// Initialize an array to hold the matches
|
||||||
|
let matches = []
|
||||||
|
|
||||||
|
// Iterate over the string, finding matches
|
||||||
|
for (const match of prompt.matchAll(regex)) {
|
||||||
|
const modelFileName = isModelAvailable(modelsCache.options.lora, match[1].trim())
|
||||||
|
if (modelFileName !== "") {
|
||||||
|
// Initialize an object to hold a match
|
||||||
|
let loraTag = {
|
||||||
|
lora_model_0: modelFileName,
|
||||||
|
}
|
||||||
|
//console.log("Model:" + modelFileName);
|
||||||
|
|
||||||
|
// If weight is provided, add it to the loraTag object
|
||||||
|
if (match[2] !== undefined && match[2] !== '') {
|
||||||
|
loraTag.lora_alpha_0 = parseFloat(match[2].trim())
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
loraTag.lora_alpha_0 = 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// If blockweights are provided, add them to the loraTag object
|
||||||
|
if (match[3] !== undefined && match[3] !== '') {
|
||||||
|
loraTag.blockweights = match[3].trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the loraTag object to the array of matches
|
||||||
|
matches.push(loraTag);
|
||||||
|
//console.log(JSON.stringify(matches));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
showToast("LoRA not found: " + match[1].trim(), 5000, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up the prompt string, e.g. from "apple, banana, <lora:...>, orange, <lora:...> , pear <lora:...>, <lora:...>" to "apple, banana, orange, pear"
|
||||||
|
let cleanedPrompt = prompt.replace(regex, '').replace(/(\s*,\s*(?=\s*,|$))|(^\s*,\s*)|\s+/g, ' ').trim();
|
||||||
|
//console.log('Matches: ' + JSON.stringify(matches));
|
||||||
|
|
||||||
|
// Return the array of matches and cleaned prompt string
|
||||||
|
return {
|
||||||
|
LoRA: matches,
|
||||||
|
prompt: cleanedPrompt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})()
|
Loading…
x
Reference in New Issue
Block a user