Compare commits

...
16 Commits
Author SHA1 Message Date
Dijkstra 1e8ed1e16f feat: added pyssss's lora view info 2024-04-09 21:09:44 +02:00
dijkstra 64113afd7f Merge pull request #18 from idrirap/issue16
feat: added lora name to output
2024-04-09 18:16:19 +02:00
Dijkstra 2bd6769b78 fix: now can use the output lora_name as an input for override_lora_name 2024-04-09 18:11:46 +02:00
Dijkstra 96a69f7cbe feat: added lora name to output 2024-04-09 17:05:22 +02:00
dijkstra 9d8b79844f Merge pull request #13 from idrirap/issue12
fix: broken preview when using both enable preview and override_lora_name
2024-03-14 23:26:17 +01:00
Dijkstra f3815b7ce4 fix: broken preview when using both enable preview and override_lora_name 2024-03-14 23:23:35 +01:00
dijkstra d5641ba745 Merge pull request #11 from deipfei/json-error-change
don't delete loras_tags.json on JSONDecodeError
2024-03-08 21:21:03 +01:00
Dustin Pfeiffer 5b5eaf3a81 don't delete loras_tags.json on JSONDecodeError 2024-02-23 15:28:01 -08:00
dijkstra 517b8a8a12 Merge pull request #9 from idrirap/issue8
feat: added tags only node. Added node to load lora names as string. …
2023-12-12 18:58:03 +01:00
Dijkstra 0be7528f10 feat: added tags only node. Added node to load lora names as string. Added the ability to override lora name from dropdown menu. + fixed bad parameters for strenght_model 2023-12-12 18:51:00 +01:00
dijkstra b63862f2e3 Merge pull request #7 from idrirap/fix_civitai_initial_search
fix: tags were never pulled from civitai the first time they were req…
2023-11-20 18:12:13 +01:00
Dijkstra 8ed3d36eaf fix: tags were never pulled from civitai the first time they were requested 2023-11-20 18:11:23 +01:00
dijkstra 8af8cce210 Merge pull request #5 from idrirap/fix_cache_stacker
fix: bug where lora_stack input get stacked with the lora_stack output exponentially
2023-11-17 18:36:32 +01:00
Dijkstra d7530a3326 fix: bug where lora_stack input get stacked with the lora_stack output exponentially 2023-11-17 18:33:28 +01:00
Dijkstra 05de5959e1 Merge branch 'main' of github.com:idrirap/ComfyUI-Lora-Auto-Trigger-Words into main 2023-11-01 18:49:28 +01:00
dijkstra 049fd1eb71 Merge pull request #3 from idrirap/dev/fix_issue2
Dev/fix issue2
2023-11-01 18:45:53 +01:00
5 changed files with 156 additions and 44 deletions
+2 -1
View File
@@ -5,4 +5,5 @@ from .nodes_utils import NODE_CLASS_MAPPINGS as nu_NCM
NODE_CLASS_MAPPINGS = dict(na_NCM, **nu_NCM) NODE_CLASS_MAPPINGS = dict(na_NCM, **nu_NCM)
#NODE_DISPLAY_NAME_MAPPINGS = dict(na_NDNM, **nu_NDNM) #NODE_DISPLAY_NAME_MAPPINGS = dict(na_NDNM, **nu_NDNM)
__all__ = ["NODE_CLASS_MAPPINGS"]#, "NODE_DISPLAY_NAME_MAPPINGS"] WEB_DIRECTORY = "./web"
__all__ = ["NODE_CLASS_MAPPINGS", "WEB_DIRECTORY"]#, "NODE_DISPLAY_NAME_MAPPINGS"]
+81 -28
View File
@@ -16,19 +16,24 @@ class LoraLoaderVanilla:
"model": ("MODEL",), "model": ("MODEL",),
"clip": ("CLIP", ), "clip": ("CLIP", ),
"lora_name": (LORA_LIST, ), "lora_name": (LORA_LIST, ),
"strength_model": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.1}), "strength_model": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}),
"strength_clip": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.1}), "strength_clip": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}),
"force_fetch": ("BOOLEAN", {"default": False}), "force_fetch": ("BOOLEAN", {"default": False}),
"append_loraname_if_empty": ("BOOLEAN", {"default": False}), "append_loraname_if_empty": ("BOOLEAN", {"default": False}),
},
"optional": {
"override_lora_name":("STRING", {"forceInput": True}),
} }
} }
RETURN_TYPES = ("MODEL", "CLIP", "LIST", "LIST") RETURN_TYPES = ("MODEL", "CLIP", "LIST", "LIST", "STRING")
RETURN_NAMES = ("MODEL", "CLIP", "civitai_tags_list", "meta_tags_list") RETURN_NAMES = ("MODEL", "CLIP", "civitai_tags_list", "meta_tags_list", "lora_name")
FUNCTION = "load_lora" FUNCTION = "load_lora"
CATEGORY = "autotrigger" CATEGORY = "autotrigger"
def load_lora(self, model, clip, lora_name, strength_model, strength_clip, force_fetch, append_loraname_if_empty): def load_lora(self, model, clip, lora_name, strength_model, strength_clip, force_fetch, append_loraname_if_empty, override_lora_name=""):
if override_lora_name != "":
lora_name = override_lora_name
meta_tags_list = sort_tags_by_frequency(get_metadata(lora_name, "loras")) meta_tags_list = sort_tags_by_frequency(get_metadata(lora_name, "loras"))
civitai_tags_list = load_and_save_tags(lora_name, force_fetch) civitai_tags_list = load_and_save_tags(lora_name, force_fetch)
@@ -51,7 +56,7 @@ class LoraLoaderVanilla:
model_lora, clip_lora = load_lora_for_models(model, clip, lora, strength_model, strength_clip) model_lora, clip_lora = load_lora_for_models(model, clip, lora, strength_model, strength_clip)
return (model_lora, clip_lora, civitai_tags_list, meta_tags_list) return (model_lora, clip_lora, civitai_tags_list, meta_tags_list, lora_name)
class LoraLoaderStackedVanilla: class LoraLoaderStackedVanilla:
@classmethod @classmethod
@@ -66,16 +71,19 @@ class LoraLoaderStackedVanilla:
}, },
"optional": { "optional": {
"lora_stack": ("LORA_STACK", ), "lora_stack": ("LORA_STACK", ),
"override_lora_name":("STRING", {"forceInput": True}),
} }
} }
RETURN_TYPES = ("LIST", "LIST", "LORA_STACK",) RETURN_TYPES = ("LIST", "LIST", "LORA_STACK", "STRING")
RETURN_NAMES = ("civitai_tags_list", "meta_tags_list", "LORA_STACK",) RETURN_NAMES = ("civitai_tags_list", "meta_tags_list", "LORA_STACK", "lora_name")
FUNCTION = "set_stack" FUNCTION = "set_stack"
#OUTPUT_NODE = False #OUTPUT_NODE = False
CATEGORY = "autotrigger" CATEGORY = "autotrigger"
def set_stack(self, lora_name, lora_weight, force_fetch, append_loraname_if_empty, lora_stack=None): def set_stack(self, lora_name, lora_weight, force_fetch, append_loraname_if_empty, lora_stack=None, override_lora_name=""):
if override_lora_name != "":
lora_name = override_lora_name
civitai_tags_list = load_and_save_tags(lora_name, force_fetch) civitai_tags_list = load_and_save_tags(lora_name, force_fetch)
meta_tags = get_metadata(lora_name, "loras") meta_tags = get_metadata(lora_name, "loras")
@@ -84,12 +92,11 @@ class LoraLoaderStackedVanilla:
civitai_tags_list = append_lora_name_if_empty(civitai_tags_list, lora_name, append_loraname_if_empty) civitai_tags_list = append_lora_name_if_empty(civitai_tags_list, lora_name, append_loraname_if_empty)
meta_tags_list = append_lora_name_if_empty(meta_tags_list, lora_name, append_loraname_if_empty) meta_tags_list = append_lora_name_if_empty(meta_tags_list, lora_name, append_loraname_if_empty)
loras = [(lora_name,lora_weight,lora_weight,)]
if lora_stack is not None: if lora_stack is not None:
lora_stack.append((lora_name,lora_weight,lora_weight,)) loras.extend(lora_stack)
else:
lora_stack = [(lora_name,lora_weight,lora_weight,)]
return (civitai_tags_list, meta_tags_list, lora_stack) return (civitai_tags_list, meta_tags_list, loras, lora_name)
class LoraLoaderAdvanced: class LoraLoaderAdvanced:
def __init__(self): def __init__(self):
@@ -104,20 +111,28 @@ class LoraLoaderAdvanced:
"model": ("MODEL",), "model": ("MODEL",),
"clip": ("CLIP", ), "clip": ("CLIP", ),
"lora_name": (LORA_LIST, ), "lora_name": (LORA_LIST, ),
"strength_model": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.1}), "strength_model": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}),
"strength_clip": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.1}), "strength_clip": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}),
"force_fetch": ("BOOLEAN", {"default": False}), "force_fetch": ("BOOLEAN", {"default": False}),
"enable_preview": ("BOOLEAN", {"default": False}), "enable_preview": ("BOOLEAN", {"default": False}),
"append_loraname_if_empty": ("BOOLEAN", {"default": False}), "append_loraname_if_empty": ("BOOLEAN", {"default": False}),
},
"optional": {
"override_lora_name":("STRING", {"forceInput": True}),
} }
} }
RETURN_TYPES = ("MODEL", "CLIP", "LIST", "LIST") RETURN_TYPES = ("MODEL", "CLIP", "LIST", "LIST", "STRING")
RETURN_NAMES = ("MODEL", "CLIP", "civitai_tags_list", "meta_tags_list") RETURN_NAMES = ("MODEL", "CLIP", "civitai_tags_list", "meta_tags_list", "lora_name")
FUNCTION = "load_lora" FUNCTION = "load_lora"
CATEGORY = "autotrigger" CATEGORY = "autotrigger"
def load_lora(self, model, clip, lora_name, strength_model, strength_clip, force_fetch, enable_preview, append_loraname_if_empty): def load_lora(self, model, clip, lora_name, strength_model, strength_clip, force_fetch, enable_preview, append_loraname_if_empty, override_lora_name=""):
if override_lora_name != "":
has_preview, prev = get_preview_path(override_lora_name, "loras")
prev = f"loras/{prev}" if has_preview else None
lora_name = {"content": override_lora_name, "image": prev, "type": "loras"}
meta_tags_list = sort_tags_by_frequency(get_metadata(lora_name["content"], "loras")) meta_tags_list = sort_tags_by_frequency(get_metadata(lora_name["content"], "loras"))
civitai_tags_list = load_and_save_tags(lora_name["content"], force_fetch) civitai_tags_list = load_and_save_tags(lora_name["content"], force_fetch)
@@ -147,10 +162,10 @@ class LoraLoaderAdvanced:
"subfolder": "lora_preview", "subfolder": "lora_preview",
"type": "temp" "type": "temp"
} }
return {"ui": {"images": [preview_output]}, "result": (model_lora, clip_lora, civitai_tags_list, meta_tags_list)} return {"ui": {"images": [preview_output]}, "result": (model_lora, clip_lora, civitai_tags_list, meta_tags_list, lora_name["content"])}
return (model_lora, clip_lora, civitai_tags_list, meta_tags_list) return (model_lora, clip_lora, civitai_tags_list, meta_tags_list, lora_name["content"])
class LoraLoaderStackedAdvanced: class LoraLoaderStackedAdvanced:
@classmethod @classmethod
@@ -167,16 +182,22 @@ class LoraLoaderStackedAdvanced:
}, },
"optional": { "optional": {
"lora_stack": ("LORA_STACK", ), "lora_stack": ("LORA_STACK", ),
"override_lora_name":("STRING", {"forceInput": True}),
} }
} }
RETURN_TYPES = ("LIST", "LIST", "LORA_STACK",) RETURN_TYPES = ("LIST", "LIST", "LORA_STACK", "STRING")
RETURN_NAMES = ("civitai_tags_list", "meta_tags_list", "LORA_STACK",) RETURN_NAMES = ("civitai_tags_list", "meta_tags_list", "LORA_STACK", "lora_name")
FUNCTION = "set_stack" FUNCTION = "set_stack"
#OUTPUT_NODE = False #OUTPUT_NODE = False
CATEGORY = "autotrigger" CATEGORY = "autotrigger"
def set_stack(self, lora_name, lora_weight, force_fetch, enable_preview, append_loraname_if_empty, lora_stack=None): def set_stack(self, lora_name, lora_weight, force_fetch, enable_preview, append_loraname_if_empty, lora_stack=None, override_lora_name=""):
if override_lora_name != "":
has_preview, prev = get_preview_path(override_lora_name, "loras")
prev = f"loras/{prev}" if has_preview else None
lora_name = {"content": override_lora_name, "image": prev, "type": "loras"}
civitai_tags_list = load_and_save_tags(lora_name["content"], force_fetch) civitai_tags_list = load_and_save_tags(lora_name["content"], force_fetch)
meta_tags = get_metadata(lora_name["content"], "loras") meta_tags = get_metadata(lora_name["content"], "loras")
@@ -185,10 +206,9 @@ class LoraLoaderStackedAdvanced:
civitai_tags_list = append_lora_name_if_empty(civitai_tags_list, lora_name["content"], append_loraname_if_empty) civitai_tags_list = append_lora_name_if_empty(civitai_tags_list, lora_name["content"], append_loraname_if_empty)
meta_tags_list = append_lora_name_if_empty(meta_tags_list, lora_name["content"], append_loraname_if_empty) meta_tags_list = append_lora_name_if_empty(meta_tags_list, lora_name["content"], append_loraname_if_empty)
loras = [(lora_name["content"],lora_weight,lora_weight,)]
if lora_stack is not None: if lora_stack is not None:
lora_stack.append((lora_name["content"],lora_weight,lora_weight,)) loras.extend(lora_stack)
else:
lora_stack = [(lora_name["content"],lora_weight,lora_weight,)]
if enable_preview: if enable_preview:
_, preview = copy_preview_to_temp(lora_name["image"]) _, preview = copy_preview_to_temp(lora_name["image"])
@@ -198,9 +218,40 @@ class LoraLoaderStackedAdvanced:
"subfolder": "lora_preview", "subfolder": "lora_preview",
"type": "temp" "type": "temp"
} }
return {"ui": {"images": [preview_output]}, "result": (civitai_tags_list, meta_tags_list, lora_stack)} return {"ui": {"images": [preview_output]}, "result": (civitai_tags_list, meta_tags_list, loras, lora_name["content"])}
return {"result": (civitai_tags_list, meta_tags_list, lora_stack)} return {"result": (civitai_tags_list, meta_tags_list, loras, lora_name["content"])}
class LoraTagsOnly:
@classmethod
def INPUT_TYPES(s):
LORA_LIST = sorted(folder_paths.get_filename_list("loras"), key=str.lower)
return {
"required": {
"lora_name": (LORA_LIST,),
"force_fetch": ("BOOLEAN", {"default": False}),
"append_loraname_if_empty": ("BOOLEAN", {"default": False}),
},
"optional": {
"override_lora_name":("STRING", {"forceInput": True}),
}
}
RETURN_TYPES = ("LIST", "LIST")
RETURN_NAMES = ("civitai_tags_list", "meta_tags_list")
FUNCTION = "ask_lora"
CATEGORY = "autotrigger"
def ask_lora(self, lora_name, force_fetch, append_loraname_if_empty, override_lora_name=""):
if override_lora_name != "":
lora_name = override_lora_name
meta_tags_list = sort_tags_by_frequency(get_metadata(lora_name, "loras"))
civitai_tags_list = load_and_save_tags(lora_name, force_fetch)
meta_tags_list = append_lora_name_if_empty(meta_tags_list, lora_name, append_loraname_if_empty)
civitai_tags_list = append_lora_name_if_empty(civitai_tags_list, lora_name, append_loraname_if_empty)
return (civitai_tags_list, meta_tags_list)
# A dictionary that contains all nodes you want to export with their names # A dictionary that contains all nodes you want to export with their names
@@ -210,6 +261,7 @@ NODE_CLASS_MAPPINGS = {
"LoraLoaderStackedVanilla": LoraLoaderStackedVanilla, "LoraLoaderStackedVanilla": LoraLoaderStackedVanilla,
"LoraLoaderAdvanced": LoraLoaderAdvanced, "LoraLoaderAdvanced": LoraLoaderAdvanced,
"LoraLoaderStackedAdvanced": LoraLoaderStackedAdvanced, "LoraLoaderStackedAdvanced": LoraLoaderStackedAdvanced,
"LoraTagsOnly": LoraTagsOnly,
} }
# A dictionary that contains the friendly/humanly readable titles for the nodes # A dictionary that contains the friendly/humanly readable titles for the nodes
@@ -218,4 +270,5 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"LoraLoaderStackedVanilla": "LoraLoaderStackedVanilla", "LoraLoaderStackedVanilla": "LoraLoaderStackedVanilla",
"LoraLoaderAdvanced": "LoraLoaderAdvanced", "LoraLoaderAdvanced": "LoraLoaderAdvanced",
"LoraLoaderStackedAdvanced": "LoraLoaderStackedAdvanced", "LoraLoaderStackedAdvanced": "LoraLoaderStackedAdvanced",
"LoraTagsOnly": "LoraTagsOnly",
} }
+27 -7
View File
@@ -1,5 +1,3 @@
import random
from .utils import * from .utils import *
class FusionText: class FusionText:
@@ -20,11 +18,13 @@ class Randomizer:
return { return {
"required": { "required": {
"text_1":("STRING", {"forceInput": True}), "text_1":("STRING", {"forceInput": True}),
"lora_1":("LORA_STACK", ),
"text_2":("STRING", {"forceInput": True} ), "text_2":("STRING", {"forceInput": True} ),
"lora_2":("LORA_STACK", ),
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}), "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
}, },
"optional": {
"lora_1":("LORA_STACK", ),
"lora_2":("LORA_STACK", ),
}
} }
RETURN_TYPES = ("STRING", "LORA_STACK") RETURN_TYPES = ("STRING", "LORA_STACK")
@@ -35,9 +35,8 @@ class Randomizer:
CATEGORY = "autotrigger" CATEGORY = "autotrigger"
def randomize(self, text_1, lora_1, text_2, lora_2, seed): def randomize(self, text_1, text_2, seed, lora_1=[], lora_2=[]):
random.seed(seed) if seed %2 == 0:
if random.random() < .5:
return (text_1, lora_1) return (text_1, lora_1)
return (text_2, lora_2) return (text_2, lora_2)
@@ -121,6 +120,25 @@ class TagsFormater:
return (output,) return (output,)
class LoraListNames:
@classmethod
def INPUT_TYPES(s):
LORA_LIST = sorted(folder_paths.get_filename_list("loras"), key=str.lower)
return {
"required": {
"lora_name": (LORA_LIST,),
}
}
RETURN_TYPES = ("STRING",)
RETURN_NAMES = ("lora_name",)
FUNCTION = "output_selected"
CATEGORY = "autotrigger"
def output_selected(self, lora_name):
name = lora_name
return (name,)
# A dictionary that contains all nodes you want to export with their names # A dictionary that contains all nodes you want to export with their names
# NOTE: names should be globally unique # NOTE: names should be globally unique
NODE_CLASS_MAPPINGS = { NODE_CLASS_MAPPINGS = {
@@ -129,6 +147,7 @@ NODE_CLASS_MAPPINGS = {
"TextInputBasic": TextInputBasic, "TextInputBasic": TextInputBasic,
"TagsSelector": TagsSelector, "TagsSelector": TagsSelector,
"TagsFormater": TagsFormater, "TagsFormater": TagsFormater,
"LoraListNames": LoraListNames,
} }
# A dictionary that contains the friendly/humanly readable titles for the nodes # A dictionary that contains the friendly/humanly readable titles for the nodes
@@ -138,4 +157,5 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"TextInputBasic": "TextInputBasic", "TextInputBasic": "TextInputBasic",
"TagsSelector": "TagsSelector", "TagsSelector": "TagsSelector",
"TagsFormater": "TagsFormater", "TagsFormater": "TagsFormater",
"LoraListNames": "LoraListNames",
} }
+8 -6
View File
@@ -31,6 +31,8 @@ def copy_preview_to_temp(file_name):
lora_less = "/".join(file_name.split("/")[1:]) lora_less = "/".join(file_name.split("/")[1:])
file_path = folder_paths.get_full_path("loras", lora_less) file_path = folder_paths.get_full_path("loras", lora_less)
if file_path is None:
return None, None
temp_path = folder_paths.get_temp_directory() temp_path = folder_paths.get_temp_directory()
preview_path = os.path.join(temp_path, "lora_preview") preview_path = os.path.join(temp_path, "lora_preview")
@@ -66,7 +68,7 @@ def load_json_from_file(file_path):
return None return None
except json.JSONDecodeError: except json.JSONDecodeError:
print(f"Error decoding JSON in file: {file_path}") print(f"Error decoding JSON in file: {file_path}")
return None raise
def save_dict_to_json(data_dict, file_path): def save_dict_to_json(data_dict, file_path):
try: try:
@@ -103,21 +105,21 @@ def load_and_save_tags(lora_name, force_fetch):
output_tags_list = [] output_tags_list = []
lora_path = folder_paths.get_full_path("loras", lora_name) lora_path = folder_paths.get_full_path("loras", lora_name)
if lora_tags is None or force_fetch: # search on civitai only if no local cache or forced if lora_tags is None or force_fetch or output_tags is None: # search on civitai only if no local cache or forced
print("calculating lora hash") print("[Lora-Auto-Trigger] calculating lora hash")
LORAsha256 = calculate_sha256(lora_path) LORAsha256 = calculate_sha256(lora_path)
print("requesting infos") print("[Lora-Auto-Trigger] requesting infos")
model_info = get_model_version_info(LORAsha256) model_info = get_model_version_info(LORAsha256)
if model_info is not None: if model_info is not None:
if "trainedWords" in model_info: if "trainedWords" in model_info:
print("tags found!") print("[Lora-Auto-Trigger] tags found!")
if lora_tags is None: if lora_tags is None:
lora_tags = {} lora_tags = {}
lora_tags[lora_name] = model_info["trainedWords"] lora_tags[lora_name] = model_info["trainedWords"]
save_dict_to_json(lora_tags, json_tags_path) save_dict_to_json(lora_tags, json_tags_path)
output_tags_list = model_info["trainedWords"] output_tags_list = model_info["trainedWords"]
else: else:
print("No informations found.") print("[Lora-Auto-Trigger] No informations found.")
if lora_tags is None: if lora_tags is None:
lora_tags = {} lora_tags = {}
lora_tags[lora_name] = [] lora_tags[lora_name] = []
+36
View File
@@ -0,0 +1,36 @@
import { app } from "../../../scripts/app.js";
import { LoraInfoDialog } from "../../ComfyUI-Custom-Scripts/js/modelInfo.js";
const infoHandlers = {
"LoraLoaderVanilla":true,
"LoraLoaderStackedVanilla":true,
"LoraLoaderAdvanced":true,
"LoraLoaderStackedAdvanced":true
}
app.registerExtension({
name: "autotrigger.LoraInfo",
beforeRegisterNodeDef(nodeType) {
if (! infoHandlers[nodeType.comfyClass]) {
return;
}
const getExtraMenuOptions = nodeType.prototype.getExtraMenuOptions;
nodeType.prototype.getExtraMenuOptions = function (_, options) {
let value = this.widgets[0].value;
if (!value) {
return;
}
if (value.content) {
value = value.content;
}
options.unshift({
content: "View info...",
callback: async () => {
new LoraInfoDialog(value).show("loras", value);
},
});
return getExtraMenuOptions?.apply(this, arguments);
};
}
});