| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- # Copyright Google AI and 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.
- """Tokenization classes for CANINE."""
- from ...tokenization_python import AddedToken, PreTrainedTokenizer
- from ...utils import logging
- logger = logging.get_logger(__name__)
- # Unicode defines 1,114,112 total “codepoints”
- UNICODE_VOCAB_SIZE = 1114112
- # Below: Constants defining canonical codepoints for special, pseudo-characters.
- # Copied from https://github.com/google-research/language/blob/master/language/canine/special_codepoints.py
- PAD = 0
- CLS = 0xE000
- SEP = 0xE001
- BOS = 0xE002
- MASK = 0xE003
- RESERVED = 0xE004
- # Maps special codepoints to human-readable names.
- SPECIAL_CODEPOINTS: dict[int, str] = {
- # Special symbols are represented using codepoints values that are valid,
- # but designated as "Private Use", meaning that they will never be assigned
- # characters by the Unicode Consortium, and are thus safe for use here.
- #
- # NOTE: Do *NOT* add any sort of [UNK_CHAR] here. They are explicitly
- # excluded and should fail with a hard error.
- CLS: "[CLS]",
- SEP: "[SEP]",
- BOS: "[BOS]",
- MASK: "[MASK]",
- PAD: "[PAD]",
- RESERVED: "[RESERVED]",
- }
- # Maps special codepoint human-readable names to their codepoint values.
- SPECIAL_CODEPOINTS_BY_NAME: dict[str, int] = {name: codepoint for codepoint, name in SPECIAL_CODEPOINTS.items()}
- class CanineTokenizer(PreTrainedTokenizer):
- r"""
- Construct a CANINE tokenizer (i.e. a character splitter). It turns text into a sequence of characters, and then
- converts each character into its Unicode code point.
- [`CanineTokenizer`] inherits from [`PreTrainedTokenizer`].
- Refer to superclass [`PreTrainedTokenizer`] for usage examples and documentation concerning parameters.
- Args:
- model_max_length (`int`, *optional*, defaults to 2048):
- The maximum sentence length the model accepts.
- """
- model_input_names = ["input_ids", "attention_mask", "token_type_ids"]
- def __init__(
- self,
- bos_token=chr(CLS),
- eos_token=chr(SEP),
- sep_token=chr(SEP),
- cls_token=chr(CLS),
- pad_token=chr(PAD),
- mask_token=chr(MASK),
- add_prefix_space=False,
- model_max_length=2048,
- **kwargs,
- ):
- bos_token = AddedToken(bos_token, lstrip=False, rstrip=False) if isinstance(bos_token, str) else bos_token
- eos_token = AddedToken(eos_token, lstrip=False, rstrip=False) if isinstance(eos_token, str) else eos_token
- sep_token = AddedToken(sep_token, lstrip=False, rstrip=False) if isinstance(sep_token, str) else sep_token
- cls_token = AddedToken(cls_token, lstrip=False, rstrip=False) if isinstance(cls_token, str) else cls_token
- pad_token = AddedToken(pad_token, lstrip=False, rstrip=False) if isinstance(pad_token, str) else pad_token
- # Mask token behave like a normal word, i.e. include the space before it
- mask_token = AddedToken(mask_token, lstrip=True, rstrip=False) if isinstance(mask_token, str) else mask_token
- # Creates a mapping for looking up the IDs of special symbols.
- self._special_codepoints: dict[str, int] = {}
- for codepoint, name in SPECIAL_CODEPOINTS.items():
- self._special_codepoints[name] = codepoint
- # Creates a mapping for looking up the string forms of special symbol IDs.
- self._special_codepoint_strings: dict[int, str] = {
- codepoint: name for name, codepoint in self._special_codepoints.items()
- }
- self._unicode_vocab_size = UNICODE_VOCAB_SIZE
- self._num_special_tokens = len(self._special_codepoints)
- super().__init__(
- bos_token=bos_token,
- eos_token=eos_token,
- sep_token=sep_token,
- cls_token=cls_token,
- pad_token=pad_token,
- mask_token=mask_token,
- add_prefix_space=add_prefix_space,
- model_max_length=model_max_length,
- token_type_ids_pattern="all_zeros",
- token_type_ids_include_special_tokens=True,
- special_tokens_pattern="cls_sep",
- **kwargs,
- )
- @property
- def vocab_size(self) -> int:
- return self._unicode_vocab_size
- def get_vocab(self):
- vocab = {chr(i): i for i in range(self.vocab_size)}
- vocab.update(self.added_tokens_encoder)
- return vocab
- def _tokenize(self, text: str) -> list[str]:
- """Tokenize a string (i.e. perform character splitting)."""
- return list(text)
- def _convert_token_to_id(self, token: str) -> int:
- """Converts a token (i.e. a Unicode character) in an id (i.e. its integer Unicode code point value)."""
- try:
- return ord(token)
- except TypeError:
- raise ValueError(f"invalid token: '{token}'")
- def _convert_id_to_token(self, index: int) -> str:
- """
- Converts a Unicode code point (integer) in a token (str). In case it's a special code point, convert to
- human-readable format.
- """
- try:
- if index in SPECIAL_CODEPOINTS:
- return SPECIAL_CODEPOINTS[index]
- return chr(index)
- except TypeError:
- raise ValueError(f"invalid id: {index}")
- def convert_tokens_to_string(self, tokens):
- return "".join(tokens)
- __all__ = ["CanineTokenizer"]
|