from transformers import PreTrainedTokenizer from typing import Dict, List, Optional, Any class ByteTokenizer(PreTrainedTokenizer): model_input_names = ["input_ids", "attention_mask"] def __init__( self, bos_token="<|bos|>", eos_token="<|eos|>", pad_token="<|pad|>", vocab_size=384, **kwargs, ): self.pad_idx = 0 self.bos_idx = 254 self.eos_idx = 255 self._vocab_size = vocab_size self.byte_to_token = [f"" for i in range(256)] self.token_to_byte = {t: i for i, t in enumerate(self.byte_to_token)} super().__init__( bos_token=bos_token, eos_token=eos_token, pad_token=pad_token, **kwargs, ) @property def vocab_size(self) -> int: return self._vocab_size def get_vocab(self) -> Dict[str, int]: vocab = {t: i for i, t in enumerate(self.byte_to_token)} vocab.update( { self.bos_token: self.bos_idx, self.eos_token: self.eos_idx, self.pad_token: self.pad_idx, } ) return vocab def _tokenize(self, text, **kwargs): return [self.byte_to_token[b] for b in text.encode("utf-8")] def _convert_token_to_id(self, token): if token == self.bos_token: return self.bos_idx if token == self.eos_token: return self.eos_idx if token == self.pad_token: return self.pad_idx return self.token_to_byte.get(token, self.pad_idx) def _convert_id_to_token(self, index): if index == self.bos_idx: return self.bos_token if index == self.eos_idx: return self.eos_token if index == self.pad_idx: return self.pad_token if 0 <= index < 256: return self.byte_to_token[index] return f"" def build_inputs_with_special_tokens(self, token_ids_0, token_ids_1=None): return [self.bos_idx] + token_ids_0 + [self.eos_idx] def _decode( self, token_ids: List[int], skip_special_tokens: bool = False, **kwargs ) -> str: clean_ids = [] for i in token_ids: if skip_special_tokens and i in [self.bos_idx, self.eos_idx, self.pad_idx]: continue if 0 <= i < 256: clean_ids.append(i) return bytes(clean_ids).decode("utf-8", errors="ignore") def save_vocabulary( self, save_directory: str, filename_prefix: Optional[str] = None ) -> tuple: return () __all__ = [ "ByteTokenizer", ]