import torch from diffusers import DDIMScheduler from diffusers import AudioLDM2Pipeline from transformers import RobertaTokenizer, RobertaTokenizerFast from diffusers.models.unets.unet_2d_condition import UNet2DConditionOutput from typing import Any, Dict, List, Optional, Tuple, Union class PipelineWrapper(torch.nn.Module): def __init__(self, model_id, device, double_precision=False, *args, **kwargs) -> None: super().__init__(*args, **kwargs) self.model_id = model_id self.device = device self.double_precision = double_precision def get_sigma(self, timestep) -> float: sqrt_recipm1_alphas_cumprod = torch.sqrt(1.0 / self.model.scheduler.alphas_cumprod - 1) return sqrt_recipm1_alphas_cumprod[timestep] def load_scheduler(self): pass def get_fn_STFT(self): pass def vae_encode(self, x: torch.Tensor): pass def vae_decode(self, x: torch.Tensor): pass def decode_to_mel(self, x: torch.Tensor): pass def encode_text(self, prompts: List[str]) -> Tuple: pass def get_variance(self, timestep, prev_timestep): pass def get_alpha_prod_t_prev(self, prev_timestep): pass def unet_forward(self, sample: torch.FloatTensor, timestep: Union[torch.Tensor, float, int], encoder_hidden_states: torch.Tensor, class_labels: Optional[torch.Tensor] = None, timestep_cond: Optional[torch.Tensor] = None, attention_mask: Optional[torch.Tensor] = None, cross_attention_kwargs: Optional[Dict[str, Any]] = None, added_cond_kwargs: Optional[Dict[str, torch.Tensor]] = None, down_block_additional_residuals: Optional[Tuple[torch.Tensor]] = None, mid_block_additional_residual: Optional[torch.Tensor] = None, encoder_attention_mask: Optional[torch.Tensor] = None, replace_h_space: Optional[torch.Tensor] = None, replace_skip_conns: Optional[Dict[int, torch.Tensor]] = None, return_dict: bool = True, zero_out_resconns: Optional[Union[int, List]] = None) -> Tuple: # By default samples have to be AT least a multiple of the overall upsampling factor. # The overall upsampling factor is equal to 2 ** (# num of upsampling layers). # However, the upsampling interpolation output size can be forced to fit any upsampling size # on the fly if necessary. default_overall_up_factor = 2**self.model.unet.num_upsamplers # upsample size should be forwarded when sample is not a multiple of `default_overall_up_factor` forward_upsample_size = False upsample_size = None if any(s % default_overall_up_factor != 0 for s in sample.shape[-2:]): # logger.info("Forward upsample size to force interpolation output size.") forward_upsample_size = True # ensure attention_mask is a bias, and give it a singleton query_tokens dimension # expects mask of shape: # [batch, key_tokens] # adds singleton query_tokens dimension: # [batch, 1, key_tokens] # this helps to broadcast it as a bias over attention scores, which will be in one of the following shapes: # [batch, heads, query_tokens, key_tokens] (e.g. torch sdp attn) # [batch * heads, query_tokens, key_tokens] (e.g. xformers or classic attn) if attention_mask is not None: # assume that mask is expressed as: # (1 = keep, 0 = discard) # convert mask into a bias that can be added to attention scores: # (keep = +0, discard = -10000.0) attention_mask = (1 - attention_mask.to(sample.dtype)) * -10000.0 attention_mask = attention_mask.unsqueeze(1) # convert encoder_attention_mask to a bias the same way we do for attention_mask if encoder_attention_mask is not None: encoder_attention_mask = (1 - encoder_attention_mask.to(sample.dtype)) * -10000.0 encoder_attention_mask = encoder_attention_mask.unsqueeze(1) # 0. center input if necessary if self.model.unet.config.center_input_sample: sample = 2 * sample - 1.0 # 1. time timesteps = timestep if not torch.is_tensor(timesteps): # TODO: this requires sync between CPU and GPU. So try to pass timesteps as tensors if you can # This would be a good case for the `match` statement (Python 3.10+) is_mps = sample.device.type == "mps" if isinstance(timestep, float): dtype = torch.float32 if is_mps else torch.float64 else: dtype = torch.int32 if is_mps else torch.int64 timesteps = torch.tensor([timesteps], dtype=dtype, device=sample.device) elif len(timesteps.shape) == 0: timesteps = timesteps[None].to(sample.device) # broadcast to batch dimension in a way that's compatible with ONNX/Core ML timesteps = timesteps.expand(sample.shape[0]) t_emb = self.model.unet.time_proj(timesteps) # `Timesteps` does not contain any weights and will always return f32 tensors # but time_embedding might actually be running in fp16. so we need to cast here. # there might be better ways to encapsulate this. t_emb = t_emb.to(dtype=sample.dtype) emb = self.model.unet.time_embedding(t_emb, timestep_cond) if self.model.unet.class_embedding is not None: if class_labels is None: raise ValueError("class_labels should be provided when num_class_embeds > 0") if self.model.unet.config.class_embed_type == "timestep": class_labels = self.model.unet.time_proj(class_labels) # `Timesteps` does not contain any weights and will always return f32 tensors # there might be better ways to encapsulate this. class_labels = class_labels.to(dtype=sample.dtype) class_emb = self.model.unet.class_embedding(class_labels).to(dtype=sample.dtype) if self.model.unet.config.class_embeddings_concat: emb = torch.cat([emb, class_emb], dim=-1) else: emb = emb + class_emb if self.model.unet.config.addition_embed_type == "text": aug_emb = self.model.unet.add_embedding(encoder_hidden_states) emb = emb + aug_emb elif self.model.unet.config.addition_embed_type == "text_image": # Kadinsky 2.1 - style if "image_embeds" not in added_cond_kwargs: raise ValueError( f"{self.model.unet.__class__} has the config param `addition_embed_type` set to 'text_image' " f"which requires the keyword argument `image_embeds` to be passed in `added_cond_kwargs`" ) image_embs = added_cond_kwargs.get("image_embeds") text_embs = added_cond_kwargs.get("text_embeds", encoder_hidden_states) aug_emb = self.model.unet.add_embedding(text_embs, image_embs) emb = emb + aug_emb if self.model.unet.time_embed_act is not None: emb = self.model.unet.time_embed_act(emb) if self.model.unet.encoder_hid_proj is not None and self.model.unet.config.encoder_hid_dim_type == "text_proj": encoder_hidden_states = self.model.unet.encoder_hid_proj(encoder_hidden_states) elif self.model.unet.encoder_hid_proj is not None and \ self.model.unet.config.encoder_hid_dim_type == "text_image_proj": # Kadinsky 2.1 - style if "image_embeds" not in added_cond_kwargs: raise ValueError( f"{self.model.unet.__class__} has the config param `encoder_hid_dim_type` set to 'text_image_proj' " f"which requires the keyword argument `image_embeds` to be passed in `added_conditions`" ) image_embeds = added_cond_kwargs.get("image_embeds") encoder_hidden_states = self.model.unet.encoder_hid_proj(encoder_hidden_states, image_embeds) # 2. pre-process sample = self.model.unet.conv_in(sample) # 3. down down_block_res_samples = (sample,) for downsample_block in self.model.unet.down_blocks: if hasattr(downsample_block, "has_cross_attention") and downsample_block.has_cross_attention: sample, res_samples = downsample_block( hidden_states=sample, temb=emb, encoder_hidden_states=encoder_hidden_states, attention_mask=attention_mask, cross_attention_kwargs=cross_attention_kwargs, encoder_attention_mask=encoder_attention_mask, ) else: sample, res_samples = downsample_block(hidden_states=sample, temb=emb) down_block_res_samples += res_samples if down_block_additional_residuals is not None: new_down_block_res_samples = () for down_block_res_sample, down_block_additional_residual in zip( down_block_res_samples, down_block_additional_residuals ): down_block_res_sample = down_block_res_sample + down_block_additional_residual new_down_block_res_samples = new_down_block_res_samples + (down_block_res_sample,) down_block_res_samples = new_down_block_res_samples # 4. mid if self.model.unet.mid_block is not None: sample = self.model.unet.mid_block( sample, emb, encoder_hidden_states=encoder_hidden_states, attention_mask=attention_mask, cross_attention_kwargs=cross_attention_kwargs, encoder_attention_mask=encoder_attention_mask, ) # print(sample.shape) if replace_h_space is None: h_space = sample.clone() else: h_space = replace_h_space sample = replace_h_space.clone() if mid_block_additional_residual is not None: sample = sample + mid_block_additional_residual extracted_res_conns = {} # 5. up for i, upsample_block in enumerate(self.model.unet.up_blocks): is_final_block = i == len(self.model.unet.up_blocks) - 1 res_samples = down_block_res_samples[-len(upsample_block.resnets):] down_block_res_samples = down_block_res_samples[: -len(upsample_block.resnets)] if replace_skip_conns is not None and replace_skip_conns.get(i): res_samples = replace_skip_conns.get(i) if zero_out_resconns is not None: if (type(zero_out_resconns) is int and i >= (zero_out_resconns - 1)) or \ type(zero_out_resconns) is list and i in zero_out_resconns: res_samples = [torch.zeros_like(x) for x in res_samples] # down_block_res_samples = [torch.zeros_like(x) for x in down_block_res_samples] extracted_res_conns[i] = res_samples # if we have not reached the final block and need to forward the # upsample size, we do it here if not is_final_block and forward_upsample_size: upsample_size = down_block_res_samples[-1].shape[2:] if hasattr(upsample_block, "has_cross_attention") and upsample_block.has_cross_attention: sample = upsample_block( hidden_states=sample, temb=emb, res_hidden_states_tuple=res_samples, encoder_hidden_states=encoder_hidden_states, cross_attention_kwargs=cross_attention_kwargs, upsample_size=upsample_size, attention_mask=attention_mask, encoder_attention_mask=encoder_attention_mask, ) else: sample = upsample_block( hidden_states=sample, temb=emb, res_hidden_states_tuple=res_samples, upsample_size=upsample_size ) # 6. post-process if self.model.unet.conv_norm_out: sample = self.model.unet.conv_norm_out(sample) sample = self.model.unet.conv_act(sample) sample = self.model.unet.conv_out(sample) if not return_dict: return (sample,) return UNet2DConditionOutput(sample=sample), h_space, extracted_res_conns class AudioLDM2Wrapper(PipelineWrapper): def __init__(self, *args, **kwargs) -> None: super().__init__(*args, **kwargs) if self.double_precision: self.model = AudioLDM2Pipeline.from_pretrained(self.model_id, torch_dtype=torch.float64).to(self.device) else: try: self.model = AudioLDM2Pipeline.from_pretrained(self.model_id, local_files_only=True).to(self.device) except FileNotFoundError: self.model = AudioLDM2Pipeline.from_pretrained(self.model_id, local_files_only=False).to(self.device) def load_scheduler(self): # self.model.scheduler = DDIMScheduler.from_config(self.model_id, subfolder="scheduler") self.model.scheduler = DDIMScheduler.from_pretrained(self.model_id, subfolder="scheduler") def get_fn_STFT(self): from audioldm.audio import TacotronSTFT return TacotronSTFT( filter_length=1024, hop_length=160, win_length=1024, n_mel_channels=64, sampling_rate=16000, mel_fmin=0, mel_fmax=8000, ) def vae_encode(self, x): # self.model.vae.disable_tiling() if x.shape[2] % 4: x = torch.nn.functional.pad(x, (0, 0, 4 - (x.shape[2] % 4), 0)) return (self.model.vae.encode(x).latent_dist.mode() * self.model.vae.config.scaling_factor).float() # return (self.encode_no_tiling(x).latent_dist.mode() * self.model.vae.config.scaling_factor).float() def vae_decode(self, x): return self.model.vae.decode(1 / self.model.vae.config.scaling_factor * x).sample def decode_to_mel(self, x): if self.double_precision: tmp = self.model.mel_spectrogram_to_waveform(x[:, 0].detach().double()).detach() tmp = self.model.mel_spectrogram_to_waveform(x[:, 0].detach().float()).detach() if len(tmp.shape) == 1: tmp = tmp.unsqueeze(0) return tmp def encode_text(self, prompts: List[str]): tokenizers = [self.model.tokenizer, self.model.tokenizer_2] text_encoders = [self.model.text_encoder, self.model.text_encoder_2] prompt_embeds_list = [] attention_mask_list = [] for tokenizer, text_encoder in zip(tokenizers, text_encoders): text_inputs = tokenizer( prompts, padding="max_length" if isinstance(tokenizer, (RobertaTokenizer, RobertaTokenizerFast)) else True, max_length=tokenizer.model_max_length, truncation=True, return_tensors="pt", ) text_input_ids = text_inputs.input_ids attention_mask = text_inputs.attention_mask untruncated_ids = tokenizer(prompts, padding="longest", return_tensors="pt").input_ids if untruncated_ids.shape[-1] >= text_input_ids.shape[-1] \ and not torch.equal(text_input_ids, untruncated_ids): removed_text = tokenizer.batch_decode( untruncated_ids[:, tokenizer.model_max_length - 1: -1]) print(f"The following part of your input was truncated because {text_encoder.config.model_type} can " f"only handle sequences up to {tokenizer.model_max_length} tokens: {removed_text}" ) text_input_ids = text_input_ids.to(self.device) attention_mask = attention_mask.to(self.device) with torch.no_grad(): if text_encoder.config.model_type == "clap": prompt_embeds = text_encoder.get_text_features( text_input_ids, attention_mask=attention_mask, ) # append the seq-len dim: (bs, hidden_size) -> (bs, seq_len, hidden_size) prompt_embeds = prompt_embeds[:, None, :] # make sure that we attend to this single hidden-state attention_mask = attention_mask.new_ones((len(prompts), 1)) else: prompt_embeds = text_encoder( text_input_ids, attention_mask=attention_mask, ) prompt_embeds = prompt_embeds[0] prompt_embeds_list.append(prompt_embeds) attention_mask_list.append(attention_mask) # print(f'prompt[0].shape: {prompt_embeds_list[0].shape}') # print(f'prompt[1].shape: {prompt_embeds_list[1].shape}') # print(f'attn[0].shape: {attention_mask_list[0].shape}') # print(f'attn[1].shape: {attention_mask_list[1].shape}') projection_output = self.model.projection_model( hidden_states=prompt_embeds_list[0], hidden_states_1=prompt_embeds_list[1], attention_mask=attention_mask_list[0], attention_mask_1=attention_mask_list[1], ) projected_prompt_embeds = projection_output.hidden_states projected_attention_mask = projection_output.attention_mask generated_prompt_embeds = self.model.generate_language_model( projected_prompt_embeds, attention_mask=projected_attention_mask, max_new_tokens=None, ) prompt_embeds = prompt_embeds.to(dtype=self.model.text_encoder_2.dtype, device=self.device) attention_mask = ( attention_mask.to(device=self.device) if attention_mask is not None else torch.ones(prompt_embeds.shape[:2], dtype=torch.long, device=self.device) ) generated_prompt_embeds = generated_prompt_embeds.to(dtype=self.model.language_model.dtype, device=self.device) return generated_prompt_embeds, prompt_embeds, attention_mask def get_variance(self, timestep, prev_timestep): alpha_prod_t = self.model.scheduler.alphas_cumprod[timestep] alpha_prod_t_prev = self.get_alpha_prod_t_prev(prev_timestep) beta_prod_t = 1 - alpha_prod_t beta_prod_t_prev = 1 - alpha_prod_t_prev variance = (beta_prod_t_prev / beta_prod_t) * (1 - alpha_prod_t / alpha_prod_t_prev) return variance def get_alpha_prod_t_prev(self, prev_timestep): return self.model.scheduler.alphas_cumprod[prev_timestep] if prev_timestep >= 0 \ else self.model.scheduler.final_alpha_cumprod def unet_forward(self, sample: torch.FloatTensor, timestep: Union[torch.Tensor, float, int], encoder_hidden_states: torch.Tensor, timestep_cond: Optional[torch.Tensor] = None, class_labels: Optional[torch.Tensor] = None, attention_mask: Optional[torch.Tensor] = None, encoder_attention_mask: Optional[torch.Tensor] = None, return_dict: bool = True, cross_attention_kwargs: Optional[Dict[str, Any]] = None, mid_block_additional_residual: Optional[torch.Tensor] = None, replace_h_space: Optional[torch.Tensor] = None, replace_skip_conns: Optional[Dict[int, torch.Tensor]] = None, zero_out_resconns: Optional[Union[int, List]] = None) -> Tuple: # Translation encoder_hidden_states_1 = class_labels class_labels = None encoder_attention_mask_1 = encoder_attention_mask encoder_attention_mask = None # return self.model.unet(sample, timestep, # encoder_hidden_states=generated_prompt_embeds, # encoder_hidden_states_1=encoder_hidden_states_1, # encoder_attention_mask_1=encoder_attention_mask_1, # ), None, None # By default samples have to be AT least a multiple of the overall upsampling factor. # The overall upsampling factor is equal to 2 ** (# num of upsampling layers). # However, the upsampling interpolation output size can be forced to fit any upsampling size # on the fly if necessary. default_overall_up_factor = 2 ** self.model.unet.num_upsamplers # upsample size should be forwarded when sample is not a multiple of `default_overall_up_factor` forward_upsample_size = False upsample_size = None if any(s % default_overall_up_factor != 0 for s in sample.shape[-2:]): # print("Forward upsample size to force interpolation output size.") forward_upsample_size = True # ensure attention_mask is a bias, and give it a singleton query_tokens dimension # expects mask of shape: # [batch, key_tokens] # adds singleton query_tokens dimension: # [batch, 1, key_tokens] # this helps to broadcast it as a bias over attention scores, which will be in one of the following shapes: # [batch, heads, query_tokens, key_tokens] (e.g. torch sdp attn) # [batch * heads, query_tokens, key_tokens] (e.g. xformers or classic attn) if attention_mask is not None: # assume that mask is expressed as: # (1 = keep, 0 = discard) # convert mask into a bias that can be added to attention scores: # (keep = +0, discard = -10000.0) attention_mask = (1 - attention_mask.to(sample.dtype)) * -10000.0 attention_mask = attention_mask.unsqueeze(1) # convert encoder_attention_mask to a bias the same way we do for attention_mask if encoder_attention_mask is not None: encoder_attention_mask = (1 - encoder_attention_mask.to(sample.dtype)) * -10000.0 encoder_attention_mask = encoder_attention_mask.unsqueeze(1) if encoder_attention_mask_1 is not None: encoder_attention_mask_1 = (1 - encoder_attention_mask_1.to(sample.dtype)) * -10000.0 encoder_attention_mask_1 = encoder_attention_mask_1.unsqueeze(1) # 1. time timesteps = timestep if not torch.is_tensor(timesteps): # TODO: this requires sync between CPU and GPU. So try to pass timesteps as tensors if you can # This would be a good case for the `match` statement (Python 3.10+) is_mps = sample.device.type == "mps" if isinstance(timestep, float): dtype = torch.float32 if is_mps else torch.float64 else: dtype = torch.int32 if is_mps else torch.int64 timesteps = torch.tensor([timesteps], dtype=dtype, device=sample.device) elif len(timesteps.shape) == 0: timesteps = timesteps[None].to(sample.device) # broadcast to batch dimension in a way that's compatible with ONNX/Core ML timesteps = timesteps.expand(sample.shape[0]) t_emb = self.model.unet.time_proj(timesteps) # `Timesteps` does not contain any weights and will always return f32 tensors # but time_embedding might actually be running in fp16. so we need to cast here. # there might be better ways to encapsulate this. t_emb = t_emb.to(dtype=sample.dtype) emb = self.model.unet.time_embedding(t_emb, timestep_cond) aug_emb = None if self.model.unet.class_embedding is not None: if class_labels is None: raise ValueError("class_labels should be provided when num_class_embeds > 0") if self.model.unet.config.class_embed_type == "timestep": class_labels = self.model.unet.time_proj(class_labels) # `Timesteps` does not contain any weights and will always return f32 tensors # there might be better ways to encapsulate this. class_labels = class_labels.to(dtype=sample.dtype) class_emb = self.model.unet.class_embedding(class_labels).to(dtype=sample.dtype) if self.model.unet.config.class_embeddings_concat: emb = torch.cat([emb, class_emb], dim=-1) else: emb = emb + class_emb emb = emb + aug_emb if aug_emb is not None else emb if self.model.unet.time_embed_act is not None: emb = self.model.unet.time_embed_act(emb) # 2. pre-process sample = self.model.unet.conv_in(sample) # 3. down down_block_res_samples = (sample,) for downsample_block in self.model.unet.down_blocks: if hasattr(downsample_block, "has_cross_attention") and downsample_block.has_cross_attention: sample, res_samples = downsample_block( hidden_states=sample, temb=emb, encoder_hidden_states=encoder_hidden_states, attention_mask=attention_mask, cross_attention_kwargs=cross_attention_kwargs, encoder_attention_mask=encoder_attention_mask, encoder_hidden_states_1=encoder_hidden_states_1, encoder_attention_mask_1=encoder_attention_mask_1, ) else: sample, res_samples = downsample_block(hidden_states=sample, temb=emb) down_block_res_samples += res_samples # 4. mid if self.model.unet.mid_block is not None: sample = self.model.unet.mid_block( sample, emb, encoder_hidden_states=encoder_hidden_states, attention_mask=attention_mask, cross_attention_kwargs=cross_attention_kwargs, encoder_attention_mask=encoder_attention_mask, encoder_hidden_states_1=encoder_hidden_states_1, encoder_attention_mask_1=encoder_attention_mask_1, ) if replace_h_space is None: h_space = sample.clone() else: h_space = replace_h_space sample = replace_h_space.clone() if mid_block_additional_residual is not None: sample = sample + mid_block_additional_residual extracted_res_conns = {} # 5. up for i, upsample_block in enumerate(self.model.unet.up_blocks): is_final_block = i == len(self.model.unet.up_blocks) - 1 res_samples = down_block_res_samples[-len(upsample_block.resnets):] down_block_res_samples = down_block_res_samples[: -len(upsample_block.resnets)] if replace_skip_conns is not None and replace_skip_conns.get(i): res_samples = replace_skip_conns.get(i) if zero_out_resconns is not None: if (type(zero_out_resconns) is int and i >= (zero_out_resconns - 1)) or \ type(zero_out_resconns) is list and i in zero_out_resconns: res_samples = [torch.zeros_like(x) for x in res_samples] # down_block_res_samples = [torch.zeros_like(x) for x in down_block_res_samples] extracted_res_conns[i] = res_samples # if we have not reached the final block and need to forward the # upsample size, we do it here if not is_final_block and forward_upsample_size: upsample_size = down_block_res_samples[-1].shape[2:] if hasattr(upsample_block, "has_cross_attention") and upsample_block.has_cross_attention: sample = upsample_block( hidden_states=sample, temb=emb, res_hidden_states_tuple=res_samples, encoder_hidden_states=encoder_hidden_states, cross_attention_kwargs=cross_attention_kwargs, upsample_size=upsample_size, attention_mask=attention_mask, encoder_attention_mask=encoder_attention_mask, encoder_hidden_states_1=encoder_hidden_states_1, encoder_attention_mask_1=encoder_attention_mask_1, ) else: sample = upsample_block( hidden_states=sample, temb=emb, res_hidden_states_tuple=res_samples, upsample_size=upsample_size ) # 6. post-process if self.model.unet.conv_norm_out: sample = self.model.unet.conv_norm_out(sample) sample = self.model.unet.conv_act(sample) sample = self.model.unet.conv_out(sample) if not return_dict: return (sample,) return UNet2DConditionOutput(sample=sample), h_space, extracted_res_conns def forward(self, *args, **kwargs): return self def load_model(model_id, device, double_precision=False): ldm_stable = AudioLDM2Wrapper(model_id=model_id, device=device, double_precision=double_precision) ldm_stable.load_scheduler() torch.cuda.empty_cache() return ldm_stable