Token
词元是模型处理的输入单位,例如子词或图像块。了解分词器如何拆分文本、视觉词元及词元成本。
Token 是 AI 模型处理的输入和输出基本单位:文本中的一个词、词的一部分、一个字符或一个字节,或者图像中的一个像素块。在Transformer读取句子或图像之前,分词器会将输入拆分成 Token,并将每个 Token 映射为一个整数 ID;随后,模型会为每个 ID 查找对应的嵌入向量。Token 数量决定了模型能处理的内容和成本:上下文窗口以 Token 数量衡量,大型语言模型(LLMs)每次生成一个 Token,而商业 API 会按输入和输出 Token 分别计费。
Token、分词与相关术语#
- 分词: 将原始输入拆分成 Token 的过程。Token 是分词过程输出的一个单位。
- 词表和 Token ID: 分词器的词表是它所识别的固定 Token 集合,每个 Token 都有一个整数 ID。BERT 使用 30,522 个 Token,GPT-2 使用 50,257 个,Llama 3 使用 128,256 个,Gemma 3 则约有 262,000 个。
- 特殊 Token: 用于标记序列结构的标记,例如文本起始、文本结束和填充 Token,或者 BERT 用于分类的
[CLS]Token 的最终嵌入。 - 嵌入: 模型第一层会根据每个 Token ID 查找对应的学习所得向量,这些向量将 Token 的含义传递到网络中。
文本 Token#
完整词汇表无法覆盖所有姓名、拼写错误和新术语,而单字符 Token 又会让序列变得很长。因此,现代分词器会使用子词:常见词会成为单个 Token,生僻词则拆分成可重复使用的片段。Sennrich 及其同事于 2016 年将字节对编码(BPE)应用于神经机器翻译:它从单个字符开始,反复合并出现频率最高的相邻字符对,直到词表达到目标大小。GPT模型会对字节应用 BPE,因此任何文本(包括代码和表情符号)都可以编码;WordPiece(BERT 使用)和 SentencePiece 的 Unigram 模型也是相关的子词方案。下面展示了从 Hugging Face Hub 加载的 CLIP BPE 分词器如何拆分单词:
from transformers import AutoTokenizer
# Load CLIP's byte-pair-encoding (BPE) tokenizer from the Hugging Face Hub
tokenizer = AutoTokenizer.from_pretrained("openai/clip-vit-base-patch32")
for text in ["bus", "double-decker bus", "unhappiness", "Ultralytics"]:
tokens = tokenizer.tokenize(text)
print(f"{text!r} -> {tokens} -> {tokenizer.convert_tokens_to_ids(tokens)}")“bus”是一个 Token,ID 为 2840;“unhappiness”会拆分成 un 和 happiness;生僻词 “Ultralytics” 会拆成三个片段:ultr、aly 和 tics。后缀 </w> 表示 CLIP 的 49,408 个 Token 词表中的词尾,而 CLIP 的文本编码器每个提示最多读取 77 个 Token。
视觉 Token#
论文《一张图像胜过 16 × 16 个词》《An Image Is Worth 16x16 Words》介绍的视觉 Transformer(ViT)会将图像拆分为固定大小的图块;在 ViT-B/16 中,每个图块为 16 × 16 像素,并将每个图块投影为一个嵌入,因此 224 × 224 图像会变成 196 个 Token。位置嵌入记录每个图块的来源位置,额外的类别 Token 则汇集分类所需的信息。这个投影通常通过卷积实现,其步幅等于卷积核大小:
import torch
# ViT-B/16 patch embedding: a 16x16 convolution with stride 16 turns each patch into one 768-dim token
patch_embed = torch.nn.Conv2d(3, 768, kernel_size=16, stride=16)
for size in (224, 448):
image = torch.rand(1, 3, size, size)
tokens = patch_embed(image).flatten(2).transpose(1, 2) # (batch, tokens, dims)
print(f"{size}x{size} image -> {tuple(tokens.shape)}")一张 224 × 224 图像会生成 196 个 Token,每个 Token 含 768 个值;将边长增加到 448 像素后,会生成 784 个 Token,是原来的四倍。自注意力会将每个 Token 与其他所有 Token 进行比较,因此 Token 数量变成四倍,注意力计算开销约会变成十六倍。这就是高分辨率模型使用窗口注意力(如 Swin Transformer)或通过Token 合并组合相似 Token 的原因。
视觉语言模型会将图像编码器生成的视觉 Token 与文本 Token 一起传入 LLM,让同一个 Transformer 同时处理两者,并逐个文本 Token 生成回答:
令牌数量为何重要#
- 上下文限制: 提示词、检索到的文档或图像,以及生成的回答都必须能放入模型的上下文窗口。
- 成本和延迟: API 会分别对输入和输出 Token 计费;输出 Token 越多,生成时间越长,因为每个 Token 都需要一个解码步骤,而该步骤会读取模型的 KV cache。
- 语言和格式: 主要使用英语训练的分词器会将其他语言、代码和较长数字拆分成更多 Token,因此相同内容的成本更高,也会更快占满上下文窗口。
- 字符级任务: 模型看到的是子词 Token,因此依赖单个字母的任务(例如统计单词中的字母数或反转单词)对模型来说比看起来更难。
实际应用#
- 文本生成: LLM 会为词表中的每个 Token 分配概率,采样一个 Token,将其附加到序列中,然后重复这一过程;核采样等采样方法会从可能性较高的 Token 中进行选择。
- 图像生成: 自回归图像模型会从通过向量量化构建的学习码本中预测离散视觉 Token,方式与 LLM 预测词语相似。
- 开放词汇检测: YOLOE-26 是清华大学 YOLOE 的 YOLO26 版本,包含在 Ultralytics 软件包中,可根据输入的类别名称查找物体。它的
set_classes()方法会使用 CLIP 的 BPE 分词器对每个名称进行分词,Apple 的 MobileCLIP2 文本编码器会将 Token 转换为嵌入,模型再将这些嵌入与图像区域进行匹配,因此即使“double-decker bus”这一类别不在 COCO 数据集中,也能仅凭文字检测出来。










