This commit is contained in:
logtd
2024-03-28 18:42:47 -06:00
commit fd802682ab
11 changed files with 407 additions and 0 deletions
+73
View File
@@ -0,0 +1,73 @@
import torch
from ..modules.attn_wrapper import get_attn_wrapper
from ..modules.ref_controller import RefController
def isinstance_str(x: object, cls_name: str):
for _cls in x.__class__.__mro__:
if _cls.__name__ == cls_name:
return True
return False
def is_transformer_block(module):
return isinstance_str(module, 'BasicTransformerBlock')
def is_temporal_block(module):
return isinstance_str(module, 'TemporalTransformerBlock')
def is_named_module_transformer_block(named_module):
if is_transformer_block(named_module[1]):
return True
elif is_temporal_block(named_module[1]):
return True
return False
def get_norm1_shape(block_module):
if is_transformer_block(block_module):
return block_module.norm1.normalized_shape[0]
elif is_temporal_block(block_module):
return block_module.norms[0].normalized_shape[0]
raise ValueError('Bad block!', block_module)
def get_block_attention(block_module):
if is_transformer_block(block_module):
return block_module.attn1
elif is_temporal_block(block_module):
return block_module.attention_blocks[0]
def sort_block(module):
return -get_norm1_shape(module)
def setup_ref_attn(model, attn_type):
# TODO: attn_type for full/mid_out
model = model.model.diffusion_model
block_modules = list(filter(is_named_module_transformer_block, model.named_modules()))
block_modules = list(map(lambda x: x[1], block_modules))
block_modules = sorted(block_modules, key=sort_block)
ref_controller = RefController()
for i, block_module in enumerate(block_modules):
if is_transformer_block(block_module):
attn = get_block_attention(block_module)
if not hasattr(attn, 'ref_mode'):
attn.__class__ = get_attn_wrapper(attn.__class__)
attn.ref_attn_weight = float(i) / float(len(block_modules))
ref_controller.add_module(attn)
temp_transformers = list(filter(lambda x: isinstance_str(x, 'TemporalTransformer3DModel'), model.named_modules()))
for _, transformer_module in temp_transformers:
ref_controller.add_temporal_transformer(transformer_module)
return ref_controller
+22
View File
@@ -0,0 +1,22 @@
import torch
def get_alphacumprod(sigma):
return 1 / ((sigma * sigma) + 1)
def add_noise(src_latent, noise, sigma):
alphas_cumprod = get_alphacumprod(sigma)
sqrt_alpha_prod = alphas_cumprod ** 0.5
sqrt_alpha_prod = sqrt_alpha_prod.flatten()
while len(sqrt_alpha_prod.shape) < len(src_latent.shape):
sqrt_alpha_prod = sqrt_alpha_prod.unsqueeze(-1)
sqrt_one_minus_alpha_prod = (1 - alphas_cumprod) ** 0.5
sqrt_one_minus_alpha_prod = sqrt_one_minus_alpha_prod.flatten()
while len(sqrt_one_minus_alpha_prod.shape) < len(src_latent.shape):
sqrt_one_minus_alpha_prod = sqrt_one_minus_alpha_prod.unsqueeze(-1)
noisy_samples = sqrt_alpha_prod * src_latent + sqrt_one_minus_alpha_prod * noise
return noisy_samples
+7
View File
@@ -0,0 +1,7 @@
class RefConfig:
def __init__(self, style_fidelity, attention_bound):
self.style_fidelity = style_fidelity
self.attention_bound = attention_bound
+93
View File
@@ -0,0 +1,93 @@
import torch
import comfy.model_management
from .ref_config import RefConfig
from ..modules.ref_controller import RefController, RefMode
from ..utils.noise_utils import add_noise
def get_base_model(model):
base_model = model
while hasattr(base_model, 'inner_model'):
base_model = base_model.inner_model
return base_model
def prepare_ref_latents(model, ref_latent):
base_model = get_base_model(model)
ref_latent = ref_latent['samples']
ref_latent = base_model.process_latent_in(ref_latent)
device = comfy.model_management.get_torch_device()
ref_latent = ref_latent.to(device)
return ref_latent
def create_model_wrapper(model, sigmas, ref_latent, extra_args, ref_config:RefConfig):
# extra_args: ['cond', 'uncond', 'cond_scale', 'model_options', 'seed', 'denoise_mask']
ref_latent = prepare_ref_latents(model, ref_latent)
# Get ref_controller
model_options = extra_args.get('model_options', {})
ref_controller: RefController = model_options.get('ref_controller', {})
ref_conds = []
for cond in extra_args['cond']:
cond = {**cond}
if 'control' in cond:
del cond['control']
ref_conds.append(cond)
ref_unconds = []
for cond in extra_args['uncond']:
cond = {**cond}
if 'control' in cond:
del cond['control']
ref_unconds.append(cond)
# Setup ref
ref_controller.clear_modules()
is_cfg = extra_args.get('cond_scale', 7) > 1
ref_controller.set_cfg(is_cfg)
ref_controller.set_style_fidelity(ref_config.style_fidelity)
ref_controller.set_attention_bound(ref_config.attention_bound)
def model_sample(latents, sigma, **kwargs):
ref_controller.get_default_temporal_values()
# Do Ref Sampling
ref_controller.set_temporal_values_to(1, 1)
ref_controller.set_mode(RefMode.WRITE)
ref_latent_noised = add_noise(ref_latent, torch.randn_like(ref_latent), sigma[0])
ref_sigma = torch.tensor([sigma[0]]*len(ref_latent)).to(sigmas.device)
model(ref_latent_noised, ref_sigma, **{**kwargs, 'cond': ref_conds, 'uncond': ref_unconds})
# Do Latent Sampling
ref_controller.set_temporal_values_to_default()
ref_controller.set_mode(RefMode.READ)
latents = model(latents, sigma, **kwargs)
# Clear refs
ref_controller.clear_modules()
ref_controller.set_mode(RefMode.OFF)
return latents
class RefModelWrapper:
inner_model = model.inner_model
def __call__(self, *args, **kwargs):
return model_sample(*args, **kwargs)
return RefModelWrapper()
def create_sampler(sample_fn, inversion_latent, ref_config):
@torch.no_grad()
def sample(model, latents, sigmas, extra_args=None, callback=None, disable=None, **extra_options):
# src_latents = prepare_src_latents(model, src_latent_image)
model_wrapper = create_model_wrapper(model, sigmas, inversion_latent, extra_args, ref_config)
output = sample_fn(model_wrapper, latents, sigmas, extra_args=extra_args, callback=callback, disable=disable)
del model_wrapper
return output
return sample