Compare commits

...
11 Commits
Author SHA1 Message Date
Dijkstra a95cba4e3b doc: last fix 2024-04-09 22:18:14 +02:00
Dijkstra 40f09582e2 doc: added View info in readme 2024-04-09 22:17:08 +02:00
Dijkstra 6635d30566 doc: updated readme 2024-04-09 22:11:55 +02:00
dijkstra 5cf49c9565 Merge pull request #19 from idrirap/issue14
feat: added pyssss's lora view info
2024-04-09 21:24:05 +02:00
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 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
12 changed files with 124 additions and 38 deletions
+70 -21
View File
@@ -2,37 +2,81 @@
This project is a fork of https://github.com/Extraltodeus/LoadLoraWithTags
The aim of these custom nodes is to get an _easy_ access to the tags used to trigger a lora.
This project is compatible with Stacked Loras from https://github.com/LucianoCirino/efficiency-nodes-comfyui/releases
I talk about **lora**, but works with **lycoris** too.
This project is compatible with Stacked Loras from https://github.com/jags111/efficiency-nodes-comfyui
When I talk about **lora**, I also mean **lycoris** too.
## Install
Some of this project nodes depends on https://github.com/pythongosssss/ComfyUI-Custom-Scripts :
- LoraLoaderAdvanced
- LoraLoaderStackedAdvanced
They get their vanilla equivalents.
- `View info...`
They get their vanilla equivalents with less features
Overall, Custom-Scripts is recommended to be able to know the content of the tag lists with the node `showText`
## Features
### Main nodes
#### Vanilla vs Advanced
Vanilla refers to nodes that have no lora preview from the menu, nor the lora list. But the features provided are the same.
> Vanilla refers to nodes that have no lora preview from the menu, nor the lora list. But the features provided are the same.
![image](./images/main.png)
#### Nodes
- LoraLoader (Vanilla or Advanced)
- LoraLoaderStacked (Vanilla or Avanced). The stacked lora input is optional.
Allow to load a lora, either the normal way, or the efficiency-nodes way.
These loaders have two custom outputs:
- civitai_tags_list: a python list of the tags related to this lora on civitai
- meta_tags_list: a python list of the tags used for training the lora embeded in it (if any)
This outputs needs to be filtered by two othere nodes:
- TagsFormater: Helper to show the available tag and their indexes
- tagsSelector: allow to filter tags and apply a weight to it.
- TagSelector contains four parameters. First the selector (see Filtering next)
- The weight `(tag:weight)`
- The boolean `ensure_comma`. To properly append comma if a prefix or suffix is added.
- The boolean `append_loraname_if_empty` which will add the name of the lora in the list of outputs if they are empty.
#### Filtering
### Nodes
#### LoraLoader (Vanilla and Advanced)
![image](./images/LoraLoader.png)
INPUT
- `override_lora_name` (optional): Used to ignore the field `lora_name` and use the name passed. Should use [LoraListNames](#loralistnames) or the `lora_name` output.
FIELDS
- `force_fetch`: Force the civitai fetching of data even if there is already something saved
- `enable_preview`: Toggle on/off the saved lora preview if any (only in advanced)
- `append_lora_if_empty`: Add the name of the lora to the list of tags if the list is empty
OUTPUT
- `civitai_tags_list`: a python list of the tags related to this lora on civitai
- `meta_tags_list`: a python list of the tags used for training the lora embeded in it (if any)
- `lora_name`: the name of the current selected lora
#### LoraLoaderStacked (Vanilla and Avanced).
![image](./images/LoraLoaderStacked.png)
INPUT
- `lora_stack` (optional): another stack of lora.
- `override_lora_name` (optional): Used to ignore the field `lora_name` and use the name passed. Should use [LoraListNames](#loralistnames) or the `lora_name` output.
FIELDS
- `force_fetch`: Force the civitai fetching of data even if there is already something saved
- `enable_preview`: Toggle on/off the saved lora preview if any (only in advanced)
- `append_lora_if_empty`: Add the name of the lora to the list of tags if the list is empty
OUTPUT
- `civitai_tags_list`: a python list of the tags related to this lora on civitai
- `meta_tags_list`: a python list of the tags used for training the lora embeded in it (if any)
- `lora_name`: the name of the current selected lora
#### LoraTagsOnly
![image](./images/LoraTagsOnly.png)
To get the tags without using the lora.
- `override_lora_name` (optional): Used to ignore the field `lora_name` and use the name passed. Should use [LoraListNames](#loralistnames) or the `lora_name` output.
OUTPUT
- `civitai_tags_list`: a python list of the tags related to this lora on civitai
- `meta_tags_list`: a python list of the tags used for training the lora embeded in it (if any)
- `lora_name`: the name of the current selected lora
#### TagsFormater
![image](./images/TagsFormater.png)
Helper to show the available tag and their indexes. Tags are sorted by training frequence. The more a tag was used, the higher in the list it is. Works for both `civitai_tags_list` and `meta_tags_list`
#### TagsSelector
![image](./images/TagsSelector.png)
Allow to filter tags and apply a weight to it.
TagSelector contains four parameters.
- `selector` (see the [Filtering](#filtering) section next)
- `weight`: to format the tag like `(tag:weight)`. Default set to 1 without the weight like `tag`.
- `ensure_comma`. To properly append comma if a prefix or suffix is added.
#### LoraListNames
![image](./images/LoraListNames.png)
List all the existing lora names. It is used as an input for `override_lora_name`
### Filtering
The format is simple. It's the same as python list index, but can select multiple index or ranges of indexes separated by comas.
`Ex: 0, 3, 5:8, -8:`
- Select a specific list of indexes: `0, 2, 3, 15`...
@@ -42,6 +86,11 @@ The format is simple. It's the same as python list index, but can select multipl
- You can use negative indexes. Like `-1` to select the last tag
- By default `:` selects everything
### View Info
![image](./images/ViewInfo.png)
Pythongossss's [View Info...](https://github.com/pythongosssss/ComfyUI-Custom-Scripts?tab=readme-ov-file#checkpointloraembedding-info) feature from ComfyUI-Custom-Scripts
### Examples
#### Example of normal workflow
![image](./images/loaderAdvanced.png)
@@ -55,5 +104,5 @@ Lora Stack can also be chained together to load multiple loras into an efficient
### Side nodes I made and kept here
- FusionText: takes two text input and join them together
- Randomizer: takes two couples text+lorastack and return randomly one them
- Randomizer: takes two couples text+lorastack and return randomly one of them
- TextInputBasic: just a text input with two additional input for text chaining
+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_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"]
Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

+14 -14
View File
@@ -26,8 +26,8 @@ class LoraLoaderVanilla:
}
}
RETURN_TYPES = ("MODEL", "CLIP", "LIST", "LIST")
RETURN_NAMES = ("MODEL", "CLIP", "civitai_tags_list", "meta_tags_list")
RETURN_TYPES = ("MODEL", "CLIP", "LIST", "LIST", "STRING")
RETURN_NAMES = ("MODEL", "CLIP", "civitai_tags_list", "meta_tags_list", "lora_name")
FUNCTION = "load_lora"
CATEGORY = "autotrigger"
@@ -56,7 +56,7 @@ class LoraLoaderVanilla:
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:
@classmethod
@@ -75,8 +75,8 @@ class LoraLoaderStackedVanilla:
}
}
RETURN_TYPES = ("LIST", "LIST", "LORA_STACK",)
RETURN_NAMES = ("civitai_tags_list", "meta_tags_list", "LORA_STACK",)
RETURN_TYPES = ("LIST", "LIST", "LORA_STACK", "STRING")
RETURN_NAMES = ("civitai_tags_list", "meta_tags_list", "LORA_STACK", "lora_name")
FUNCTION = "set_stack"
#OUTPUT_NODE = False
CATEGORY = "autotrigger"
@@ -96,7 +96,7 @@ class LoraLoaderStackedVanilla:
if lora_stack is not None:
loras.extend(lora_stack)
return (civitai_tags_list, meta_tags_list, loras)
return (civitai_tags_list, meta_tags_list, loras, lora_name)
class LoraLoaderAdvanced:
def __init__(self):
@@ -122,8 +122,8 @@ class LoraLoaderAdvanced:
}
}
RETURN_TYPES = ("MODEL", "CLIP", "LIST", "LIST")
RETURN_NAMES = ("MODEL", "CLIP", "civitai_tags_list", "meta_tags_list")
RETURN_TYPES = ("MODEL", "CLIP", "LIST", "LIST", "STRING")
RETURN_NAMES = ("MODEL", "CLIP", "civitai_tags_list", "meta_tags_list", "lora_name")
FUNCTION = "load_lora"
CATEGORY = "autotrigger"
@@ -162,10 +162,10 @@ class LoraLoaderAdvanced:
"subfolder": "lora_preview",
"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:
@classmethod
@@ -186,8 +186,8 @@ class LoraLoaderStackedAdvanced:
}
}
RETURN_TYPES = ("LIST", "LIST", "LORA_STACK",)
RETURN_NAMES = ("civitai_tags_list", "meta_tags_list", "LORA_STACK",)
RETURN_TYPES = ("LIST", "LIST", "LORA_STACK", "STRING")
RETURN_NAMES = ("civitai_tags_list", "meta_tags_list", "LORA_STACK", "lora_name")
FUNCTION = "set_stack"
#OUTPUT_NODE = False
CATEGORY = "autotrigger"
@@ -218,9 +218,9 @@ class LoraLoaderStackedAdvanced:
"subfolder": "lora_preview",
"type": "temp"
}
return {"ui": {"images": [preview_output]}, "result": (civitai_tags_list, meta_tags_list, loras)}
return {"ui": {"images": [preview_output]}, "result": (civitai_tags_list, meta_tags_list, loras, lora_name["content"])}
return {"result": (civitai_tags_list, meta_tags_list, loras)}
return {"result": (civitai_tags_list, meta_tags_list, loras, lora_name["content"])}
class LoraTagsOnly:
@classmethod
+2 -2
View File
@@ -68,7 +68,7 @@ def load_json_from_file(file_path):
return None
except json.JSONDecodeError:
print(f"Error decoding JSON in file: {file_path}")
return None
raise
def save_dict_to_json(data_dict, file_path):
try:
@@ -221,4 +221,4 @@ def append_lora_name_if_empty(tags_list, lora_path, enabled):
filename = os.path.basename(filename)
tags_list.append(filename)
return tags_list
return tags_list
+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);
};
}
});