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

from ...utils import logging


a_							=      logging.get_logger(__name__)




def       __lowerCAmelCase      (						A_   : Optional[int]						,	A_   : Any					)    ->  int:
  __UpperCAmelCase						    =       nn.functional.normalize(__SCREAMING_SNAKE_CASE					)
  __UpperCAmelCase						    =       nn.functional.normalize(__SCREAMING_SNAKE_CASE					)
  return torch.mm(__SCREAMING_SNAKE_CASE						,	normalized_text_embeds.t()					)





class 			UpperCAmelCase__    (		lowercase__					):



  """simple docstring"""






  lowerCAmelCase__		:	Any    		= CLIPConfig

  lowerCAmelCase__		:	List[Any]    		= ['CLIPEncoderLayer']






  def __init__(				self:			List[Any]				,				__lowerCAmelCase:			Any   ) -> Dict:




    '''simple docstring'''




    super().__init__(__lowerCAmelCase   )

    __UpperCAmelCase						    =       CLIPVisionModel(config.vision_config   )
    __UpperCAmelCase						    =       nn.Linear(config.vision_config.hidden_size				,				config.projection_dim				,				bias=__lowerCAmelCase   )

    __UpperCAmelCase						    =       nn.Parameter(torch.ones(17				,				config.projection_dim   )				,				requires_grad=__lowerCAmelCase   )
    __UpperCAmelCase						    =       nn.Parameter(torch.ones(3				,				config.projection_dim   )				,				requires_grad=__lowerCAmelCase   )

    __UpperCAmelCase						    =       nn.Parameter(torch.ones(17   )				,				requires_grad=__lowerCAmelCase   )
    __UpperCAmelCase						    =       nn.Parameter(torch.ones(3   )				,				requires_grad=__lowerCAmelCase   )






  @torch.no_grad()
  def 	_UpperCAmelCase				(				self:			str				,				__lowerCAmelCase:			Tuple				,				__lowerCAmelCase:			List[str]   ) -> int:




    '''simple docstring'''




    __UpperCAmelCase						    =       self.vision_model(__lowerCAmelCase   )[1]  # pooled_output
    __UpperCAmelCase						    =       self.visual_projection(__lowerCAmelCase   )

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

    __UpperCAmelCase						    =       []
    __UpperCAmelCase						    =       image_embeds.shape[0]
    for i in range(__lowerCAmelCase   ):
      __UpperCAmelCase						    =       {"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
      __UpperCAmelCase						    =       0.0

      for concept_idx in range(len(special_cos_dist[0]   )   ):
        __UpperCAmelCase						    =       special_cos_dist[i][concept_idx]
        __UpperCAmelCase						    =       self.special_care_embeds_weights[concept_idx].item()
        __UpperCAmelCase						    =       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]}   )
          __UpperCAmelCase						    =       0.01

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

      result.append(__lowerCAmelCase   )

    __UpperCAmelCase						    =       [len(res["bad_concepts"]   ) > 0 for res in result]

    return images, has_nsfw_concepts






  @torch.no_grad()
  def 	_UpperCAmelCase				(				self:			Optional[Any]				,				__lowerCAmelCase:			int				,				__lowerCAmelCase:			List[Any]   ) -> Tuple:




    '''simple docstring'''




    __UpperCAmelCase						    =       self.vision_model(__lowerCAmelCase   )[1]  # pooled_output
    __UpperCAmelCase						    =       self.visual_projection(__lowerCAmelCase   )

    __UpperCAmelCase						    =       cosine_distance(__lowerCAmelCase				,				self.special_care_embeds   )
    __UpperCAmelCase						    =       cosine_distance(__lowerCAmelCase				,				self.concept_embeds   )

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

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

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

    return images, has_nsfw_concepts




from abc import ABC, abstractmethod
from argparse import ArgumentParser


class 			UpperCAmelCase__    (		snake_case					):



  """simple docstring"""






  @staticmethod
  @abstractmethod
  def 	_UpperCAmelCase				(				__lowerCAmelCase:			ArgumentParser   ) -> Tuple:




    '''simple docstring'''




    raise NotImplementedError()






  @abstractmethod
  def 	_UpperCAmelCase				(				self:			List[str]   ) -> List[Any]:




    '''simple docstring'''




    raise NotImplementedError()



