import numpy as np
import torch
import torch.nn as nn
from transformers import CLIPConfig, CLIPVisionModel, PreTrainedModel

from ...utils import logging


lowerCAmelCase__      		=					logging.get_logger(__name__)






def  __lowerCamelCase						(		lowerCAmelCase__      ,    lowerCAmelCase__      ):
       lowerCAmelCase__	      =   nn.functional.normalize(lowerCAmelCase__      )
       lowerCAmelCase__	      =   nn.functional.normalize(lowerCAmelCase__      )
       return torch.mm(lowerCAmelCase__      ,    normalized_text_embeds.t()      )



class 							a_					(		SCREAMING_SNAKE_CASE		):






 '''simple docstring'''






 UpperCAmelCase_      					=   CLIPConfig

 UpperCAmelCase_      					=   ['CLIPEncoderLayer']




 def __init__(     self   :    int     ,       lowercase__   :    CLIPConfig):







        '''simple docstring'''



        super().__init__(lowercase__)

        lowerCAmelCase__	      =   CLIPVisionModel(config.vision_config)
        lowerCAmelCase__	      =   nn.Linear(config.vision_config.hidden_size     ,       config.projection_dim     ,       bias=lowercase__)

        lowerCAmelCase__	      =   nn.Parameter(torch.ones(17     ,       config.projection_dim)     ,       requires_grad=lowercase__)
        lowerCAmelCase__	      =   nn.Parameter(torch.ones(3     ,       config.projection_dim)     ,       requires_grad=lowercase__)

        lowerCAmelCase__	      =   nn.Parameter(torch.ones(17)     ,       requires_grad=lowercase__)
        lowerCAmelCase__	      =   nn.Parameter(torch.ones(3)     ,       requires_grad=lowercase__)




 @torch.no_grad()
 def 						__snake_case		(     self   :    int     ,       lowercase__   :    List[str]     ,       lowercase__   :    Union[str, Any]):







        '''simple docstring'''



        lowerCAmelCase__	      =   self.vision_model(lowercase__)[1]  # pooled_output
        lowerCAmelCase__	      =   self.visual_projection(lowercase__)

        # we always cast to float32 as this does not cause significant overhead and is compatible with bfloat16
        lowerCAmelCase__	      =   cosine_distance(lowercase__     ,       self.special_care_embeds).cpu().float().numpy()
        lowerCAmelCase__	      =   cosine_distance(lowercase__     ,       self.concept_embeds).cpu().float().numpy()

        lowerCAmelCase__	      =   []
        lowerCAmelCase__	      =   image_embeds.shape[0]
        for i in range(lowercase__):
               lowerCAmelCase__	      =   {'special_scores': {}, 'special_care': [], 'concept_scores': {}, 'bad_concepts': []}

               # increase this value to create a stronger `nfsw` filter
               # at the cost of increasing the possibility of filtering benign images
               lowerCAmelCase__	      =   0.0

               for concept_idx in range(len(special_cos_dist[0])):
                      lowerCAmelCase__	      =   special_cos_dist[i][concept_idx]
                      lowerCAmelCase__	      =   self.special_care_embeds_weights[concept_idx].item()
                      lowerCAmelCase__	      =   round(concept_cos - concept_threshold + adjustment     ,       3)
                      if result_img["special_scores"][concept_idx] > 0:
                             result_img["special_care"].append({concept_idx, result_img['special_scores'][concept_idx]})
                             lowerCAmelCase__	      =   0.01

               for concept_idx in range(len(cos_dist[0])):
                      lowerCAmelCase__	      =   cos_dist[i][concept_idx]
                      lowerCAmelCase__	      =   self.concept_embeds_weights[concept_idx].item()
                      lowerCAmelCase__	      =   round(concept_cos - concept_threshold + adjustment     ,       3)
                      if result_img["concept_scores"][concept_idx] > 0:
                             result_img["bad_concepts"].append(lowercase__)

               result.append(lowercase__)

        lowerCAmelCase__	      =   [len(res['bad_concepts']) > 0 for res in result]

        for idx, has_nsfw_concept in enumerate(lowercase__):
               if has_nsfw_concept:
                      if torch.is_tensor(lowercase__) or torch.is_tensor(images[0]):
                             lowerCAmelCase__	      =   torch.zeros_like(images[idx])  # black image
                      else:
                             lowerCAmelCase__	      =   np.zeros(images[idx].shape)  # black image

        if any(lowercase__):
               logger.warning(
                   'Potential NSFW content was detected in one or more images. A black image will be returned instead.'
                   ' Try again with a different prompt and/or seed.')

        return images, has_nsfw_concepts




 @torch.no_grad()
 def 						__snake_case		(     self   :    Dict     ,       lowercase__   :    torch.FloatTensor     ,       lowercase__   :    torch.FloatTensor):







        '''simple docstring'''



        lowerCAmelCase__	      =   self.vision_model(lowercase__)[1]  # pooled_output
        lowerCAmelCase__	      =   self.visual_projection(lowercase__)

        lowerCAmelCase__	      =   cosine_distance(lowercase__     ,       self.special_care_embeds)
        lowerCAmelCase__	      =   cosine_distance(lowercase__     ,       self.concept_embeds)

        # increase this value to create a stronger `nsfw` filter
        # at the cost of increasing the possibility of filtering benign images
        lowerCAmelCase__	      =   0.0

        lowerCAmelCase__	      =   special_cos_dist - self.special_care_embeds_weights + adjustment
        # special_scores = special_scores.round(decimals=3)
        lowerCAmelCase__	      =   torch.any(special_scores > 0     ,       dim=1)
        lowerCAmelCase__	      =   special_care * 0.01
        lowerCAmelCase__	      =   special_adjustment.unsqueeze(1).expand(-1     ,       cos_dist.shape[1])

        lowerCAmelCase__	      =   (cos_dist - self.concept_embeds_weights) + special_adjustment
        # concept_scores = concept_scores.round(decimals=3)
        lowerCAmelCase__	      =   torch.any(concept_scores > 0     ,       dim=1)

        lowerCAmelCase__	      =   0.0  # black image

        return images, has_nsfw_concepts

import unittest

from cer import CER


lowerCAmelCase__      		=					CER()
class 							a_					(		unittest.TestCase		):






 '''simple docstring'''






 def 						__snake_case		(     self   :    Any):







        '''simple docstring'''



        lowerCAmelCase__	      =   ['White House']
        lowerCAmelCase__	      =   ['white house']
        # S = 2, D = 0, I = 0, N = 11, CER = 2 / 11
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__)
        self.assertTrue(abs(char_error_rate - 0.1_818_181_818) < 1e-6)




 def 						__snake_case		(     self   :    List[Any]):







        '''simple docstring'''



        lowerCAmelCase__	      =   ['were wolf']
        lowerCAmelCase__	      =   ['werewolf']
        # S = 0, D = 0, I = 1, N = 9, CER = 1 / 9
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__)
        self.assertTrue(abs(char_error_rate - 0.1_111_111) < 1e-6)

        lowerCAmelCase__	      =   ['werewolf']
        lowerCAmelCase__	      =   ['weae     wolf']
        # S = 1, D = 1, I = 0, N = 8, CER = 0.25
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__)
        self.assertTrue(abs(char_error_rate - 0.25) < 1e-6)

        # consecutive whitespaces case 1
        lowerCAmelCase__	      =   ['were wolf']
        lowerCAmelCase__	      =   ['were               wolf']
        # S = 0, D = 0, I = 0, N = 9, CER = 0
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__)
        self.assertTrue(abs(char_error_rate - 0.0) < 1e-6)

        # consecutive whitespaces case 2
        lowerCAmelCase__	      =   ['were   wolf']
        lowerCAmelCase__	      =   ['were               wolf']
        # S = 0, D = 0, I = 0, N = 9, CER = 0
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__)
        self.assertTrue(abs(char_error_rate - 0.0) < 1e-6)




 def 						__snake_case		(     self   :    Optional[Any]):







        '''simple docstring'''



        lowerCAmelCase__	      =   ['werewolf']
        lowerCAmelCase__	      =   ['weaewolf']
        # S = 1, D = 0, I = 0, N = 8, CER = 0.125
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__)
        self.assertTrue(abs(char_error_rate - 0.125) < 1e-6)




 def 						__snake_case		(     self   :    Tuple):







        '''simple docstring'''



        lowerCAmelCase__	      =   ['werewolf']
        lowerCAmelCase__	      =   ['wereawolf']
        # S = 0, D = 1, I = 0, N = 8, CER = 0.125
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__)
        self.assertTrue(abs(char_error_rate - 0.125) < 1e-6)




 def 						__snake_case		(     self   :    Optional[int]):







        '''simple docstring'''



        lowerCAmelCase__	      =   ['werewolf']
        lowerCAmelCase__	      =   ['wereolf']
        # S = 0, D = 0, I = 1, N = 8, CER = 0.125
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__)
        self.assertTrue(abs(char_error_rate - 0.125) < 1e-6)




 def 						__snake_case		(     self   :    str):







        '''simple docstring'''



        lowerCAmelCase__	      =   ['werewolf']
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__)
        self.assertEqual(lowercase__     ,       0.0)




 def 						__snake_case		(     self   :    Tuple):







        '''simple docstring'''



        lowerCAmelCase__	      =   ['werewolf', 'I am your father']
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__)
        self.assertEqual(lowercase__     ,       0.0)

        lowerCAmelCase__	      =   ['werewolf', 'I am your father', 'doge']
        lowerCAmelCase__	      =   ['werxwolf', 'I       am your father', 'doge']
        # S = 1, D = 0, I = 0, N = 28, CER = 1 / 28
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__)
        self.assertTrue(abs(char_error_rate - 0.03_571_428) < 1e-6)




 def 						__snake_case		(     self   :    Tuple):







        '''simple docstring'''



        lowerCAmelCase__	      =   ['My hovercraft', 'is full of eels']
        lowerCAmelCase__	      =   ['My hovercraft is full', ' of eels']
        # S = 0, D = 0, I = 2, N = 28, CER = 2 / 28
        # whitespace at the front of " of eels" will be strip during preporcessing
        # so need to insert 2 whitespaces
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__     ,       concatenate_texts=lowercase__)
        self.assertTrue(abs(char_error_rate - 0.071_428) < 1e-6)




 def 						__snake_case		(     self   :    Dict):







        '''simple docstring'''



        lowerCAmelCase__	      =   ['我能吞下玻璃而不伤身体']
        lowerCAmelCase__	      =   [' 能吞虾玻璃而 不霜身体啦']
        # S = 3, D = 2, I = 0, N = 11, CER = 5 / 11
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__)
        self.assertTrue(abs(char_error_rate - 0.4_545_454_545) < 1e-6)

        lowerCAmelCase__	      =   ['我能吞下玻璃', '而不伤身体']
        lowerCAmelCase__	      =   ['我    能 吞 下 玻 璃', '而不伤身体']
        # S = 0, D = 5, I = 0, N = 11, CER = 5 / 11
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__)
        self.assertTrue(abs(char_error_rate - 0.454_545_454_545) < 1e-6)

        lowerCAmelCase__	      =   ['我能吞下玻璃而不伤身体']
        lowerCAmelCase__	      =   cer.compute(predictions=lowercase__     ,       references=lowercase__)
        self.assertFalse(lowercase__     ,       0.0)




 def 						__snake_case		(     self   :    Dict):







        '''simple docstring'''



        lowerCAmelCase__	      =   ['']
        lowerCAmelCase__	      =   ['Hypothesis']
        with self.assertRaises(lowercase__):
               cer.compute(predictions=lowercase__     ,       references=lowercase__)


if __name__ == "__main__":
    unittest.main()
