From 8c37607b829c0f3365af4466fdfda38b06cb07d8 Mon Sep 17 00:00:00 2001 From: Vladimir Mandic Date: Fri, 25 Apr 2025 13:51:58 -0400 Subject: [PATCH] add histrory ui Signed-off-by: Vladimir Mandic --- CHANGELOG.md | 6 +++++ modules/shared_state.py | 1 + modules/ui_history.py | 56 +++++++++++++++++++++++++++++++++++++++++ modules/ui_settings.py | 5 +++- wiki | 2 +- 5 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 modules/ui_history.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ad8d1f62..7dc920895 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,12 +42,18 @@ pre-load quantization support LoRA support *if you're low on VRAM, NNCF is as close as a catch-all solution* + - **OpenVINO** update to 2025.1.0 and Torch to 2.7 + - **ROCm** update to Torch 2.7 - **HiDream-I1** optimized offloading and prompt-encode caching it now works in 12GB VRAM / 26GB RAM! - **CogView3** and **CogView4** model loader optimizations - **Sana** model loader optimizations - add explicit offload after encode prompt configure in *settings -> text encoder -> offload* +- **UI** + - new History tab where you can see all jobs since the server startup + and optionally download any of the previously generated images/videos + access via *system -> history* - **API** - new [API Wiki](https://github.com/vladmandic/sdnext/wiki/API) - server will now maintain job history which can be queried via API diff --git a/modules/shared_state.py b/modules/shared_state.py index f6a91482b..b9434c637 100644 --- a/modules/shared_state.py +++ b/modules/shared_state.py @@ -192,6 +192,7 @@ class State: self.prediction_type = "epsilon" self.api = api or self.api self.time_start = time.time() + self.time_end = None self.history('begin') if debug_output: log.trace(f'State begin: {self}') diff --git a/modules/ui_history.py b/modules/ui_history.py new file mode 100644 index 000000000..1d25dada7 --- /dev/null +++ b/modules/ui_history.py @@ -0,0 +1,56 @@ +import time +import gradio as gr +from modules import shared + + +def refresh(): + def ts(t): + try: + return time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(t)) + except Exception: + return '' + + items = [] + for item in shared.state.state_history: + items.append([ + item['id'], + item['job'], + item['op'], + ts(item['start']), + ts(item['end']), + len(item['outputs']), + ]) + shared.log.info(f"History: records={len(items)}") + if len(items) == 0: + items = None + return gr.Dataframe.update(value=items) + + +def select(evt: gr.SelectData, _data): + if evt.index is None or len(evt.index) == 0: + return [] + row = evt.index[0] + item = shared.state.state_history[row] if row < len(shared.state.state_history) else {} + shared.log.debug(f"History: select={row}:{len(shared.state.state_history)} {item}") + files = item.get('outputs', []) + return gr.Files.update(value=files) + + +def create_ui(): + with gr.Row(): + btn_refresh = gr.Button("Refresh") + with gr.Row(): + history_table = gr.DataFrame( + value=None, + headers=['ID', 'Job', 'Op', 'Start', 'End', 'Outputs'], + label='History data', + show_label=True, + interactive=False, + wrap=True, + overflow_row_behaviour='paginate', + max_rows=50, + ) + with gr.Row(): + history_files = gr.Files(label="Task files", interactive=False) + btn_refresh.click(fn=refresh, inputs=[], outputs=[history_table]) + history_table.select(fn=select, inputs=[history_table], outputs=[history_files]) diff --git a/modules/ui_settings.py b/modules/ui_settings.py index bda278a81..eea3350f3 100644 --- a/modules/ui_settings.py +++ b/modules/ui_settings.py @@ -1,6 +1,6 @@ import os import gradio as gr -from modules import timer, shared, paths, theme, sd_models, modelloader, ui_common, ui_loadsave, generation_parameters_copypaste, call_queue, script_callbacks +from modules import timer, shared, paths, theme, sd_models, modelloader, ui_common, ui_loadsave, ui_history, generation_parameters_copypaste, call_queue, script_callbacks text_settings = None # holds json of entire shared.opts @@ -242,6 +242,9 @@ def create_ui(): loadsave.create_ui() create_dirty_indicator("tab_defaults", [], interactive=False) + with gr.TabItem("History", id="system_history", elem_id="tab_history"): + ui_history.create_ui() + with gr.TabItem("ONNX", id="onnx_config", elem_id="tab_onnx"): from modules.onnx_impl import ui as ui_onnx ui_onnx.create_ui() diff --git a/wiki b/wiki index b5c7eaa8a..d57624e45 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit b5c7eaa8ac8d23da0f733ac54e9ef71543f85416 +Subproject commit d57624e45e2fa6f827e1e3134ee9a1a996476fd5