


# Copyright 2023 The HuggingFace Inc. team. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import copy
import importlib.metadata
import json
import os
from dataclasses import dataclass
from typing import Any, Dict, Union

from packaging import version

from ..utils import is_torch_available, logging


if is_torch_available():
   import torch


SCREAMING_SNAKE_CASE       :		Optional[int]         =				logging.get_logger(__name__)






@dataclass
class      UpperCamelCase					:


   '''simple docstring'''







   def __init__(     self   ,							UpperCamelCase_=False   ,							UpperCamelCase_=False   ,							UpperCamelCase_=6.0   ,							UpperCamelCase_=None   ,							UpperCamelCase_=False   ,							UpperCamelCase_=False   ,							UpperCamelCase_=None   ,							UpperCamelCase_="fp4"   ,							UpperCamelCase_=False   ,							**UpperCamelCase_   ,							):
        lowercase_       :Union[str, Any]     =       load_in_abit
        lowercase_       :Any     =       load_in_abit
        lowercase_       :Dict     =       llm_inta_threshold
        lowercase_       :Union[str, Any]     =       llm_inta_skip_modules
        lowercase_       :str     =       llm_inta_enable_fpaa_cpu_offload
        lowercase_       :List[str]     =       llm_inta_has_fpaa_weight
        lowercase_       :Union[str, Any]     =       bnb_abit_quant_type
        lowercase_       :Tuple     =       bnb_abit_use_double_quant

        if bnb_abit_compute_dtype is None:
             lowercase_       :Dict     =       torch.floataa
        elif isinstance(UpperCamelCase_   ,							UpperCamelCase_		):
             lowercase_       :Tuple     =       getattr(UpperCamelCase_   ,							UpperCamelCase_		)
        elif isinstance(UpperCamelCase_   ,							torch.dtype		):
             lowercase_       :Any     =       bnb_abit_compute_dtype
        else:
             raise ValueError('''bnb_4bit_compute_dtype must be a string or a torch.dtype'''		)

        self.post_init()
   def 		UpperCamelCase  (     self		):
        if not isinstance(self.llm_inta_threshold   ,							UpperCamelCase_		):
             raise ValueError('''llm_int8_threshold must be a float'''		)

        if self.llm_inta_skip_modules is not None and not isinstance(self.llm_inta_skip_modules   ,							UpperCamelCase_		):
             raise ValueError('''llm_int8_skip_modules must be a list of strings'''		)
        if not isinstance(self.llm_inta_enable_fpaa_cpu_offload   ,							UpperCamelCase_		):
             raise ValueError('''llm_int8_enable_fp32_cpu_offload must be a boolean'''		)

        if not isinstance(self.llm_inta_has_fpaa_weight   ,							UpperCamelCase_		):
             raise ValueError('''llm_int8_has_fp16_weight must be a boolean'''		)

        if self.bnb_abit_compute_dtype is not None and not isinstance(self.bnb_abit_compute_dtype   ,							torch.dtype		):
             raise ValueError('''bnb_4bit_compute_dtype must be torch.dtype'''		)

        if not isinstance(self.bnb_abit_quant_type   ,							UpperCamelCase_		):
             raise ValueError('''bnb_4bit_quant_type must be a string'''		)

        if not isinstance(self.bnb_abit_use_double_quant   ,							UpperCamelCase_		):
             raise ValueError('''bnb_4bit_use_double_quant must be a boolean'''		)

        if self.load_in_abit and not version.parse(importlib.metadata.version('''bitsandbytes'''		)		) >= version.parse(
            '''0.39.0'''		):
             raise ValueError(
                 '''4 bit quantization requires bitsandbytes>=0.39.0 - please upgrade your bitsandbytes version'''		)
   def 		UpperCamelCase  (     self		):
        return self.load_in_abit or self.load_in_abit
   def 		UpperCamelCase  (     self		):
        if self.load_in_abit:
             return "llm_int8"
        elif self.load_in_abit and self.bnb_abit_quant_type == "fp4":
             return "fp4"
        elif self.load_in_abit and self.bnb_abit_quant_type == "nf4":
             return "nf4"
        else:
             return None
   @classmethod
   def 		UpperCamelCase  (     cls   ,							UpperCamelCase_   ,							UpperCamelCase_   ,							**UpperCamelCase_		):
        lowercase_       :Any     =       cls(**UpperCamelCase_		)

        lowercase_       :str     =       []
        for key, value in kwargs.items():
             if hasattr(UpperCamelCase_   ,							UpperCamelCase_		):
                  setattr(UpperCamelCase_   ,							UpperCamelCase_   ,							UpperCamelCase_		)
                  to_remove.append(UpperCamelCase_		)
        for key in to_remove:
             kwargs.pop(UpperCamelCase_   ,							UpperCamelCase_		)

        if return_unused_kwargs:
             return config, kwargs
        else:
             return config
   def 		UpperCamelCase  (     self   ,							UpperCamelCase_		):
        with open(UpperCamelCase_   ,							'''w'''   ,							encoding='''utf-8'''		) as writer:
             lowercase_       :Optional[Any]     =       self.to_dict()
             lowercase_       :Union[str, Any]     =       json.dumps(UpperCamelCase_   ,							indent=2   ,							sort_keys=UpperCamelCase_		) + '''\n'''

             writer.write(UpperCamelCase_		)
   def 		UpperCamelCase  (     self		):
        lowercase_       :Tuple     =       copy.deepcopy(self.__dict__		)
        lowercase_       :Dict     =       str(output['''bnb_4bit_compute_dtype''']		).split('''.'''		)[1]

        return output
   def __repr__(     self		):
        return f"{self.__class__.__name__} {self.to_json_string()}"
   def 		UpperCamelCase  (     self   ,							UpperCamelCase_ = True		):
        if use_diff is True:
             lowercase_       :Optional[int]     =       self.to_diff_dict()
        else:
             lowercase_       :List[Any]     =       self.to_dict()
        return json.dumps(UpperCamelCase_   ,							indent=2   ,							sort_keys=UpperCamelCase_		) + "\n"




   def 		UpperCamelCase  (     self		):
        lowercase_       :Dict     =       self.to_dict()

        # get the default config dict
        lowercase_       :Any     =       BitsAndBytesConfig().to_dict()

        lowercase_       :Optional[int]     =       {}

        # only serialize values that differ from the default config
        for key, value in config_dict.items():
             if value != default_config_dict[key]:
                  lowercase_       :int     =       value

        return serializable_config_dict





import gc
import unittest

import numpy as np
import torch
from transformers import CLIPTextConfig, CLIPTextModel, CLIPTokenizer

from diffusers import TransformeraDModel, VQDiffusionPipeline, VQDiffusionScheduler, VQModel
from diffusers.pipelines.vq_diffusion.pipeline_vq_diffusion import LearnedClassifierFreeSamplingEmbeddings
from diffusers.utils import load_numpy, slow, torch_device
from diffusers.utils.testing_utils import require_torch_gpu


SCREAMING_SNAKE_CASE       :		int         =				False






class      UpperCamelCase					(		unittest.TestCase     ):


   '''simple docstring'''







   def 		UpperCamelCase  (     self		):
        # clean up the VRAM after each test
        super().tearDown()
        gc.collect()
        torch.cuda.empty_cache()
   @property
   def 		UpperCamelCase  (     self		):
        return 12
   @property
   def 		UpperCamelCase  (     self		):
        return 12
   @property
   def 		UpperCamelCase  (     self		):
        return 32
   @property
   def 		UpperCamelCase  (     self		):
        torch.manual_seed(0		)
        lowercase_       :List[Any]     =       VQModel(
            block_out_channels=[32, 64]   ,							in_channels=3   ,							out_channels=3   ,							down_block_types=['''DownEncoderBlock2D''', '''DownEncoderBlock2D''']   ,							up_block_types=['''UpDecoderBlock2D''', '''UpDecoderBlock2D''']   ,							latent_channels=3   ,							num_vq_embeddings=self.num_embed   ,							vq_embed_dim=3   ,							)
        return model
   @property
   def 		UpperCamelCase  (     self		):
        lowercase_       :Optional[Any]     =       CLIPTokenizer.from_pretrained('''hf-internal-testing/tiny-random-clip'''		)
        return tokenizer
   @property
   def 		UpperCamelCase  (     self		):
        torch.manual_seed(0		)
        lowercase_       :int     =       CLIPTextConfig(
            bos_token_id=0   ,							eos_token_id=2   ,							hidden_size=self.text_embedder_hidden_size   ,							intermediate_size=37   ,							layer_norm_eps=1E-05   ,							num_attention_heads=4   ,							num_hidden_layers=5   ,							pad_token_id=1   ,							vocab_size=1000   ,							)
        return CLIPTextModel(UpperCamelCase_		)
   @property
   def 		UpperCamelCase  (     self		):
        torch.manual_seed(0		)

        lowercase_       :int     =       12
        lowercase_       :List[Any]     =       12

        lowercase_       :Dict     =       {
            '''attention_bias''': True,
            '''cross_attention_dim''': 32,
            '''attention_head_dim''': height * width,
            '''num_attention_heads''': 1,
            '''num_vector_embeds''': self.num_embed,
            '''num_embeds_ada_norm''': self.num_embeds_ada_norm,
            '''norm_num_groups''': 32,
            '''sample_size''': width,
            '''activation_fn''': '''geglu-approximate''',
        }

        lowercase_       :int     =       TransformeraDModel(**UpperCamelCase_		)
        return model
   def 		UpperCamelCase  (     self		):
        lowercase_       :List[str]     =       '''cpu'''

        lowercase_       :int     =       self.dummy_vqvae
        lowercase_       :int     =       self.dummy_text_encoder
        lowercase_       :Any     =       self.dummy_tokenizer
        lowercase_       :Optional[int]     =       self.dummy_transformer
        lowercase_       :List[str]     =       VQDiffusionScheduler(self.num_embed		)
        lowercase_       :int     =       LearnedClassifierFreeSamplingEmbeddings(learnable=UpperCamelCase_		)

        lowercase_       :List[Any]     =       VQDiffusionPipeline(
            vqvae=UpperCamelCase_   ,							text_encoder=UpperCamelCase_   ,							tokenizer=UpperCamelCase_   ,							transformer=UpperCamelCase_   ,							scheduler=UpperCamelCase_   ,							learned_classifier_free_sampling_embeddings=UpperCamelCase_   ,							)
        lowercase_       :Union[str, Any]     =       pipe.to(UpperCamelCase_		)
        pipe.set_progress_bar_config(disable=UpperCamelCase_		)

        lowercase_       :Dict     =       '''teddy bear playing in the pool'''

        lowercase_       :Dict     =       torch.Generator(device=UpperCamelCase_		).manual_seed(0		)
        lowercase_       :Optional[int]     =       pipe([prompt]   ,							generator=UpperCamelCase_   ,							num_inference_steps=2   ,							output_type='''np'''		)
        lowercase_       :Any     =       output.images

        lowercase_       :Tuple     =       torch.Generator(device=UpperCamelCase_		).manual_seed(0		)
        lowercase_       :str     =       pipe(
            [prompt]   ,							generator=UpperCamelCase_   ,							output_type='''np'''   ,							return_dict=UpperCamelCase_   ,							num_inference_steps=2		)[0]

        lowercase_       :Optional[Any]     =       image[0, -3:, -3:, -1]
        lowercase_       :Tuple     =       image_from_tuple[0, -3:, -3:, -1]

        assert image.shape == (1, 24, 24, 3)

        lowercase_       :str     =       np.array([0.6551, 0.6168, 0.5008, 0.5676, 0.5659, 0.4295, 0.6073, 0.5599, 0.4992]		)

        assert np.abs(image_slice.flatten() - expected_slice		).max() < 1E-2
        assert np.abs(image_from_tuple_slice.flatten() - expected_slice		).max() < 1E-2




   def 		UpperCamelCase  (     self		):
        lowercase_       :int     =       '''cpu'''

        lowercase_       :Dict     =       self.dummy_vqvae
        lowercase_       :str     =       self.dummy_text_encoder
        lowercase_       :List[Any]     =       self.dummy_tokenizer
        lowercase_       :Any     =       self.dummy_transformer
        lowercase_       :Optional[Any]     =       VQDiffusionScheduler(self.num_embed		)
        lowercase_       :List[str]     =       LearnedClassifierFreeSamplingEmbeddings(
            learnable=UpperCamelCase_   ,							hidden_size=self.text_embedder_hidden_size   ,							length=tokenizer.model_max_length		)

        lowercase_       :Optional[int]     =       VQDiffusionPipeline(
            vqvae=UpperCamelCase_   ,							text_encoder=UpperCamelCase_   ,							tokenizer=UpperCamelCase_   ,							transformer=UpperCamelCase_   ,							scheduler=UpperCamelCase_   ,							learned_classifier_free_sampling_embeddings=UpperCamelCase_   ,							)
        lowercase_       :Dict     =       pipe.to(UpperCamelCase_		)
        pipe.set_progress_bar_config(disable=UpperCamelCase_		)

        lowercase_       :int     =       '''teddy bear playing in the pool'''

        lowercase_       :Tuple     =       torch.Generator(device=UpperCamelCase_		).manual_seed(0		)
        lowercase_       :Optional[int]     =       pipe([prompt]   ,							generator=UpperCamelCase_   ,							num_inference_steps=2   ,							output_type='''np'''		)
        lowercase_       :Optional[Any]     =       output.images

        lowercase_       :Optional[int]     =       torch.Generator(device=UpperCamelCase_		).manual_seed(0		)
        lowercase_       :Dict     =       pipe(
            [prompt]   ,							generator=UpperCamelCase_   ,							output_type='''np'''   ,							return_dict=UpperCamelCase_   ,							num_inference_steps=2		)[0]

        lowercase_       :List[str]     =       image[0, -3:, -3:, -1]
        lowercase_       :Optional[int]     =       image_from_tuple[0, -3:, -3:, -1]

        assert image.shape == (1, 24, 24, 3)

        lowercase_       :Dict     =       np.array([0.6693, 0.6075, 0.4959, 0.5701, 0.5583, 0.4333, 0.6171, 0.5684, 0.4988]		)

        assert np.abs(image_slice.flatten() - expected_slice		).max() < 2.0
        assert np.abs(image_from_tuple_slice.flatten() - expected_slice		).max() < 1E-2






@slow
@require_torch_gpu
class      UpperCamelCase					(		unittest.TestCase     ):


   '''simple docstring'''







   def 		UpperCamelCase  (     self		):
        # clean up the VRAM after each test
        super().tearDown()
        gc.collect()
        torch.cuda.empty_cache()




   def 		UpperCamelCase  (     self		):
        lowercase_       :List[str]     =       load_numpy(
            '''https://huggingface.co/datasets/hf-internal-testing/diffusers-images/resolve/main'''
            '''/vq_diffusion/teddy_bear_pool_classifier_free_sampling.npy'''		)

        lowercase_       :int     =       VQDiffusionPipeline.from_pretrained('''microsoft/vq-diffusion-ithq'''		)
        lowercase_       :Tuple     =       pipeline.to(UpperCamelCase_		)
        pipeline.set_progress_bar_config(disable=UpperCamelCase_		)

        # requires GPU generator for gumbel softmax
        # don't use GPU generator in tests though
        lowercase_       :Dict     =       torch.Generator(device=UpperCamelCase_		).manual_seed(0		)
        lowercase_       :int     =       pipeline(
            '''teddy bear playing in the pool'''   ,							num_images_per_prompt=1   ,							generator=UpperCamelCase_   ,							output_type='''np'''   ,							)

        lowercase_       :List[str]     =       output.images[0]

        assert image.shape == (256, 256, 3)
        assert np.abs(expected_image - image		).max() < 2.0

