Proper tokenizer.model is absent
LLama2 contained tokenizer.model which was loadable into SentencePieceProcessor. Llama3 is missing it. The file in originals, with the same name is just a text file of all tokens, it is not the loadable model. Am I missing something?
Wait....Llama3 switched to TikToken tokenizer? Am I correct?
Ok, yeah, confirming that Llama3 has switched to tiktoken from sentencepiece. Here is a wrapper code you may use (still WIP but seems to work):
import os
import sentencepiece as spm
import tiktoken
from tiktoken.load import load_tiktoken_bpe
from pathlib import Path
from typing import Dict
class TokenizerInterface:
def __init__(self, model_path):
self.model_path = model_path
def encode(self, text):
raise NotImplementedError("This method should be overridden by subclasses.")
def decode(self, tokens):
raise NotImplementedError("This method should be overridden by subclasses.")
def bos_id(self):
raise NotImplementedError("This method should be overridden by subclasses.")
def eos_id(self):
raise NotImplementedError("This method should be overridden by subclasses.")
class SentencePieceWrapper(TokenizerInterface):
def __init__(self, model_path):
super().__init__(model_path)
self.processor = spm.SentencePieceProcessor(str(model_path))
def encode(self, text):
return self.processor.EncodeAsIds(text)
def decode(self, tokens):
return self.processor.DecodeIds(tokens)
def bos_id(self):
return self.processor.bos_id()
def eos_id(self):
return self.processor.eos_id()
class TiktokenWrapper(TokenizerInterface):
"""
Tokenizing and encoding/decoding text using the Tiktoken tokenizer.
"""
special_tokens: Dict[str, int]
num_reserved_special_tokens = 256
pat_str = r"(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}{1,3}| ?[^\s\p{L}\p{N}]+[\r\n]*|\s*[\r\n]+|\s+(?!\S)|\s+" # noqa: E501
def __init__(self, model_path):
super().__init__(model_path)
assert os.path.isfile(model_path), str(model_path)
mergeable_ranks = load_tiktoken_bpe(str(model_path))
num_base_tokens = len(mergeable_ranks)
special_tokens = [
"<|begin_of_text|>",
"<|end_of_text|>",
"<|reserved_special_token_0|>",
"<|reserved_special_token_1|>",
"<|reserved_special_token_2|>",
"<|reserved_special_token_3|>",
"<|start_header_id|>",
"<|end_header_id|>",
"<|reserved_special_token_4|>",
"<|eot_id|>", # end of turn
] + [
f"<|reserved_special_token_{i}|>"
for i in range(5, self.num_reserved_special_tokens - 5)
]
self.special_tokens = {
token: num_base_tokens + i for i, token in enumerate(special_tokens)
}
self.model = tiktoken.Encoding(
name=Path(model_path).name,
pat_str=self.pat_str,
mergeable_ranks=mergeable_ranks,
special_tokens=self.special_tokens,
)
# BOS / EOS token IDs
self._bos_id: int = self.special_tokens["<|begin_of_text|>"]
self._eos_id: int = self.special_tokens["<|end_of_text|>"]
def encode(self, text):
return self.model.encode(text)
def decode(self, tokens):
return self.model.decode(tokens)
def bos_id(self):
return self._bos_id
def eos_id(self):
return self._eos_id
def get_tokenizer(tokenizer_model_path, model_name):
"""
Factory function to get the appropriate tokenizer based on the model name.
Args:
- tokenizer_model_path (str): The file path to the tokenizer model.
- model_name (str): The name of the model, used to determine the tokenizer type.
Returns:
- TokenizerInterface: An instance of a tokenizer.
"""
if "Llama-3" in str(model_name):
return TiktokenWrapper(tokenizer_model_path)
else:
return SentencePieceWrapper(tokenizer_model_path)
Hmmm, so run the demos it need a file named tokenizer.model. Someone says the file is no longer there.
At the end of the day this closed discussion didn't result if producing a tokenizer.model file.
What am I missing.
There is a tokenizer.model file in 'original' sub-dir. The thing is - you need to use TikTokenizer to load it instead of the previous SentencePiece one. The code above shows you how to handle it.
Hello.
I wonder if there is an article / document that describes the tiktoken algorithm in plain English.