From dfa258de5f87ea7f5ff49e29ddf6e7b34ff8ebff Mon Sep 17 00:00:00 2001 From: Vespinian Date: Wed, 15 Mar 2023 22:17:32 -0400 Subject: [PATCH 1/5] Made copies of global scriptrunners, now we clear the copied scriptrunner of alwayson_scripts and only add back the ones that that were requested --- modules/api/api.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/modules/api/api.py b/modules/api/api.py index 35e17afc..afbc202a 100644 --- a/modules/api/api.py +++ b/modules/api/api.py @@ -3,6 +3,7 @@ import io import time import datetime import uvicorn +import copy from threading import Lock from io import BytesIO from gradio.processing_utils import decode_base64_to_file @@ -202,6 +203,7 @@ class Api: script_args[0] = 0 # Now check for always on scripts + alwayson_script_to_run = [] # list to replace the one from the global ScriptRunner we copied if request.alwayson_scripts and (len(request.alwayson_scripts) > 0): for alwayson_script_name in request.alwayson_scripts.keys(): alwayson_script = self.get_script(alwayson_script_name, script_runner) @@ -210,13 +212,21 @@ class Api: # Selectable script in always on script param check if alwayson_script.alwayson == False: raise HTTPException(status_code=422, detail=f"Cannot have a selectable script in the always on scripts params") - # always on script with no arg should always run so you don't really need to add them to the requests + # all good, so add to run list and set its args if any + alwayson_script_to_run.append(alwayson_script) if "args" in request.alwayson_scripts[alwayson_script_name]: script_args[alwayson_script.args_from:alwayson_script.args_to] = request.alwayson_scripts[alwayson_script_name]["args"] + + # Remove always on scripts that were not included in the request by resetting the script list in out ScriptRunner + script_runner.alwayson_scripts.clear() + script_runner.alwayson_scripts = alwayson_script_to_run + script_runner.scripts.clear() + script_runner.scripts = alwayson_script_to_run + script_runner.selectable_scripts + return script_args def text2imgapi(self, txt2imgreq: StableDiffusionTxt2ImgProcessingAPI): - script_runner = scripts.scripts_txt2img + script_runner = copy.copy(scripts.scripts_txt2img) # copy so we don't overwrite our globals if not script_runner.scripts: script_runner.initialize_scripts(False) ui.create_ui() @@ -268,7 +278,7 @@ class Api: if mask: mask = decode_base64_to_image(mask) - script_runner = scripts.scripts_img2img + script_runner = copy.copy(scripts.scripts_img2img) # copy so we don't overwrite our globals if not script_runner.scripts: script_runner.initialize_scripts(True) ui.create_ui() From f04bd037a51de3c65072581d9a7dfed1d0d2887e Mon Sep 17 00:00:00 2001 From: Vespinian Date: Wed, 15 Mar 2023 22:27:54 -0400 Subject: [PATCH 2/5] Comment fix --- modules/api/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/api/api.py b/modules/api/api.py index afbc202a..8c06cf20 100644 --- a/modules/api/api.py +++ b/modules/api/api.py @@ -217,7 +217,7 @@ class Api: if "args" in request.alwayson_scripts[alwayson_script_name]: script_args[alwayson_script.args_from:alwayson_script.args_to] = request.alwayson_scripts[alwayson_script_name]["args"] - # Remove always on scripts that were not included in the request by resetting the script list in out ScriptRunner + # Remove always on scripts that were not included in the request by resetting the script list in our ScriptRunner script_runner.alwayson_scripts.clear() script_runner.alwayson_scripts = alwayson_script_to_run script_runner.scripts.clear() From db602b100e271e902e120fa8aa5c859e3ef3962f Mon Sep 17 00:00:00 2001 From: Vespinian Date: Sat, 25 Mar 2023 14:11:38 -0400 Subject: [PATCH 3/5] Revert "Comment fix" This reverts commit f04bd037a51de3c65072581d9a7dfed1d0d2887e. --- modules/api/api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/api/api.py b/modules/api/api.py index 8c06cf20..afbc202a 100644 --- a/modules/api/api.py +++ b/modules/api/api.py @@ -217,7 +217,7 @@ class Api: if "args" in request.alwayson_scripts[alwayson_script_name]: script_args[alwayson_script.args_from:alwayson_script.args_to] = request.alwayson_scripts[alwayson_script_name]["args"] - # Remove always on scripts that were not included in the request by resetting the script list in our ScriptRunner + # Remove always on scripts that were not included in the request by resetting the script list in out ScriptRunner script_runner.alwayson_scripts.clear() script_runner.alwayson_scripts = alwayson_script_to_run script_runner.scripts.clear() From f3715795710b3b39029325b88a2c101279c2dd2c Mon Sep 17 00:00:00 2001 From: Vespinian Date: Sat, 25 Mar 2023 14:11:46 -0400 Subject: [PATCH 4/5] Revert "Made copies of global scriptrunners, now we clear the copied scriptrunner of alwayson_scripts and only add back the ones that that were requested" This reverts commit dfa258de5f87ea7f5ff49e29ddf6e7b34ff8ebff. --- modules/api/api.py | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/modules/api/api.py b/modules/api/api.py index afbc202a..35e17afc 100644 --- a/modules/api/api.py +++ b/modules/api/api.py @@ -3,7 +3,6 @@ import io import time import datetime import uvicorn -import copy from threading import Lock from io import BytesIO from gradio.processing_utils import decode_base64_to_file @@ -203,7 +202,6 @@ class Api: script_args[0] = 0 # Now check for always on scripts - alwayson_script_to_run = [] # list to replace the one from the global ScriptRunner we copied if request.alwayson_scripts and (len(request.alwayson_scripts) > 0): for alwayson_script_name in request.alwayson_scripts.keys(): alwayson_script = self.get_script(alwayson_script_name, script_runner) @@ -212,21 +210,13 @@ class Api: # Selectable script in always on script param check if alwayson_script.alwayson == False: raise HTTPException(status_code=422, detail=f"Cannot have a selectable script in the always on scripts params") - # all good, so add to run list and set its args if any - alwayson_script_to_run.append(alwayson_script) + # always on script with no arg should always run so you don't really need to add them to the requests if "args" in request.alwayson_scripts[alwayson_script_name]: script_args[alwayson_script.args_from:alwayson_script.args_to] = request.alwayson_scripts[alwayson_script_name]["args"] - - # Remove always on scripts that were not included in the request by resetting the script list in out ScriptRunner - script_runner.alwayson_scripts.clear() - script_runner.alwayson_scripts = alwayson_script_to_run - script_runner.scripts.clear() - script_runner.scripts = alwayson_script_to_run + script_runner.selectable_scripts - return script_args def text2imgapi(self, txt2imgreq: StableDiffusionTxt2ImgProcessingAPI): - script_runner = copy.copy(scripts.scripts_txt2img) # copy so we don't overwrite our globals + script_runner = scripts.scripts_txt2img if not script_runner.scripts: script_runner.initialize_scripts(False) ui.create_ui() @@ -278,7 +268,7 @@ class Api: if mask: mask = decode_base64_to_image(mask) - script_runner = copy.copy(scripts.scripts_img2img) # copy so we don't overwrite our globals + script_runner = scripts.scripts_img2img if not script_runner.scripts: script_runner.initialize_scripts(True) ui.create_ui() From 23f6dfce4cd3969dab7e707142e7da7c389704fa Mon Sep 17 00:00:00 2001 From: Vespinian Date: Sat, 25 Mar 2023 14:16:35 -0400 Subject: [PATCH 5/5] Reworked this PR, now we have 2 default arg list (one for each tab) that will be initialized on the first api request and then reused afterwards. The init_script_args copies the corresponding default list and applies the modifications asked by the api request. --- modules/api/api.py | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/modules/api/api.py b/modules/api/api.py index 35e17afc..596b20b2 100644 --- a/modules/api/api.py +++ b/modules/api/api.py @@ -3,6 +3,7 @@ import io import time import datetime import uvicorn +import gradio as gr from threading import Lock from io import BytesIO from gradio.processing_utils import decode_base64_to_file @@ -152,6 +153,9 @@ class Api: self.add_api_route("/sdapi/v1/memory", self.get_memory, methods=["GET"], response_model=MemoryResponse) self.add_api_route("/sdapi/v1/scripts", self.get_scripts_list, methods=["GET"], response_model=ScriptsList) + self.default_script_arg_txt2img = [] + self.default_script_arg_img2img = [] + def add_api_route(self, path: str, endpoint, **kwargs): if shared.cmd_opts.api_auth: return self.app.add_api_route(path, endpoint, dependencies=[Depends(self.auth)], **kwargs) @@ -185,7 +189,7 @@ class Api: script_idx = script_name_to_index(script_name, script_runner.scripts) return script_runner.scripts[script_idx] - def init_script_args(self, request, selectable_scripts, selectable_idx, script_runner): + def init_default_script_args(self, script_runner): #find max idx from the scripts in runner and generate a none array to init script_args last_arg_index = 1 for script in script_runner.scripts: @@ -193,13 +197,24 @@ class Api: last_arg_index = script.args_to # None everywhere except position 0 to initialize script args script_args = [None]*last_arg_index + script_args[0] = 0 + + # get default values + with gr.Blocks(): # will throw errors calling ui function without this + for script in script_runner.scripts: + if script.ui(script.is_img2img): + ui_default_values = [] + for elem in script.ui(script.is_img2img): + ui_default_values.append(elem.value) + script_args[script.args_from:script.args_to] = ui_default_values + return script_args + + def init_script_args(self, request, default_script_args, selectable_scripts, selectable_idx, script_runner): + script_args = default_script_args.copy() # position 0 in script_arg is the idx+1 of the selectable script that is going to be run when using scripts.scripts_*2img.run() if selectable_scripts: script_args[selectable_scripts.args_from:selectable_scripts.args_to] = request.script_args script_args[0] = selectable_idx + 1 - else: - # when [0] = 0 no selectable script to run - script_args[0] = 0 # Now check for always on scripts if request.alwayson_scripts and (len(request.alwayson_scripts) > 0): @@ -220,6 +235,8 @@ class Api: if not script_runner.scripts: script_runner.initialize_scripts(False) ui.create_ui() + if not self.default_script_arg_txt2img: + self.default_script_arg_txt2img = self.init_default_script_args(script_runner) selectable_scripts, selectable_script_idx = self.get_selectable_script(txt2imgreq.script_name, script_runner) populate = txt2imgreq.copy(update={ # Override __init__ params @@ -235,7 +252,7 @@ class Api: args.pop('script_args', None) # will refeed them to the pipeline directly after initializing them args.pop('alwayson_scripts', None) - script_args = self.init_script_args(txt2imgreq, selectable_scripts, selectable_script_idx, script_runner) + script_args = self.init_script_args(txt2imgreq, self.default_script_arg_txt2img, selectable_scripts, selectable_script_idx, script_runner) send_images = args.pop('send_images', True) args.pop('save_images', None) @@ -272,6 +289,8 @@ class Api: if not script_runner.scripts: script_runner.initialize_scripts(True) ui.create_ui() + if not self.default_script_arg_img2img: + self.default_script_arg_img2img = self.init_default_script_args(script_runner) selectable_scripts, selectable_script_idx = self.get_selectable_script(img2imgreq.script_name, script_runner) populate = img2imgreq.copy(update={ # Override __init__ params @@ -289,7 +308,7 @@ class Api: args.pop('script_args', None) # will refeed them to the pipeline directly after initializing them args.pop('alwayson_scripts', None) - script_args = self.init_script_args(img2imgreq, selectable_scripts, selectable_script_idx, script_runner) + script_args = self.init_script_args(img2imgreq, self.default_script_arg_img2img, selectable_scripts, selectable_script_idx, script_runner) send_images = args.pop('send_images', True) args.pop('save_images', None)