| import os |
| import comfy.sd |
| import comfy.utils |
| import folder_paths |
| import json |
| import urllib.request |
| import urllib.parse |
|
|
| _TRIPLE_LORA_CACHE = {} |
| CACHE_FILE = os.path.join(os.path.dirname(__file__), "dolphin_lora_trigger_cache.json") |
|
|
| def get_trigger_words(lora_name): |
| if lora_name == "None": return [] |
| cache = {} |
| if os.path.exists(CACHE_FILE): |
| try: |
| with open(CACHE_FILE, "r") as f: cache = json.load(f) |
| except: pass |
| if lora_name in cache: return cache[lora_name] |
|
|
| try: |
| |
| |
| query = urllib.parse.quote(lora_name.replace(".safetensors", "")) |
| url = f"https://civitaired.com/api/v1/model-versions/by-file?query={query}" |
| |
| req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'}) |
| with urllib.request.urlopen(req, timeout=5) as res: |
| data = json.load(res) |
| |
| triggers = data.get("trainedWords", []) |
| cache[lora_name] = triggers |
| with open(CACHE_FILE, "w") as f: json.dump(cache, f) |
| return triggers |
| except Exception as e: |
| print(f"โ ๏ธ [Dolphin] civitaired.com ํธ๋ฆฌ๊ฑฐ ์๋ ์กฐํ ์คํจ: {e}") |
| return [] |
|
|
| class DolphinTripleLoraMatrix: |
| @classmethod |
| def INPUT_TYPES(s): |
| loras = ["None"] + folder_paths.get_filename_list("loras") |
| inputs = { |
| "model_base": ("MODEL",), "clip_base": ("CLIP",), |
| "model_high": ("MODEL",), "clip_high": ("CLIP",), |
| "model_low": ("MODEL",), "clip_low": ("CLIP",), |
| } |
| for i in range(1, 7): |
| inputs[f"lora_{i}"] = (loras, {"default": "None"}) |
| inputs[f"weights_{i}"] = ("STRING", {"default": "0.0, 0.0, 0.0"}) |
| return {"required": inputs} |
|
|
| RETURN_TYPES = ("MODEL", "CLIP", "MODEL", "CLIP", "MODEL", "CLIP", "STRING") |
| RETURN_NAMES = ("M_BASE", "C_BASE", "M_HIGH", "C_HIGH", "M_LOW", "C_LOW", "trigger_words") |
| FUNCTION = "apply_matrix" |
| CATEGORY = "Dolphin" |
|
|
| def apply_matrix(self, model_base, clip_base, model_high, clip_high, model_low, clip_low, **kwargs): |
| m_b, c_b = model_base, clip_base |
| m_h, c_h = model_high, clip_high |
| m_l, c_l = model_low, clip_low |
| all_triggers = [] |
|
|
| for i in range(1, 7): |
| lora_name = kwargs.get(f"lora_{i}") |
| w_str = kwargs.get(f"weights_{i}") |
| |
| if lora_name == "None": continue |
| |
| |
| all_triggers.extend(get_trigger_words(lora_name)) |
| |
| try: |
| parts = [float(x.strip()) for x in w_str.split(',')] |
| wb, wh, wl = parts[0], parts[1], parts[2] |
| except: continue |
|
|
| if lora_name not in _TRIPLE_LORA_CACHE: |
| path = folder_paths.get_full_path("loras", lora_name) |
| _TRIPLE_LORA_CACHE[lora_name] = comfy.utils.load_torch_file(path) |
| data = _TRIPLE_LORA_CACHE[lora_name] |
|
|
| if wb != 0: m_b, c_b = comfy.sd.load_lora_for_models(m_b, c_b, data, wb, wb) |
| if wh != 0: m_h, c_h = comfy.sd.load_lora_for_models(m_h, c_h, data, wh, wh) |
| if wl != 0: m_l, c_l = comfy.sd.load_lora_for_models(m_l, c_l, data, wl, wl) |
| |
| return (m_b, c_b, m_h, c_h, m_l, c_l, ", ".join(list(set(all_triggers)))) |