nikdevs commited on
Commit
b66c0ec
·
verified ·
1 Parent(s): a2620fd

minimax worker: lora_from_url.py

Browse files
Files changed (1) hide show
  1. worker/lora_from_url.py +65 -0
worker/lora_from_url.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ComfyUI custom node: load a LoRA fetched from a URL at request time.
2
+
3
+ Lets serverless workflows reference LoRAs by URL (HF, civitai, anywhere)
4
+ instead of requiring the file to be pre-baked into the image. Downloads are
5
+ cached on the worker's disk keyed by URL hash. Supports HF_TOKEN and
6
+ CIVITAI_TOKEN env vars for authenticated downloads.
7
+ """
8
+
9
+ import hashlib
10
+ import os
11
+ import urllib.request
12
+
13
+ import comfy.sd
14
+ import comfy.utils
15
+
16
+ CACHE_DIR = "/lora-cache"
17
+ os.makedirs(CACHE_DIR, exist_ok=True)
18
+
19
+
20
+ def _fetch(url: str) -> str:
21
+ path = os.path.join(CACHE_DIR, hashlib.sha1(url.encode()).hexdigest() + ".safetensors")
22
+ if os.path.exists(path):
23
+ return path
24
+ headers = {}
25
+ hf_token = os.environ.get("HF_TOKEN")
26
+ if hf_token and "huggingface.co" in url:
27
+ headers["Authorization"] = f"Bearer {hf_token}"
28
+ civitai_token = os.environ.get("CIVITAI_TOKEN")
29
+ if civitai_token and "civitai" in url:
30
+ url += ("&" if "?" in url else "?") + "token=" + civitai_token
31
+ req = urllib.request.Request(url, headers=headers)
32
+ tmp = path + ".part"
33
+ with urllib.request.urlopen(req, timeout=600) as r, open(tmp, "wb") as f:
34
+ while chunk := r.read(1 << 20):
35
+ f.write(chunk)
36
+ os.rename(tmp, path)
37
+ return path
38
+
39
+
40
+ class LoraFromURLModelOnly:
41
+ @classmethod
42
+ def INPUT_TYPES(cls):
43
+ return {
44
+ "required": {
45
+ "model": ("MODEL",),
46
+ "url": ("STRING", {"default": ""}),
47
+ "strength": ("FLOAT", {"default": 1.0, "min": -10.0, "max": 10.0, "step": 0.01}),
48
+ }
49
+ }
50
+
51
+ RETURN_TYPES = ("MODEL",)
52
+ FUNCTION = "load"
53
+ CATEGORY = "loaders"
54
+
55
+ def load(self, model, url, strength):
56
+ url = (url or "").strip()
57
+ if not url or strength == 0:
58
+ return (model,)
59
+ lora_sd = comfy.utils.load_torch_file(_fetch(url), safe_load=True)
60
+ model_lora, _ = comfy.sd.load_lora_for_models(model, None, lora_sd, strength, 0)
61
+ return (model_lora,)
62
+
63
+
64
+ NODE_CLASS_MAPPINGS = {"LoraFromURLModelOnly": LoraFromURLModelOnly}
65
+ NODE_DISPLAY_NAME_MAPPINGS = {"LoraFromURLModelOnly": "Load LoRA from URL (model only)"}