big rework of progressbar/preview system to allow multiple users to prompts at the same time and do not get previews of each other
parent
ebfdd7baeb
commit
d8b90ac121
@ -1,8 +1,17 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
function start_training_textual_inversion(){
|
function start_training_textual_inversion(){
|
||||||
requestProgress('ti')
|
|
||||||
gradioApp().querySelector('#ti_error').innerHTML=''
|
gradioApp().querySelector('#ti_error').innerHTML=''
|
||||||
|
|
||||||
return args_to_array(arguments)
|
var id = randomId()
|
||||||
|
requestProgress(id, gradioApp().getElementById('ti_output'), gradioApp().getElementById('ti_gallery'), function(){}, function(progress){
|
||||||
|
gradioApp().getElementById('ti_progress').innerHTML = progress.textinfo
|
||||||
|
})
|
||||||
|
|
||||||
|
var res = args_to_array(arguments)
|
||||||
|
|
||||||
|
res[0] = id
|
||||||
|
|
||||||
|
return res
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,96 @@
|
|||||||
|
import base64
|
||||||
|
import io
|
||||||
|
import time
|
||||||
|
|
||||||
|
import gradio as gr
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
|
from modules.shared import opts
|
||||||
|
|
||||||
|
import modules.shared as shared
|
||||||
|
|
||||||
|
|
||||||
|
current_task = None
|
||||||
|
pending_tasks = {}
|
||||||
|
finished_tasks = []
|
||||||
|
|
||||||
|
|
||||||
|
def start_task(id_task):
|
||||||
|
global current_task
|
||||||
|
|
||||||
|
current_task = id_task
|
||||||
|
pending_tasks.pop(id_task, None)
|
||||||
|
|
||||||
|
|
||||||
|
def finish_task(id_task):
|
||||||
|
global current_task
|
||||||
|
|
||||||
|
if current_task == id_task:
|
||||||
|
current_task = None
|
||||||
|
|
||||||
|
finished_tasks.append(id_task)
|
||||||
|
if len(finished_tasks) > 16:
|
||||||
|
finished_tasks.pop(0)
|
||||||
|
|
||||||
|
|
||||||
|
def add_task_to_queue(id_job):
|
||||||
|
pending_tasks[id_job] = time.time()
|
||||||
|
|
||||||
|
|
||||||
|
class ProgressRequest(BaseModel):
|
||||||
|
id_task: str = Field(default=None, title="Task ID", description="id of the task to get progress for")
|
||||||
|
id_live_preview: int = Field(default=-1, title="Live preview image ID", description="id of last received last preview image")
|
||||||
|
|
||||||
|
|
||||||
|
class ProgressResponse(BaseModel):
|
||||||
|
active: bool = Field(title="Whether the task is being worked on right now")
|
||||||
|
queued: bool = Field(title="Whether the task is in queue")
|
||||||
|
completed: bool = Field(title="Whether the task has already finished")
|
||||||
|
progress: float = Field(default=None, title="Progress", description="The progress with a range of 0 to 1")
|
||||||
|
eta: float = Field(default=None, title="ETA in secs")
|
||||||
|
live_preview: str = Field(default=None, title="Live preview image", description="Current live preview; a data: uri")
|
||||||
|
id_live_preview: int = Field(default=None, title="Live preview image ID", description="Send this together with next request to prevent receiving same image")
|
||||||
|
textinfo: str = Field(default=None, title="Info text", description="Info text used by WebUI.")
|
||||||
|
|
||||||
|
|
||||||
|
def setup_progress_api(app):
|
||||||
|
return app.add_api_route("/internal/progress", progressapi, methods=["POST"], response_model=ProgressResponse)
|
||||||
|
|
||||||
|
|
||||||
|
def progressapi(req: ProgressRequest):
|
||||||
|
active = req.id_task == current_task
|
||||||
|
queued = req.id_task in pending_tasks
|
||||||
|
completed = req.id_task in finished_tasks
|
||||||
|
|
||||||
|
if not active:
|
||||||
|
return ProgressResponse(active=active, queued=queued, completed=completed, id_live_preview=-1, textinfo="In queue..." if queued else "Waiting...")
|
||||||
|
|
||||||
|
progress = 0
|
||||||
|
|
||||||
|
if shared.state.job_count > 0:
|
||||||
|
progress += shared.state.job_no / shared.state.job_count
|
||||||
|
if shared.state.sampling_steps > 0:
|
||||||
|
progress += 1 / shared.state.job_count * shared.state.sampling_step / shared.state.sampling_steps
|
||||||
|
|
||||||
|
progress = min(progress, 1)
|
||||||
|
|
||||||
|
elapsed_since_start = time.time() - shared.state.time_start
|
||||||
|
predicted_duration = elapsed_since_start / progress if progress > 0 else None
|
||||||
|
eta = predicted_duration - elapsed_since_start if predicted_duration is not None else None
|
||||||
|
|
||||||
|
id_live_preview = req.id_live_preview
|
||||||
|
shared.state.set_current_image()
|
||||||
|
if opts.live_previews_enable and shared.state.id_live_preview != req.id_live_preview:
|
||||||
|
image = shared.state.current_image
|
||||||
|
if image is not None:
|
||||||
|
buffered = io.BytesIO()
|
||||||
|
image.save(buffered, format="png")
|
||||||
|
live_preview = 'data:image/png;base64,' + base64.b64encode(buffered.getvalue()).decode("ascii")
|
||||||
|
id_live_preview = shared.state.id_live_preview
|
||||||
|
else:
|
||||||
|
live_preview = None
|
||||||
|
else:
|
||||||
|
live_preview = None
|
||||||
|
|
||||||
|
return ProgressResponse(active=active, queued=queued, completed=completed, progress=progress, eta=eta, live_preview=live_preview, id_live_preview=id_live_preview, textinfo=shared.state.textinfo)
|
||||||
|
|
||||||
@ -1,101 +0,0 @@
|
|||||||
import time
|
|
||||||
|
|
||||||
import gradio as gr
|
|
||||||
|
|
||||||
from modules.shared import opts
|
|
||||||
|
|
||||||
import modules.shared as shared
|
|
||||||
|
|
||||||
|
|
||||||
def calc_time_left(progress, threshold, label, force_display, show_eta):
|
|
||||||
if progress == 0:
|
|
||||||
return ""
|
|
||||||
else:
|
|
||||||
time_since_start = time.time() - shared.state.time_start
|
|
||||||
eta = (time_since_start/progress)
|
|
||||||
eta_relative = eta-time_since_start
|
|
||||||
if (eta_relative > threshold and show_eta) or force_display:
|
|
||||||
if eta_relative > 3600:
|
|
||||||
return label + time.strftime('%H:%M:%S', time.gmtime(eta_relative))
|
|
||||||
elif eta_relative > 60:
|
|
||||||
return label + time.strftime('%M:%S', time.gmtime(eta_relative))
|
|
||||||
else:
|
|
||||||
return label + time.strftime('%Ss', time.gmtime(eta_relative))
|
|
||||||
else:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
def check_progress_call(id_part):
|
|
||||||
if shared.state.job_count == 0:
|
|
||||||
return "", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
|
|
||||||
|
|
||||||
progress = 0
|
|
||||||
|
|
||||||
if shared.state.job_count > 0:
|
|
||||||
progress += shared.state.job_no / shared.state.job_count
|
|
||||||
if shared.state.sampling_steps > 0:
|
|
||||||
progress += 1 / shared.state.job_count * shared.state.sampling_step / shared.state.sampling_steps
|
|
||||||
|
|
||||||
# Show progress percentage and time left at the same moment, and base it also on steps done
|
|
||||||
show_eta = progress >= 0.01 or shared.state.sampling_step >= 10
|
|
||||||
|
|
||||||
time_left = calc_time_left(progress, 1, " ETA: ", shared.state.time_left_force_display, show_eta)
|
|
||||||
if time_left != "":
|
|
||||||
shared.state.time_left_force_display = True
|
|
||||||
|
|
||||||
progress = min(progress, 1)
|
|
||||||
|
|
||||||
progressbar = ""
|
|
||||||
if opts.show_progressbar:
|
|
||||||
progressbar = f"""<div class='progressDiv'><div class='progress' style="overflow:visible;width:{progress * 100}%;white-space:nowrap;">{" " * 2 + str(int(progress*100))+"%" + time_left if show_eta else ""}</div></div>"""
|
|
||||||
|
|
||||||
image = gr.update(visible=False)
|
|
||||||
preview_visibility = gr.update(visible=False)
|
|
||||||
|
|
||||||
if opts.live_previews_enable:
|
|
||||||
shared.state.set_current_image()
|
|
||||||
image = shared.state.current_image
|
|
||||||
|
|
||||||
if image is None:
|
|
||||||
image = gr.update(value=None)
|
|
||||||
else:
|
|
||||||
preview_visibility = gr.update(visible=True)
|
|
||||||
|
|
||||||
if shared.state.textinfo is not None:
|
|
||||||
textinfo_result = gr.HTML.update(value=shared.state.textinfo, visible=True)
|
|
||||||
else:
|
|
||||||
textinfo_result = gr.update(visible=False)
|
|
||||||
|
|
||||||
return f"<span id='{id_part}_progress_span' style='display: none'>{time.time()}</span><p>{progressbar}</p>", preview_visibility, image, textinfo_result
|
|
||||||
|
|
||||||
|
|
||||||
def check_progress_call_initial(id_part):
|
|
||||||
shared.state.job_count = -1
|
|
||||||
shared.state.current_latent = None
|
|
||||||
shared.state.current_image = None
|
|
||||||
shared.state.textinfo = None
|
|
||||||
shared.state.time_start = time.time()
|
|
||||||
shared.state.time_left_force_display = False
|
|
||||||
|
|
||||||
return check_progress_call(id_part)
|
|
||||||
|
|
||||||
|
|
||||||
def setup_progressbar(progressbar, preview, id_part, textinfo=None):
|
|
||||||
if textinfo is None:
|
|
||||||
textinfo = gr.HTML(visible=False)
|
|
||||||
|
|
||||||
check_progress = gr.Button('Check progress', elem_id=f"{id_part}_check_progress", visible=False)
|
|
||||||
check_progress.click(
|
|
||||||
fn=lambda: check_progress_call(id_part),
|
|
||||||
show_progress=False,
|
|
||||||
inputs=[],
|
|
||||||
outputs=[progressbar, preview, preview, textinfo],
|
|
||||||
)
|
|
||||||
|
|
||||||
check_progress_initial = gr.Button('Check progress (first)', elem_id=f"{id_part}_check_progress_initial", visible=False)
|
|
||||||
check_progress_initial.click(
|
|
||||||
fn=lambda: check_progress_call_initial(id_part),
|
|
||||||
show_progress=False,
|
|
||||||
inputs=[],
|
|
||||||
outputs=[progressbar, preview, preview, textinfo],
|
|
||||||
)
|
|
||||||
Loading…
Reference in New Issue