optional model loader and integrate image info

This commit is contained in:
Vladimir Mandic
2023-04-17 15:31:43 -04:00
parent f5a29752e7
commit 8b1f26324b
9 changed files with 88 additions and 66 deletions
+12 -7
View File
@@ -19,18 +19,23 @@ body:
- type: markdown
attributes:
value: |
Any issues without version information will be closed
Look at console log and copy the version string from there
For example: `Version: f256fb8b Fri Apr 14 17:41:30 2023 -0400`
Any issues without version information will be closed
Look at console log and copy the version string from there
For example: `Version: f256fb8b Fri Apr 14 17:41:30 2023 -0400`
Additionally provide any relevant platorm information (OS, browser, versions)
Additionally provide any relevant platorm information (OS, browser, versions)
- type: markdown
attributes:
value: |
If issue is setup, installation or startup related, please check `setup.log` before reporting
And when posting console logs, please use code blocks (\`\`\`) to format them insead of uploading screenshots
And when posting console logs, please use code blocks ( \`\`\` ) to format them insead of uploading screenshots
- type: markdown
attributes:
value: |
If possible update to latest version before reporting the issue as older versions cannot be properly supported
And search existing **issues** and **discussions** before creating a new one
If you have additional extensions installed, try to reproduce the issue with user extensions disabled
And if the issue is with compatibility with specific extension, mark it as such when creating the issue
- type: markdown
attributes:
value: |
If possible update to latest version before reporting the issue as older versions cannot be properly supported
And search existing **issues** and **discussions** before creating a new one
+17 -12
View File
@@ -1,24 +1,29 @@
# TODO
## Always-on
- Pick & merge PRs from main repo
## Fixes
Stuff to be fixed...
- Reconnect UI to ops in progress on browser restart
- Redo Extensions tab: see <https://vladmandic.github.io/sd-extension-manager/pages/extensions.html>
- Cleanup & integrate CSS into single file
- Replace PngInfo/EXIF metadata handler
- Pick & merge PRs from main repo
- Create new GitHub hooks/actions for CI/CD
- Investigate integration with `Torch-DirectML`
- Set defaults for Apple M1
- Revisit `torch.compile`
- Ask to download default model
- Stream-load as option
- Dont spawn extensions installer
- Remove `models` from git repo
- Merge `Image Info` into `Process`
- Refresh theme list
## Features
- Redo Extensions tab: see <https://vladmandic.github.io/sd-extension-manager/pages/extensions.html>
- Stream-load models as option for slow storage
- Replace **PngInfo** / **EXIF** metadata handler
- Investigate integration with `Torch-DirectML`
- Investigate best practices for **Apple M1**
- Investigate best practices for **AMD GPUs**
## Investigate
- Revisit `torch.compile`
## Integration
+2 -2
View File
@@ -50,7 +50,7 @@ def load_models(model_path: str, model_url: str = None, command_path: str = None
if ext_blacklist is not None and any([full_path.endswith(x) for x in ext_blacklist]):
continue
if len(ext_filter) != 0:
model_name, extension = os.path.splitext(file)
_model_name, extension = os.path.splitext(file)
if extension not in ext_filter:
continue
if file not in output:
@@ -75,7 +75,7 @@ def friendly_name(file: str):
file = urlparse(file).path
file = os.path.basename(file)
model_name, extension = os.path.splitext(file)
model_name, _extension = os.path.splitext(file)
return model_name
+21 -28
View File
@@ -22,7 +22,7 @@ model_dir = "Stable-diffusion"
model_path = os.path.abspath(os.path.join(paths.models_path, model_dir))
checkpoints_list = {}
checkpoint_alisases = {}
checkpoint_aliases = {}
checkpoints_loaded = collections.OrderedDict()
@@ -56,7 +56,7 @@ class CheckpointInfo:
def register(self):
checkpoints_list[self.title] = self
for i in self.ids:
checkpoint_alisases[i] = self
checkpoint_aliases[i] = self
def calculate_shorthash(self):
self.sha256 = hashes.sha256(self.filename, "checkpoint/" + self.name)
@@ -103,32 +103,31 @@ def checkpoint_tiles():
def list_models():
checkpoints_list.clear()
checkpoint_alisases.clear()
cmd_ckpt = shared.cmd_opts.ckpt
if shared.cmd_opts.no_download_sd_model or cmd_ckpt != shared.sd_model_file or os.path.exists(cmd_ckpt):
model_url = None
else:
model_url = "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.safetensors"
model_list = modelloader.load_models(model_path=model_path, model_url=model_url, command_path=shared.opts.ckpt_dir, ext_filter=[".ckpt", ".safetensors"], download_name="v1-5-pruned-emaonly.safetensors", ext_blacklist=[".vae.ckpt", ".vae.safetensors"])
if os.path.exists(cmd_ckpt):
checkpoint_info = CheckpointInfo(cmd_ckpt)
checkpoint_aliases.clear()
model_list = modelloader.load_models(model_path=model_path, model_url=None, command_path=shared.opts.ckpt_dir, ext_filter=[".ckpt", ".safetensors"], download_name=None, ext_blacklist=[".vae.ckpt", ".vae.safetensors"])
if shared.cmd_opts.ckpt is not None and os.path.exists(shared.cmd_opts.ckpt):
checkpoint_info = CheckpointInfo(shared.cmd_opts.ckpt)
checkpoint_info.register()
shared.opts.data['sd_model_checkpoint'] = checkpoint_info.title
elif cmd_ckpt is not None and cmd_ckpt != shared.default_sd_model_file:
print("Checkpoint in --ckpt argument not found", file=sys.stderr)
elif shared.cmd_opts.ckpt != shared.default_sd_model_file:
print(f"Checkpoint not found: {shared.cmd_opts.ckpt}", file=sys.stderr)
for filename in sorted(model_list, key=str.lower):
checkpoint_info = CheckpointInfo(filename)
checkpoint_info.register()
shared.log.info(f'Available models: {shared.opts.ckpt_dir} {len(checkpoints_list)}')
print(f'Available models: {shared.opts.ckpt_dir} {len(checkpoints_list)}')
if len(checkpoints_list) == 0:
if not shared.cmd_opts.no_download_sd_model:
key = input('Download the default model? (y/N) ')
if key.lower().startswith == 'y':
model_url = "https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.safetensors"
model_list = modelloader.load_models(model_path=model_path, model_url=model_url, command_path=shared.opts.ckpt_dir, ext_filter=[".ckpt", ".safetensors"], download_name="v1-5-pruned-emaonly.safetensors", ext_blacklist=[".vae.ckpt", ".vae.safetensors"])
for filename in sorted(model_list, key=str.lower):
checkpoint_info = CheckpointInfo(filename)
checkpoint_info.register()
def get_closet_checkpoint_match(search_string):
checkpoint_info = checkpoint_alisases.get(search_string, None)
checkpoint_info = checkpoint_aliases.get(search_string, None)
if checkpoint_info is not None:
return checkpoint_info
@@ -157,18 +156,12 @@ def model_hash(filename):
def select_checkpoint():
model_checkpoint = shared.opts.sd_model_checkpoint
checkpoint_info = checkpoint_alisases.get(model_checkpoint, None)
checkpoint_info = checkpoint_aliases.get(model_checkpoint, None)
if checkpoint_info is not None:
return checkpoint_info
if len(checkpoints_list) == 0:
print("No checkpoints found. When searching for checkpoints, looked at:", file=sys.stderr)
if shared.cmd_opts.ckpt is not None:
print(f" - file {os.path.abspath(shared.cmd_opts.ckpt)}", file=sys.stderr)
print(f" - directory {model_path}", file=sys.stderr)
if shared.opts.ckpt_dir is not None:
print(f" - directory {os.path.abspath(shared.opts.ckpt_dir)}", file=sys.stderr)
print("Can't run without a checkpoint. Find and place a .ckpt or .safetensors file into any of those locations. The program will exit.", file=sys.stderr)
print("Cannot run without a checkpoint", file=sys.stderr)
exit(1)
checkpoint_info = next(iter(checkpoints_list.values()))
+4 -2
View File
@@ -925,6 +925,7 @@ def create_ui():
with gr.Blocks(analytics_enabled=False) as extras_interface:
ui_postprocessing.create_ui()
"""
with gr.Blocks(analytics_enabled=False) as pnginfo_interface:
with gr.Row().style(equal_height=False):
with gr.Column(variant='panel'):
@@ -947,6 +948,7 @@ def create_ui():
inputs=[image],
outputs=[html, generation_info, html2],
)
"""
def update_interp_description(value):
interp_description_css = "<p style='margin-bottom: 2.5em'>{}</p>"
@@ -1480,8 +1482,8 @@ def create_ui():
interfaces = [
(txt2img_interface, "From Text", "txt2img"),
(img2img_interface, "From Image", "img2img"),
(extras_interface, "Process", "extras"),
(pnginfo_interface, "Image Info", "pnginfo"),
(extras_interface, "Process Image", "extras"),
# (pnginfo_interface, "Image Info", "pnginfo"),
# (modelmerger_interface, "Checkpoint Merger", "modelmerger"),
(train_interface, "Train", "ti"),
]
+2 -2
View File
@@ -119,7 +119,7 @@ Requested path was: {f}
if not shared.cmd_opts.hide_ui_dir_config:
path = os.path.normpath(f)
if platform.system() == "Windows":
os.startfile(path)
os.startfile(path) # pylint: disable=no-member
elif platform.system() == "Darwin":
sp.Popen(["open", path])
elif "microsoft-standard-WSL2" in platform.uname().release:
@@ -134,7 +134,7 @@ Requested path was: {f}
generation_info = None
with gr.Column():
with gr.Row(elem_id=f"image_buttons_{tabname}", elem_classes="image-buttons"):
open_folder_button = gr.Button('Load', visible=not shared.cmd_opts.hide_ui_dir_config)
open_folder_button = gr.Button('show', visible=not shared.cmd_opts.hide_ui_dir_config)
if tabname != "extras":
save = gr.Button('Save', elem_id=f'save_{tabname}')
+21 -4
View File
@@ -1,7 +1,8 @@
import gradio as gr
from modules import scripts_postprocessing, scripts, shared, gfpgan_model, codeformer_model, ui_common, postprocessing, call_queue
import modules.generation_parameters_copypaste as parameters_copypaste
from modules.call_queue import wrap_gradio_gpu_call, wrap_queued_call, wrap_gradio_call
from modules.extras import run_pnginfo
def create_ui():
tab_index = gr.State(value=0)
@@ -9,28 +10,44 @@ def create_ui():
with gr.Row().style(equal_height=False, variant='compact'):
with gr.Column(variant='compact'):
with gr.Tabs(elem_id="mode_extras"):
with gr.TabItem('Single Image', elem_id="extras_single_tab") as tab_single:
with gr.TabItem('Process Image', elem_id="extras_single_tab") as tab_single:
extras_image = gr.Image(label="Source", source="upload", interactive=True, type="pil", elem_id="extras_image")
with gr.TabItem('Batch Process', elem_id="extras_batch_process_tab") as tab_batch:
with gr.TabItem('Process Batch', elem_id="extras_batch_process_tab") as tab_batch:
image_batch = gr.File(label="Batch Process", file_count="multiple", interactive=True, type="file", elem_id="extras_image_batch")
with gr.TabItem('Batch from Directory', elem_id="extras_batch_directory_tab") as tab_batch_dir:
with gr.TabItem('Process Folder', elem_id="extras_batch_directory_tab") as tab_batch_dir:
extras_batch_input_dir = gr.Textbox(label="Input directory", **shared.hide_dirs, placeholder="A directory on the same machine where the server is running.", elem_id="extras_batch_input_dir")
extras_batch_output_dir = gr.Textbox(label="Output directory", **shared.hide_dirs, placeholder="Leave blank to save images to the default path.", elem_id="extras_batch_output_dir")
show_extras_results = gr.Checkbox(label='Show result images', value=True, elem_id="extras_show_extras_results")
with gr.Row():
buttons = parameters_copypaste.create_buttons(["txt2img", "img2img", "inpaint"])
submit = gr.Button('Generate', elem_id="extras_generate", variant='primary')
script_inputs = scripts.scripts_postproc.setup_ui()
with gr.Column():
result_images, html_info_x, html_info, html_log = ui_common.create_output_panel("extras", shared.opts.outdir_extras_samples)
html_info = gr.HTML()
generation_info = gr.Textbox(visible=False, elem_id="pnginfo_generation_info")
html2_info = gr.HTML()
for tabname, button in buttons.items():
parameters_copypaste.register_paste_params_button(parameters_copypaste.ParamBinding(paste_button=button, tabname=tabname, source_text_component=generation_info, source_image_component=extras_image))
tab_single.select(fn=lambda: 0, inputs=[], outputs=[tab_index])
tab_batch.select(fn=lambda: 1, inputs=[], outputs=[tab_index])
tab_batch_dir.select(fn=lambda: 2, inputs=[], outputs=[tab_index])
extras_image.change(
fn=wrap_gradio_call(run_pnginfo),
inputs=[extras_image],
outputs=[html_info, generation_info, html2_info],
)
submit.click(
fn=call_queue.wrap_gradio_gpu_call(postprocessing.run_postprocessing, extra_outputs=[None, '']),
inputs=[
+8 -8
View File
@@ -349,7 +349,7 @@ def check_extensions():
newest = max(newest, ts)
newest_all = max(newest_all, newest)
log.debug(f'Extension version: {time.ctime(newest)} {folder}{os.pathsep}{ext}')
return newest_all
return round(newest_all)
# check version of the main repo and optionally upgrade it
@@ -393,10 +393,9 @@ def check_version():
# check if we can run setup in quick mode
def check_timestamp():
if not quick_allowed:
return False
if not os.path.isfile('setup.log'):
if not quick_allowed or not os.path.isfile('setup.log'):
return False
ok = True
setup_time = -1
with open('setup.log', 'r', encoding='utf8') as f:
lines = f.readlines()
@@ -410,15 +409,16 @@ def check_timestamp():
exit(1)
log.debug(f'Repository update time: {time.ctime(int(version_time))}')
if setup_time == -1:
return False
ok = False
log.debug(f'Previous setup time: {time.ctime(setup_time)}')
if setup_time < version_time:
return False
ok = False
extension_time = check_extensions()
log.debug(f'Latest extensions time: {time.ctime(extension_time)}')
if setup_time < extension_time:
return False
return True
ok = False
log.debug(f'Timestamps: version:{version_time} setup:{setup_time} extension:{extension_time}')
return ok
def parse_args():