Team Ai
Modelpublic

codefuse-ai/CodeFuse-DevOps-Model-7B-Chat

sourceHugging Faceotherupdated 2y agoView on Hugging Face
10likes21downloads
tokenization_qwen.py229 linesDownload Raw Back to root
1# Copyright (c) Alibaba Cloud.2#3# This source code is licensed under the license found in the4# LICENSE file in the root directory of this source tree.5 6"""Tokenization classes for QWen."""7 8import base649import logging10import os11import unicodedata12from typing import Collection, Dict, List, Set, Tuple, Union13 14import tiktoken15from transformers import PreTrainedTokenizer, AddedToken16 17logger = logging.getLogger(__name__)18 19 20VOCAB_FILES_NAMES = {"vocab_file": "qwen.tiktoken"}21 22PAT_STR = r"""(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}| ?[^\s\p{L}\p{N}]+[\r\n]*|\s*[\r\n]+|\s+(?!\S)|\s+"""23ENDOFTEXT = "<|endoftext|>"24IMSTART = "<|im_start|>"25IMEND = "<|im_end|>"26# as the default behavior is changed to allow special tokens in27# regular texts, the surface forms of special tokens need to be28# as different as possible to minimize the impact29EXTRAS = tuple((f"<|extra_{i}|>" for i in range(205)))30SPECIAL_TOKENS = (31    ENDOFTEXT,32    IMSTART,33    IMEND,34) + EXTRAS35 36 37def _load_tiktoken_bpe(tiktoken_bpe_file: str) -> Dict[bytes, int]:38    with open(tiktoken_bpe_file, "rb") as f:39        contents = f.read()40    return {41        base64.b64decode(token): int(rank)42        for token, rank in (line.split() for line in contents.splitlines() if line)43    }44 45class QWenTokenizer(PreTrainedTokenizer):46    """QWen tokenizer."""47 48    vocab_files_names = VOCAB_FILES_NAMES49 50    def __init__(51        self,52        vocab_file,53        errors="replace",54        **kwargs,55    ):56        super().__init__(**kwargs)57 58        self.errors = errors  # how to handle errors in decoding59 60        self.mergeable_ranks = _load_tiktoken_bpe(vocab_file)  # type: dict[bytes, int]61        self.special_tokens = {62            token: index63            for index, token in enumerate(64                SPECIAL_TOKENS, start=len(self.mergeable_ranks)65            )66        }67 68        enc = tiktoken.Encoding(69            "Qwen",70            pat_str=PAT_STR,71            mergeable_ranks=self.mergeable_ranks,72            special_tokens=self.special_tokens,73        )74        assert (75            len(self.mergeable_ranks) + len(self.special_tokens) == enc.n_vocab76        ), f"{len(self.mergeable_ranks) + len(self.special_tokens)} != {enc.n_vocab} in encoding"77 78        self.decoder = {79            v: k for k, v in self.mergeable_ranks.items()80        }  # type: dict[int, bytes|str]81        self.decoder.update({v: k for k, v in self.special_tokens.items()})82 83        self.tokenizer = enc  # type: tiktoken.Encoding84 85        self.eod_id = self.tokenizer.eot_token86        self.im_start_id = self.special_tokens[IMSTART]87        self.im_end_id = self.special_tokens[IMEND]88 89    def __len__(self) -> int:90        return self.tokenizer.n_vocab91 92    def get_vocab(self) -> Dict[bytes, int]:93        return self.mergeable_ranks94 95    def convert_tokens_to_ids(96        self, tokens: Union[bytes, str, List[Union[bytes, str]]]97    ) -> List[int]:98        ids = []99        if isinstance(tokens, (str, bytes)):100            if tokens in self.special_tokens:101                return self.special_tokens[tokens]102            else:103                return self.mergeable_ranks.get(tokens)104        for token in tokens:105            if token in self.special_tokens:106                ids.append(self.special_tokens[token])107            else:108                ids.append(self.mergeable_ranks.get(token))109        return ids110 111    def _add_tokens(self, new_tokens: Union[List[str], List[AddedToken]], special_tokens: bool = False) -> int:112        if not special_tokens and new_tokens:113            raise ValueError('Adding regular tokens is not supported')114        for token in new_tokens:115            surface_form = token.content if isinstance(token, AddedToken) else token116            if surface_form not in SPECIAL_TOKENS:117                raise ValueError('Adding unknown special tokens is not supported')118        return 0119 120    def save_vocabulary(self, save_directory: str, **kwargs) -> Tuple[str]:121        """122        Save only the vocabulary of the tokenizer (vocabulary).123 124        Returns:125            `Tuple(str)`: Paths to the files saved.126        """127        file_path = os.path.join(save_directory, "qwen.tiktoken")128        with open(file_path, "w", encoding="utf8") as w:129            for k, v in self.mergeable_ranks.items():130                line = base64.b64encode(k).decode("utf8") + " " + str(v) + "\n"131                w.write(line)132        return (file_path,)133 134    def tokenize(135        self,136        text: str,137        allowed_special: Union[Set, str] = "all",138        disallowed_special: Union[Collection, str] = (),139        **kwargs,140    ) -> List[Union[bytes, str]]:141        """142        Converts a string in a sequence of tokens.143 144        Args:145            text (`str`):146                The sequence to be encoded.147            allowed_special (`Literal["all"]` or `set`):148                The surface forms of the tokens to be encoded as special tokens in regular texts.149                Default to "all".150            disallowed_special (`Literal["all"]` or `Collection`):151                The surface forms of the tokens that should not be in regular texts and trigger errors.152                Default to an empty tuple.153 154            kwargs (additional keyword arguments, *optional*):155                Will be passed to the underlying model specific encode method.156 157        Returns:158            `List[bytes|str]`: The list of tokens.159        """160        tokens = []161        text = unicodedata.normalize("NFC", text)162 163        # this implementation takes a detour: text -> token id -> token surface forms164        for t in self.tokenizer.encode(165            text, allowed_special=allowed_special, disallowed_special=disallowed_special166        ):167            tokens.append(self.decoder[t])168        return tokens169 170    def convert_tokens_to_string(self, tokens: List[Union[bytes, str]]) -> str:171        """172        Converts a sequence of tokens in a single string.173        """174        text = ""175        temp = b""176        for t in tokens:177            if isinstance(t, str):178                if temp:179                    text += temp.decode("utf-8", errors=self.errors)180                    temp = b""181                text += t182            elif isinstance(t, bytes):183                temp += t184            else:185                raise TypeError("token should only be of type types or str")186        if temp:187            text += temp.decode("utf-8", errors=self.errors)188        return text189 190    @property191    def vocab_size(self):192        return self.tokenizer.n_vocab193 194    def _convert_id_to_token(self, index: int) -> Union[bytes, str]:195        """Converts an id to a token, special tokens included"""196        if index in self.decoder:197            return self.decoder[index]198        raise ValueError("unknown ids")199 200    def _convert_token_to_id(self, token: Union[bytes, str]) -> int:201        """Converts a token to an id using the vocab, special tokens included"""202        if token in self.special_tokens:203            return self.special_tokens[token]204        if token in self.mergeable_ranks:205            return self.mergeable_ranks[token]206        raise ValueError("unknown token")207 208    def _tokenize(self, text: str, **kwargs):209        """210        Converts a string in a sequence of tokens (string), using the tokenizer. Split in words for word-based211        vocabulary or sub-words for sub-word-based vocabularies (BPE/SentencePieces/WordPieces).212 213        Do NOT take care of added tokens.214        """215        raise NotImplementedError216 217    def _decode(218        self,219        token_ids: Union[int, List[int]],220        skip_special_tokens: bool = False,221        errors: str = None,222        **kwargs,223    ) -> str:224        if isinstance(token_ids, int):225            token_ids = [token_ids]226        if skip_special_tokens:227            token_ids = [i for i in token_ids if i < self.eod_id]228        return self.tokenizer.decode(token_ids, errors=errors or self.errors)229