Compare commits

...

7 Commits

Author SHA1 Message Date
Dominik Reh
7fdad1bf62 Add back ability to use hashes in black/whitelist
They are displayed in the UI after all, just not in the dropdown but at the bottom
2023-01-14 14:57:39 +01:00
Dominik Reh
a91a098243 Change blacklist to use model name instead of hash
Hotfix for recent webui changes to use proper sha256 hashes, which is currently not displayed in the UI
2023-01-14 14:24:44 +01:00
Dominik Reh
c663abcbcb Fix wiki links showing on embeddings & wildcards 2023-01-13 19:33:43 +01:00
Dominik Reh
bec222f2b3 Fix for 1-letter completion
Completion would sometimes not show if the prompt was only one letter long and identical to the previous completion
2023-01-12 15:54:57 +01:00
Dominik Reh
d4db6a7907 Option to show ? wiki links for danbooru/e621 tags
Disabled by default since the wiki pages likely contain NSFW images.
Closes #109
2023-01-12 15:49:53 +01:00
Dominik Reh
52593e6ac8 Update setting descriptions for black/whitelist 2023-01-12 14:45:16 +01:00
Dominik Reh
849e346924 Black/whitelisting options for models
Enables selective (de)activation based on model hash.
Closes #14
2023-01-12 14:35:54 +01:00
2 changed files with 101 additions and 6 deletions

View File

@@ -70,6 +70,13 @@ const autocompleteCSS = `
flex-grow: 1;
color: var(--meta-text-color);
}
.acWikiLink {
padding: 0.5rem;
margin: -0.5rem 0 -0.5rem -0.5rem;
}
.acWikiLink:hover {
text-decoration: underline;
}
.acListItem.acEmbeddingV1 {
color: var(--embedding-v1-color);
}
@@ -158,7 +165,9 @@ async function syncOptions() {
txt2img: opts["tac_activeIn.txt2img"],
img2img: opts["tac_activeIn.img2img"],
negativePrompts: opts["tac_activeIn.negativePrompts"],
thirdParty: opts["tac_activeIn.thirdParty"]
thirdParty: opts["tac_activeIn.thirdParty"],
modelList: opts["tac_activeIn.modelList"],
modelListMode: opts["tac_activeIn.modelListMode"]
},
// Results related settings
maxResults: opts["tac_maxResults"],
@@ -167,6 +176,7 @@ async function syncOptions() {
delayTime: opts["tac_delayTime"],
useWildcards: opts["tac_useWildcards"],
useEmbeddings: opts["tac_useEmbeddings"],
showWikiLinks: opts["tac_showWikiLinks"],
// Insertion related settings
replaceUnderscores: opts["tac_replaceUnderscores"],
escapeParentheses: opts["tac_escapeParentheses"],
@@ -256,6 +266,30 @@ function hideResults(textArea) {
selectedTag = null;
}
var currentModelHash = "";
var currentModelName = "";
// Function to check activation criteria
function isEnabled() {
if (CFG.activeIn.global) {
let modelList = CFG.activeIn.modelList
.split(",")
.map(x => x.trim())
.filter(x => x.length > 0);
let shortHash = currentModelHash.substring(0, 10);
if (CFG.activeIn.modelListMode.toLowerCase() === "blacklist") {
// If the current model is in the blacklist, disable
return modelList.filter(x => x === currentModelName || x === currentModelHash || x === shortHash).length === 0;
} else {
// If the current model is in the whitelist, enable.
// An empty whitelist is ignored.
return modelList.length === 0 || modelList.filter(x => x === currentModelName || x === currentModelHash || x === shortHash).length > 0;
}
} else {
return false;
}
}
const WEIGHT_REGEX = /[([]([^,()[\]:| ]+)(?::(?:\d+(?:\.\d+)?|\.\d+))?[)\]]/g;
const TAG_REGEX = /(<[^\t\n\r,>]+>?|[^\s,|<>]+|<)/g
const WC_REGEX = /\b__([^, ]+)__([^, ]*)\b/g;
@@ -383,7 +417,6 @@ function addResultsToList(textArea, results, tagword, resetList) {
let itemText = document.createElement("div");
itemText.classList.add("acListItem");
flexDiv.appendChild(itemText);
let displayText = "";
// If the tag matches the tagword, we don't need to display the alias
@@ -421,6 +454,33 @@ function addResultsToList(textArea, results, tagword, resetList) {
// Print search term bolded in result
itemText.innerHTML = displayText.replace(tagword, `<b>${tagword}</b>`);
// Add wiki link if the setting is enabled and a supported tag set loaded
if (CFG.showWikiLinks
&& (result.type === ResultType.tag)
&& (tagFileName.toLowerCase().startsWith("danbooru") || tagFileName.toLowerCase().startsWith("e621"))) {
let wikiLink = document.createElement("a");
wikiLink.classList.add("acWikiLink");
wikiLink.innerText = "?";
let linkPart = displayText;
// Only use alias result if it is one
if (displayText.includes("➝"))
linkPart = displayText.split(" ➝ ")[1];
// Set link based on selected file
let tagFileNameLower = tagFileName.toLowerCase();
if (tagFileNameLower.startsWith("danbooru")) {
wikiLink.href = `https://danbooru.donmai.us/wiki_pages/${linkPart}`;
} else if (tagFileNameLower.startsWith("e621")) {
wikiLink.href = `https://e621.net/wiki_pages/${linkPart}`;
}
wikiLink.target = "_blank";
flexDiv.appendChild(wikiLink);
}
flexDiv.appendChild(itemText);
// Add post count & color if it's a tag
// Wildcards & Embeds have no tag category
if (![ResultType.wildcardFile, ResultType.wildcardTag, ResultType.embedding].includes(result.type)) {
@@ -436,7 +496,7 @@ function addResultsToList(textArea, results, tagword, resetList) {
if (!colorGroup[cat])
cat = "-1";
itemText.style = `color: ${colorGroup[cat][mode]};`;
flexDiv.style = `color: ${colorGroup[cat][mode]};`;
}
// Post count
@@ -514,11 +574,13 @@ var originalTagword = "";
var resultCount = 0;
async function autocomplete(textArea, prompt, fixedTag = null) {
// Return if the function is deactivated in the UI
if (!CFG.activeIn.global) return;
if (!isEnabled()) return;
// Guard for empty prompt
if (prompt.length === 0) {
hideResults(textArea);
previousTags = [];
tagword = "";
return;
}
@@ -533,6 +595,14 @@ async function autocomplete(textArea, prompt, fixedTag = null) {
.concat(weightedTags);
}
// Guard for no tags
if (!tags || tags.length === 0) {
previousTags = [];
tagword = "";
hideResults(textArea);
return;
}
let tagCountChange = tags.length - previousTags.length;
let diff = difference(tags, previousTags);
previousTags = tags;
@@ -859,8 +929,8 @@ async function autocomplete(textArea, prompt, fixedTag = null) {
var oldSelectedTag = null;
function navigateInList(textArea, event) {
// Return if the function is deactivated in the UI
if (!CFG.activeIn.global) return;
// Return if the function is deactivated in the UI or the current model is excluded due to white/blacklist settings
if (!isEnabled()) return;
validKeys = ["ArrowUp", "ArrowDown", "PageUp", "PageDown", "Home", "End", "Enter", "Tab", "Escape"];
@@ -1033,6 +1103,28 @@ async function setup() {
});
});
// Add change listener to model dropdown to react to model changes
let modelDropdown = gradioApp().querySelector("#setting_sd_model_checkpoint select");
currentModelName = modelDropdown.value;
modelDropdown.addEventListener("change", () => {
setTimeout(() => {
currentModelName = modelDropdown.value;
}, 100);
});
// Add mutation observer for the model hash text to also allow hash-based blacklist again
let modelHashText = gradioApp().querySelector("#sd_checkpoint_hash");
if (modelHashText) {
currentModelHash = modelHashText.title
let modelHashObserver = new MutationObserver((mutationList, observer) => {
for (const mutation of mutationList) {
if (mutation.type === "attributes" && mutation.attributeName === "title") {
currentModelHash = mutation.target.title;
}
}
});
modelHashObserver.observe(modelHashText, { attributes: true });
}
// Not found, we're on a page without prompt textareas
if (textAreas.every(v => v === null || v === undefined)) return;
// Already added or unnecessary to add

View File

@@ -215,6 +215,8 @@ def on_ui_settings():
shared.opts.add_option("tac_activeIn.img2img", shared.OptionInfo(True, "Active in img2img (Requires restart)", section=TAC_SECTION))
shared.opts.add_option("tac_activeIn.negativePrompts", shared.OptionInfo(True, "Active in negative prompts (Requires restart)", section=TAC_SECTION))
shared.opts.add_option("tac_activeIn.thirdParty", shared.OptionInfo(True, "Active in third party textboxes [Dataset Tag Editor] (Requires restart)", section=TAC_SECTION))
shared.opts.add_option("tac_activeIn.modelList", shared.OptionInfo("", "List of model names (with file extension) or their hashes to use as black/whitelist, separated by commas.", section=TAC_SECTION))
shared.opts.add_option("tac_activeIn.modelListMode", shared.OptionInfo("Blacklist", "Mode to use for model list", gr.Dropdown, lambda: {"choices": ["Blacklist","Whitelist"]}, section=TAC_SECTION))
# Results related settings
shared.opts.add_option("tac_maxResults", shared.OptionInfo(5, "Maximum results", section=TAC_SECTION))
shared.opts.add_option("tac_showAllResults", shared.OptionInfo(False, "Show all results", section=TAC_SECTION))
@@ -222,6 +224,7 @@ def on_ui_settings():
shared.opts.add_option("tac_delayTime", shared.OptionInfo(100, "Time in ms to wait before triggering completion again (Requires restart)", section=TAC_SECTION))
shared.opts.add_option("tac_useWildcards", shared.OptionInfo(True, "Search for wildcards", section=TAC_SECTION))
shared.opts.add_option("tac_useEmbeddings", shared.OptionInfo(True, "Search for embeddings", section=TAC_SECTION))
shared.opts.add_option("tac_showWikiLinks", shared.OptionInfo(False, "Show '?' next to tags, linking to its Danbooru or e621 wiki page (Warning: This is an external site and very likely contains NSFW examples!)", section=TAC_SECTION))
# Insertion related settings
shared.opts.add_option("tac_replaceUnderscores", shared.OptionInfo(True, "Replace underscores with spaces on insertion", section=TAC_SECTION))
shared.opts.add_option("tac_escapeParentheses", shared.OptionInfo(True, "Escape parentheses on insertion", section=TAC_SECTION))