Compare commits

..
Author SHA1 Message Date
Dijkstra 2e889c7018 chore: detail the difference between tags and trigger words 2025-07-26 17:46:52 +02:00
Dijkstra 52157dff5a Merge pull request #39 from idrirap/dev/issue38
fix: no longer crash when internet is unavailable
2025-01-16 09:38:20 +01:00
Dijkstra 8c18075e9f chore: update node version 2025-01-16 09:37:53 +01:00
Dijkstra e0ec5dee30 fix: no longer crash when internet is unavailable 2025-01-16 09:35:17 +01:00
Dijkstra c09e56b21f Merge pull request #36 from idrirap/dev/issue33
Dev/issue33
2024-10-31 19:53:14 +01:00
Dijkstra 763152c041 chore: set clip strength to 0 when there is no CLIP. (just in case) 2024-10-31 19:51:46 +01:00
Dijkstra c85b302a61 chore: CLIP is not optional in the LoraLoaderVanilla and LoraLoaderAdvanced 2024-10-31 19:49:13 +01:00
Dijkstra 6484968fbe Merge pull request #35 from idrirap/dev/issue34
fix: sometimes the preview image extension is prefixed with '.preview'
2024-10-31 19:15:58 +01:00
Dijkstra 9a212d13e7 fix: sometimes the preview image extension is prefixed with '.preview' 2024-10-31 19:14:31 +01:00
Dijkstra b02bea5480 chore: bump version + added MIT license 2024-06-20 17:56:49 +02:00
Dijkstra 8c4b7941a6 chore: improved description 2024-06-20 17:50:07 +02:00
dijkstra 070751dbf1 Merge pull request #24 from idrirap/dev/add_registryId
feat: set publisherId
2024-06-20 17:35:06 +02:00
Dijkstra 41f6277830 feat: set publisherId 2024-06-20 17:34:27 +02:00
dijkstra 03ddfbfe66 Merge pull request #21 from haohaocreates/publish
Add Github Action for Publishing to Comfy Registry
2024-06-20 17:28:55 +02:00
dijkstra 885a1c8371 Merge pull request #22 from haohaocreates/pyproject
Add pyproject.toml for Custom Node Registry
2024-06-20 17:28:45 +02:00
haohaocreates 8656b2ebaf chore(pyproject): Add pyproject.toml for Custom Node Registry 2024-05-22 17:25:44 -04:00
haohaocreates c3759e7b30 chore(publish): Add Github Action for Publishing to Comfy Registry 2024-05-22 17:25:41 -04:00
Dijkstra 236e230515 doc: added trigger explanation 2024-04-09 22:35:48 +02:00
dijkstra 23ef04b1cb Merge pull request #20 from idrirap/update_readme
Update readme
2024-04-09 22:18:38 +02:00
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
13 changed files with 136 additions and 33 deletions
+21
View File
@@ -0,0 +1,21 @@
name: Publish to Comfy registry
on:
workflow_dispatch:
push:
branches:
- main
paths:
- "pyproject.toml"
jobs:
publish-node:
name: Publish Custom Node to registry
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Publish Custom Node
uses: Comfy-Org/publish-node-action@main
with:
## Add your own personal access token to your Github Repository secrets and reference it here.
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
+81 -22
View File
@@ -1,38 +1,92 @@
# ComfyUI-Lora-Auto-Trigger-Words
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.
The aim of these custom nodes is to get an _easy_ access to the **trigger words** (or **tags**) used to trigger a lora.
*Note that trigger words and tags are used interchangeably in this readme and means the same thing.*
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
### Lora Trigger Words
Lora trigger words are imported from two sources :
- Civitai api (only for civitai models)
![image](./images/CivitaiTriggerWords.png)
- Model training metadata (when available)
#### 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 +96,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 +114,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
Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

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

+8 -5
View File
@@ -14,7 +14,6 @@ class LoraLoaderVanilla:
return {
"required": {
"model": ("MODEL",),
"clip": ("CLIP", ),
"lora_name": (LORA_LIST, ),
"strength_model": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}),
"strength_clip": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}),
@@ -22,6 +21,7 @@ class LoraLoaderVanilla:
"append_loraname_if_empty": ("BOOLEAN", {"default": False}),
},
"optional": {
"clip": ("CLIP", ),
"override_lora_name":("STRING", {"forceInput": True}),
}
}
@@ -31,7 +31,9 @@ class LoraLoaderVanilla:
FUNCTION = "load_lora"
CATEGORY = "autotrigger"
def load_lora(self, model, clip, lora_name, strength_model, strength_clip, force_fetch, append_loraname_if_empty, override_lora_name=""):
def load_lora(self, model, lora_name, strength_model, strength_clip, force_fetch, append_loraname_if_empty, clip=None, override_lora_name=""):
if clip is None:
strength_clip=0
if override_lora_name != "":
lora_name = override_lora_name
meta_tags_list = sort_tags_by_frequency(get_metadata(lora_name, "loras"))
@@ -109,7 +111,6 @@ class LoraLoaderAdvanced:
return {
"required": {
"model": ("MODEL",),
"clip": ("CLIP", ),
"lora_name": (LORA_LIST, ),
"strength_model": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}),
"strength_clip": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}),
@@ -118,6 +119,7 @@ class LoraLoaderAdvanced:
"append_loraname_if_empty": ("BOOLEAN", {"default": False}),
},
"optional": {
"clip": ("CLIP", ),
"override_lora_name":("STRING", {"forceInput": True}),
}
}
@@ -127,7 +129,9 @@ class LoraLoaderAdvanced:
FUNCTION = "load_lora"
CATEGORY = "autotrigger"
def load_lora(self, model, clip, lora_name, strength_model, strength_clip, force_fetch, enable_preview, append_loraname_if_empty, override_lora_name=""):
def load_lora(self, model, lora_name, strength_model, strength_clip, force_fetch, enable_preview, append_loraname_if_empty, clip=None, override_lora_name=""):
if clip is None:
strength_clip=0
if override_lora_name != "":
has_preview, prev = get_preview_path(override_lora_name, "loras")
prev = f"loras/{prev}" if has_preview else None
@@ -253,7 +257,6 @@ class LoraTagsOnly:
return (civitai_tags_list, meta_tags_list)
# A dictionary that contains all nodes you want to export with their names
# NOTE: names should be globally unique
NODE_CLASS_MAPPINGS = {
+14
View File
@@ -0,0 +1,14 @@
[project]
name = "comfyui-lora-auto-trigger-words"
description = "The aim of these custom nodes is to get an easy access to the tags used to trigger a lora / lycoris. Extract the tags from civitai or from the safetensors metadatas when available."
version = "1.0.4"
license = "MIT"
[project.urls]
Repository = "https://github.com/idrirap/ComfyUI-Lora-Auto-Trigger-Words"
# Used by Comfy Registry https://comfyregistry.org
[tool.comfy]
PublisherId = "dijkstra"
DisplayName = "ComfyUI-Lora-Auto-Trigger-Words"
Icon = ""
+12 -6
View File
@@ -15,11 +15,14 @@ def get_preview_path(name, type):
file_path_no_ext = os.path.splitext(file_path)[0]
item_image=None
for ext in ["png", "jpg", "jpeg", "preview.png"]:
has_image = os.path.isfile(file_path_no_ext + "." + ext)
if has_image:
item_image = f"{file_name}.{ext}"
for ext in ["png", "jpg", "jpeg", "gif"]:
if item_image is not None:
break
for ext2 in ["", ".preview"]:
has_image = os.path.isfile(file_path_no_ext + ext2 + "." + ext)
if has_image:
item_image = f"{file_name}{ext2}.{ext}"
break
return has_image, item_image
@@ -80,8 +83,11 @@ def save_dict_to_json(data_dict, file_path):
def get_model_version_info(hash_value):
api_url = f"https://civitai.com/api/v1/model-versions/by-hash/{hash_value}"
response = requests.get(api_url)
try:
response = requests.get(api_url)
except Exception as e:
print(f"[Lora-Auto-Trigger] {e}")
return None
if response.status_code == 200:
return response.json()
else: