



import os
import re
from shutil import copyfile
from typing import List, Optional, Tuple

from ...tokenization_utils import PreTrainedTokenizer
from ...utils import logging


lowercase_	       =			logging.get_logger(__name__)

lowercase_	       =			{
    '''vocab_file''': '''vocab.txt''',
    '''merges_file''': '''bpe.codes''',
}

lowercase_	       =			{
    '''vocab_file''': {
        '''vinai/phobert-base''': '''https://huggingface.co/vinai/phobert-base/resolve/main/vocab.txt''',
        '''vinai/phobert-large''': '''https://huggingface.co/vinai/phobert-large/resolve/main/vocab.txt''',
    },
    '''merges_file''': {
        '''vinai/phobert-base''': '''https://huggingface.co/vinai/phobert-base/resolve/main/bpe.codes''',
        '''vinai/phobert-large''': '''https://huggingface.co/vinai/phobert-large/resolve/main/bpe.codes''',
    },
}

lowercase_	       =			{
    '''vinai/phobert-base''': 2_56,
    '''vinai/phobert-large''': 2_56,
}






def 					__lowerCAmelCase		(  __lowerCamelCase	:    List[Any]	)  ->						List[Any]:
					__lowerCAmelCase	   =set()
					__lowerCAmelCase	   =word[0]
					for char in word[1:]:
										pairs.add((prev_char, char)	)
										__lowerCAmelCase	   =char

					__lowerCAmelCase	   =set(_snake_case	)
					return pairs






class 						__a (     __UpperCAmelCase				):
	SCREAMING_SNAKE_CASE       =       VOCAB_FILES_NAMES
	SCREAMING_SNAKE_CASE       =       PRETRAINED_VOCAB_FILES_MAP
	SCREAMING_SNAKE_CASE       =       PRETRAINED_POSITIONAL_EMBEDDINGS_SIZES






	def __init__(						self							:    Optional[Any]				,	snake_case_							:    Dict				,	snake_case_							:    Tuple				,	snake_case_							:    int="<s>"				,	snake_case_							:    Dict="</s>"				,	snake_case_							:    List[Any]="</s>"				,	snake_case_							:    Dict="<s>"				,	snake_case_							:    Union[str, Any]="<unk>"				,	snake_case_							:    List[Any]="<pad>"				,	snake_case_							:    int="<mask>"				,	**snake_case_							:    List[Any]				,	)->							Any:
						super().__init__(
						    bos_token=UpperCAmelCase_				,	eos_token=UpperCAmelCase_				,	unk_token=UpperCAmelCase_				,	sep_token=UpperCAmelCase_				,	cls_token=UpperCAmelCase_				,	pad_token=UpperCAmelCase_				,	mask_token=UpperCAmelCase_				,	**UpperCAmelCase_				,	)

						__lowerCAmelCase	   =vocab_file
						__lowerCAmelCase	   =merges_file

						__lowerCAmelCase	   ={}
						__lowerCAmelCase	   =0
						__lowerCAmelCase	   =1
						__lowerCAmelCase	   =2
						__lowerCAmelCase	   =3

						self.add_from_file(UpperCAmelCase_)

						__lowerCAmelCase	   ={v: k for k, v in self.encoder.items()}

						with open(UpperCAmelCase_				,	encoding="""utf-8""") as merges_handle:
											__lowerCAmelCase	   =merges_handle.read().split("""\n""")[:-1]
						__lowerCAmelCase	   =[tuple(merge.split()[:-1]) for merge in merges]
						__lowerCAmelCase	   =dict(zip(UpperCAmelCase_				,	range(len(UpperCAmelCase_))))
						__lowerCAmelCase	   ={}






	def 		UpperCamelCase							(						self							:    Union[str, Any]				,	snake_case_							:    List[Any]				,	snake_case_							:    Union[str, Any] = None)->							int:

						if token_ids_a is None:
											return [self.cls_token_id] + token_ids_a + [self.sep_token_id]
						__lowerCAmelCase	   =[self.cls_token_id]
						__lowerCAmelCase	   =[self.sep_token_id]
						return cls + token_ids_a + sep + sep + token_ids_a + sep






	def 		UpperCamelCase							(						self							:    str				,	snake_case_							:    Tuple				,	snake_case_							:    List[Any] = None				,	snake_case_							:    str = False)->							str:

						if already_has_special_tokens:
											return super().get_special_tokens_mask(
											    token_ids_a=UpperCAmelCase_				,	token_ids_a=UpperCAmelCase_				,	already_has_special_tokens=UpperCAmelCase_)

						if token_ids_a is None:
											return [1] + ([0] * len(UpperCAmelCase_)) + [1]
						return [1] + ([0] * len(UpperCAmelCase_)) + [1, 1] + ([0] * len(UpperCAmelCase_)) + [1]






	def 		UpperCamelCase							(						self							:    List[str]				,	snake_case_							:    Any				,	snake_case_							:    Optional[int] = None)->							Optional[int]:
						__lowerCAmelCase	   =[self.sep_token_id]
						__lowerCAmelCase	   =[self.cls_token_id]

						if token_ids_a is None:
											return len(cls + token_ids_a + sep) * [0]
						return len(cls + token_ids_a + sep + sep + token_ids_a + sep) * [0]






	@property
	def 		UpperCamelCase							(						self							:    List[Any])->							Tuple:
						return len(self.encoder)






	def 		UpperCamelCase							(						self							:    List[str])->							Any:
						return dict(self.encoder				,	**self.added_tokens_encoder)






	def 		UpperCamelCase							(						self							:    List[Any]				,	snake_case_							:    List[str])->							List[str]:
						if token in self.cache:
											return self.cache[token]
						__lowerCAmelCase	   =tuple(UpperCAmelCase_)
						__lowerCAmelCase	   =tuple(list(word[:-1]) + [word[-1] + """</w>"""])
						__lowerCAmelCase	   =get_pairs(UpperCAmelCase_)

						if not pairs:
											return token

						while True:
											__lowerCAmelCase	   =min(UpperCAmelCase_				,	key=lambda snake_case_: self.bpe_ranks.get(UpperCAmelCase_				,	float("""inf""")))
											if bigram not in self.bpe_ranks:
																break
											__lowerCAmelCase   ,	__lowerCAmelCase	   =bigram
											__lowerCAmelCase	   =[]
											__lowerCAmelCase	   =0
											while i < len(UpperCAmelCase_):
																try:
																					__lowerCAmelCase	   =word.index(UpperCAmelCase_				,	UpperCAmelCase_)
																except ValueError:
																					new_word.extend(word[i:])
																					break
																else:
																					new_word.extend(word[i:j])
																					__lowerCAmelCase	   =j

																if word[i] == first and i < len(UpperCAmelCase_) - 1 and word[i + 1] == second:
																					new_word.append(first + second)
																					i += 2
																else:
																					new_word.append(word[i])
																					i += 1
											__lowerCAmelCase	   =tuple(UpperCAmelCase_)
											__lowerCAmelCase	   =new_word
											if len(UpperCAmelCase_) == 1:
																break
											else:
																__lowerCAmelCase	   =get_pairs(UpperCAmelCase_)
						__lowerCAmelCase	   ="""@@ """.join(UpperCAmelCase_)
						__lowerCAmelCase	   =word[:-4]
						__lowerCAmelCase	   =word
						return word






	def 		UpperCamelCase							(						self							:    List[Any]				,	snake_case_							:    Any)->							Optional[Any]:
						__lowerCAmelCase	   =[]

						__lowerCAmelCase	   =re.findall(R"""\S+\n?"""				,	UpperCAmelCase_)

						for token in words:
											split_tokens.extend(list(self.bpe(UpperCAmelCase_).split(""" """)))
						return split_tokens






	def 		UpperCamelCase							(						self							:    Any				,	snake_case_							:    List[str])->							Any:
						return self.encoder.get(UpperCAmelCase_				,	self.encoder.get(self.unk_token))






	def 		UpperCamelCase							(						self							:    Union[str, Any]				,	snake_case_							:    Tuple)->							List[str]:
						return self.decoder.get(UpperCAmelCase_				,	self.unk_token)






	def 		UpperCamelCase							(						self							:    int				,	snake_case_							:    Optional[Any])->							Union[str, Any]:
						__lowerCAmelCase	   =""" """.join(UpperCAmelCase_).replace("""@@ """				,	"""""").strip()
						return out_string






	def 		UpperCamelCase							(						self							:    Dict				,	snake_case_							:    Optional[int]				,	snake_case_							:    Dict = None)->							Dict:
						if not os.path.isdir(UpperCAmelCase_):
											logger.error(F"""Vocabulary path ({save_directory}) should be a directory""")
											return
						__lowerCAmelCase	   =os.path.join(
						    UpperCAmelCase_				,	(filename_prefix + """-""" if filename_prefix else """""") + VOCAB_FILES_NAMES["""vocab_file"""])
						__lowerCAmelCase	   =os.path.join(
						    UpperCAmelCase_				,	(filename_prefix + """-""" if filename_prefix else """""") + VOCAB_FILES_NAMES["""merges_file"""])

						if os.path.abspath(self.vocab_file) != os.path.abspath(UpperCAmelCase_):
											copyfile(self.vocab_file				,	UpperCAmelCase_)

						if os.path.abspath(self.merges_file) != os.path.abspath(UpperCAmelCase_):
											copyfile(self.merges_file				,	UpperCAmelCase_)

						return out_vocab_file, out_merge_file






	def 		UpperCamelCase							(						self							:    Dict				,	snake_case_							:    List[str])->							List[Any]:
						if isinstance(UpperCAmelCase_				,	UpperCAmelCase_):
											try:
																with open(UpperCAmelCase_				,	"""r"""				,	encoding="""utf-8""") as fd:
																					self.add_from_file(UpperCAmelCase_)
											except FileNotFoundError as fnfe:
																raise fnfe
											except UnicodeError:
																raise Exception(F"""Incorrect encoding detected in {f}, please rebuild the dataset""")
											return

						__lowerCAmelCase	   =f.readlines()
						for lineTmp in lines:
											__lowerCAmelCase	   =lineTmp.strip()
											__lowerCAmelCase	   =line.rfind(""" """)
											if idx == -1:
																raise ValueError("""Incorrect dictionary format, expected \'<token> <cnt>\'""")
											__lowerCAmelCase	   =line[:idx]
											__lowerCAmelCase	   =len(self.encoder)









from dataclasses import asdict, dataclass
from typing import Optional

from ...configuration_utils import PretrainedConfig
from ...utils import logging


lowercase_	       =			logging.get_logger(__name__)

# TODO Update this
lowercase_	       =			{
    '''facebook/esm-1b''': '''https://huggingface.co/facebook/esm-1b/resolve/main/config.json''',
    # See all ESM models at https://huggingface.co/models?filter=esm
}






class 						__a (     SCREAMING_SNAKE_CASE				):
	SCREAMING_SNAKE_CASE       =       "esm"



	def __init__(						self							:    Any				,	snake_case_							:    List[str]=None				,	snake_case_							:    Tuple=None				,	snake_case_							:    str=None				,	snake_case_							:    str=7_68				,	snake_case_							:    Optional[int]=12				,	snake_case_							:    Tuple=12				,	snake_case_							:    Dict=30_72				,	snake_case_							:    Optional[Any]=0.1				,	snake_case_							:    Dict=0.1				,	snake_case_							:    Optional[Any]=10_26				,	snake_case_							:    int=0.0_2				,	snake_case_							:    Any=1e-12				,	snake_case_							:    Union[str, Any]="absolute"				,	snake_case_							:    Optional[int]=True				,	snake_case_							:    Tuple=None				,	snake_case_							:    Optional[int]=False				,	snake_case_							:    int=False				,	snake_case_							:    Optional[int]=None				,	snake_case_							:    List[Any]=None				,	**snake_case_							:    Optional[int]				,	)->							Any:
						super().__init__(pad_token_id=snake_case_				,	mask_token_id=snake_case_				,	**snake_case_)

						__lowerCAmelCase	   =vocab_size
						__lowerCAmelCase	   =hidden_size
						__lowerCAmelCase	   =num_hidden_layers
						__lowerCAmelCase	   =num_attention_heads
						__lowerCAmelCase	   =intermediate_size
						__lowerCAmelCase	   =hidden_dropout_prob
						__lowerCAmelCase	   =attention_probs_dropout_prob
						__lowerCAmelCase	   =max_position_embeddings
						__lowerCAmelCase	   =initializer_range
						__lowerCAmelCase	   =layer_norm_eps
						__lowerCAmelCase	   =position_embedding_type
						__lowerCAmelCase	   =use_cache
						__lowerCAmelCase	   =emb_layer_norm_before
						__lowerCAmelCase	   =token_dropout
						__lowerCAmelCase	   =is_folding_model
						if is_folding_model:
											if esmfold_config is None:
																logger.info("""No esmfold_config supplied for folding model, using default values.""")
																__lowerCAmelCase	   =EsmFoldConfig()
											elif isinstance(snake_case_				,	snake_case_):
																__lowerCAmelCase	   =EsmFoldConfig(**snake_case_)
											__lowerCAmelCase	   =esmfold_config
											if vocab_list is None:
																logger.warning("""No vocab_list supplied for folding model, assuming the ESM-2 vocabulary!""")
																__lowerCAmelCase	   =get_default_vocab_list()
											else:
																__lowerCAmelCase	   =vocab_list
						else:
											__lowerCAmelCase	   =None
											__lowerCAmelCase	   =None
						if self.esmfold_config is not None and getattr(self.esmfold_config				,	"""use_esm_attn_map"""				,	snake_case_):
											raise ValueError("""The HuggingFace port of ESMFold does not support use_esm_attn_map at this time!""")



	def 		UpperCamelCase							(						self							:    Dict)->							Union[str, Any]:
						__lowerCAmelCase	   =super().to_dict()
						if isinstance(self.esmfold_config				,	snake_case_):
											__lowerCAmelCase	   =self.esmfold_config.to_dict()
						return output






@dataclass
class 						__a :
	SCREAMING_SNAKE_CASE       =       None
	SCREAMING_SNAKE_CASE       =       True
	SCREAMING_SNAKE_CASE       =       False
	SCREAMING_SNAKE_CASE       =       False
	SCREAMING_SNAKE_CASE       =       False
	SCREAMING_SNAKE_CASE       =       0

	SCREAMING_SNAKE_CASE       =       True
	SCREAMING_SNAKE_CASE       =       False

	SCREAMING_SNAKE_CASE       =       128
	SCREAMING_SNAKE_CASE       =       None



	def 		UpperCamelCase							(						self							:    Dict)->							List[Any]:
						if self.trunk is None:
											__lowerCAmelCase	   =TrunkConfig()
						elif isinstance(self.trunk				,	snake_case_):
											__lowerCAmelCase	   =TrunkConfig(**self.trunk)



	def 		UpperCamelCase							(						self							:    Optional[Any])->							int:
						__lowerCAmelCase	   =asdict(self)
						__lowerCAmelCase	   =self.trunk.to_dict()
						return output






@dataclass
class 						__a :
	SCREAMING_SNAKE_CASE       =       48
	SCREAMING_SNAKE_CASE       =       1024
	SCREAMING_SNAKE_CASE       =       128
	SCREAMING_SNAKE_CASE       =       32
	SCREAMING_SNAKE_CASE       =       32
	SCREAMING_SNAKE_CASE       =       32
	SCREAMING_SNAKE_CASE       =       0
	SCREAMING_SNAKE_CASE       =       0
	SCREAMING_SNAKE_CASE       =       False
	SCREAMING_SNAKE_CASE       =       4
	SCREAMING_SNAKE_CASE       =       128
	SCREAMING_SNAKE_CASE       =       None



	def 		UpperCamelCase							(						self							:    Tuple)->							Optional[int]:
						if self.structure_module is None:
											__lowerCAmelCase	   =StructureModuleConfig()
						elif isinstance(self.structure_module				,	snake_case_):
											__lowerCAmelCase	   =StructureModuleConfig(**self.structure_module)

						if self.max_recycles <= 0:
											raise ValueError(F"""`max_recycles` should be positive, got {self.max_recycles}.""")
						if self.sequence_state_dim % self.sequence_state_dim != 0:
											raise ValueError(
											    """`sequence_state_dim` should be a round multiple of `sequence_state_dim`, got"""
											    F""" {self.sequence_state_dim} and {self.sequence_state_dim}.""")
						if self.pairwise_state_dim % self.pairwise_state_dim != 0:
											raise ValueError(
											    """`pairwise_state_dim` should be a round multiple of `pairwise_state_dim`, got"""
											    F""" {self.pairwise_state_dim} and {self.pairwise_state_dim}.""")

						__lowerCAmelCase	   =self.sequence_state_dim // self.sequence_head_width
						__lowerCAmelCase	   =self.pairwise_state_dim // self.pairwise_head_width

						if self.sequence_state_dim != sequence_num_heads * self.sequence_head_width:
											raise ValueError(
											    """`sequence_state_dim` should be equal to `sequence_num_heads * sequence_head_width, got"""
											    F""" {self.sequence_state_dim} != {sequence_num_heads} * {self.sequence_head_width}.""")
						if self.pairwise_state_dim != pairwise_num_heads * self.pairwise_head_width:
											raise ValueError(
											    """`pairwise_state_dim` should be equal to `pairwise_num_heads * pairwise_head_width, got"""
											    F""" {self.pairwise_state_dim} != {pairwise_num_heads} * {self.pairwise_head_width}.""")
						if self.pairwise_state_dim % 2 != 0:
											raise ValueError(F"""`pairwise_state_dim` should be even, got {self.pairwise_state_dim}.""")

						if self.dropout >= 0.4:
											raise ValueError(F"""`dropout` should not be greater than 0.4, got {self.dropout}.""")



	def 		UpperCamelCase							(						self							:    Dict)->							Any:
						__lowerCAmelCase	   =asdict(self)
						__lowerCAmelCase	   =self.structure_module.to_dict()
						return output






@dataclass
class 						__a :
	SCREAMING_SNAKE_CASE       =       384
	SCREAMING_SNAKE_CASE       =       128
	SCREAMING_SNAKE_CASE       =       16
	SCREAMING_SNAKE_CASE       =       128
	SCREAMING_SNAKE_CASE       =       12
	SCREAMING_SNAKE_CASE       =       4
	SCREAMING_SNAKE_CASE       =       8
	SCREAMING_SNAKE_CASE       =       0.1
	SCREAMING_SNAKE_CASE       =       8
	SCREAMING_SNAKE_CASE       =       1
	SCREAMING_SNAKE_CASE       =       2
	SCREAMING_SNAKE_CASE       =       7
	SCREAMING_SNAKE_CASE       =       10
	SCREAMING_SNAKE_CASE       =       1E-8
	SCREAMING_SNAKE_CASE       =       1E5



	def 		UpperCamelCase							(						self							:    Any)->							Tuple:
						return asdict(self)






def 					__lowerCAmelCase		(  )  ->						List[Any]:
					return (
					    "<cls>",
					    "<pad>",
					    "<eos>",
					    "<unk>",
					    "L",
					    "A",
					    "G",
					    "V",
					    "S",
					    "E",
					    "R",
					    "T",
					    "I",
					    "D",
					    "P",
					    "K",
					    "Q",
					    "N",
					    "F",
					    "Y",
					    "M",
					    "H",
					    "W",
					    "C",
					    "X",
					    "B",
					    "U",
					    "Z",
					    "O",
					    ".",
					    "-",
					    "<null_1>",
					    "<mask>",
					)




