Files
laksjdjf-cgem156-ComfyUI/scripts/cd_tuner/node.py
T
2026-07-04 08:23:56 +09:00

103 lines
3.8 KiB
Python

import torch
from comfy_api.v0_0_2 import io
from ... import ROOT_NAME
CATEGORY_NAME = ROOT_NAME + "cd-tuner"
class CDTuner(io.ComfyNode):
@classmethod
def define_schema(cls) -> io.Schema:
return io.Schema(
node_id="CD_Tuner|cgem156",
display_name="CD Tuner 🍌",
category=CATEGORY_NAME,
inputs=[
io.Model.Input("model"),
io.Float.Input("detail_1", default=0, min=-10, max=10, step=0.1),
io.Float.Input("detail_2", default=0, min=-10, max=10, step=0.1),
io.Float.Input("contrast_1", default=0, min=-20, max=20, step=0.1),
io.Int.Input("start", default=0, min=0, max=1000, step=1, display_mode=io.NumberDisplay.number),
io.Int.Input("end", default=1000, min=0, max=1000, step=1, display_mode=io.NumberDisplay.number),
],
outputs=[
io.Model.Output(),
],
)
@classmethod
def execute(cls, model, detail_1, detail_2, contrast_1, start, end) -> io.NodeOutput:
'''
detail_1: 最初のConv層のweightを減らしbiasを増やすことで、detailを増やす・・?
detail_2: 最後のConv層前のGroupNormの以下略
contrast_1: 最後のConv層のbiasの0チャンネル目を増やすことでコントラストを増やす・・・?
'''
new_model = model.clone()
ratios = fineman([detail_1, detail_2, contrast_1])
storedweights = {}
# unet計算前後のパッチ
def apply_cdtuner(model_function, kwargs):
t = new_model.model.model_sampling.timestep(kwargs["timestep"])
if t[0] < (1000 - end) or t[0] > (1000 - start):
return model_function(kwargs["input"], kwargs["timestep"], **kwargs["c"])
for i, name in enumerate(ADJUSTS):
# 元の重みをロード
storedweights[name] = getset_nested_module_tensor(True, new_model, name).clone()
if 4 > i:
new_weight = storedweights[name] * ratios[i]
else:
device = storedweights[name].device
dtype = storedweights[name].dtype
new_weight = storedweights[name] + torch.tensor(ratios[i], device=device, dtype=dtype)
# 重みを書き換え
getset_nested_module_tensor(False, new_model, name, new_tensor=new_weight)
retval = model_function(kwargs["input"], kwargs["timestep"], **kwargs["c"])
# 重みを元に戻す
for name in ADJUSTS:
getset_nested_module_tensor(False, new_model, name, new_tensor=storedweights[name])
return retval
new_model.set_model_unet_function_wrapper(apply_cdtuner)
return io.NodeOutput(new_model)
def getset_nested_module_tensor(clone, model, tensor_path, new_tensor=None):
sdmodules = tensor_path.split('.')
target_module = model
last_attr = None
for module_name in sdmodules if clone else sdmodules[:-1]:
if module_name.isdigit():
target_module = target_module[int(module_name)]
else:
target_module = getattr(target_module, module_name)
if clone:
return target_module
last_attr = sdmodules[-1]
setattr(target_module, last_attr, torch.nn.Parameter(new_tensor))
# なんでfineman?
def fineman(fine):
fine = [
1 - fine[0] * 0.01,
1 + fine[0] * 0.02,
1 - fine[1] * 0.01,
1 + fine[1] * 0.02,
[fine[2] * 0.02, 0, 0, 0]
]
return fine
ADJUSTS = [
"model.diffusion_model.input_blocks.0.0.weight",
"model.diffusion_model.input_blocks.0.0.bias",
"model.diffusion_model.out.0.weight",
"model.diffusion_model.out.0.bias",
"model.diffusion_model.out.2.bias",
]