Path: blob/master/extensions-builtin/Lora/ui_edit_user_metadata.py
2447 views
import datetime1import html2import random34import gradio as gr5import re67from modules import ui_extra_networks_user_metadata8910def is_non_comma_tagset(tags):11average_tag_length = sum(len(x) for x in tags.keys()) / len(tags)1213return average_tag_length >= 16141516re_word = re.compile(r"[-_\w']+")17re_comma = re.compile(r" *, *")181920def build_tags(metadata):21tags = {}2223ss_tag_frequency = metadata.get("ss_tag_frequency", {})24if ss_tag_frequency is not None and hasattr(ss_tag_frequency, 'items'):25for _, tags_dict in ss_tag_frequency.items():26for tag, tag_count in tags_dict.items():27tag = tag.strip()28tags[tag] = tags.get(tag, 0) + int(tag_count)2930if tags and is_non_comma_tagset(tags):31new_tags = {}3233for text, text_count in tags.items():34for word in re.findall(re_word, text):35if len(word) < 3:36continue3738new_tags[word] = new_tags.get(word, 0) + text_count3940tags = new_tags4142ordered_tags = sorted(tags.keys(), key=tags.get, reverse=True)4344return [(tag, tags[tag]) for tag in ordered_tags]454647class LoraUserMetadataEditor(ui_extra_networks_user_metadata.UserMetadataEditor):48def __init__(self, ui, tabname, page):49super().__init__(ui, tabname, page)5051self.select_sd_version = None5253self.taginfo = None54self.edit_activation_text = None55self.slider_preferred_weight = None56self.edit_notes = None5758def save_lora_user_metadata(self, name, desc, sd_version, activation_text, preferred_weight, negative_text, notes):59user_metadata = self.get_user_metadata(name)60user_metadata["description"] = desc61user_metadata["sd version"] = sd_version62user_metadata["activation text"] = activation_text63user_metadata["preferred weight"] = preferred_weight64user_metadata["negative text"] = negative_text65user_metadata["notes"] = notes6667self.write_user_metadata(name, user_metadata)6869def get_metadata_table(self, name):70table = super().get_metadata_table(name)71item = self.page.items.get(name, {})72metadata = item.get("metadata") or {}7374keys = {75'ss_output_name': "Output name:",76'ss_sd_model_name': "Model:",77'ss_clip_skip': "Clip skip:",78'ss_network_module': "Kohya module:",79}8081for key, label in keys.items():82value = metadata.get(key, None)83if value is not None and str(value) != "None":84table.append((label, html.escape(value)))8586ss_training_started_at = metadata.get('ss_training_started_at')87if ss_training_started_at:88table.append(("Date trained:", datetime.datetime.utcfromtimestamp(float(ss_training_started_at)).strftime('%Y-%m-%d %H:%M')))8990ss_bucket_info = metadata.get("ss_bucket_info")91if ss_bucket_info and "buckets" in ss_bucket_info:92resolutions = {}93for _, bucket in ss_bucket_info["buckets"].items():94resolution = bucket["resolution"]95resolution = f'{resolution[1]}x{resolution[0]}'9697resolutions[resolution] = resolutions.get(resolution, 0) + int(bucket["count"])9899resolutions_list = sorted(resolutions.keys(), key=resolutions.get, reverse=True)100resolutions_text = html.escape(", ".join(resolutions_list[0:4]))101if len(resolutions) > 4:102resolutions_text += ", ..."103resolutions_text = f"<span title='{html.escape(', '.join(resolutions_list))}'>{resolutions_text}</span>"104105table.append(('Resolutions:' if len(resolutions_list) > 1 else 'Resolution:', resolutions_text))106107image_count = 0108for _, params in metadata.get("ss_dataset_dirs", {}).items():109image_count += int(params.get("img_count", 0))110111if image_count:112table.append(("Dataset size:", image_count))113114return table115116def put_values_into_components(self, name):117user_metadata = self.get_user_metadata(name)118values = super().put_values_into_components(name)119120item = self.page.items.get(name, {})121metadata = item.get("metadata") or {}122123tags = build_tags(metadata)124gradio_tags = [(tag, str(count)) for tag, count in tags[0:24]]125126return [127*values[0:5],128item.get("sd_version", "Unknown"),129gr.HighlightedText.update(value=gradio_tags, visible=True if tags else False),130user_metadata.get('activation text', ''),131float(user_metadata.get('preferred weight', 0.0)),132user_metadata.get('negative text', ''),133gr.update(visible=True if tags else False),134gr.update(value=self.generate_random_prompt_from_tags(tags), visible=True if tags else False),135]136137def generate_random_prompt(self, name):138item = self.page.items.get(name, {})139metadata = item.get("metadata") or {}140tags = build_tags(metadata)141142return self.generate_random_prompt_from_tags(tags)143144def generate_random_prompt_from_tags(self, tags):145max_count = None146res = []147for tag, count in tags:148if not max_count:149max_count = count150151v = random.random() * max_count152if count > v:153for x in "({[]})":154tag = tag.replace(x, '\\' + x)155res.append(tag)156157return ", ".join(sorted(res))158159def create_extra_default_items_in_left_column(self):160161# this would be a lot better as gr.Radio but I can't make it work162self.select_sd_version = gr.Dropdown(['SD1', 'SD2', 'SDXL', 'Unknown'], value='Unknown', label='Stable Diffusion version', interactive=True)163164def create_editor(self):165self.create_default_editor_elems()166167self.taginfo = gr.HighlightedText(label="Training dataset tags")168self.edit_activation_text = gr.Text(label='Activation text', info="Will be added to prompt along with Lora")169self.slider_preferred_weight = gr.Slider(label='Preferred weight', info="Set to 0 to disable", minimum=0.0, maximum=2.0, step=0.01)170self.edit_negative_text = gr.Text(label='Negative prompt', info="Will be added to negative prompts")171with gr.Row() as row_random_prompt:172with gr.Column(scale=8):173random_prompt = gr.Textbox(label='Random prompt', lines=4, max_lines=4, interactive=False)174175with gr.Column(scale=1, min_width=120):176generate_random_prompt = gr.Button('Generate', size="lg", scale=1)177178self.edit_notes = gr.TextArea(label='Notes', lines=4)179180generate_random_prompt.click(fn=self.generate_random_prompt, inputs=[self.edit_name_input], outputs=[random_prompt], show_progress=False)181182def select_tag(activation_text, evt: gr.SelectData):183tag = evt.value[0]184185words = re.split(re_comma, activation_text)186if tag in words:187words = [x for x in words if x != tag and x.strip()]188return ", ".join(words)189190return activation_text + ", " + tag if activation_text else tag191192self.taginfo.select(fn=select_tag, inputs=[self.edit_activation_text], outputs=[self.edit_activation_text], show_progress=False)193194self.create_default_buttons()195196viewed_components = [197self.edit_name,198self.edit_description,199self.html_filedata,200self.html_preview,201self.edit_notes,202self.select_sd_version,203self.taginfo,204self.edit_activation_text,205self.slider_preferred_weight,206self.edit_negative_text,207row_random_prompt,208random_prompt,209]210211self.button_edit\212.click(fn=self.put_values_into_components, inputs=[self.edit_name_input], outputs=viewed_components)\213.then(fn=lambda: gr.update(visible=True), inputs=[], outputs=[self.box])214215edited_components = [216self.edit_description,217self.select_sd_version,218self.edit_activation_text,219self.slider_preferred_weight,220self.edit_negative_text,221self.edit_notes,222]223224225self.setup_save_handler(self.button_save, self.save_lora_user_metadata, edited_components)226227228