Merge pull request #1546 from easydiffusion/beta

Use v3 for everyone
This commit is contained in:
cmdr2 2023-08-31 20:03:57 +05:30 committed by GitHub
commit 013860e3c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 165 additions and 59 deletions

View File

@ -17,6 +17,7 @@
- **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. - **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 ### Detailed changelog
* 3.0.3 - 31 Aug 2023 - Auto-save images to disk (if enabled by the user) when upscaling/fixing using the buttons on the image.
* 3.0.3 - 30 Aug 2023 - Allow loading NovelAI-based custom models. * 3.0.3 - 30 Aug 2023 - Allow loading NovelAI-based custom models.
* 3.0.3 - 30 Aug 2023 - Fix broken VAE tiling. This allows you to create larger images with lesser VRAM usage. * 3.0.3 - 30 Aug 2023 - Fix broken VAE tiling. This allows you to create larger images with lesser VRAM usage.
* 3.0.3 - 30 Aug 2023 - Allow blocking NSFW images using a server-side config. This prevents the browser from generating NSFW images or changing the config. Open `config.yaml` in a text editor (e.g. Notepad), and add `block_nsfw: true` at the end, and save the file. * 3.0.3 - 30 Aug 2023 - Allow blocking NSFW images using a server-side config. This prevents the browser from generating NSFW images or changing the config. Open `config.yaml` in a text editor (e.g. Notepad), and add `block_nsfw: true` at the end, and save the file.

View File

@ -61,7 +61,7 @@ APP_CONFIG_DEFAULTS = {
"ui": { "ui": {
"open_browser_on_start": True, "open_browser_on_start": True,
}, },
"test_diffusers": True, "use_v3_engine": True,
} }
IMAGE_EXTENSIONS = [ IMAGE_EXTENSIONS = [
@ -116,9 +116,9 @@ def getConfig(default_val=APP_CONFIG_DEFAULTS):
shutil.move(config_legacy_yaml, config_yaml_path) shutil.move(config_legacy_yaml, config_yaml_path)
def set_config_on_startup(config: dict): def set_config_on_startup(config: dict):
if getConfig.__test_diffusers_on_startup is None: if getConfig.__use_v3_engine_on_startup is None:
getConfig.__test_diffusers_on_startup = config.get("test_diffusers", True) getConfig.__use_v3_engine_on_startup = config.get("use_v3_engine", True)
config["config_on_startup"] = {"test_diffusers": getConfig.__test_diffusers_on_startup} config["config_on_startup"] = {"use_v3_engine": getConfig.__use_v3_engine_on_startup}
if os.path.isfile(config_yaml_path): if os.path.isfile(config_yaml_path):
try: try:
@ -166,7 +166,7 @@ def getConfig(default_val=APP_CONFIG_DEFAULTS):
return default_val return default_val
getConfig.__test_diffusers_on_startup = None getConfig.__use_v3_engine_on_startup = None
def setConfig(config): def setConfig(config):

View File

@ -30,7 +30,7 @@ def init(device):
from easydiffusion import app from easydiffusion import app
app_config = app.getConfig() app_config = app.getConfig()
context.test_diffusers = app_config.get("test_diffusers", True) context.test_diffusers = app_config.get("use_v3_engine", True)
log.info("Device usage during initialization:") log.info("Device usage during initialization:")
get_device_usage(device, log_info=True, process_usage_only=False) get_device_usage(device, log_info=True, process_usage_only=False)

View File

@ -15,8 +15,10 @@ from easydiffusion.types import (
FilterImageRequest, FilterImageRequest,
MergeRequest, MergeRequest,
TaskData, TaskData,
RenderTaskData,
ModelsData, ModelsData,
OutputFormatData, OutputFormatData,
SaveToDiskData,
convert_legacy_render_req_to_new, convert_legacy_render_req_to_new,
) )
from easydiffusion.utils import log from easydiffusion.utils import log
@ -64,7 +66,7 @@ class SetAppConfigRequest(BaseModel, extra=Extra.allow):
ui_open_browser_on_start: bool = None ui_open_browser_on_start: bool = None
listen_to_network: bool = None listen_to_network: bool = None
listen_port: int = None listen_port: int = None
test_diffusers: bool = True use_v3_engine: bool = True
def init(): def init():
@ -173,7 +175,7 @@ def set_app_config_internal(req: SetAppConfigRequest):
config["net"] = {} config["net"] = {}
config["net"]["listen_port"] = int(req.listen_port) config["net"]["listen_port"] = int(req.listen_port)
config["test_diffusers"] = req.test_diffusers config["use_v3_engine"] = req.use_v3_engine
for property, property_value in req.dict().items(): for property, property_value in req.dict().items():
if property_value is not None and property not in req.__fields__ and property not in PROTECTED_CONFIG_KEYS: if property_value is not None and property not in req.__fields__ and property not in PROTECTED_CONFIG_KEYS:
@ -262,9 +264,10 @@ def render_internal(req: dict):
# separate out the request data into rendering and task-specific data # separate out the request data into rendering and task-specific data
render_req: GenerateImageRequest = GenerateImageRequest.parse_obj(req) render_req: GenerateImageRequest = GenerateImageRequest.parse_obj(req)
task_data: TaskData = TaskData.parse_obj(req) task_data: RenderTaskData = RenderTaskData.parse_obj(req)
models_data: ModelsData = ModelsData.parse_obj(req) models_data: ModelsData = ModelsData.parse_obj(req)
output_format: OutputFormatData = OutputFormatData.parse_obj(req) output_format: OutputFormatData = OutputFormatData.parse_obj(req)
save_data: SaveToDiskData = SaveToDiskData.parse_obj(req)
# Overwrite user specified save path # Overwrite user specified save path
config = app.getConfig() config = app.getConfig()
@ -281,7 +284,7 @@ def render_internal(req: dict):
) )
# enqueue the task # enqueue the task
task = RenderTask(render_req, task_data, models_data, output_format) task = RenderTask(render_req, task_data, models_data, output_format, save_data)
return enqueue_task(task) return enqueue_task(task)
except HTTPException as e: except HTTPException as e:
raise e raise e
@ -292,13 +295,14 @@ def render_internal(req: dict):
def filter_internal(req: dict): def filter_internal(req: dict):
try: try:
session_id = req.get("session_id", "session")
filter_req: FilterImageRequest = FilterImageRequest.parse_obj(req) filter_req: FilterImageRequest = FilterImageRequest.parse_obj(req)
task_data: TaskData = TaskData.parse_obj(req)
models_data: ModelsData = ModelsData.parse_obj(req) models_data: ModelsData = ModelsData.parse_obj(req)
output_format: OutputFormatData = OutputFormatData.parse_obj(req) output_format: OutputFormatData = OutputFormatData.parse_obj(req)
save_data: SaveToDiskData = SaveToDiskData.parse_obj(req)
# enqueue the task # enqueue the task
task = FilterTask(filter_req, session_id, models_data, output_format) task = FilterTask(filter_req, task_data, models_data, output_format, save_data)
return enqueue_task(task) return enqueue_task(task)
except HTTPException as e: except HTTPException as e:
raise e raise e

View File

@ -1,12 +1,25 @@
import os
import json import json
import pprint import pprint
import time
from numpy import base_repr
from sdkit.filter import apply_filters from sdkit.filter import apply_filters
from sdkit.models import load_model from sdkit.models import load_model
from sdkit.utils import img_to_base64_str, get_image, log from sdkit.utils import img_to_base64_str, get_image, log, save_images
from easydiffusion import model_manager, runtime from easydiffusion import model_manager, runtime
from easydiffusion.types import FilterImageRequest, FilterImageResponse, ModelsData, OutputFormatData from easydiffusion.types import (
FilterImageRequest,
FilterImageResponse,
ModelsData,
OutputFormatData,
SaveToDiskData,
TaskData,
GenerateImageRequest,
)
from easydiffusion.utils.save_utils import format_folder_name
from .task import Task from .task import Task
@ -15,13 +28,22 @@ class FilterTask(Task):
"For applying filters to input images" "For applying filters to input images"
def __init__( def __init__(
self, req: FilterImageRequest, session_id: str, models_data: ModelsData, output_format: OutputFormatData self,
req: FilterImageRequest,
task_data: TaskData,
models_data: ModelsData,
output_format: OutputFormatData,
save_data: SaveToDiskData,
): ):
super().__init__(session_id) super().__init__(task_data.session_id)
task_data.request_id = self.id
self.request = req self.request = req
self.task_data = task_data
self.models_data = models_data self.models_data = models_data
self.output_format = output_format self.output_format = output_format
self.save_data = save_data
# convert to multi-filter format, if necessary # convert to multi-filter format, if necessary
if isinstance(req.filter, str): if isinstance(req.filter, str):
@ -34,13 +56,15 @@ class FilterTask(Task):
def run(self): def run(self):
"Runs the image filtering task on the assigned thread" "Runs the image filtering task on the assigned thread"
from easydiffusion import app
context = runtime.context context = runtime.context
model_manager.resolve_model_paths(self.models_data) model_manager.resolve_model_paths(self.models_data)
model_manager.reload_models_if_necessary(context, self.models_data) model_manager.reload_models_if_necessary(context, self.models_data)
model_manager.fail_if_models_did_not_load(context) model_manager.fail_if_models_did_not_load(context)
print_task_info(self.request, self.models_data, self.output_format) print_task_info(self.request, self.models_data, self.output_format, self.save_data)
if isinstance(self.request.image, list): if isinstance(self.request.image, list):
images = [get_image(img) for img in self.request.image] images = [get_image(img) for img in self.request.image]
@ -50,6 +74,26 @@ class FilterTask(Task):
images = filter_images(context, images, self.request.filter, self.request.filter_params) images = filter_images(context, images, self.request.filter, self.request.filter_params)
output_format = self.output_format output_format = self.output_format
if self.save_data.save_to_disk_path is not None:
app_config = app.getConfig()
folder_format = app_config.get("folder_format", "$id")
dummy_req = GenerateImageRequest()
img_id = base_repr(int(time.time() * 10000), 36)[-7:] # Base 36 conversion, 0-9, A-Z
save_dir_path = os.path.join(
self.save_data.save_to_disk_path, format_folder_name(folder_format, dummy_req, self.task_data)
)
save_images(
images,
save_dir_path,
file_name=img_id,
output_format=output_format.output_format,
output_quality=output_format.output_quality,
output_lossless=output_format.output_lossless,
)
images = [ images = [
img_to_base64_str( img_to_base64_str(
img, output_format.output_format, output_format.output_quality, output_format.output_lossless img, output_format.output_format, output_format.output_quality, output_format.output_lossless
@ -60,6 +104,7 @@ class FilterTask(Task):
res = FilterImageResponse(self.request, self.models_data, images=images) res = FilterImageResponse(self.request, self.models_data, images=images)
res = res.json() res = res.json()
self.buffer_queue.put(json.dumps(res)) self.buffer_queue.put(json.dumps(res))
log.info("Filter task completed") log.info("Filter task completed")
self.response = res self.response = res
@ -105,11 +150,15 @@ def after_filter(context, filter_name, filter_params, previous_state):
load_model(context, "realesrgan") load_model(context, "realesrgan")
def print_task_info(req: FilterImageRequest, models_data: ModelsData, output_format: OutputFormatData): def print_task_info(
req: FilterImageRequest, models_data: ModelsData, output_format: OutputFormatData, save_data: SaveToDiskData
):
req_str = pprint.pformat({"filter": req.filter, "filter_params": req.filter_params}).replace("[", "\[") req_str = pprint.pformat({"filter": req.filter, "filter_params": req.filter_params}).replace("[", "\[")
models_data = pprint.pformat(models_data.dict()).replace("[", "\[") models_data = pprint.pformat(models_data.dict()).replace("[", "\[")
output_format = pprint.pformat(output_format.dict()).replace("[", "\[") output_format = pprint.pformat(output_format.dict()).replace("[", "\[")
save_data = pprint.pformat(save_data.dict()).replace("[", "\[")
log.info(f"request: {req_str}") log.info(f"request: {req_str}")
log.info(f"models data: {models_data}") log.info(f"models data: {models_data}")
log.info(f"output format: {output_format}") log.info(f"output format: {output_format}")
log.info(f"save data: {save_data}")

View File

@ -4,9 +4,9 @@ import queue
import time import time
from easydiffusion import model_manager, runtime from easydiffusion import model_manager, runtime
from easydiffusion.types import GenerateImageRequest, ModelsData, OutputFormatData from easydiffusion.types import GenerateImageRequest, ModelsData, OutputFormatData, SaveToDiskData
from easydiffusion.types import Image as ResponseImage from easydiffusion.types import Image as ResponseImage
from easydiffusion.types import GenerateImageResponse, TaskData, UserInitiatedStop from easydiffusion.types import GenerateImageResponse, RenderTaskData, UserInitiatedStop
from easydiffusion.utils import get_printable_request, log, save_images_to_disk from easydiffusion.utils import get_printable_request, log, save_images_to_disk
from sdkit.generate import generate_images from sdkit.generate import generate_images
from sdkit.utils import ( from sdkit.utils import (
@ -28,15 +28,23 @@ class RenderTask(Task):
"For image generation" "For image generation"
def __init__( def __init__(
self, req: GenerateImageRequest, task_data: TaskData, models_data: ModelsData, output_format: OutputFormatData self,
req: GenerateImageRequest,
task_data: RenderTaskData,
models_data: ModelsData,
output_format: OutputFormatData,
save_data: SaveToDiskData,
): ):
super().__init__(task_data.session_id) super().__init__(task_data.session_id)
task_data.request_id = self.id task_data.request_id = self.id
self.render_request: GenerateImageRequest = req # Initial Request
self.task_data: TaskData = task_data self.render_request = req # Initial Request
self.task_data = task_data
self.models_data = models_data self.models_data = models_data
self.output_format = output_format self.output_format = output_format
self.save_data = save_data
self.temp_images: list = [None] * req.num_outputs * (1 if task_data.show_only_filtered_image else 2) self.temp_images: list = [None] * req.num_outputs * (1 if task_data.show_only_filtered_image else 2)
def run(self): def run(self):
@ -87,6 +95,7 @@ class RenderTask(Task):
self.task_data, self.task_data,
self.models_data, self.models_data,
self.output_format, self.output_format,
self.save_data,
self.buffer_queue, self.buffer_queue,
self.temp_images, self.temp_images,
step_callback, step_callback,
@ -129,22 +138,23 @@ class RenderTask(Task):
def make_images( def make_images(
context, context,
req: GenerateImageRequest, req: GenerateImageRequest,
task_data: TaskData, task_data: RenderTaskData,
models_data: ModelsData, models_data: ModelsData,
output_format: OutputFormatData, output_format: OutputFormatData,
save_data: SaveToDiskData,
data_queue: queue.Queue, data_queue: queue.Queue,
task_temp_images: list, task_temp_images: list,
step_callback, step_callback,
): ):
context.stop_processing = False context.stop_processing = False
print_task_info(req, task_data, models_data, output_format) print_task_info(req, task_data, models_data, output_format, save_data)
images, seeds = make_images_internal( images, seeds = make_images_internal(
context, req, task_data, models_data, output_format, data_queue, task_temp_images, step_callback context, req, task_data, models_data, output_format, save_data, data_queue, task_temp_images, step_callback
) )
res = GenerateImageResponse( res = GenerateImageResponse(
req, task_data, models_data, output_format, images=construct_response(images, seeds, output_format) req, task_data, models_data, output_format, save_data, images=construct_response(images, seeds, output_format)
) )
res = res.json() res = res.json()
data_queue.put(json.dumps(res)) data_queue.put(json.dumps(res))
@ -154,25 +164,32 @@ def make_images(
def print_task_info( def print_task_info(
req: GenerateImageRequest, task_data: TaskData, models_data: ModelsData, output_format: OutputFormatData req: GenerateImageRequest,
task_data: RenderTaskData,
models_data: ModelsData,
output_format: OutputFormatData,
save_data: SaveToDiskData,
): ):
req_str = pprint.pformat(get_printable_request(req, task_data, output_format)).replace("[", "\[") req_str = pprint.pformat(get_printable_request(req, task_data, output_format, save_data)).replace("[", "\[")
task_str = pprint.pformat(task_data.dict()).replace("[", "\[") task_str = pprint.pformat(task_data.dict()).replace("[", "\[")
models_data = pprint.pformat(models_data.dict()).replace("[", "\[") models_data = pprint.pformat(models_data.dict()).replace("[", "\[")
output_format = pprint.pformat(output_format.dict()).replace("[", "\[") output_format = pprint.pformat(output_format.dict()).replace("[", "\[")
save_data = pprint.pformat(save_data.dict()).replace("[", "\[")
log.info(f"request: {req_str}") log.info(f"request: {req_str}")
log.info(f"task data: {task_str}") log.info(f"task data: {task_str}")
# log.info(f"models data: {models_data}") # log.info(f"models data: {models_data}")
log.info(f"output format: {output_format}") log.info(f"output format: {output_format}")
log.info(f"save data: {save_data}")
def make_images_internal( def make_images_internal(
context, context,
req: GenerateImageRequest, req: GenerateImageRequest,
task_data: TaskData, task_data: RenderTaskData,
models_data: ModelsData, models_data: ModelsData,
output_format: OutputFormatData, output_format: OutputFormatData,
save_data: SaveToDiskData,
data_queue: queue.Queue, data_queue: queue.Queue,
task_temp_images: list, task_temp_images: list,
step_callback, step_callback,
@ -194,8 +211,8 @@ def make_images_internal(
filters, filter_params = task_data.filters, task_data.filter_params filters, filter_params = task_data.filters, task_data.filter_params
filtered_images = filter_images(context, images, filters, filter_params) if not user_stopped else images filtered_images = filter_images(context, images, filters, filter_params) if not user_stopped else images
if task_data.save_to_disk_path is not None: if save_data.save_to_disk_path is not None:
save_images_to_disk(images, filtered_images, req, task_data, output_format) save_images_to_disk(images, filtered_images, req, task_data, output_format, save_data)
seeds = [*range(req.seed, req.seed + len(images))] seeds = [*range(req.seed, req.seed + len(images))]
if task_data.show_only_filtered_image or filtered_images is images: if task_data.show_only_filtered_image or filtered_images is images:
@ -207,7 +224,7 @@ def make_images_internal(
def generate_images_internal( def generate_images_internal(
context, context,
req: GenerateImageRequest, req: GenerateImageRequest,
task_data: TaskData, task_data: RenderTaskData,
models_data: ModelsData, models_data: ModelsData,
data_queue: queue.Queue, data_queue: queue.Queue,
task_temp_images: list, task_temp_images: list,
@ -298,7 +315,7 @@ def construct_response(images: list, seeds: list, output_format: OutputFormatDat
def make_step_callback( def make_step_callback(
context, context,
req: GenerateImageRequest, req: GenerateImageRequest,
task_data: TaskData, task_data: RenderTaskData,
data_queue: queue.Queue, data_queue: queue.Queue,
task_temp_images: list, task_temp_images: list,
step_callback, step_callback,

View File

@ -58,10 +58,17 @@ class OutputFormatData(BaseModel):
output_lossless: bool = False output_lossless: bool = False
class SaveToDiskData(BaseModel):
save_to_disk_path: str = None
metadata_output_format: str = "txt" # or "json"
class TaskData(BaseModel): class TaskData(BaseModel):
request_id: str = None request_id: str = None
session_id: str = "session" session_id: str = "session"
save_to_disk_path: str = None
class RenderTaskData(TaskData):
vram_usage_level: str = "balanced" # or "low" or "medium" vram_usage_level: str = "balanced" # or "low" or "medium"
use_face_correction: Union[str, List[str]] = None # or "GFPGANv1.3" use_face_correction: Union[str, List[str]] = None # or "GFPGANv1.3"
@ -80,7 +87,6 @@ class TaskData(BaseModel):
show_only_filtered_image: bool = False show_only_filtered_image: bool = False
block_nsfw: bool = False block_nsfw: bool = False
metadata_output_format: str = "txt" # or "json"
stream_image_progress: bool = False stream_image_progress: bool = False
stream_image_progress_interval: int = 5 stream_image_progress_interval: int = 5
clip_skip: bool = False clip_skip: bool = False
@ -126,12 +132,14 @@ class GenerateImageResponse:
task_data: TaskData, task_data: TaskData,
models_data: ModelsData, models_data: ModelsData,
output_format: OutputFormatData, output_format: OutputFormatData,
save_data: SaveToDiskData,
images: list, images: list,
): ):
self.render_request = render_request self.render_request = render_request
self.task_data = task_data self.task_data = task_data
self.models_data = models_data self.models_data = models_data
self.output_format = output_format self.output_format = output_format
self.save_data = save_data
self.images = images self.images = images
def json(self): def json(self):
@ -141,6 +149,7 @@ class GenerateImageResponse:
task_data = self.task_data.dict() task_data = self.task_data.dict()
task_data.update(self.output_format.dict()) task_data.update(self.output_format.dict())
task_data.update(self.save_data.dict())
res = { res = {
"status": "succeeded", "status": "succeeded",

View File

@ -7,7 +7,7 @@ from datetime import datetime
from functools import reduce from functools import reduce
from easydiffusion import app from easydiffusion import app
from easydiffusion.types import GenerateImageRequest, TaskData, OutputFormatData from easydiffusion.types import GenerateImageRequest, TaskData, RenderTaskData, OutputFormatData, SaveToDiskData
from numpy import base_repr from numpy import base_repr
from sdkit.utils import save_dicts, save_images from sdkit.utils import save_dicts, save_images
from sdkit.models.model_loader.embeddings import get_embedding_token from sdkit.models.model_loader.embeddings import get_embedding_token
@ -95,7 +95,7 @@ def format_folder_name(format: str, req: GenerateImageRequest, task_data: TaskDa
def format_file_name( def format_file_name(
format: str, format: str,
req: GenerateImageRequest, req: GenerateImageRequest,
task_data: TaskData, task_data: RenderTaskData,
now: float, now: float,
batch_file_number: int, batch_file_number: int,
folder_img_number: ImageNumber, folder_img_number: ImageNumber,
@ -118,13 +118,18 @@ def format_file_name(
def save_images_to_disk( def save_images_to_disk(
images: list, filtered_images: list, req: GenerateImageRequest, task_data: TaskData, output_format: OutputFormatData images: list,
filtered_images: list,
req: GenerateImageRequest,
task_data: RenderTaskData,
output_format: OutputFormatData,
save_data: SaveToDiskData,
): ):
now = time.time() now = time.time()
app_config = app.getConfig() app_config = app.getConfig()
folder_format = app_config.get("folder_format", "$id") 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)) save_dir_path = os.path.join(save_data.save_to_disk_path, format_folder_name(folder_format, req, task_data))
metadata_entries = get_metadata_entries_for_request(req, task_data, output_format) metadata_entries = get_metadata_entries_for_request(req, task_data, output_format, save_data)
file_number = calculate_img_number(save_dir_path, task_data) file_number = calculate_img_number(save_dir_path, task_data)
make_filename = make_filename_callback( make_filename = make_filename_callback(
app_config.get("filename_format", "$p_$tsb64"), app_config.get("filename_format", "$p_$tsb64"),
@ -143,8 +148,8 @@ def save_images_to_disk(
output_quality=output_format.output_quality, output_quality=output_format.output_quality,
output_lossless=output_format.output_lossless, output_lossless=output_format.output_lossless,
) )
if task_data.metadata_output_format: if save_data.metadata_output_format:
for metadata_output_format in task_data.metadata_output_format.split(","): for metadata_output_format in save_data.metadata_output_format.split(","):
if metadata_output_format.lower() in ["json", "txt", "embed"]: if metadata_output_format.lower() in ["json", "txt", "embed"]:
save_dicts( save_dicts(
metadata_entries, metadata_entries,
@ -179,8 +184,8 @@ def save_images_to_disk(
output_quality=output_format.output_quality, output_quality=output_format.output_quality,
output_lossless=output_format.output_lossless, output_lossless=output_format.output_lossless,
) )
if task_data.metadata_output_format: if save_data.metadata_output_format:
for metadata_output_format in task_data.metadata_output_format.split(","): for metadata_output_format in save_data.metadata_output_format.split(","):
if metadata_output_format.lower() in ["json", "txt", "embed"]: if metadata_output_format.lower() in ["json", "txt", "embed"]:
save_dicts( save_dicts(
metadata_entries, metadata_entries,
@ -191,11 +196,13 @@ def save_images_to_disk(
) )
def get_metadata_entries_for_request(req: GenerateImageRequest, task_data: TaskData, output_format: OutputFormatData): def get_metadata_entries_for_request(
metadata = get_printable_request(req, task_data, output_format) req: GenerateImageRequest, task_data: RenderTaskData, output_format: OutputFormatData, save_data: SaveToDiskData
):
metadata = get_printable_request(req, task_data, output_format, save_data)
# if text, format it in the text format expected by the UI # if text, format it in the text format expected by the UI
is_txt_format = task_data.metadata_output_format and "txt" in task_data.metadata_output_format.lower().split(",") is_txt_format = save_data.metadata_output_format and "txt" in save_data.metadata_output_format.lower().split(",")
if is_txt_format: if is_txt_format:
def format_value(value): def format_value(value):
@ -214,13 +221,16 @@ def get_metadata_entries_for_request(req: GenerateImageRequest, task_data: TaskD
return entries return entries
def get_printable_request(req: GenerateImageRequest, task_data: TaskData, output_format: OutputFormatData): def get_printable_request(
req: GenerateImageRequest, task_data: RenderTaskData, output_format: OutputFormatData, save_data: SaveToDiskData
):
req_metadata = req.dict() req_metadata = req.dict()
task_data_metadata = task_data.dict() task_data_metadata = task_data.dict()
task_data_metadata.update(output_format.dict()) task_data_metadata.update(output_format.dict())
task_data_metadata.update(save_data.dict())
app_config = app.getConfig() app_config = app.getConfig()
using_diffusers = app_config.get("test_diffusers", True) using_diffusers = app_config.get("use_v3_engine", True)
# Save the metadata in the order defined in TASK_TEXT_MAPPING # Save the metadata in the order defined in TASK_TEXT_MAPPING
metadata = {} metadata = {}
@ -240,7 +250,9 @@ def get_printable_request(req: GenerateImageRequest, task_data: TaskData, output
# Check if the filename has the right extension # Check if the filename has the right extension
if not any(map(lambda ext: entry.name.endswith(ext), embeddings_extensions)): if not any(map(lambda ext: entry.name.endswith(ext), embeddings_extensions)):
continue continue
embedding_name_regex = regex.compile(r"(^|[\s,])" + regex.escape(get_embedding_token(entry.name)) + r"([+-]*$|[\s,]|[+-]+[\s,])") embedding_name_regex = regex.compile(
r"(^|[\s,])" + regex.escape(get_embedding_token(entry.name)) + r"([+-]*$|[\s,]|[+-]+[\s,])"
)
if embedding_name_regex.search(req.prompt) or embedding_name_regex.search(req.negative_prompt): if embedding_name_regex.search(req.prompt) or embedding_name_regex.search(req.negative_prompt):
used_embeddings.append(entry.path) used_embeddings.append(entry.path)
elif entry.is_dir(): elif entry.is_dir():
@ -269,7 +281,17 @@ def get_printable_request(req: GenerateImageRequest, task_data: TaskData, output
del metadata[key] del metadata[key]
else: else:
for key in ( for key in (
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 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]
@ -279,7 +301,7 @@ def get_printable_request(req: GenerateImageRequest, task_data: TaskData, output
def make_filename_callback( def make_filename_callback(
filename_format: str, filename_format: str,
req: GenerateImageRequest, req: GenerateImageRequest,
task_data: TaskData, task_data: RenderTaskData,
folder_img_number: int, folder_img_number: int,
suffix=None, suffix=None,
now=None, now=None,
@ -296,7 +318,7 @@ def make_filename_callback(
return make_filename return make_filename
def _calculate_img_number(save_dir_path: str, task_data: TaskData): def _calculate_img_number(save_dir_path: str, task_data: RenderTaskData):
def get_highest_img_number(accumulator: int, file: os.DirEntry) -> int: def get_highest_img_number(accumulator: int, file: os.DirEntry) -> int:
if not file.is_file: if not file.is_file:
return accumulator return accumulator
@ -340,5 +362,5 @@ def _calculate_img_number(save_dir_path: str, task_data: TaskData):
_calculate_img_number.session_img_numbers = {} _calculate_img_number.session_img_numbers = {}
def calculate_img_number(save_dir_path: str, task_data: TaskData): def calculate_img_number(save_dir_path: str, task_data: RenderTaskData):
return ImageNumber(lambda: _calculate_img_number(save_dir_path, task_data)) return ImageNumber(lambda: _calculate_img_number(save_dir_path, task_data))

View File

@ -852,6 +852,10 @@ function applyInlineFilter(filterName, path, filterParams, img, statusText, tool
} }
filterReq.model_paths[filterName] = path filterReq.model_paths[filterName] = path
if (saveToDiskField.checked && diskPathField.value.trim() !== "") {
filterReq.save_to_disk_path = diskPathField.value.trim()
}
tools.spinnerStatus.innerText = statusText tools.spinnerStatus.innerText = statusText
tools.spinner.classList.remove("displayNone") tools.spinner.classList.remove("displayNone")

View File

@ -238,7 +238,7 @@ var PARAMETERS = [
default: false, default: false,
}, },
{ {
id: "test_diffusers", id: "use_v3_engine",
type: ParameterType.checkbox, type: ParameterType.checkbox,
label: "Use the new v3 engine (diffusers)", label: "Use the new v3 engine (diffusers)",
note: note:
@ -420,7 +420,7 @@ let listenPortField = document.querySelector("#listen_port")
let useBetaChannelField = document.querySelector("#use_beta_channel") let useBetaChannelField = document.querySelector("#use_beta_channel")
let uiOpenBrowserOnStartField = document.querySelector("#ui_open_browser_on_start") let uiOpenBrowserOnStartField = document.querySelector("#ui_open_browser_on_start")
let confirmDangerousActionsField = document.querySelector("#confirm_dangerous_actions") let confirmDangerousActionsField = document.querySelector("#confirm_dangerous_actions")
let testDiffusers = document.querySelector("#test_diffusers") let testDiffusers = document.querySelector("#use_v3_engine")
let profileNameField = document.querySelector("#profileName") let profileNameField = document.querySelector("#profileName")
let saveSettingsBtn = document.querySelector("#save-system-settings-btn") let saveSettingsBtn = document.querySelector("#save-system-settings-btn")
@ -465,13 +465,13 @@ async function getAppConfig() {
} }
let testDiffusersEnabled = true let testDiffusersEnabled = true
if (config.test_diffusers === false) { if (config.use_v3_engine === false) {
testDiffusersEnabled = false testDiffusersEnabled = false
} }
testDiffusers.checked = testDiffusersEnabled testDiffusers.checked = testDiffusersEnabled
if (config.config_on_startup) { if (config.config_on_startup) {
if (config.config_on_startup?.test_diffusers) { if (config.config_on_startup?.use_v3_engine) {
document.body.classList.add("diffusers-enabled-on-startup") document.body.classList.add("diffusers-enabled-on-startup")
document.body.classList.remove("diffusers-disabled-on-startup") document.body.classList.remove("diffusers-disabled-on-startup")
} else { } else {