Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
AUTOMATIC1111
GitHub Repository: AUTOMATIC1111/stable-diffusion-webui
Path: blob/master/extensions-builtin/Lora/ui_edit_user_metadata.py
2447 views
1
import datetime
2
import html
3
import random
4
5
import gradio as gr
6
import re
7
8
from modules import ui_extra_networks_user_metadata
9
10
11
def is_non_comma_tagset(tags):
12
average_tag_length = sum(len(x) for x in tags.keys()) / len(tags)
13
14
return average_tag_length >= 16
15
16
17
re_word = re.compile(r"[-_\w']+")
18
re_comma = re.compile(r" *, *")
19
20
21
def build_tags(metadata):
22
tags = {}
23
24
ss_tag_frequency = metadata.get("ss_tag_frequency", {})
25
if ss_tag_frequency is not None and hasattr(ss_tag_frequency, 'items'):
26
for _, tags_dict in ss_tag_frequency.items():
27
for tag, tag_count in tags_dict.items():
28
tag = tag.strip()
29
tags[tag] = tags.get(tag, 0) + int(tag_count)
30
31
if tags and is_non_comma_tagset(tags):
32
new_tags = {}
33
34
for text, text_count in tags.items():
35
for word in re.findall(re_word, text):
36
if len(word) < 3:
37
continue
38
39
new_tags[word] = new_tags.get(word, 0) + text_count
40
41
tags = new_tags
42
43
ordered_tags = sorted(tags.keys(), key=tags.get, reverse=True)
44
45
return [(tag, tags[tag]) for tag in ordered_tags]
46
47
48
class LoraUserMetadataEditor(ui_extra_networks_user_metadata.UserMetadataEditor):
49
def __init__(self, ui, tabname, page):
50
super().__init__(ui, tabname, page)
51
52
self.select_sd_version = None
53
54
self.taginfo = None
55
self.edit_activation_text = None
56
self.slider_preferred_weight = None
57
self.edit_notes = None
58
59
def save_lora_user_metadata(self, name, desc, sd_version, activation_text, preferred_weight, negative_text, notes):
60
user_metadata = self.get_user_metadata(name)
61
user_metadata["description"] = desc
62
user_metadata["sd version"] = sd_version
63
user_metadata["activation text"] = activation_text
64
user_metadata["preferred weight"] = preferred_weight
65
user_metadata["negative text"] = negative_text
66
user_metadata["notes"] = notes
67
68
self.write_user_metadata(name, user_metadata)
69
70
def get_metadata_table(self, name):
71
table = super().get_metadata_table(name)
72
item = self.page.items.get(name, {})
73
metadata = item.get("metadata") or {}
74
75
keys = {
76
'ss_output_name': "Output name:",
77
'ss_sd_model_name': "Model:",
78
'ss_clip_skip': "Clip skip:",
79
'ss_network_module': "Kohya module:",
80
}
81
82
for key, label in keys.items():
83
value = metadata.get(key, None)
84
if value is not None and str(value) != "None":
85
table.append((label, html.escape(value)))
86
87
ss_training_started_at = metadata.get('ss_training_started_at')
88
if ss_training_started_at:
89
table.append(("Date trained:", datetime.datetime.utcfromtimestamp(float(ss_training_started_at)).strftime('%Y-%m-%d %H:%M')))
90
91
ss_bucket_info = metadata.get("ss_bucket_info")
92
if ss_bucket_info and "buckets" in ss_bucket_info:
93
resolutions = {}
94
for _, bucket in ss_bucket_info["buckets"].items():
95
resolution = bucket["resolution"]
96
resolution = f'{resolution[1]}x{resolution[0]}'
97
98
resolutions[resolution] = resolutions.get(resolution, 0) + int(bucket["count"])
99
100
resolutions_list = sorted(resolutions.keys(), key=resolutions.get, reverse=True)
101
resolutions_text = html.escape(", ".join(resolutions_list[0:4]))
102
if len(resolutions) > 4:
103
resolutions_text += ", ..."
104
resolutions_text = f"<span title='{html.escape(', '.join(resolutions_list))}'>{resolutions_text}</span>"
105
106
table.append(('Resolutions:' if len(resolutions_list) > 1 else 'Resolution:', resolutions_text))
107
108
image_count = 0
109
for _, params in metadata.get("ss_dataset_dirs", {}).items():
110
image_count += int(params.get("img_count", 0))
111
112
if image_count:
113
table.append(("Dataset size:", image_count))
114
115
return table
116
117
def put_values_into_components(self, name):
118
user_metadata = self.get_user_metadata(name)
119
values = super().put_values_into_components(name)
120
121
item = self.page.items.get(name, {})
122
metadata = item.get("metadata") or {}
123
124
tags = build_tags(metadata)
125
gradio_tags = [(tag, str(count)) for tag, count in tags[0:24]]
126
127
return [
128
*values[0:5],
129
item.get("sd_version", "Unknown"),
130
gr.HighlightedText.update(value=gradio_tags, visible=True if tags else False),
131
user_metadata.get('activation text', ''),
132
float(user_metadata.get('preferred weight', 0.0)),
133
user_metadata.get('negative text', ''),
134
gr.update(visible=True if tags else False),
135
gr.update(value=self.generate_random_prompt_from_tags(tags), visible=True if tags else False),
136
]
137
138
def generate_random_prompt(self, name):
139
item = self.page.items.get(name, {})
140
metadata = item.get("metadata") or {}
141
tags = build_tags(metadata)
142
143
return self.generate_random_prompt_from_tags(tags)
144
145
def generate_random_prompt_from_tags(self, tags):
146
max_count = None
147
res = []
148
for tag, count in tags:
149
if not max_count:
150
max_count = count
151
152
v = random.random() * max_count
153
if count > v:
154
for x in "({[]})":
155
tag = tag.replace(x, '\\' + x)
156
res.append(tag)
157
158
return ", ".join(sorted(res))
159
160
def create_extra_default_items_in_left_column(self):
161
162
# this would be a lot better as gr.Radio but I can't make it work
163
self.select_sd_version = gr.Dropdown(['SD1', 'SD2', 'SDXL', 'Unknown'], value='Unknown', label='Stable Diffusion version', interactive=True)
164
165
def create_editor(self):
166
self.create_default_editor_elems()
167
168
self.taginfo = gr.HighlightedText(label="Training dataset tags")
169
self.edit_activation_text = gr.Text(label='Activation text', info="Will be added to prompt along with Lora")
170
self.slider_preferred_weight = gr.Slider(label='Preferred weight', info="Set to 0 to disable", minimum=0.0, maximum=2.0, step=0.01)
171
self.edit_negative_text = gr.Text(label='Negative prompt', info="Will be added to negative prompts")
172
with gr.Row() as row_random_prompt:
173
with gr.Column(scale=8):
174
random_prompt = gr.Textbox(label='Random prompt', lines=4, max_lines=4, interactive=False)
175
176
with gr.Column(scale=1, min_width=120):
177
generate_random_prompt = gr.Button('Generate', size="lg", scale=1)
178
179
self.edit_notes = gr.TextArea(label='Notes', lines=4)
180
181
generate_random_prompt.click(fn=self.generate_random_prompt, inputs=[self.edit_name_input], outputs=[random_prompt], show_progress=False)
182
183
def select_tag(activation_text, evt: gr.SelectData):
184
tag = evt.value[0]
185
186
words = re.split(re_comma, activation_text)
187
if tag in words:
188
words = [x for x in words if x != tag and x.strip()]
189
return ", ".join(words)
190
191
return activation_text + ", " + tag if activation_text else tag
192
193
self.taginfo.select(fn=select_tag, inputs=[self.edit_activation_text], outputs=[self.edit_activation_text], show_progress=False)
194
195
self.create_default_buttons()
196
197
viewed_components = [
198
self.edit_name,
199
self.edit_description,
200
self.html_filedata,
201
self.html_preview,
202
self.edit_notes,
203
self.select_sd_version,
204
self.taginfo,
205
self.edit_activation_text,
206
self.slider_preferred_weight,
207
self.edit_negative_text,
208
row_random_prompt,
209
random_prompt,
210
]
211
212
self.button_edit\
213
.click(fn=self.put_values_into_components, inputs=[self.edit_name_input], outputs=viewed_components)\
214
.then(fn=lambda: gr.update(visible=True), inputs=[], outputs=[self.box])
215
216
edited_components = [
217
self.edit_description,
218
self.select_sd_version,
219
self.edit_activation_text,
220
self.slider_preferred_weight,
221
self.edit_negative_text,
222
self.edit_notes,
223
]
224
225
226
self.setup_save_handler(self.button_save, self.save_lora_user_metadata, edited_components)
227
228