Merge branch 'master' into directml

This commit is contained in:
Seunghoon Lee
2023-04-25 23:37:44 +09:00
17 changed files with 67 additions and 85 deletions
+2
View File
@@ -32,6 +32,8 @@ venv
/models/**/*
/interrogate/**/*
/train/log/**/*
/textual_inversion/**/*
/detected_maps/**/*
/tmp
/log
/cert
+1
View File
@@ -8,6 +8,7 @@ Stuff to be fixed...
- Run VAE with hires at 1280
- Transformers version
- Move Restart Server from WebUI to Launch and reload modules
- gr.Dropdowns with None selected
## Features
+1 -1
View File
@@ -77,7 +77,7 @@ function requestProgress(id_task, progressbarContainer, gallery, atEnd = null, o
setTitle("")
if (divProgress) parentProgressbar.removeChild(divProgress)
if (parentGallery) parentGallery.removeChild(livePreview)
atEnd()
if (atEnd) atEnd()
}
var fun = function(id_task, id_live_preview){
+1
View File
@@ -5,6 +5,7 @@ function start_training_textual_inversion(){
gradioApp().querySelector('#ti_error').innerHTML=''
var id = randomId()
const onProgress = (progress) => gradioApp().getElementById('ti_progress').innerHTML = progress.textinfo;
// requestProgress(id_task, progressbarContainer, gallery, atEnd = null, onProgress = null, once = false) {
requestProgress(id, gradioApp().getElementById('ti_output'), gradioApp().getElementById('ti_gallery'), null, onProgress, false)
var res = args_to_array(arguments)
res[0] = id
+5 -1
View File
@@ -67,12 +67,16 @@ def compatibility_args(opts, args):
parser.add_argument("--disable-nan-check", help=argparse.SUPPRESS, default=opts.disable_nan_check)
parser.add_argument("--token-merging", help=argparse.SUPPRESS, default=opts.token_merging)
parser.add_argument("--rollback-vae", help=argparse.SUPPRESS, default=opts.rollback_vae)
parser.add_argument("--no-half", help=argparse.SUPPRESS, default=opts.no_half)
parser.add_argument("--no-half-vae", help=argparse.SUPPRESS, default=opts.no_half_vae)
parser.add_argument("--precision", help=argparse.SUPPRESS, default=opts.precision)
parser.add_argument("--api", help=argparse.SUPPRESS, default=True)
opts.use_old_emphasis_implementation = False
opts.use_old_karras_scheduler_sigmas = False
opts.no_dpmpp_sde_batch_determinism = False
opts.use_old_hires_fix_width_height = False
parser.add_argument("--lora-dir", help=argparse.SUPPRESS, default=opts.lora_dir)
args = parser.parse_args()
if 'lyco_dir' in args:
+5 -6
View File
@@ -5,12 +5,11 @@ import shutil
import torch
import tqdm
from modules import shared, images, sd_models, sd_vae, sd_models_config
from modules.ui_common import plaintext_to_html
import gradio as gr
import safetensors.torch
from modules import shared, images, sd_models, sd_vae, sd_models_config
def run_pnginfo(image):
if image is None:
@@ -130,14 +129,14 @@ def run_modelmerger(id_task, primary_model_name, secondary_model_name, tertiary_
result_is_instruct_pix2pix_model = False
if theta_func2:
shared.state.textinfo = f"Loading B"
shared.state.textinfo = "Loading B"
print(f"Loading {secondary_model_info.filename}...")
theta_1 = sd_models.read_state_dict(secondary_model_info.filename)
else:
theta_1 = None
if theta_func1:
shared.state.textinfo = f"Loading C"
shared.state.textinfo = "Loading C"
print(f"Loading {tertiary_model_info.filename}...")
theta_2 = sd_models.read_state_dict(tertiary_model_info.filename)
@@ -193,7 +192,7 @@ def run_modelmerger(id_task, primary_model_name, secondary_model_name, tertiary_
result_is_inpainting_model = True
else:
theta_0[key] = theta_func2(a, b, multiplier)
theta_0[key] = to_half(theta_0[key], save_as_half)
shared.state.sampling_step += 1
+1 -1
View File
@@ -634,7 +634,7 @@ def read_info_from_image(image):
if isinstance(val, bytes): # decode bytestring
items[key] = safe_decode_string(val)
for key in ['exif', 'ExifOffset', 'JpegIFOffset', 'JpegIFByteCount', 'ExifVersion', 'icc_profile', 'jfif', 'jfif_version', 'jfif_unit', 'jfif_density', 'adobe', 'photoshop', 'loop', 'duration']: # remove unwanted tags
for key in ['exif', 'ExifOffset', 'JpegIFOffset', 'JpegIFByteCount', 'ExifVersion', 'icc_profile', 'jfif', 'jfif_version', 'jfif_unit', 'jfif_density', 'adobe', 'photoshop', 'loop', 'duration', 'dpi']: # remove unwanted tags
items.pop(key, None)
if items.get("Software", None) == "NovelAI":
+1 -1
View File
@@ -474,6 +474,7 @@ def create_infotext(p, all_prompts, all_seeds, all_subseeds, comments=None, iter
"Size": f"{p.width}x{p.height}",
"Model hash": getattr(p, 'sd_model_hash', None if not opts.add_model_hash_to_info or not shared.sd_model.sd_model_hash else shared.sd_model.sd_model_hash),
"Model": (None if not opts.add_model_name_to_info or not shared.sd_model.sd_checkpoint_info.model_name else shared.sd_model.sd_checkpoint_info.model_name.replace(',', '').replace(':', '')),
"VAE": (None if not opts.add_model_name_to_info or sd_vae.loaded_vae_file is None else os.path.splitext(os.path.basename(sd_vae.loaded_vae_file))[0]),
"Variation seed": (None if p.subseed_strength == 0 else all_subseeds[index]),
"Variation seed strength": (None if p.subseed_strength == 0 else p.subseed_strength),
"Seed resize from": (None if p.seed_resize_from_w == 0 or p.seed_resize_from_h == 0 else f"{p.seed_resize_from_w}x{p.seed_resize_from_h}"),
@@ -490,7 +491,6 @@ def create_infotext(p, all_prompts, all_seeds, all_subseeds, comments=None, iter
"Token merging stride x": None if opts.token_merging_stride_x == 2 else opts.token_merging_stride_x,
"Token merging stride y": None if opts.token_merging_stride_y == 2 else opts.token_merging_stride_y
}
generation_params.update(p.extra_generation_params)
generation_params_text = ", ".join([k if k == v else f'{k}: {generation_parameters_copypaste.quote(v)}' for k, v in generation_params.items() if v is not None])
+23 -29
View File
@@ -1,23 +1,19 @@
import os
from collections import namedtuple
import torch
import tqdm
import html
import csv
from collections import namedtuple
import torch
import tqdm
import safetensors.torch
from rich import print # pylint: disable=redefined-builtin
import numpy as np
from PIL import Image, PngImagePlugin
from torch.utils.tensorboard import SummaryWriter
from modules import shared, devices, sd_hijack, processing, sd_models, images, sd_samplers, sd_hijack_checkpoint, errors
import modules.textual_inversion.dataset
from modules.textual_inversion.learn_schedule import LearnRateScheduler
from modules.textual_inversion.image_embedding import embedding_to_b64, embedding_from_b64, insert_image_data_embed, extract_image_data_embed, caption_image_overlay
from modules.textual_inversion.logging import save_settings_to_file
from rich import print # pylint: disable=redefined-builtin
TextualInversionTemplate = namedtuple("TextualInversionTemplate", ["name", "path"])
textual_inversion_templates = {}
@@ -26,7 +22,7 @@ textual_inversion_templates = {}
def list_textual_inversion_templates():
textual_inversion_templates.clear()
for root, dirs, fns in os.walk(shared.opts.embeddings_templates_dir):
for root, _dirs, fns in os.walk(shared.opts.embeddings_templates_dir):
for fn in fns:
path = os.path.join(root, fn)
@@ -198,7 +194,7 @@ class EmbeddingDatabase:
if not os.path.isdir(embdir.path):
return
for root, dirs, fns in os.walk(embdir.path, followlinks=True):
for root, _dirs, fns in os.walk(embdir.path, followlinks=True):
for fn in fns:
try:
fullfn = os.path.join(root, fn)
@@ -214,7 +210,7 @@ class EmbeddingDatabase:
def load_textual_inversion_embeddings(self, force_reload=False):
if not force_reload:
need_reload = False
for path, embdir in self.embedding_dirs.items():
for _path, embdir in self.embedding_dirs.items():
if embdir.has_changed():
need_reload = True
break
@@ -227,7 +223,7 @@ class EmbeddingDatabase:
self.skipped_embeddings.clear()
self.expected_shape = self.get_expected_shape()
for path, embdir in self.embedding_dirs.items():
for _path, embdir in self.embedding_dirs.items():
self.load_from_dir(embdir)
embdir.update()
@@ -270,13 +266,13 @@ def create_embedding(name, num_vectors_per_token, overwrite_old, init_text='*'):
# Remove illegal characters from name.
name = "".join( x for x in name if (x.isalnum() or x in "._- "))
fn = os.path.join(shared.opts.embeddings_dir, f"{name}.pt")
if not overwrite_old:
assert not os.path.exists(fn), f"file {fn} already exists"
embedding = Embedding(vec, name)
embedding.step = 0
embedding.save(fn)
if not overwrite_old and os.path.exists(fn):
print(f"Embedding already exists: {fn}")
else:
embedding = Embedding(vec, name)
embedding.step = 0
embedding.save(fn)
print(f'Created embedding: {fn} vectors {num_vectors_per_token} init {init_text}')
return fn
@@ -288,7 +284,7 @@ def write_loss(log_directory, filename, step, epoch_len, values):
return
write_csv_header = False if os.path.exists(os.path.join(log_directory, filename)) else True
with open(os.path.join(log_directory, filename), "a+", newline='') as fout:
with open(os.path.join(log_directory, filename), "a+", newline='', encoding='utf-8') as fout:
csv_writer = csv.DictWriter(fout, fieldnames=["step", "epoch", "epoch_step", *(values.keys())])
if write_csv_header:
@@ -460,7 +456,7 @@ def train_embedding(id_task, embedding_name, learn_rate, batch_size, gradient_st
try:
sd_hijack_checkpoint.add()
for i in range((steps-initial_step) * gradient_step):
for _i in range((steps-initial_step) * gradient_step):
if scheduler.finished:
break
if shared.state.interrupted:
@@ -574,7 +570,7 @@ def train_embedding(id_task, embedding_name, learn_rate, batch_size, gradient_st
if image is not None:
shared.state.assign_current_image(image)
last_saved_image, last_text_info = images.save_image(image, images_dir, "", p.seed, p.prompt, shared.opts.samples_format, processed.infotexts[0], p=p, forced_filename=forced_filename, save_to_dirs=False)
last_saved_image, _last_text_info = images.save_image(image, images_dir, "", p.seed, p.prompt, shared.opts.samples_format, processed.infotexts[0], p=p, forced_filename=forced_filename, save_to_dirs=False)
last_saved_image += f", prompt: {preview_text}"
if shared.opts.training_enable_tensorboard and shared.opts.training_tensorboard_save_images:
@@ -587,18 +583,17 @@ def train_embedding(id_task, embedding_name, learn_rate, batch_size, gradient_st
info = PngImagePlugin.PngInfo()
data = torch.load(last_saved_file)
info.add_text("sd-ti-embedding", embedding_to_b64(data))
title = "<{}>".format(data.get('name', '???'))
title = f"<{data.get('name', '???')}>"
try:
vectorSize = list(data['string_to_param'].values())[0].shape[0]
except Exception as e:
except Exception:
vectorSize = '?'
checkpoint = sd_models.select_checkpoint()
footer_left = checkpoint.model_name
footer_mid = '[{}]'.format(checkpoint.shorthash)
footer_right = '{}v {}s'.format(vectorSize, steps_done)
footer_mid = f'[{checkpoint.shorthash}]'
footer_right = f'{vectorSize}v {steps_done}s'
captioned_image = caption_image_overlay(image, title, footer_left, footer_mid, footer_right)
captioned_image = insert_image_data_embed(captioned_image, data)
@@ -606,7 +601,7 @@ def train_embedding(id_task, embedding_name, learn_rate, batch_size, gradient_st
captioned_image.save(last_saved_image_chunks, "PNG", pnginfo=info)
embedding_yet_to_be_embedded = False
last_saved_image, last_text_info = images.save_image(image, images_dir, "", p.seed, p.prompt, shared.opts.samples_format, processed.infotexts[0], p=p, forced_filename=forced_filename, save_to_dirs=False)
last_saved_image, _last_text_info = images.save_image(image, images_dir, "", p.seed, p.prompt, shared.opts.samples_format, processed.infotexts[0], p=p, forced_filename=forced_filename, save_to_dirs=False)
last_saved_image += f", prompt: {preview_text}"
shared.state.job_no = embedding.step
@@ -624,7 +619,6 @@ Last saved image: {html.escape(last_saved_image)}<br/>
save_embedding(embedding, optimizer, checkpoint, embedding_name, filename, remove_cached_checksum=True)
except Exception as e:
errors.display(e, 'embedding train')
pass
finally:
pbar.leave = False
pbar.close()
-5
View File
@@ -1,7 +1,5 @@
import html
import gradio as gr
import modules.textual_inversion.textual_inversion
import modules.textual_inversion.preprocess
from modules import sd_hijack, shared
@@ -9,9 +7,7 @@ from modules import sd_hijack, shared
def create_embedding(name, initialization_text, nvpt, overwrite_old):
filename = modules.textual_inversion.textual_inversion.create_embedding(name, nvpt, overwrite_old, init_text=initialization_text)
sd_hijack.model_hijack.embedding_db.load_textual_inversion_embeddings()
return gr.Dropdown.update(choices=sorted(sd_hijack.model_hijack.embedding_db.word_embeddings.keys())), f"Created: {filename}", ""
@@ -42,4 +38,3 @@ Embedding saved to {html.escape(filename)}
finally:
if not apply_optimizations:
sd_hijack.apply_optimizations()
+2 -31
View File
@@ -1127,7 +1127,7 @@ def create_ui():
gradient_step = gr.Number(label='Gradient accumulation steps', value=1, precision=0, elem_id="train_gradient_step")
dataset_directory = gr.Textbox(label='Dataset directory', placeholder="Path to directory with input images", elem_id="train_dataset_directory")
log_directory = gr.Textbox(label='Log directory', placeholder="Path to directory where to write outputs", value="textual_inversion", elem_id="train_log_directory")
log_directory = gr.Textbox(label='Log directory', placeholder="Path to directory where to write outputs", value="train/log/embeddings", elem_id="train_log_directory")
with FormRow():
template_file = gr.Dropdown(label='Prompt template', value="style_filewords.txt", elem_id="train_template_file", choices=get_textual_inversion_template_names())
@@ -1136,7 +1136,7 @@ def create_ui():
training_width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="train_training_width")
training_height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="train_training_height")
varsize = gr.Checkbox(label="Do not resize images", value=False, elem_id="train_varsize")
steps = gr.Number(label='Max steps', value=100000, precision=0, elem_id="train_steps")
steps = gr.Number(label='Max steps', value=1000, precision=0, elem_id="train_steps")
with FormRow():
create_image_every = gr.Number(label='Save an image to log directory every N steps, 0 to disable', value=500, precision=0, elem_id="train_create_image_every")
@@ -1740,32 +1740,3 @@ def reload_javascript():
if not hasattr(shared, 'GradioTemplateResponseOriginal'):
shared.GradioTemplateResponseOriginal = gradio.routes.templates.TemplateResponse
def versions_html():
import torch
import launch
python_version = ".".join([str(x) for x in sys.version_info[0:3]])
commit = launch.commit_hash()
short_commit = commit[0:8]
if shared.xformers_available:
import xformers
xformers_version = xformers.__version__
else:
xformers_version = "N/A"
return f"""
python: <span title="{sys.version}">{python_version}</span>
 • 
torch: {getattr(torch, '__long_version__',torch.__version__)}
 • 
xformers: {xformers_version}
 • 
gradio: {gr.__version__}
 • 
commit: <a href="https://github.com/vladmandic/automatic/commit/{commit}">{short_commit}</a>
 • 
checkpoint: <a id="sd_checkpoint_hash">N/A</a>
"""
-2
View File
@@ -1,6 +1,5 @@
import json
import os
from modules import shared, ui_extra_networks
@@ -14,7 +13,6 @@ class ExtraNetworksPageHypernetworks(ui_extra_networks.ExtraNetworksPage):
def list_items(self):
for name, path in shared.hypernetworks.items():
path, ext = os.path.splitext(path)
yield {
"name": name,
"filename": path,
@@ -25,12 +25,12 @@ class ExtraNetworksPageTextualInversion(ui_extra_networks.ExtraNetworksPage):
for embedding in embeddings:
path, _ext = os.path.splitext(embedding.filename)
yield {
"name": embedding.name,
"name": os.path.splitext(embedding.name)[0],
"filename": embedding.filename,
"preview": self.find_preview(path),
"description": self.find_description(path),
"search_term": self.search_terms_from_path(embedding.filename),
"prompt": json.dumps(embedding.name),
"prompt": json.dumps(os.path.splitext(embedding.name)[0]),
"local_preview": f"{path}.preview.{shared.opts.samples_format}",
}
+8 -1
View File
@@ -32,17 +32,24 @@ def create_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(elem_id="pnginfo_html_info")
generation_info = gr.Textbox(elem_id="pnginfo_generation_info", label="Parameters")
generation_info = gr.Textbox(elem_id="pnginfo_generation_info", label="Parameters", visible=False)
generation_info_pretty = gr.Textbox(elem_id="pnginfo_generation_info_pretty", label="Parameters")
gr.HTML('Full metadata')
html2_info = gr.HTML(elem_id="pnginfo_html2_info")
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))
def pretty_geninfo(generation_info):
return generation_info.replace(', ', '\n')
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])
generation_info.change(fn=pretty_geninfo, inputs=[generation_info], outputs=[generation_info_pretty])
extras_image.change(
fn=wrap_gradio_call(run_pnginfo),
inputs=[extras_image],
+13 -3
View File
@@ -137,12 +137,18 @@ def update(folder):
branch = git('branch', folder)
if 'main' in branch:
git('checkout main', folder)
branch = 'main'
elif 'master' in branch:
git('checkout master', folder)
branch = 'master'
else:
log.warning(f'Unknown branch for: {folder}')
git('pull --autostash --rebase', folder)
branch = git('branch', folder)
branch = None
if branch is None:
git('pull --autostash --rebase', folder)
else:
git(f'pull origin {branch} --autostash --rebase', folder)
# branch = git('branch', folder)
# clone git repository
@@ -175,6 +181,9 @@ def check_python():
if shutil.which(git_cmd) is None:
log.error('Git not found')
exit(1)
else:
git_version = git('--version', folder=None, ignore=False)
log.debug(f'Git {git_version.replace("git version", "").strip()}')
# check torch version
@@ -325,6 +334,7 @@ def install_extensions():
def install_submodules():
log.info('Installing submodules')
txt = git('submodule')
log.debug(f'Submodules list: {txt}')
if 'no submodule mapping found' in txt:
log.warning('Attempting repository recover')
git('add .')
@@ -334,7 +344,7 @@ def install_submodules():
git('reset --hard origin/master')
git('checkout master')
log.info('Continuing setup')
git('submodule --quiet update --init --recursive')
txt = git('submodule --quiet update --init --recursive')
if not args.noupdate:
log.info('Updating submodules')
submodules = git('submodule').splitlines()