Buckets:
| from typing_extensions import override | |
| import comfy.sd | |
| import comfy.utils | |
| import folder_paths | |
| from comfy_api.latest import ComfyExtension, io | |
| from comfy_api.latest._io import _DynamicGroup | |
| def _load_lora_file(lora_name: str): | |
| lora_path = folder_paths.get_full_path_or_raise("loras", lora_name) | |
| return comfy.utils.load_torch_file(lora_path, safe_load=True, return_metadata=True) | |
| def _lora_template() -> list[io.Input]: | |
| return [ | |
| io.Combo.Input("lora_name", options=folder_paths.get_filename_list("loras"), | |
| tooltip="The name of the LoRA file to apply."), | |
| io.Float.Input("strength", default=1.0, min=-100.0, max=100.0, step=0.01, | |
| tooltip="How strongly to apply this LoRA. 0 = off, negative inverts the effect."), | |
| io.Boolean.Input("enabled", default=True, | |
| tooltip="Turn off to skip this LoRA without changing its file or strength."), | |
| ] | |
| class LoadLoraModel(io.ComfyNode): | |
| def define_schema(cls): | |
| return io.Schema( | |
| node_id="LoadLoraModel", | |
| display_name="Load LoRA (Model)", | |
| search_aliases=["lora", "load lora", "apply lora", "lora model", "lora stack"], | |
| category="model/loaders", | |
| description="Apply a stack of LoRAs to a diffusion model. Add one row per LoRA; " | |
| "each row picks a LoRA file and its strength.", | |
| inputs=[ | |
| io.Model.Input("model", tooltip="The diffusion model the LoRAs will be applied to."), | |
| _DynamicGroup.Input( | |
| "loras", | |
| template=_lora_template(), | |
| min=1, | |
| max=20, | |
| tooltip="Each row applies one LoRA to the model.", | |
| group_name="LoRA", | |
| ), | |
| ], | |
| outputs=[io.Model.Output(tooltip="The modified diffusion model.")], | |
| ) | |
| def execute(cls, model, loras: list[dict]) -> io.NodeOutput: | |
| for row in loras: | |
| lora_name = row.get("lora_name") | |
| strength = row["strength"] | |
| if not lora_name or not row["enabled"] or strength == 0: | |
| continue | |
| lora, metadata = _load_lora_file(lora_name) | |
| model, _ = comfy.sd.load_lora_for_models(model, None, lora, strength, 0, lora_metadata=metadata) | |
| return io.NodeOutput(model) | |
| class LoadLoraTextEncoder(io.ComfyNode): | |
| def define_schema(cls): | |
| return io.Schema( | |
| node_id="LoadLoraTextEncoder", | |
| display_name="Load LoRA (Text Encoder)", | |
| search_aliases=["lora", "load lora", "apply lora", "clip lora", "lora stack"], | |
| category="model/loaders", | |
| description="Apply a stack of LoRAs to a CLIP text encoder. Add one row per LoRA; " | |
| "each row picks a LoRA file and its strength.", | |
| inputs=[ | |
| io.Clip.Input("clip", tooltip="The CLIP text encoder the LoRAs will be applied to."), | |
| _DynamicGroup.Input( | |
| "loras", | |
| template=_lora_template(), | |
| min=1, | |
| max=20, | |
| tooltip="Each row applies one LoRA to the text encoder.", | |
| group_name="LoRA", | |
| ), | |
| ], | |
| outputs=[io.Clip.Output(tooltip="The modified CLIP text encoder.")], | |
| ) | |
| def execute(cls, clip, loras: list[dict]) -> io.NodeOutput: | |
| for row in loras: | |
| lora_name = row.get("lora_name") | |
| strength = row["strength"] | |
| if not lora_name or not row["enabled"] or strength == 0: | |
| continue | |
| lora, metadata = _load_lora_file(lora_name) | |
| _, clip = comfy.sd.load_lora_for_models(None, clip, lora, 0, strength, lora_metadata=metadata) | |
| return io.NodeOutput(clip) | |
| class LoraStackExtension(ComfyExtension): | |
| async def get_node_list(self) -> list[type[io.ComfyNode]]: | |
| return [ | |
| LoadLoraModel, | |
| LoadLoraTextEncoder, | |
| ] | |
| async def comfy_entrypoint() -> LoraStackExtension: | |
| return LoraStackExtension() | |
Xet Storage Details
- Size:
- 4.27 kB
- Xet hash:
- 27c119f405f1442938ef24e98f8974756dd7369cbc1c8f6f4e2c59ebf7bf87b5
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.