diff --git a/.gitignore b/.gitignore
index fa8769047..8a9c92f78 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,6 +32,8 @@ venv
/models/**/*
/interrogate/**/*
/train/log/**/*
+/textual_inversion/**/*
+/detected_maps/**/*
/tmp
/log
/cert
diff --git a/TODO.md b/TODO.md
index fc4bdc1c5..da4d28d5d 100644
--- a/TODO.md
+++ b/TODO.md
@@ -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
diff --git a/extensions-builtin/sd-webui-controlnet b/extensions-builtin/sd-webui-controlnet
index 9eeb71a79..f16c9e522 160000
--- a/extensions-builtin/sd-webui-controlnet
+++ b/extensions-builtin/sd-webui-controlnet
@@ -1 +1 @@
-Subproject commit 9eeb71a796b06f912e1e66acecf4242d165db67b
+Subproject commit f16c9e5221bcf9490f5fd93ff0d38027a14bc4d6
diff --git a/javascript/progressbar.js b/javascript/progressbar.js
index e9b6bf5d5..7d218ff05 100644
--- a/javascript/progressbar.js
+++ b/javascript/progressbar.js
@@ -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){
diff --git a/javascript/textualInversion.js b/javascript/textualInversion.js
index 883092547..8a50ec601 100644
--- a/javascript/textualInversion.js
+++ b/javascript/textualInversion.js
@@ -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
diff --git a/modules/cmd_args.py b/modules/cmd_args.py
index e6364e7fe..4a496dd57 100644
--- a/modules/cmd_args.py
+++ b/modules/cmd_args.py
@@ -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:
diff --git a/modules/extras.py b/modules/extras.py
index 1907a18b1..c0ae9477f 100644
--- a/modules/extras.py
+++ b/modules/extras.py
@@ -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
diff --git a/modules/images.py b/modules/images.py
index a137e73dc..8b3c539c3 100644
--- a/modules/images.py
+++ b/modules/images.py
@@ -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":
diff --git a/modules/lora b/modules/lora
index 852481e14..ac4935bf7 160000
--- a/modules/lora
+++ b/modules/lora
@@ -1 +1 @@
-Subproject commit 852481e14d08d510377813790ade557b4e2313f5
+Subproject commit ac4935bf79942f966d7b6578e8fbb9ee5f12d4ad
diff --git a/modules/processing.py b/modules/processing.py
index 43200c9ff..a546e4f19 100644
--- a/modules/processing.py
+++ b/modules/processing.py
@@ -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])
diff --git a/modules/textual_inversion/textual_inversion.py b/modules/textual_inversion/textual_inversion.py
index 9bcf205ab..24ccf743f 100644
--- a/modules/textual_inversion/textual_inversion.py
+++ b/modules/textual_inversion/textual_inversion.py
@@ -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)}
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()
diff --git a/modules/textual_inversion/ui.py b/modules/textual_inversion/ui.py
index af7ddb1e7..8afd8ef04 100644
--- a/modules/textual_inversion/ui.py
+++ b/modules/textual_inversion/ui.py
@@ -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()
-
diff --git a/modules/ui.py b/modules/ui.py
index 0077102c3..83249d39c 100644
--- a/modules/ui.py
+++ b/modules/ui.py
@@ -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: {python_version}
- •
-torch: {getattr(torch, '__long_version__',torch.__version__)}
- •
-xformers: {xformers_version}
- •
-gradio: {gr.__version__}
- •
-commit: {short_commit}
- •
-checkpoint: N/A
-"""
diff --git a/modules/ui_extra_networks_hypernets.py b/modules/ui_extra_networks_hypernets.py
index 3deb9cbac..545898486 100644
--- a/modules/ui_extra_networks_hypernets.py
+++ b/modules/ui_extra_networks_hypernets.py
@@ -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,
diff --git a/modules/ui_extra_networks_textual_inversion.py b/modules/ui_extra_networks_textual_inversion.py
index b8dd408d8..1abf39675 100644
--- a/modules/ui_extra_networks_textual_inversion.py
+++ b/modules/ui_extra_networks_textual_inversion.py
@@ -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}",
}
diff --git a/modules/ui_postprocessing.py b/modules/ui_postprocessing.py
index 23c2d60bc..243631d88 100644
--- a/modules/ui_postprocessing.py
+++ b/modules/ui_postprocessing.py
@@ -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],
diff --git a/setup.py b/setup.py
index 2531c37cb..69b86012d 100644
--- a/setup.py
+++ b/setup.py
@@ -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()