From d3f9156854b3d6b4c3d5d736f3b0454743203076 Mon Sep 17 00:00:00 2001 From: Manuel Schmid Date: Sat, 18 Nov 2023 13:02:39 +0100 Subject: [PATCH 1/6] only make stop_button and skip_button interactive when rendering process starts fix inconsistency in behaviour of stop_button and skip_button as it was possible to skip or stop other users processes while still being in queue --- webui.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/webui.py b/webui.py index d1381d5e..35ef0629 100644 --- a/webui.py +++ b/webui.py @@ -31,7 +31,9 @@ def generate_clicked(*args): yield gr.update(visible=True, value=modules.html.make_progress_html(1, 'Waiting for task to start ...')), \ gr.update(visible=True, value=None), \ gr.update(visible=False, value=None), \ - gr.update(visible=False) + gr.update(visible=False), \ + gr.update(visible=True, interactive=True), \ + gr.update(visible=True, interactive=True) worker.async_tasks.append(task) @@ -51,17 +53,23 @@ def generate_clicked(*args): yield gr.update(visible=True, value=modules.html.make_progress_html(percentage, title)), \ gr.update(visible=True, value=image) if image is not None else gr.update(), \ gr.update(), \ - gr.update(visible=False) + gr.update(visible=False), \ + gr.update(visible=True), \ + gr.update(visible=True) if flag == 'results': yield gr.update(visible=True), \ gr.update(visible=True), \ gr.update(visible=True, value=product), \ - gr.update(visible=False) + gr.update(visible=False), \ + gr.update(visible=True), \ + gr.update(visible=True) if flag == 'finish': yield gr.update(visible=False), \ gr.update(visible=False), \ gr.update(visible=False), \ - gr.update(visible=True, value=product) + gr.update(visible=True, value=product), \ + gr.update(visible=False), \ + gr.update(visible=False) finished = True execution_time = time.perf_counter() - execution_start_time @@ -437,10 +445,10 @@ with shared.gradio_root: ctrls += [outpaint_selections, inpaint_input_image] ctrls += ip_ctrls - generate_button.click(lambda: (gr.update(visible=True, interactive=True), gr.update(visible=True, interactive=True), gr.update(visible=False), []), outputs=[stop_button, skip_button, generate_button, gallery]) \ + generate_button.click(lambda: (gr.update(visible=True, interactive=False), gr.update(visible=True, interactive=False), gr.update(visible=False), []), outputs=[stop_button, skip_button, generate_button, gallery]) \ .then(fn=refresh_seed, inputs=[seed_random, image_seed], outputs=image_seed) \ .then(advanced_parameters.set_all_advanced_parameters, inputs=adps) \ - .then(fn=generate_clicked, inputs=ctrls, outputs=[progress_html, progress_window, progress_gallery, gallery]) \ + .then(fn=generate_clicked, inputs=ctrls, outputs=[progress_html, progress_window, progress_gallery, gallery, stop_button, skip_button]) \ .then(lambda: (gr.update(visible=True), gr.update(visible=False), gr.update(visible=False)), outputs=[generate_button, stop_button, skip_button]) \ .then(fn=lambda: None, _js='playNotification').then(fn=lambda: None, _js='refresh_grid_delayed') From 617255d040a97b849d5ec698c0fb4ef0168a5e32 Mon Sep 17 00:00:00 2001 From: Manuel Schmid Date: Sat, 18 Nov 2023 17:20:41 +0100 Subject: [PATCH 2/6] use AsyncTask for last_stop handling instead of shared --- modules/async_worker.py | 3 ++- shared.py | 3 +-- webui.py | 7 ++++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/modules/async_worker.py b/modules/async_worker.py index b4207591..0ca051d0 100644 --- a/modules/async_worker.py +++ b/modules/async_worker.py @@ -6,6 +6,7 @@ class AsyncTask: self.args = args self.yields = [] self.results = [] + self.last_stop = False async_tasks = [] @@ -722,7 +723,7 @@ def worker(): yield_result(async_task, imgs, do_not_show_finished_images=len(tasks) == 1) except fcbh.model_management.InterruptProcessingException as e: - if shared.last_stop == 'skip': + if async_task.last_stop == 'skip': print('User skipped') continue else: diff --git a/shared.py b/shared.py index 269809e3..21a2a864 100644 --- a/shared.py +++ b/shared.py @@ -1,2 +1 @@ -gradio_root = None -last_stop = None +gradio_root = None \ No newline at end of file diff --git a/webui.py b/webui.py index 35ef0629..aa936d79 100644 --- a/webui.py +++ b/webui.py @@ -20,12 +20,13 @@ from modules.private_logger import get_current_html_path from modules.ui_gradio_extensions import reload_javascript from modules.auth import auth_enabled, check_auth +currentTask = gr.State() def generate_clicked(*args): # outputs=[progress_html, progress_window, progress_gallery, gallery] execution_start_time = time.perf_counter() - task = worker.AsyncTask(args=list(args)) + currentTask.value = task = worker.AsyncTask(args=list(args)) finished = False yield gr.update(visible=True, value=modules.html.make_progress_html(1, 'Waiting for task to start ...')), \ @@ -117,13 +118,13 @@ with shared.gradio_root: def stop_clicked(): import fcbh.model_management as model_management - shared.last_stop = 'stop' + currentTask.value.last_stop = 'stop' model_management.interrupt_current_processing() return [gr.update(interactive=False)] * 2 def skip_clicked(): import fcbh.model_management as model_management - shared.last_stop = 'skip' + currentTask.value.last_stop = 'skip' model_management.interrupt_current_processing() return From 83efbbd2fac52c34661fbaf0448d56722731b3da Mon Sep 17 00:00:00 2001 From: Manuel Schmid Date: Sat, 18 Nov 2023 17:23:37 +0100 Subject: [PATCH 3/6] Revert "only make stop_button and skip_button interactive when rendering process starts" This reverts commit d3f9156854b3d6b4c3d5d736f3b0454743203076. --- webui.py | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/webui.py b/webui.py index aa936d79..e43a6c96 100644 --- a/webui.py +++ b/webui.py @@ -32,9 +32,7 @@ def generate_clicked(*args): yield gr.update(visible=True, value=modules.html.make_progress_html(1, 'Waiting for task to start ...')), \ gr.update(visible=True, value=None), \ gr.update(visible=False, value=None), \ - gr.update(visible=False), \ - gr.update(visible=True, interactive=True), \ - gr.update(visible=True, interactive=True) + gr.update(visible=False) worker.async_tasks.append(task) @@ -54,23 +52,17 @@ def generate_clicked(*args): yield gr.update(visible=True, value=modules.html.make_progress_html(percentage, title)), \ gr.update(visible=True, value=image) if image is not None else gr.update(), \ gr.update(), \ - gr.update(visible=False), \ - gr.update(visible=True), \ - gr.update(visible=True) + gr.update(visible=False) if flag == 'results': yield gr.update(visible=True), \ gr.update(visible=True), \ gr.update(visible=True, value=product), \ - gr.update(visible=False), \ - gr.update(visible=True), \ - gr.update(visible=True) + gr.update(visible=False) if flag == 'finish': yield gr.update(visible=False), \ gr.update(visible=False), \ gr.update(visible=False), \ - gr.update(visible=True, value=product), \ - gr.update(visible=False), \ - gr.update(visible=False) + gr.update(visible=True, value=product) finished = True execution_time = time.perf_counter() - execution_start_time @@ -446,10 +438,10 @@ with shared.gradio_root: ctrls += [outpaint_selections, inpaint_input_image] ctrls += ip_ctrls - generate_button.click(lambda: (gr.update(visible=True, interactive=False), gr.update(visible=True, interactive=False), gr.update(visible=False), []), outputs=[stop_button, skip_button, generate_button, gallery]) \ + generate_button.click(lambda: (gr.update(visible=True, interactive=True), gr.update(visible=True, interactive=True), gr.update(visible=False), []), outputs=[stop_button, skip_button, generate_button, gallery]) \ .then(fn=refresh_seed, inputs=[seed_random, image_seed], outputs=image_seed) \ .then(advanced_parameters.set_all_advanced_parameters, inputs=adps) \ - .then(fn=generate_clicked, inputs=ctrls, outputs=[progress_html, progress_window, progress_gallery, gallery, stop_button, skip_button]) \ + .then(fn=generate_clicked, inputs=ctrls, outputs=[progress_html, progress_window, progress_gallery, gallery]) \ .then(lambda: (gr.update(visible=True), gr.update(visible=False), gr.update(visible=False)), outputs=[generate_button, stop_button, skip_button]) \ .then(fn=lambda: None, _js='playNotification').then(fn=lambda: None, _js='refresh_grid_delayed') From ebad9ea9760cb45d822c3242524a10611c08f0ac Mon Sep 17 00:00:00 2001 From: Manuel Schmid Date: Sat, 18 Nov 2023 20:46:09 +0100 Subject: [PATCH 4/6] introduce state for task skipping/stopping --- modules/async_worker.py | 6 +++++- webui.py | 39 +++++++++++++++++++++++---------------- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/modules/async_worker.py b/modules/async_worker.py index 0ca051d0..e6cc8a49 100644 --- a/modules/async_worker.py +++ b/modules/async_worker.py @@ -7,6 +7,7 @@ class AsyncTask: self.yields = [] self.results = [] self.last_stop = False + self.processing = False async_tasks = [] @@ -115,6 +116,7 @@ def worker(): @torch.inference_mode() def handler(async_task): execution_start_time = time.perf_counter() + async_task.processing = True args = async_task.args args.reverse() @@ -660,6 +662,8 @@ def worker(): execution_start_time = time.perf_counter() try: + if async_task.last_stop is not False: + fcbh.model_management.interrupt_current_processing() positive_cond, negative_cond = task['c'], task['uc'] if 'cn' in goals: @@ -732,7 +736,7 @@ def worker(): execution_time = time.perf_counter() - execution_start_time print(f'Generating and saving time: {execution_time:.2f} seconds') - + async_task.processing = False return while True: diff --git a/webui.py b/webui.py index e43a6c96..3dde192c 100644 --- a/webui.py +++ b/webui.py @@ -20,13 +20,15 @@ from modules.private_logger import get_current_html_path from modules.ui_gradio_extensions import reload_javascript from modules.auth import auth_enabled, check_auth -currentTask = gr.State() +def get_task(*args): + args = list(args) + currentTask = args.pop(0) + currentTask = worker.AsyncTask(args=args) + return currentTask -def generate_clicked(*args): +def generate_clicked(task): # outputs=[progress_html, progress_window, progress_gallery, gallery] - execution_start_time = time.perf_counter() - currentTask.value = task = worker.AsyncTask(args=list(args)) finished = False yield gr.update(visible=True, value=modules.html.make_progress_html(1, 'Waiting for task to start ...')), \ @@ -82,6 +84,7 @@ shared.gradio_root = gr.Blocks( css=modules.html.css).queue() with shared.gradio_root: + currentTask = gr.State(worker.AsyncTask(args=[])) with gr.Row(): with gr.Column(scale=2): with gr.Row(): @@ -108,21 +111,24 @@ with shared.gradio_root: skip_button = gr.Button(label="Skip", value="Skip", elem_classes='type_row_half', visible=False) stop_button = gr.Button(label="Stop", value="Stop", elem_classes='type_row_half', elem_id='stop_button', visible=False) - def stop_clicked(): + def stop_clicked(currentTask): import fcbh.model_management as model_management - currentTask.value.last_stop = 'stop' - model_management.interrupt_current_processing() - return [gr.update(interactive=False)] * 2 + currentTask.last_stop = 'stop' + if (currentTask.processing): + model_management.interrupt_current_processing() + return [gr.update(interactive=False)] * 2, currentTask - def skip_clicked(): + def skip_clicked(currentTask): import fcbh.model_management as model_management - currentTask.value.last_stop = 'skip' - model_management.interrupt_current_processing() - return + currentTask.last_stop = 'skip' + if (currentTask.processing): + model_management.interrupt_current_processing() + return currentTask - stop_button.click(stop_clicked, outputs=[skip_button, stop_button], + stop_button.click(stop_clicked, inputs=currentTask, outputs=[skip_button, stop_button, currentTask], queue=False, show_progress=False, _js='cancelGenerateForever') - skip_button.click(skip_clicked, queue=False, show_progress=False) + skip_button.click(skip_clicked, inputs=currentTask, outputs=currentTask, + queue=False, show_progress=False) with gr.Row(elem_classes='advanced_check_row'): input_image_checkbox = gr.Checkbox(label='Input Image', value=False, container=False, elem_classes='min_check') advanced_checkbox = gr.Checkbox(label='Advanced', value=modules.config.default_advanced_checkbox, container=False, elem_classes='min_check') @@ -428,7 +434,7 @@ with shared.gradio_root: .then(fn=lambda: None, _js='refresh_grid_delayed', queue=False, show_progress=False) ctrls = [ - prompt, negative_prompt, style_selections, + currentTask, prompt, negative_prompt, style_selections, performance_selection, aspect_ratios_selection, image_number, image_seed, sharpness, guidance_scale ] @@ -441,7 +447,8 @@ with shared.gradio_root: generate_button.click(lambda: (gr.update(visible=True, interactive=True), gr.update(visible=True, interactive=True), gr.update(visible=False), []), outputs=[stop_button, skip_button, generate_button, gallery]) \ .then(fn=refresh_seed, inputs=[seed_random, image_seed], outputs=image_seed) \ .then(advanced_parameters.set_all_advanced_parameters, inputs=adps) \ - .then(fn=generate_clicked, inputs=ctrls, outputs=[progress_html, progress_window, progress_gallery, gallery]) \ + .then(fn=get_task, inputs=ctrls, outputs=currentTask) \ + .then(fn=generate_clicked, inputs=currentTask, outputs=[progress_html, progress_window, progress_gallery, gallery]) \ .then(lambda: (gr.update(visible=True), gr.update(visible=False), gr.update(visible=False)), outputs=[generate_button, stop_button, skip_button]) \ .then(fn=lambda: None, _js='playNotification').then(fn=lambda: None, _js='refresh_grid_delayed') From 8060e50a88adfac3d35235c8bbc1af68f80e50bc Mon Sep 17 00:00:00 2001 From: Manuel Schmid Date: Sat, 18 Nov 2023 21:00:35 +0100 Subject: [PATCH 5/6] fix return parameters of stop_clicked --- webui.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webui.py b/webui.py index 3dde192c..be2e55f9 100644 --- a/webui.py +++ b/webui.py @@ -116,9 +116,10 @@ with shared.gradio_root: currentTask.last_stop = 'stop' if (currentTask.processing): model_management.interrupt_current_processing() - return [gr.update(interactive=False)] * 2, currentTask + return gr.update(interactive=False), gr.update(interactive=False), currentTask def skip_clicked(currentTask): + print(currentTask.last_stop) import fcbh.model_management as model_management currentTask.last_stop = 'skip' if (currentTask.processing): From 4a576bf08be6bd6926d12240492db4406437decb Mon Sep 17 00:00:00 2001 From: Manuel Schmid Date: Sat, 18 Nov 2023 21:40:14 +0100 Subject: [PATCH 6/6] code cleanup, do not disable skip/stop on stop_clicked --- webui.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/webui.py b/webui.py index be2e55f9..a00eb7ed 100644 --- a/webui.py +++ b/webui.py @@ -116,20 +116,17 @@ with shared.gradio_root: currentTask.last_stop = 'stop' if (currentTask.processing): model_management.interrupt_current_processing() - return gr.update(interactive=False), gr.update(interactive=False), currentTask + return currentTask def skip_clicked(currentTask): - print(currentTask.last_stop) import fcbh.model_management as model_management currentTask.last_stop = 'skip' if (currentTask.processing): model_management.interrupt_current_processing() return currentTask - stop_button.click(stop_clicked, inputs=currentTask, outputs=[skip_button, stop_button, currentTask], - queue=False, show_progress=False, _js='cancelGenerateForever') - skip_button.click(skip_clicked, inputs=currentTask, outputs=currentTask, - queue=False, show_progress=False) + stop_button.click(stop_clicked, inputs=currentTask, outputs=currentTask, queue=False, show_progress=False, _js='cancelGenerateForever') + skip_button.click(skip_clicked, inputs=currentTask, outputs=currentTask, queue=False, show_progress=False) with gr.Row(elem_classes='advanced_check_row'): input_image_checkbox = gr.Checkbox(label='Input Image', value=False, container=False, elem_classes='min_check') advanced_checkbox = gr.Checkbox(label='Advanced', value=modules.config.default_advanced_checkbox, container=False, elem_classes='min_check')