CoolFace
Modelpublic

SlitherCode/tiny-edu-166m

sourceHugging Facemitupdated 4mo agoView on Hugging Face
0likes8downloads
tokenization_parchment.py103 linesDownload Raw Back to root
1import os2import json3import tiktoken4from transformers import PreTrainedTokenizer5 6VOCAB_FILES_NAMES = {"vocab_file": "tiktoken_encoding.json"}7 8 9class TiktokenTokenizer(PreTrainedTokenizer):10    """11    HuggingFace-compatible tokenizer wrapping tiktoken's cl100k_base.12    Produces byte-identical token IDs to tiktoken.get_encoding("cl100k_base").13    Tokens are represented internally as their raw bytes decoded via latin-114    (a lossless bijection for arbitrary byte sequences).15    """16 17    vocab_files_names = VOCAB_FILES_NAMES18    model_input_names = ["input_ids", "attention_mask"]19 20    def __init__(self, vocab_file=None, encoding_name="cl100k_base", **kwargs):21        self.encoding_name = encoding_name22        self._build_enc()23 24        eot_str = self._id_to_tok[self._enc.eot_token]  # "<|endoftext|>"25 26        # When loading from saved config, special tokens are already in kwargs —27        # pop them so we don't pass duplicates to super().__init__().28        kwargs.pop("bos_token", None)29        kwargs.pop("eos_token", None)30        kwargs.pop("pad_token", None)31        kwargs.pop("unk_token", None)32 33        super().__init__(34            encoding_name=encoding_name,35            bos_token=eot_str,36            eos_token=eot_str,37            pad_token=eot_str,38            unk_token=eot_str,39            **kwargs,40        )41 42    def _build_enc(self):43        self._enc = tiktoken.get_encoding(self.encoding_name)44        self._id_to_tok = {}45        self._tok_to_id = {}46        for i in range(self._enc.n_vocab):47            try:48                s = self._enc.decode_single_token_bytes(i).decode("latin-1")49            except Exception:50                s = f"<|special_{i}|>"51            self._id_to_tok[i] = s52            self._tok_to_id[s] = i53 54    # ── Required interface ─────────────────────────────────────────────────────55 56    @property57    def vocab_size(self):58        return self._enc.n_vocab  # 10027759 60    def get_vocab(self):61        return dict(self._tok_to_id)62 63    def _tokenize(self, text):64        ids = self._enc.encode(text, allowed_special="all")65        return [self._id_to_tok[i] for i in ids]66 67    def _convert_token_to_id(self, token):68        return self._tok_to_id.get(token, self._enc.eot_token)69 70    def _convert_id_to_token(self, index):71        return self._id_to_tok.get(index, "<|unk|>")72 73    def convert_tokens_to_string(self, tokens):74        raw = b"".join(t.encode("latin-1") for t in tokens)75        return raw.decode("utf-8", errors="replace")76 77    def build_inputs_with_special_tokens(self, token_ids_0, token_ids_1=None):78        """No BOS/EOS added — matches bare tiktoken encode() behaviour."""79        if token_ids_1 is None:80            return token_ids_081        return token_ids_0 + token_ids_182 83    def save_vocabulary(self, save_directory, filename_prefix=None):84        os.makedirs(save_directory, exist_ok=True)85        fname = (filename_prefix + "-" if filename_prefix else "") + VOCAB_FILES_NAMES["vocab_file"]86        vocab_file = os.path.join(save_directory, fname)87        with open(vocab_file, "w", encoding="utf-8") as f:88            json.dump({"encoding_name": self.encoding_name}, f)89        return (vocab_file,)90 91    # ── Pickle support (tiktoken objects aren't picklable) ─────────────────────92 93    def __getstate__(self):94        state = self.__dict__.copy()95        state.pop("_enc", None)96        state.pop("_id_to_tok", None)97        state.pop("_tok_to_id", None)98        return state99 100    def __setstate__(self, state):101        self.__dict__.update(state)102        self._build_enc()103