



from typing import List, Optional, Union

import torch
from transformers import (
    XLMRobertaTokenizer,
)

from ...models import UNetaDConditionModel, VQModel
from ...pipelines import DiffusionPipeline
from ...pipelines.pipeline_utils import ImagePipelineOutput
from ...schedulers import DDIMScheduler, DDPMScheduler
from ...utils import (
    is_accelerate_available,
    is_accelerate_version,
    logging,
    randn_tensor,
    replace_example_docstring,
)
from .text_encoder import MultilingualCLIP


lowercase_													=      logging.get_logger(__name__)  # pylint: disable=invalid-name

lowercase_													=      '''
    Examples:
        ```py
        >>> from diffusers import KandinskyPipeline, KandinskyPriorPipeline
        >>> import torch

        >>> pipe_prior = KandinskyPriorPipeline.from_pretrained("kandinsky-community/Kandinsky-2-1-prior")
        >>> pipe_prior.to("cuda")

        >>> prompt = "red cat, 4k photo"
        >>> out = pipe_prior(prompt)
        >>> image_emb = out.image_embeds
        >>> negative_image_emb = out.negative_image_embeds

        >>> pipe = KandinskyPipeline.from_pretrained("kandinsky-community/kandinsky-2-1")
        >>> pipe.to("cuda")

        >>> image = pipe(
        ...     prompt,
        ...     image_embeds=image_emb,
        ...     negative_image_embeds=negative_image_emb,
        ...     height=768,
        ...     width=768,
        ...     num_inference_steps=100,
        ... ).images

        >>> image[0].save("cat.png")
        ```
'''






def        __lowerCAmelCase		(	__lowerCamelCase						:     Any					, __lowerCamelCase						:     Tuple					, __lowerCamelCase						:     Tuple=8						)	->    Optional[Any]:
					__lowerCAmelCase						 =h // scale_factor**2
					if h % scale_factor**2 != 0:
										new_h += 1
					__lowerCAmelCase						 =w // scale_factor**2
					if w % scale_factor**2 != 0:
										new_w += 1
					return new_h * scale_factor, new_w * scale_factor






class     __a			(  SCREAMING_SNAKE_CASE					):



	def __init__(    self				:     List[Any]					,						snake_case_				:     MultilingualCLIP					,						snake_case_				:     XLMRobertaTokenizer					,						snake_case_				:     UNetaDConditionModel					,						snake_case_				:     Union[DDIMScheduler, DDPMScheduler]					,						snake_case_				:     VQModel					,						)->				Union[str, Any]:
						super().__init__()

						self.register_modules(
						    text_encoder=snake_case_					,						tokenizer=snake_case_					,						unet=snake_case_					,						scheduler=snake_case_					,						movq=snake_case_					,						)
						__lowerCAmelCase						 =2 ** (len(self.movq.config.block_out_channels) - 1)



	def 		UpperCamelCase				(    self				:     List[str]					,						snake_case_				:     Dict					,						snake_case_				:     List[str]					,						snake_case_				:     Union[str, Any]					,						snake_case_				:     int					,						snake_case_				:     str					,						snake_case_				:     Any)->				Optional[int]:
						if latents is None:
											__lowerCAmelCase						 =randn_tensor(snake_case_					,						generator=snake_case_					,						device=snake_case_					,						dtype=snake_case_)
						else:
											if latents.shape != shape:
																raise ValueError(F"""Unexpected latents shape, got {latents.shape}, expected {shape}""")
											__lowerCAmelCase						 =latents.to(snake_case_)

						__lowerCAmelCase						 =latents * scheduler.init_noise_sigma
						return latents



	def 		UpperCamelCase				(    self				:     Dict					,						snake_case_				:     Any					,						snake_case_				:     Union[str, Any]					,						snake_case_				:     Tuple					,						snake_case_				:     Dict					,						snake_case_				:     Tuple=None					,						)->				Optional[int]:
						__lowerCAmelCase						 =len(snake_case_) if isinstance(snake_case_					,						snake_case_) else 1
						# get prompt text embeddings
						__lowerCAmelCase						 =self.tokenizer(
						    snake_case_					,						padding="""max_length"""					,						truncation=snake_case_					,						max_length=77					,						return_attention_mask=snake_case_					,						add_special_tokens=snake_case_					,						return_tensors="""pt"""					,						)

						__lowerCAmelCase						 =text_inputs.input_ids
						__lowerCAmelCase						 =self.tokenizer(snake_case_					,						padding="""longest"""					,						return_tensors="""pt""").input_ids

						if untruncated_ids.shape[-1] >= text_input_ids.shape[-1] and not torch.equal(snake_case_					,						snake_case_):
											__lowerCAmelCase						 =self.tokenizer.batch_decode(untruncated_ids[:, self.tokenizer.model_max_length - 1 : -1])
											logger.warning(
											    """The following part of your input was truncated because CLIP can only handle sequences up to"""
											    F""" {self.tokenizer.model_max_length} tokens: {removed_text}""")

						__lowerCAmelCase						 =text_input_ids.to(snake_case_)
						__lowerCAmelCase						 =text_inputs.attention_mask.to(snake_case_)

						__lowerCAmelCase ,						__lowerCAmelCase						 =self.text_encoder(
						    input_ids=snake_case_					,						attention_mask=snake_case_)

						__lowerCAmelCase						 =prompt_embeds.repeat_interleave(snake_case_					,						dim=0)
						__lowerCAmelCase						 =text_encoder_hidden_states.repeat_interleave(snake_case_					,						dim=0)
						__lowerCAmelCase						 =text_mask.repeat_interleave(snake_case_					,						dim=0)

						if do_classifier_free_guidance:
											__lowerCAmelCase						 =42
											if negative_prompt is None:
																__lowerCAmelCase						 =[""""""] * batch_size
											elif type(snake_case_) is not type(snake_case_):
																raise TypeError(
																    F"""`negative_prompt` should be the same type to `prompt`, but got {type(snake_case_)} !="""
																    F""" {type(snake_case_)}.""")
											elif isinstance(snake_case_					,						snake_case_):
																__lowerCAmelCase						 =[negative_prompt]
											elif batch_size != len(snake_case_):
																raise ValueError(
																    F"""`negative_prompt`: {negative_prompt} has batch size {len(snake_case_)}, but `prompt`:"""
																    F""" {prompt} has batch size {batch_size}. Please make sure that passed `negative_prompt` matches"""
																    """ the batch size of `prompt`.""")
											else:
																__lowerCAmelCase						 =negative_prompt

											__lowerCAmelCase						 =self.tokenizer(
											    snake_case_					,						padding="""max_length"""					,						max_length=77					,						truncation=snake_case_					,						return_attention_mask=snake_case_					,						add_special_tokens=snake_case_					,						return_tensors="""pt"""					,						)
											__lowerCAmelCase						 =uncond_input.input_ids.to(snake_case_)
											__lowerCAmelCase						 =uncond_input.attention_mask.to(snake_case_)

											__lowerCAmelCase ,						__lowerCAmelCase						 =self.text_encoder(
											    input_ids=snake_case_					,						attention_mask=snake_case_)

											# duplicate unconditional embeddings for each generation per prompt, using mps friendly method

											__lowerCAmelCase						 =negative_prompt_embeds.shape[1]
											__lowerCAmelCase						 =negative_prompt_embeds.repeat(1					,						snake_case_)
											__lowerCAmelCase						 =negative_prompt_embeds.view(batch_size * num_images_per_prompt					,						snake_case_)

											__lowerCAmelCase						 =uncond_text_encoder_hidden_states.shape[1]
											__lowerCAmelCase						 =uncond_text_encoder_hidden_states.repeat(1					,						snake_case_					,						1)
											__lowerCAmelCase						 =uncond_text_encoder_hidden_states.view(
											    batch_size * num_images_per_prompt					,						snake_case_					,						-1)
											__lowerCAmelCase						 =uncond_text_mask.repeat_interleave(snake_case_					,						dim=0)

											# done duplicates

											# For classifier free guidance, we need to do two forward passes.
											# Here we concatenate the unconditional and text embeddings into a single batch
											# to avoid doing two forward passes
											__lowerCAmelCase						 =torch.cat([negative_prompt_embeds, prompt_embeds])
											__lowerCAmelCase						 =torch.cat([uncond_text_encoder_hidden_states, text_encoder_hidden_states])

											__lowerCAmelCase						 =torch.cat([uncond_text_mask, text_mask])

						return prompt_embeds, text_encoder_hidden_states, text_mask



	def 		UpperCamelCase				(    self				:     Tuple					,						snake_case_				:     Optional[Any]=0)->				int:
						if is_accelerate_available():
											from accelerate import cpu_offload
						else:
											raise ImportError("""Please install accelerate via `pip install accelerate`""")

						__lowerCAmelCase						 =torch.device(F"""cuda:{gpu_id}""")

						__lowerCAmelCase						 =[
						    self.unet,
						    self.text_encoder,
						    self.movq,
						]
						for cpu_offloaded_model in models:
											if cpu_offloaded_model is not None:
																cpu_offload(snake_case_					,						snake_case_)



	def 		UpperCamelCase				(    self				:     Dict					,						snake_case_				:     Optional[Any]=0)->				str:
						if is_accelerate_available() and is_accelerate_version(""">="""					,						"""0.17.0.dev0"""):
											from accelerate import cpu_offload_with_hook
						else:
											raise ImportError("""`enable_model_cpu_offload` requires `accelerate v0.17.0` or higher.""")

						__lowerCAmelCase						 =torch.device(F"""cuda:{gpu_id}""")

						if self.device.type != "cpu":
											self.to("""cpu"""					,						silence_dtype_warnings=snake_case_)
											torch.cuda.empty_cache()  # otherwise we don't see the memory savings (but they probably exist)

						__lowerCAmelCase						 =None
						for cpu_offloaded_model in [self.text_encoder, self.unet, self.movq]:
											__lowerCAmelCase ,						__lowerCAmelCase						 =cpu_offload_with_hook(snake_case_					,						snake_case_					,						prev_module_hook=snake_case_)

						if self.safety_checker is not None:
											__lowerCAmelCase ,						__lowerCAmelCase						 =cpu_offload_with_hook(self.safety_checker					,						snake_case_					,						prev_module_hook=snake_case_)

						# We'll offload the last model manually.
						__lowerCAmelCase						 =hook



	@property
	# Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion.StableDiffusionPipeline._execution_device
	def 		UpperCamelCase				(    self				:     Any)->				Dict:
						if not hasattr(self.unet					,						"""_hf_hook"""):
											return self.device
						for module in self.unet.modules():
											if (
											    hasattr(snake_case_					,						"""_hf_hook""")
											    and hasattr(module._hf_hook					,						"""execution_device""")
											    and module._hf_hook.execution_device is not None
											):
																return torch.device(module._hf_hook.execution_device)
						return self.device



	@torch.no_grad()
	@replace_example_docstring(snake_case_)
	def __call__(    self				:     Union[str, Any]					,						snake_case_				:     Union[str, List[str]]					,						snake_case_				:     Union[torch.FloatTensor, List[torch.FloatTensor]]					,						snake_case_				:     Union[torch.FloatTensor, List[torch.FloatTensor]]					,						snake_case_				:     Optional[Union[str, List[str]]] = None					,						snake_case_				:     int = 5_12					,						snake_case_				:     int = 5_12					,						snake_case_				:     int = 1_00					,						snake_case_				:     float = 4.0					,						snake_case_				:     int = 1					,						snake_case_				:     Optional[Union[torch.Generator, List[torch.Generator]]] = None					,						snake_case_				:     Optional[torch.FloatTensor] = None					,						snake_case_				:     Optional[str] = "pil"					,						snake_case_				:     bool = True					,						)->				List[str]:

						if isinstance(snake_case_					,						snake_case_):
											__lowerCAmelCase						 =1
						elif isinstance(snake_case_					,						snake_case_):
											__lowerCAmelCase						 =len(snake_case_)
						else:
											raise ValueError(F"""`prompt` has to be of type `str` or `list` but is {type(snake_case_)}""")

						__lowerCAmelCase						 =self._execution_device

						__lowerCAmelCase						 =batch_size * num_images_per_prompt
						__lowerCAmelCase						 =guidance_scale > 1.0

						__lowerCAmelCase ,						__lowerCAmelCase ,						__lowerCAmelCase						 =self._encode_prompt(
						    snake_case_					,						snake_case_					,						snake_case_					,						snake_case_					,						snake_case_)

						if isinstance(snake_case_					,						snake_case_):
											__lowerCAmelCase						 =torch.cat(snake_case_					,						dim=0)
						if isinstance(snake_case_					,						snake_case_):
											__lowerCAmelCase						 =torch.cat(snake_case_					,						dim=0)

						if do_classifier_free_guidance:
											__lowerCAmelCase						 =image_embeds.repeat_interleave(snake_case_					,						dim=0)
											__lowerCAmelCase						 =negative_image_embeds.repeat_interleave(snake_case_					,						dim=0)

						__lowerCAmelCase						 =torch.cat([negative_image_embeds, image_embeds]					,						dim=0).to(
						    dtype=prompt_embeds.dtype					,						device=snake_case_)

						self.scheduler.set_timesteps(snake_case_					,						device=snake_case_)
						__lowerCAmelCase						 =self.scheduler.timesteps

						__lowerCAmelCase						 =self.unet.config.in_channels

						__lowerCAmelCase ,						__lowerCAmelCase						 =get_new_h_w(snake_case_					,						snake_case_					,						self.movq_scale_factor)

						# create initial latent
						__lowerCAmelCase						 =self.prepare_latents(
						    (batch_size, num_channels_latents, height, width)					,						text_encoder_hidden_states.dtype					,						snake_case_					,						snake_case_					,						snake_case_					,						self.scheduler					,						)

						for i, t in enumerate(self.progress_bar(snake_case_)):
											# expand the latents if we are doing classifier free guidance
											__lowerCAmelCase						 =torch.cat([latents] * 2) if do_classifier_free_guidance else latents

											__lowerCAmelCase						 ={"""text_embeds""": prompt_embeds, """image_embeds""": image_embeds}
											__lowerCAmelCase						 =self.unet(
											    sample=snake_case_					,						timestep=snake_case_					,						encoder_hidden_states=snake_case_					,						added_cond_kwargs=snake_case_					,						return_dict=snake_case_					,						)[0]

											if do_classifier_free_guidance:
																__lowerCAmelCase ,						__lowerCAmelCase						 =noise_pred.split(latents.shape[1]					,						dim=1)
																__lowerCAmelCase ,						__lowerCAmelCase						 =noise_pred.chunk(2)
																__lowerCAmelCase ,						__lowerCAmelCase						 =variance_pred.chunk(2)
																__lowerCAmelCase						 =noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)
																__lowerCAmelCase						 =torch.cat([noise_pred, variance_pred_text]					,						dim=1)

											if not (
											    hasattr(self.scheduler.config					,						"""variance_type""")
											    and self.scheduler.config.variance_type in ["learned", "learned_range"]
											):
																__lowerCAmelCase ,						__lowerCAmelCase						 =noise_pred.split(latents.shape[1]					,						dim=1)

											# compute the previous noisy sample x_t -> x_t-1
											__lowerCAmelCase						 =self.scheduler.step(
											    snake_case_					,						snake_case_					,						snake_case_					,						generator=snake_case_					,						).prev_sample
						# post-processing
						__lowerCAmelCase						 =self.movq.decode(snake_case_					,						force_not_quantize=snake_case_)["""sample"""]

						if output_type not in ["pt", "np", "pil"]:
											raise ValueError(F"""Only the output types `pt`, `pil` and `np` are supported not output_type={output_type}""")

						if output_type in ["np", "pil"]:
											__lowerCAmelCase						 =image * 0.5 + 0.5
											__lowerCAmelCase						 =image.clamp(0					,						1)
											__lowerCAmelCase						 =image.cpu().permute(0					,						2					,						3					,						1).float().numpy()

						if output_type == "pil":
											__lowerCAmelCase						 =self.numpy_to_pil(snake_case_)

						if not return_dict:
											return (image,)

						return ImagePipelineOutput(images=snake_case_)









def        __lowerCAmelCase		(	__lowerCamelCase						:     int					, __lowerCamelCase						:     int						)	->    bool:
					return numa ^ numa < 0


if __name__ == "__main__":
				import doctest

				doctest.testmod()




