Add "Load Multi LoRA" node

This commit is contained in:
pkpk
2024-02-11 05:45:05 +09:00
parent 7408046dcb
commit d428d89c9d
4 changed files with 188 additions and 7 deletions
+103
View File
@@ -0,0 +1,103 @@
import comfy.sd
import comfy.utils
import comfy.clip_vision
import comfy.model_detection
import comfy.model_management
import comfy.model_patcher
import comfy.checkpoint_pickle
import folder_paths
from .utils import download_file, load_torch_bin
class LoadTempMultiLoRA:
CKPT_TYPE = ["auto", "safetensors", "other"]
def __init__(self):
self.loaded_lora = {}
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"model": ("MODEL",),
"clip": ("CLIP", ),
"ckpt_url": ("STRING", {"default": "", "multiline": True, "dynamicPrompts": False}),
"ckpt_type": (LoadTempMultiLoRA.CKPT_TYPE, {"default": "auto"}),
"download_split": ("INT", {"default": 4, "min": 1, "max": 8, "step": 1}),
"strength_model": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}),
"strength_clip": ("FLOAT", {"default": 1.0, "min": -20.0, "max": 20.0, "step": 0.01}),
},
}
RETURN_TYPES = ("MODEL", "CLIP")
FUNCTION = "load_multi_lora"
CATEGORY = "temporary_loaders"
def load_multi_lora(self, model, clip, ckpt_url, ckpt_type, download_split, strength_model, strength_clip):
model_lora, clip_lora = model, clip
lora_dic = {}
for line in ckpt_url.splitlines():
if line.startswith("#"):
continue
else:
info = line.split(":")
if len(info) < 2:
continue
if line.startswith("file:"):
file_name = line[5:]
model_lora, clip_lora = self.load_lora_file(model_lora, clip_lora, file_name, strength_model, strength_clip, lora_dic)
continue
if line.startswith("http:") or line.startswith("https:"):
url = "{}:{}".format(info[0].strip(), info[1].strip())
model_lora, clip_lora = self.load_lora_url(model_lora, clip_lora, url, ckpt_type, download_split, strength_model, strength_clip, lora_dic)
continue
try:
isFile = info[-2].strip().startswith("file")
url = info[-1].strip() if isFile else "{}:{}".format(info[-2].strip(), info[-1].strip())
strength_m = float(info[0]) if len(info[0]) > 0 else strength_model
strength_c = float(info[1]) if len(info[1]) > 0 else strength_clip
m_type = info[2].strip() if len(info) == 5 and info[2].strip() in LoadTempMultiLoRA.CKPT_TYPE else ckpt_type
except:
raise Exception("Not according to format. The only accepted formats are\r\n{url}\r\n{strength_model}:{strength_clip}:{url}\r\n{strength_model}:{strength_clip}:{ckpt_type}:{url}")
if isFile:
model_lora, clip_lora = self.load_lora_file(model_lora, clip_lora, url, strength_m, strength_c, lora_dic)
else:
model_lora, clip_lora = self.load_lora_url(model_lora, clip_lora, url, m_type, download_split, strength_m, strength_c, lora_dic)
tmp = self.loaded_lora
self.loaded_lora = lora_dic
tmp.clear()
del tmp
return (model_lora, clip_lora)
def load_lora_url(self, model, clip, ckpt_url, ckpt_type, download_split, strength_model, strength_clip, lora_dic):
if strength_model == 0 and strength_clip == 0:
return (model, clip)
lora = self.loaded_lora.get(ckpt_url)
if lora is None:
bin, file_name = download_file(ckpt_url, download_split)
if bin is None:
raise file_name if file_name is not None else Exception("Download failed.")
is_safetensors = file_name.endswith(".safetensors") if ckpt_type =="auto" else ckpt_type == "safetensors"
lora = load_torch_bin(bin, is_safetensors, safe_load=True)
lora_dic[ckpt_url] = lora
model_lora, clip_lora = comfy.sd.load_lora_for_models(model, clip, lora, strength_model, strength_clip)
return (model_lora, clip_lora)
def load_lora_file(self, model, clip, lora_name, strength_model, strength_clip, lora_dic):
if strength_model == 0 and strength_clip == 0:
return (model, clip)
lora_path = folder_paths.get_full_path("loras", lora_name)
lora = self.loaded_lora.get(lora_path)
if lora is None:
lora = comfy.utils.load_torch_file(lora_path, safe_load=True)
lora_dic[lora_path] = lora
model_lora, clip_lora = comfy.sd.load_lora_for_models(model, clip, lora, strength_model, strength_clip)
return (model_lora, clip_lora)
+46
View File
@@ -0,0 +1,46 @@
# ComfyUI-TemporaryLoader
入力されたURLからモデルをダウンロードして読み込むComfyUIのカスタムノードです。
モデルは一時的にメモリにダウンロードされ、ストレージには保存されません。
## Installation
1. ComfyUIのcustom_nodesディレクトリで `git clone https://github.com/pkpkTech/ComfyUI-TemporaryLoader` を実行
1. ComfyUI-TemporaryLoaderディレクトリに移動して `pip install -r requirements.txt` を実行
## Nodes
"temporary_loader" カテゴリに、"Load Checkpoint (Temporary)" と "Load LoRA (Temporary)" ノードが追加されます。
標準のLoadノードに以下の項目が追加されています。
- ckpt_url: 使用するモデルのURL。
- ckpt_type: モデルの種類。`auto`でダウンロードしたファイルの拡張子で自動的に判断されますが、ファイル名が取得できない場合もあるので、その時に`safetensors`か`ohter`かを手動で選択してください。
- download_split: 並列ダウンロードの分割数。
これらに加えて、"Load Multi LoRA (Temporary)"ノードも追加されます。<br>
これは、複数のLoRAを読み込むためのノードです。<br>
URL、または標準のLoRA Loaderと同じようにファイル名を指定して読み込みます。<br>
下記のフォーマットに従って記述してください
`{LoRA URL}` or `file:{LoRA file name}` - 例) `https://example.com/anylora.safetensors` or `file:anylora.safetensors`
`{strength_model}:{strength_clip}:{LoRA URL} or file:{LoRA file name}` - 例) `0.4:1.0:https://example.com/anylora.safetensors`
`{strength_model}:{strength_clip}:{ckpt_type}:{LoRA URL} or file:{LoRA file name}` - 例) `0.4:1.0:other:https://example.com/anylora.unknownext`
strength_model、strength_clip、ckpt_typeをテキストで指定していないLoRAには、ノードの設定値が反映されます。<br>
一部のみ指定することもできます - 例) `0.1::https://example.com/anylora.safetensors` (strength_modelが0.1になり、strength_clipとckpt_typeはノードの設定に従う)
何のLoRAか忘れないようにコメントを書くこともできます。<br>
コメントは行頭を`#`にしてください。
例)
```
#あのLoRA
https://example.com/anylora.safetensors
#すごそうなLoRA
0.3::https://example.com/superlora.safetensors
#いつものLoRA
0.5:0.8:file:favorite_lora_v6.safetensors
```
+33 -4
View File
@@ -1,16 +1,45 @@
# ComfyUI-TemporaryLoader
This is a custom node of ComfyUI that downloads and loads models from the input URL. The model is temporarily downloaded into memory and not saved to storage.
This could be useful when trying out models or when using various models on machines with limited storage. Since the model is downloaded into memory, expect higher memory usage than usual.
This could be useful when trying out models or when using various models on machines with limited storage.
## Installation:
1. Use `git clone https://github.com/pkpkTech/ComfyUI-TemporaryLoader` in your ComfyUI custom nodes directory
## Installation
1. Use `git clone https://github.com/pkpkTech/ComfyUI-TemporaryLoader` in your ComfyUI custom_nodes directory
1. Use `pip install -r requirements.txt` in ComfyUI-TemporaryLoader directory
## Usage
## Nodes
The "Load Checkpoint (Temporary)" and "Load LoRA (Temporary)" nodes will be added to the temporary_loader category.
In addition to the standard Load node, the following items are added
- ckpt_url: URL of the model
- ckpt_type: With `auto`, it looks at the file extension of the downloaded file.
- download_split: Specify the number of splits for parallel downloading.
In addition to these, a "Load Multi LoRA (Temporary)" node is also added.<br>
This is a node for loading multiple LoRAs.<br>
It can be loaded by URL or by specifying a filename in the same way as the standard LoRA Loader.<br>
Follow the format below
`{LoRA URL}` or `file:{LoRA file name}` - e.g.) `https://example.com/anylora.safetensors` or `file:anylora.safetensors`
`{strength_model}:{strength_clip}:{LoRA URL} or file:{LoRA file name}` - e.g.) `0.4:1.0:https://example.com/anylora.safetensors`
`{strength_model}:{strength_clip}:{ckpt_type}:{LoRA URL} or file:{LoRA file name}` - e.g.) `0.4:1.0:other:https://example.com/anylora.pt`
LoRAs for which strength_model, strength_clip and ckpt_type are not specified in text will reflect the node's set values.
You can also specify only a part - e.g.) `0.1::https://example.com/anylora.safetensors` (strength_model is 0.1, strength_clip and ckpt_type follow node settings).
To avoid confusion as to what LoRA it is, you can also write a comment.
Comments should start the line with `#`.
e.g.)
```
#thatLoRA
https://example.com/anylora.safetensors
#The LoRA of the super landscape
0.3::https://example.com/superlora.safetensors
#The usual LoRA
0.5:0.8:file:favorite_lora_v6.safetensors
```
+6 -3
View File
@@ -1,13 +1,16 @@
from .LoadTempCheckpoint import LoadTempCheckpoint
from .LoadTempLoRA import LoadTempLoRA
from .LoadTempMultiLoRA import LoadTempMultiLoRA
NODE_CLASS_MAPPINGS = {
"LoadTempCheckpoint": LoadTempCheckpoint,
"LoadTempLoRA": LoadTempLoRA
"LoadTempLoRA": LoadTempLoRA,
"LoadTempMultiLoRA": LoadTempMultiLoRA,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"LoadTempCheckpoint": "Load Checkpoint (Temporary)",
"LoadTempLoRA": "Load LoRA (Temporary)"
"LoadTempCheckpoint": "Checkpoint Loader (Temporary)",
"LoadTempLoRA": "Load LoRA (Temporary)",
"LoadTempMultiLoRA": "Load Multi LoRA (Temporary)",
}
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']