style_ref
This commit is contained in:
+75
-23
@@ -1,17 +1,51 @@
|
||||
import torch
|
||||
|
||||
from comfy.ldm.modules.attention import optimized_attention, optimized_attention_masked
|
||||
from comfy.ldm.util import default
|
||||
|
||||
from .ref_controller import RefMode
|
||||
|
||||
|
||||
|
||||
|
||||
def get_attn_wrapper(cls):
|
||||
class RefAttention(cls):
|
||||
ref_mode = RefMode.OFF
|
||||
ref_bank = None
|
||||
normal_mode = RefMode.OFF
|
||||
kv_mode = RefMode.OFF
|
||||
normal_bank = None
|
||||
k_bank = None
|
||||
v_bank = None
|
||||
is_cfg = True
|
||||
style_fidelity = 0.5
|
||||
content_fidelity = 0.5
|
||||
ref_attn_weight = 1.0
|
||||
attention_bound = 1.0
|
||||
hidden_states = None
|
||||
block_type = None
|
||||
block_idx = None
|
||||
|
||||
def _attention_mechanism(self, q, k, v, mask):
|
||||
if mask is None:
|
||||
out = optimized_attention(q, k, v, self.heads)
|
||||
else:
|
||||
out = optimized_attention_masked(q, k, v, self.heads, mask)
|
||||
return self.to_out(out)
|
||||
|
||||
def _get_qkv(self, x, context=None, value=None):
|
||||
q = self.to_q(x)
|
||||
context = default(context, x)
|
||||
k = self.to_k(context)
|
||||
if value is not None:
|
||||
v = self.to_v(value)
|
||||
del value
|
||||
else:
|
||||
v = self.to_v(context)
|
||||
return q,k,v
|
||||
|
||||
def clean(self):
|
||||
self.normal_bank = None
|
||||
self.k_bank = None
|
||||
self.v_bank = None
|
||||
|
||||
def forward(self, *args, **kwargs):
|
||||
if self.ref_mode == RefMode.OFF:
|
||||
@@ -20,25 +54,45 @@ def get_attn_wrapper(cls):
|
||||
return self._ref_forward(*args, **kwargs)
|
||||
|
||||
def _ref_forward(self, norm_hidden_states, context, **kwargs):
|
||||
if self.ref_mode == RefMode.WRITE:
|
||||
self.ref_bank = norm_hidden_states.detach().clone()
|
||||
return super().forward(norm_hidden_states, context, **kwargs)
|
||||
if self.ref_mode == RefMode.READ:
|
||||
if self.attention_bound > self.ref_attn_weight:
|
||||
bank = self.ref_bank
|
||||
context = default(context, norm_hidden_states)
|
||||
value = kwargs.get('value', None)
|
||||
value = default(value, context)
|
||||
|
||||
self.ref_bank = None
|
||||
bank_hidden_states = torch.cat([norm_hidden_states, bank], dim=1)
|
||||
attn_output_uc = (
|
||||
super().forward(
|
||||
norm_hidden_states,
|
||||
bank_hidden_states,
|
||||
**kwargs
|
||||
)
|
||||
)
|
||||
attn_output = attn_output_uc
|
||||
if self.is_cfg and self.style_fidelity > 0:
|
||||
attn_output_c = attn_output_uc.clone()
|
||||
if self.ref_mode == RefMode.WRITE:
|
||||
if self.normal_mode == RefMode.WRITE and self.attention_bound > self.ref_attn_weight:
|
||||
self.normal_bank = norm_hidden_states.detach().clone()
|
||||
if self.kv_mode == RefMode.WRITE:
|
||||
q,k,v = self._get_qkv(norm_hidden_states, context, **kwargs)
|
||||
self.k_bank = k.detach().clone()
|
||||
self.v_bank = v.detach().clone()
|
||||
mask = kwargs['mask'] if 'mask' in kwargs else None
|
||||
return self._attention_mechanism(q,k,v,mask=mask)
|
||||
else:
|
||||
return super().forward(norm_hidden_states, context, **kwargs)
|
||||
if self.ref_mode == RefMode.READ:
|
||||
normal_bank = None
|
||||
if self.normal_mode == RefMode.READ and self.attention_bound > self.ref_attn_weight:
|
||||
normal_bank = self.normal_bank
|
||||
self.normal_bank = None
|
||||
|
||||
if normal_bank is not None:
|
||||
context = torch.cat([context, normal_bank], dim=1)
|
||||
value = torch.cat([value, normal_bank], dim=1)
|
||||
|
||||
|
||||
q, k, v = self._get_qkv(norm_hidden_states, context, value)
|
||||
|
||||
if self.kv_mode == RefMode.READ:
|
||||
k = self.k_bank
|
||||
v = self.v_bank
|
||||
self.k_bank = None
|
||||
self.v_bank = None
|
||||
|
||||
mask = kwargs['mask'] if 'mask' in kwargs else None
|
||||
attn_output = self._attention_mechanism(q,k,v, mask=mask)
|
||||
|
||||
if normal_bank is not None and self.is_cfg and self.content_fidelity > 0:
|
||||
attn_output_c = attn_output.clone()
|
||||
uc_mask = torch.Tensor(
|
||||
[1] * (norm_hidden_states.shape[0] // 2)
|
||||
+ [0] * (norm_hidden_states.shape[0] // 2)
|
||||
@@ -49,9 +103,7 @@ def get_attn_wrapper(cls):
|
||||
**kwargs
|
||||
)
|
||||
attn_output_c[uc_mask] = attn_sub
|
||||
attn_output = self.style_fidelity * attn_output_c + (1.0 - self.style_fidelity) * attn_output_uc
|
||||
else:
|
||||
attn_output = super().forward(norm_hidden_states, context, **kwargs)
|
||||
return self.content_fidelity * attn_output_c + (1.0 - self.content_fidelity) * attn_output
|
||||
return attn_output
|
||||
|
||||
return RefAttention
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
import enum
|
||||
|
||||
class BlockType(enum.Enum):
|
||||
OUTPUT = 'OUTPUT'
|
||||
+24
-24
@@ -1,5 +1,7 @@
|
||||
import enum
|
||||
|
||||
from .block_type import BlockType
|
||||
|
||||
|
||||
class RefMode(enum.Enum):
|
||||
OFF = 1
|
||||
@@ -17,43 +19,41 @@ class RefController:
|
||||
self.modules.append(module)
|
||||
|
||||
def set_mode(self, mode: RefMode):
|
||||
print('------- CTRL SETTING MODE TO', mode, 'FOR', len(self.modules))
|
||||
for module in self.modules:
|
||||
module.ref_mode = mode
|
||||
if mode == RefMode.OFF:
|
||||
self.set_kv_mode(mode)
|
||||
self.set_normal_mode(mode)
|
||||
|
||||
def set_normal_mode(self, mode: RefMode):
|
||||
for module in self.modules:
|
||||
module.normal_mode = mode
|
||||
|
||||
def set_kv_mode(self, mode: RefMode, count = None):
|
||||
for module in self.modules:
|
||||
module.kv_mode = RefMode.OFF
|
||||
if mode == RefMode.OFF or count is None:
|
||||
count = len(self.modules)
|
||||
output_modules = list(filter(lambda m: m.block_type == BlockType.OUTPUT, self.modules))
|
||||
output_modules = sorted(output_modules, key=lambda m: -m.block_idx)[:count]
|
||||
for module in output_modules:
|
||||
module.kv_mode = mode
|
||||
|
||||
def clear_modules(self):
|
||||
print('------- CTRL CLEARING MODULES FOR', len(self.modules))
|
||||
for module in self.modules:
|
||||
module.ref_bank = None
|
||||
module.clean()
|
||||
self.set_mode(RefMode.OFF)
|
||||
self.set_kv_mode(RefMode.OFF, len(self.modules))
|
||||
self.set_normal_mode(RefMode.OFF)
|
||||
|
||||
def set_cfg(self, cfg: bool):
|
||||
print('------- CTRL SETTING CFG TO', cfg, 'FOR', len(self.modules))
|
||||
for module in self.modules:
|
||||
module.is_cfg = cfg
|
||||
|
||||
def set_attention_bound(self, attention_bound: float):
|
||||
print('------- CTRL SETTING attention bound TO', attention_bound, 'FOR', len(self.modules))
|
||||
for module in self.modules:
|
||||
module.attention_bound = attention_bound
|
||||
|
||||
def set_style_fidelity(self, style_fidelity: float):
|
||||
print('------- CTRL SETTING style fidelity TO', style_fidelity, 'FOR', len(self.modules))
|
||||
def set_content_fidelity(self, content_fidelity: float):
|
||||
for module in self.modules:
|
||||
module.style_fidelity = style_fidelity
|
||||
|
||||
def add_temporal_transformer(self, module):
|
||||
self.temp_modules.append(module)
|
||||
|
||||
def get_default_temporal_values(self):
|
||||
if len(self.temp_modules) > 0:
|
||||
self.default_full_length = self.temp_modules[0].full_length
|
||||
self.default_video_length = self.temp_modules[0].video_length
|
||||
|
||||
def set_temporal_values_to(self, full_length, video_length):
|
||||
for module in self.temp_modules:
|
||||
module.full_length = full_length
|
||||
module.video_length = video_length
|
||||
|
||||
def set_temporal_values_to_default(self):
|
||||
self.set_temporal_values_to(self.default_full_length, self.default_video_length)
|
||||
module.content_fidelity = content_fidelity
|
||||
|
||||
+75
-27
@@ -1,46 +1,97 @@
|
||||
import torch
|
||||
|
||||
from .ref_controller import RefController, RefMode
|
||||
from ..utils.ref_config import RefConfig
|
||||
from ..utils.ref_content_config import RefContentConfig
|
||||
from ..utils.ref_style_config import RefStyleConfig
|
||||
from ..utils.noise_utils import add_noise
|
||||
|
||||
def get_unet_wrapper(cls, ref_controller: RefController):
|
||||
class RefUNet(cls):
|
||||
is_ref = True
|
||||
def forward(self, x, timesteps=None, context=None, y=None, control=None, transformer_options={}, **kwargs):
|
||||
if 'ref_config' not in transformer_options:
|
||||
return super().forward(x,
|
||||
timesteps=timesteps,
|
||||
context=context,
|
||||
y=y,
|
||||
control=control,
|
||||
transformer_options=transformer_options,
|
||||
**kwargs)
|
||||
|
||||
ref_config: RefConfig = transformer_options['ref_config']
|
||||
|
||||
def _ref_content_forward(self, x, timesteps=None, context=None, y=None, control=None, transformer_options={}, **kwargs):
|
||||
ref_config: RefContentConfig = transformer_options.get('ref_content_config', None)
|
||||
if ref_config is None:
|
||||
return RefMode.OFF
|
||||
ref_latent = ref_config.ref_latent
|
||||
ref_latent = torch.cat([ref_latent]*2)
|
||||
|
||||
sigma = ref_config.sampling.sigma(timesteps)
|
||||
start_sigma = ref_config.sampling.percent_to_sigma(ref_config.content_start_percent)
|
||||
end_sigma = ref_config.sampling.percent_to_sigma(ref_config.content_end_percent)
|
||||
if not (start_sigma >= sigma[0] >= end_sigma):
|
||||
return RefMode.OFF
|
||||
|
||||
ref_latent_noised = add_noise(ref_latent, torch.randn_like(ref_latent), sigma[0]).to(x.device).to(x.dtype)
|
||||
|
||||
ref_controller.set_cfg(True) #TODO
|
||||
ref_controller.set_attention_bound(ref_config.attention_bound)
|
||||
ref_controller.set_style_fidelity(ref_config.style_fidelity)
|
||||
ref_controller.set_cfg(len(transformer_options['cond_or_uncond']) > 1) # TODO
|
||||
ref_controller.set_attention_bound(ref_config.content_attention_bound)
|
||||
ref_controller.set_content_fidelity(ref_config.content_fideltiy)
|
||||
|
||||
ref_controller.set_normal_mode(RefMode.WRITE)
|
||||
super().forward(ref_latent_noised,
|
||||
timesteps=timesteps,
|
||||
context=context,
|
||||
y=y,
|
||||
control=None,
|
||||
transformer_options=transformer_options,
|
||||
**kwargs)
|
||||
ref_controller.set_normal_mode(RefMode.OFF)
|
||||
|
||||
return RefMode.READ
|
||||
|
||||
def _ref_style_forward(self, x, timesteps=None, context=None, y=None, control=None, transformer_options={}, **kwargs):
|
||||
ref_config: RefStyleConfig = transformer_options.get('ref_style_config', None)
|
||||
if ref_config is None:
|
||||
return RefMode.OFF, None
|
||||
ref_latent = ref_config.style_latent
|
||||
ref_latent = torch.cat([ref_latent]*2)
|
||||
sigma = ref_config.sampling.sigma(timesteps)
|
||||
start_sigma = ref_config.sampling.percent_to_sigma(ref_config.style_start_percent)
|
||||
end_sigma = ref_config.sampling.percent_to_sigma(ref_config.style_end_percent)
|
||||
if not (start_sigma >= sigma[0] >= end_sigma):
|
||||
return RefMode.OFF, None
|
||||
|
||||
ref_latent_noised = add_noise(ref_latent, torch.randn_like(ref_latent), sigma[0]).to(x.device).to(x.dtype)
|
||||
|
||||
ref_controller.set_kv_mode(RefMode.WRITE, ref_config.style_count)
|
||||
super().forward(ref_latent_noised,
|
||||
timesteps=timesteps,
|
||||
context=ref_config.style_prompt.to(ref_latent_noised.device).half(),
|
||||
y=y,
|
||||
control=None,
|
||||
transformer_options=transformer_options,
|
||||
**kwargs)
|
||||
ref_controller.set_kv_mode(RefMode.OFF)
|
||||
|
||||
return RefMode.READ, ref_config.style_count
|
||||
|
||||
|
||||
def forward(self, x, timesteps=None, context=None, y=None, control=None, transformer_options={}, **kwargs):
|
||||
ref_controller.set_mode(RefMode.OFF)
|
||||
ref_controller.clear_modules()
|
||||
try:
|
||||
ref_controller.set_mode(RefMode.WRITE)
|
||||
super().forward(ref_latent_noised,
|
||||
timesteps=timesteps,
|
||||
context=context,
|
||||
y=y,
|
||||
control=None,
|
||||
transformer_options=transformer_options,
|
||||
**kwargs)
|
||||
|
||||
normal_read = self._ref_content_forward(
|
||||
x,
|
||||
timesteps=timesteps,
|
||||
context=context,
|
||||
y=y,
|
||||
control=control,
|
||||
transformer_options=transformer_options,
|
||||
**kwargs
|
||||
)
|
||||
kv_read, kv_count = self._ref_style_forward(
|
||||
x,
|
||||
timesteps=timesteps,
|
||||
context=context,
|
||||
y=y,
|
||||
control=control,
|
||||
transformer_options=transformer_options,
|
||||
**kwargs
|
||||
)
|
||||
ref_controller.set_mode(RefMode.READ)
|
||||
ref_controller.set_normal_mode(normal_read)
|
||||
ref_controller.set_kv_mode(kv_read, kv_count)
|
||||
output = super().forward(x,
|
||||
timesteps=timesteps,
|
||||
context=context,
|
||||
@@ -50,9 +101,6 @@ def get_unet_wrapper(cls, ref_controller: RefController):
|
||||
**kwargs)
|
||||
ref_controller.set_mode(RefMode.OFF)
|
||||
return output
|
||||
# except Exception as e:
|
||||
# print('issue with ref')
|
||||
# raise e
|
||||
finally:
|
||||
ref_controller.clear_modules()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user