test(nodes): require static tooltips
This commit is contained in:
+84
-64
@@ -936,34 +936,52 @@ class LoRAMultiMerge(io.ComfyNode):
|
||||
tooltip="Number of LoRAs to merge"),
|
||||
# LoRA 1
|
||||
io.Combo.Input("lora_1", options=folder_paths.get_filename_list("loras"), tooltip="First LoRA"),
|
||||
io.Float.Input("weight_1", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Float.Input("weight_1", default=1.0, min=-10.0, max=10.0, step=0.01,
|
||||
tooltip="Scale LoRA 1's represented delta before merging; negative values subtract it."),
|
||||
# LoRA 2
|
||||
io.Combo.Input("lora_2", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_2", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_2", options=["None"] + folder_paths.get_filename_list("loras"), default="None",
|
||||
tooltip="Optional LoRA 2; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_2", default=1.0, min=-10.0, max=10.0, step=0.01,
|
||||
tooltip="Scale LoRA 2's represented delta before merging."),
|
||||
# LoRA 3
|
||||
io.Combo.Input("lora_3", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_3", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_3", options=["None"] + folder_paths.get_filename_list("loras"), default="None",
|
||||
tooltip="Optional LoRA 3; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_3", default=1.0, min=-10.0, max=10.0, step=0.01,
|
||||
tooltip="Scale LoRA 3's represented delta before merging."),
|
||||
# LoRA 4
|
||||
io.Combo.Input("lora_4", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_4", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_4", options=["None"] + folder_paths.get_filename_list("loras"), default="None",
|
||||
tooltip="Optional LoRA 4; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_4", default=1.0, min=-10.0, max=10.0, step=0.01,
|
||||
tooltip="Scale LoRA 4's represented delta before merging."),
|
||||
# LoRA 5
|
||||
io.Combo.Input("lora_5", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_5", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_5", options=["None"] + folder_paths.get_filename_list("loras"), default="None",
|
||||
tooltip="Optional LoRA 5; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_5", default=1.0, min=-10.0, max=10.0, step=0.01,
|
||||
tooltip="Scale LoRA 5's represented delta before merging."),
|
||||
# LoRA 6
|
||||
io.Combo.Input("lora_6", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_6", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_6", options=["None"] + folder_paths.get_filename_list("loras"), default="None",
|
||||
tooltip="Optional LoRA 6; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_6", default=1.0, min=-10.0, max=10.0, step=0.01,
|
||||
tooltip="Scale LoRA 6's represented delta before merging."),
|
||||
# LoRA 7
|
||||
io.Combo.Input("lora_7", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_7", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_7", options=["None"] + folder_paths.get_filename_list("loras"), default="None",
|
||||
tooltip="Optional LoRA 7; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_7", default=1.0, min=-10.0, max=10.0, step=0.01,
|
||||
tooltip="Scale LoRA 7's represented delta before merging."),
|
||||
# LoRA 8
|
||||
io.Combo.Input("lora_8", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_8", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_8", options=["None"] + folder_paths.get_filename_list("loras"), default="None",
|
||||
tooltip="Optional LoRA 8; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_8", default=1.0, min=-10.0, max=10.0, step=0.01,
|
||||
tooltip="Scale LoRA 8's represented delta before merging."),
|
||||
|
||||
io.Combo.Input("merge_mode", options=["concatenate", "weighted_sum"], default="concatenate",
|
||||
tooltip="concatenate: safe, increases rank. weighted_sum: fixed rank (to max input rank), mathematically lossy but standard in Kohya."),
|
||||
io.String.Input("output_filename", default="merged_lora"),
|
||||
io.Combo.Input("save_dtype", options=["fp16", "bf16", "fp32"], default="fp16"),
|
||||
io.Combo.Input("device", options=["cuda", "cpu"], default="cuda"),
|
||||
io.String.Input("output_filename", default="merged_lora",
|
||||
tooltip="Output filename without extension, written under ComfyUI's LoRA directory."),
|
||||
io.Combo.Input("save_dtype", options=["fp16", "bf16", "fp32"], default="fp16",
|
||||
tooltip="Requested dtype for generated factors; each logical layer's source factor precision is considered independently of scalar alpha."),
|
||||
io.Combo.Input("device", options=["cuda", "cpu"], default="cuda",
|
||||
tooltip="Device for per-target arithmetic; a CUDA OOM retries only the affected target on CPU."),
|
||||
io.Boolean.Input("include_1d_diffs", default=False,
|
||||
tooltip="Include and merge 1D direct-diff tensors as FP32."),
|
||||
],
|
||||
@@ -1025,32 +1043,34 @@ class LoRAMultiMergeDARE(io.ComfyNode):
|
||||
inputs=[
|
||||
io.Combo.Input("base_model", options=["None"] + folder_paths.get_filename_list("diffusion_models"), default="None",
|
||||
tooltip="Optional reference model to resolve key naming issues across formats. If None, input keys are preserved verbatim."),
|
||||
io.Combo.Input("lora_count", options=[str(i) for i in range(1, 9)], default="2"),
|
||||
io.Combo.Input("lora_count", options=[str(i) for i in range(1, 9)], default="2",
|
||||
tooltip="Use the first N LoRA selectors; selectors beyond this count are ignored."),
|
||||
# LoRA 1
|
||||
io.Combo.Input("lora_1", options=folder_paths.get_filename_list("loras"), tooltip="First LoRA"),
|
||||
io.Float.Input("weight_1", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Float.Input("weight_1", default=1.0, min=-10.0, max=10.0, step=0.01,
|
||||
tooltip="Scale LoRA 1's represented delta before DARE-Ties merging; negative values subtract it."),
|
||||
# ...
|
||||
io.Combo.Input("lora_2", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_2", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_3", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_3", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_4", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_4", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_5", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_5", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_6", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_6", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_7", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_7", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_8", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_8", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_2", options=["None"] + folder_paths.get_filename_list("loras"), default="None", tooltip="Optional LoRA 2; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_2", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 2's represented delta before DARE-Ties merging."),
|
||||
io.Combo.Input("lora_3", options=["None"] + folder_paths.get_filename_list("loras"), default="None", tooltip="Optional LoRA 3; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_3", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 3's represented delta before DARE-Ties merging."),
|
||||
io.Combo.Input("lora_4", options=["None"] + folder_paths.get_filename_list("loras"), default="None", tooltip="Optional LoRA 4; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_4", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 4's represented delta before DARE-Ties merging."),
|
||||
io.Combo.Input("lora_5", options=["None"] + folder_paths.get_filename_list("loras"), default="None", tooltip="Optional LoRA 5; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_5", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 5's represented delta before DARE-Ties merging."),
|
||||
io.Combo.Input("lora_6", options=["None"] + folder_paths.get_filename_list("loras"), default="None", tooltip="Optional LoRA 6; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_6", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 6's represented delta before DARE-Ties merging."),
|
||||
io.Combo.Input("lora_7", options=["None"] + folder_paths.get_filename_list("loras"), default="None", tooltip="Optional LoRA 7; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_7", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 7's represented delta before DARE-Ties merging."),
|
||||
io.Combo.Input("lora_8", options=["None"] + folder_paths.get_filename_list("loras"), default="None", tooltip="Optional LoRA 8; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_8", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 8's represented delta before DARE-Ties merging."),
|
||||
|
||||
io.Float.Input("drop_rate", default=0.1, min=0.0, max=1.0, step=0.01, tooltip="DARE drop rate"),
|
||||
io.Float.Input("trim_quantile", default=0.2, min=0.0, max=1.0, step=0.01, tooltip="TIES trim quantile (drops smallest values)"),
|
||||
io.Int.Input("seed", default=42, min=0, max=0xffffffffffffffff),
|
||||
io.String.Input("output_filename", default="merged_lora_dare"),
|
||||
io.Combo.Input("save_dtype", options=["fp16", "bf16", "fp32"], default="fp16"),
|
||||
io.Combo.Input("device", options=["cuda", "cpu"], default="cuda"),
|
||||
io.Float.Input("drop_rate", default=0.1, min=0.0, max=1.0, step=0.01, tooltip="Fraction of factor values randomly dropped before rescaling; higher values increase sparsification."),
|
||||
io.Float.Input("trim_quantile", default=0.2, min=0.0, max=1.0, step=0.01, tooltip="Remove the lowest-magnitude fraction before resolving sign conflicts with TIES."),
|
||||
io.Int.Input("seed", default=42, min=0, max=0xffffffffffffffff, tooltip="Random seed for reproducible DARE masks."),
|
||||
io.String.Input("output_filename", default="merged_lora_dare", tooltip="Output filename without extension, written under ComfyUI's LoRA directory."),
|
||||
io.Combo.Input("save_dtype", options=["fp16", "bf16", "fp32"], default="fp16", tooltip="Requested dtype for generated factors; scalar alpha tensors do not determine factor precision."),
|
||||
io.Combo.Input("device", options=["cuda", "cpu"], default="cuda", tooltip="Device for per-target arithmetic; a CUDA OOM retries only the affected target on CPU."),
|
||||
io.Boolean.Input("include_1d_diffs", default=False,
|
||||
tooltip="Include and merge 1D direct-diff tensors as FP32."),
|
||||
],
|
||||
@@ -1143,34 +1163,34 @@ class LoRAMultiMergeDAREEnhanced(io.ComfyNode):
|
||||
inputs=[
|
||||
io.Combo.Input("base_model", options=["None"] + folder_paths.get_filename_list("diffusion_models"), default="None",
|
||||
tooltip="Optional reference model to resolve key naming issues across formats. If None, input keys are preserved verbatim."),
|
||||
io.Combo.Input("lora_count", options=[str(i) for i in range(1, 9)], default="2"),
|
||||
io.Combo.Input("lora_count", options=[str(i) for i in range(1, 9)], default="2", tooltip="Use the first N LoRA selectors; selectors beyond this count are ignored."),
|
||||
# LoRA 1
|
||||
io.Combo.Input("lora_1", options=folder_paths.get_filename_list("loras"), tooltip="First LoRA"),
|
||||
io.Float.Input("weight_1", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Float.Input("weight_1", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 1's represented delta before enhanced DARE-Ties merging; negative values subtract it."),
|
||||
# ...
|
||||
io.Combo.Input("lora_2", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_2", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_3", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_3", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_4", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_4", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_5", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_5", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_6", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_6", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_7", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_7", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_8", options=["None"] + folder_paths.get_filename_list("loras"), default="None"),
|
||||
io.Float.Input("weight_8", default=1.0, min=-10.0, max=10.0, step=0.01),
|
||||
io.Combo.Input("lora_2", options=["None"] + folder_paths.get_filename_list("loras"), default="None", tooltip="Optional LoRA 2; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_2", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 2's represented delta before enhanced DARE-Ties merging."),
|
||||
io.Combo.Input("lora_3", options=["None"] + folder_paths.get_filename_list("loras"), default="None", tooltip="Optional LoRA 3; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_3", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 3's represented delta before enhanced DARE-Ties merging."),
|
||||
io.Combo.Input("lora_4", options=["None"] + folder_paths.get_filename_list("loras"), default="None", tooltip="Optional LoRA 4; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_4", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 4's represented delta before enhanced DARE-Ties merging."),
|
||||
io.Combo.Input("lora_5", options=["None"] + folder_paths.get_filename_list("loras"), default="None", tooltip="Optional LoRA 5; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_5", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 5's represented delta before enhanced DARE-Ties merging."),
|
||||
io.Combo.Input("lora_6", options=["None"] + folder_paths.get_filename_list("loras"), default="None", tooltip="Optional LoRA 6; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_6", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 6's represented delta before enhanced DARE-Ties merging."),
|
||||
io.Combo.Input("lora_7", options=["None"] + folder_paths.get_filename_list("loras"), default="None", tooltip="Optional LoRA 7; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_7", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 7's represented delta before enhanced DARE-Ties merging."),
|
||||
io.Combo.Input("lora_8", options=["None"] + folder_paths.get_filename_list("loras"), default="None", tooltip="Optional LoRA 8; used only when included by LoRA Count."),
|
||||
io.Float.Input("weight_8", default=1.0, min=-10.0, max=10.0, step=0.01, tooltip="Scale LoRA 8's represented delta before enhanced DARE-Ties merging."),
|
||||
|
||||
io.Float.Input("mask_power", default=2.0, min=0.001, max=10.0, step=0.01, tooltip="Mask power (Curve. 2.0 = quadratic)"),
|
||||
io.Float.Input("min_keep_prob", default=0.01, min=0.0, max=1.0, step=0.01, tooltip="Minimum keep probability (Floor to prevent explosion)"),
|
||||
io.Float.Input("mask_smooth", default=0.0, min=0.0, max=1.0, step=0.01, tooltip="Mask smoothness factor (0.0 = pure dropout, 1.0 = soft scale)"),
|
||||
io.Float.Input("trim_quantile", default=0.2, min=0.0, max=1.0, step=0.01, tooltip="TIES trim quantile (drops smallest values)"),
|
||||
io.Int.Input("seed", default=42, min=0, max=0xffffffffffffffff),
|
||||
io.String.Input("output_filename", default="merged_lora_dare_enhanced"),
|
||||
io.Combo.Input("save_dtype", options=["fp16", "bf16", "fp32"], default="fp16"),
|
||||
io.Combo.Input("device", options=["cuda", "cpu"], default="cuda"),
|
||||
io.Float.Input("mask_power", default=2.0, min=0.001, max=10.0, step=0.01, tooltip="Exponent shaping magnitude-based keep probabilities; larger values favor high-magnitude values more strongly."),
|
||||
io.Float.Input("min_keep_prob", default=0.01, min=0.0, max=1.0, step=0.01, tooltip="Lower bound for each value's keep probability, limiting inverse-probability rescaling."),
|
||||
io.Float.Input("mask_smooth", default=0.0, min=0.0, max=1.0, step=0.01, tooltip="Blend between stochastic masking at 0 and smooth probability scaling at 1."),
|
||||
io.Float.Input("trim_quantile", default=0.2, min=0.0, max=1.0, step=0.01, tooltip="Remove the lowest-magnitude fraction before resolving sign conflicts with TIES."),
|
||||
io.Int.Input("seed", default=42, min=0, max=0xffffffffffffffff, tooltip="Random seed for reproducible enhanced DARE masks."),
|
||||
io.String.Input("output_filename", default="merged_lora_dare_enhanced", tooltip="Output filename without extension, written under ComfyUI's LoRA directory."),
|
||||
io.Combo.Input("save_dtype", options=["fp16", "bf16", "fp32"], default="fp16", tooltip="Requested dtype for generated factors; scalar alpha tensors do not determine factor precision."),
|
||||
io.Combo.Input("device", options=["cuda", "cpu"], default="cuda", tooltip="Device for per-target arithmetic; a CUDA OOM retries only the affected target on CPU."),
|
||||
io.Boolean.Input("include_1d_diffs", default=False,
|
||||
tooltip="Include and merge 1D direct-diff tensors as FP32."),
|
||||
],
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import ast
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
NODE_DIR = Path(__file__).resolve().parents[1] / "nodes"
|
||||
|
||||
|
||||
def test_every_schema_input_has_a_direct_static_tooltip():
|
||||
missing = []
|
||||
non_static = []
|
||||
|
||||
for path in sorted(NODE_DIR.glob("*.py")):
|
||||
tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path))
|
||||
for call in ast.walk(tree):
|
||||
if not (
|
||||
isinstance(call, ast.Call)
|
||||
and isinstance(call.func, ast.Attribute)
|
||||
and call.func.attr == "Input"
|
||||
):
|
||||
continue
|
||||
|
||||
name = (
|
||||
call.args[0].value
|
||||
if call.args and isinstance(call.args[0], ast.Constant)
|
||||
else "<dynamic input name>"
|
||||
)
|
||||
tooltip = next(
|
||||
(keyword.value for keyword in call.keywords if keyword.arg == "tooltip"),
|
||||
None,
|
||||
)
|
||||
location = f"{path.name}:{call.lineno}:{name}"
|
||||
if tooltip is None:
|
||||
missing.append(location)
|
||||
elif not (
|
||||
isinstance(tooltip, ast.Constant)
|
||||
and isinstance(tooltip.value, str)
|
||||
and tooltip.value.strip()
|
||||
):
|
||||
non_static.append(location)
|
||||
|
||||
assert not missing, "Inputs without tooltips:\n" + "\n".join(missing)
|
||||
assert not non_static, "Tooltips must be direct non-empty string literals:\n" + "\n".join(non_static)
|
||||
Reference in New Issue
Block a user