目录

分词器

分词器是任何大型语言模型(LLM)的关键组成部分。它们将原始文本转换为标记ID,这些ID索引到嵌入向量中,模型可以理解这些向量。

在torchtune中,分词器的作用是将Message对象转换为标记ID以及任何必要的模型特定的特殊标记。

from torchtune.data import Message
from torchtune.models.phi3 import phi3_mini_tokenizer

sample = {
    "input": "user prompt",
    "output": "model response",
}

msgs = [
    Message(role="user", content=sample["input"]),
    Message(role="assistant", content=sample["output"])
]

p_tokenizer = phi3_mini_tokenizer("/tmp/Phi-3-mini-4k-instruct/tokenizer.model")
tokens, mask = p_tokenizer.tokenize_messages(msgs)
print(tokens)
# [1, 32010, 29871, 13, 1792, 9508, 32007, 29871, 13, 32001, 29871, 13, 4299, 2933, 32007, 29871, 13]
print(p_tokenizer.decode(tokens))
# '\nuser prompt \n \nmodel response \n'

模型分词器通常基于底层的字节对编码算法,例如 SentencePiece 或 TikToken,两者在 torchtune 中均得到支持。

从Hugging Face下载分词器

在 Hugging Face 上托管的模型还附带了它们训练时使用的分词器。当使用 tune download 时,这些分词器会与模型权重一起自动下载。例如,以下命令会下载 Mistral-7B 模型权重和分词器:

tune download mistralai/Mistral-7B-v0.1 --output-dir /tmp/Mistral-7B-v0.1 --hf-token <HF_TOKEN>
cd /tmp/Mistral-7B-v0.1/
ls tokenizer.model
# tokenizer.model

从文件加载分词器

下载分词器文件后,可以通过指向配置中或构造函数中的分词器模型的文件路径,将其加载到相应的分词器类中。如果已经将文件下载到其他位置,也可以传入自定义的文件路径。

# In code
from torchtune.models.mistral import mistral_tokenizer

m_tokenizer = mistral_tokenizer("/tmp/Mistral-7B-v0.1/tokenizer.model")
type(m_tokenizer)
# <class 'torchtune.models.mistral._tokenizer.MistralTokenizer'>
# In config
tokenizer:
  _component_: torchtune.models.mistral.mistral_tokenizer
  path: /tmp/Mistral-7B-v0.1/tokenizer.model

设置最大序列长度

设置最大序列长度可以控制内存使用并符合模型规范。

# In code
from torchtune.models.mistral import mistral_tokenizer

m_tokenizer = mistral_tokenizer("/tmp/Mistral-7B-v0.1/tokenizer.model", max_seq_len=8192)

# Set an arbitrarily small seq len for demonstration
from torchtune.data import Message

m_tokenizer = mistral_tokenizer("/tmp/Mistral-7B-v0.1/tokenizer.model", max_seq_len=7)
msg = Message(role="user", content="hello world")
tokens, mask = m_tokenizer.tokenize_messages([msg])
print(len(tokens))
# 7
print(tokens)
# [1, 733, 16289, 28793, 6312, 28709, 2]
print(m_tokenizer.decode(tokens))
# '[INST] hello'
# In config
tokenizer:
  _component_: torchtune.models.mistral.mistral_tokenizer
  path: /tmp/Mistral-7B-v0.1/tokenizer.model
  max_seq_len: 8192

提示模板

提示模板通过将其传递给任何模型分词器来启用。有关更多详细信息,请参阅 提示模板

特殊标记

特殊标记是模型特有的标签,用于提示模型。它们与提示模板不同,因为它们被分配了自己唯一的标记ID。关于特殊标记和提示模板之间区别的详细讨论,请参阅提示模板

模型分词器会自动在您的数据中添加特殊标记,您无需进行任何额外配置。您还可以通过传入一个JSON文件的路径来自定义特殊标记,以便进行实验。这不会修改底层 tokenizer.model 以支持新的特殊标记ID——确保分词器文件正确编码是您的责任。此外,请注意,某些模型需要特定的特殊标记才能正常使用,例如 Llama3 Instruct 中的 "<|eot_id|>"

例如,这里我们更改了 Llama3 Instruct 中的 "<|begin_of_text|>""<|end_of_text|>" 令牌 ID:

# tokenizer/special_tokens.json
{
    "added_tokens": [
        {
            "id": 128257,
            "content": "<|begin_of_text|>",
        },
        {
            "id": 128258,
            "content": "<|end_of_text|>",
        },
        # Remaining required special tokens
        ...
    ]
}
# In code
from torchtune.models.llama3 import llama3_tokenizer

tokenizer = llama3_tokenizer(
    path="/tmp/Meta-Llama-3-8B-Instruct/original/tokenizer.model",
    special_tokens_path="tokenizer/special_tokens.json",
)
print(tokenizer.special_tokens)
# {'<|begin_of_text|>': 128257, '<|end_of_text|>': 128258, ...}
# In config
tokenizer:
  _component_: torchtune.models.llama3.llama3_tokenizer
  path: /tmp/Meta-Llama-3-8B-Instruct/original/tokenizer.model
  special_tokens_path: tokenizer/special_tokens.json

基础分词器

BaseTokenizer 是执行实际字符串到标记 ID 转换及其逆转换的基础字节对编码模块。 在 torchtune 中,它们需要实现 encodedecode 方法,这些方法由 模型分词器 调用, 用于在原始文本和标记 ID 之间进行转换。

class BaseTokenizer(Protocol):

    def encode(self, text: str, **kwargs: Dict[str, Any]) -> List[int]:
        """
        Given a string, return the encoded list of token ids.

        Args:
            text (str): The text to encode.
            **kwargs (Dict[str, Any]): kwargs.

        Returns:
            List[int]: The encoded list of token ids.
        """
        pass

    def decode(self, token_ids: List[int], **kwargs: Dict[str, Any]) -> str:
        """
        Given a list of token ids, return the decoded text, optionally including special tokens.

        Args:
            token_ids (List[int]): The list of token ids to decode.
            **kwargs (Dict[str, Any]): kwargs.

        Returns:
            str: The decoded text.
        """
        pass

如果您加载任何 模型分词器,您可以看到它调用其底层的 BaseTokenizer 来进行实际的编码和解码。

from torchtune.models.mistral import mistral_tokenizer
from torchtune.modules.tokenizers import SentencePieceBaseTokenizer

m_tokenizer = mistral_tokenizer("/tmp/Mistral-7B-v0.1/tokenizer.model")
# Mistral uses SentencePiece for its underlying BPE
sp_tokenizer = SentencePieceBaseTokenizer("/tmp/Mistral-7B-v0.1/tokenizer.model")

text = "hello world"

print(m_tokenizer.encode(text))
# [1, 6312, 28709, 1526, 2]

print(sp_tokenizer.encode(text))
# [1, 6312, 28709, 1526, 2]

模型分词器

ModelTokenizer 是特定于某个模型的。它们需要实现 tokenize_messages 方法, 该方法将消息列表转换为 token ID 列表。

class ModelTokenizer(Protocol):

    special_tokens: Dict[str, int]
    max_seq_len: Optional[int]

    def tokenize_messages(
        self, messages: List[Message], **kwargs: Dict[str, Any]
    ) -> Tuple[List[int], List[bool]]:
        """
        Given a list of messages, return a list of tokens and list of masks for
        the concatenated and formatted messages.

        Args:
            messages (List[Message]): The list of messages to tokenize.
            **kwargs (Dict[str, Any]): kwargs.

        Returns:
            Tuple[List[int], List[bool]]: The list of token ids and the list of masks.
        """
        pass

它们之所以是模型特定的,并且不同于基础分词器,是因为它们添加了所有必要的特殊标记或提示模板,以用于提示模型。

from torchtune.models.mistral import mistral_tokenizer
from torchtune.modules.tokenizers import SentencePieceBaseTokenizer
from torchtune.data import Message

m_tokenizer = mistral_tokenizer("/tmp/Mistral-7B-v0.1/tokenizer.model")
# Mistral uses SentencePiece for its underlying BPE
sp_tokenizer = SentencePieceBaseTokenizer("/tmp/Mistral-7B-v0.1/tokenizer.model")

text = "hello world"
msg = Message(role="user", content=text)

tokens, mask = m_tokenizer.tokenize_messages([msg])
print(tokens)
# [1, 733, 16289, 28793, 6312, 28709, 1526, 28705, 733, 28748, 16289, 28793]
print(sp_tokenizer.encode(text))
# [1, 6312, 28709, 1526, 2]
print(m_tokenizer.decode(tokens))
# [INST] hello world  [/INST]
print(sp_tokenizer.decode(sp_tokenizer.encode(text)))
# hello world

文档

访问 PyTorch 的全面开发人员文档

查看文档

教程

获取面向初学者和高级开发人员的深入教程

查看教程

资源

查找开发资源并解答您的问题

查看资源