游乐游手机版
首页/AI热点日报/热点详情

GPT Tokenizer工作原理:核心机制与实现全过程深度解析

类型:热点整理2026-07-20
GPTtokenizer将文本分割成token,英语常见单词有唯一token且大小写与空格关键,其他语言切分偏向英语。存在位于嵌入空间中心的故障token如davidjl。使用tiktoken库可基于模型编码方案计算token数,ttok命令行工具支持统计与截断。

在 GPT 大语言模型中,tokenizer 是连接原始文本和模型理解的桥梁。本文将为你系统性地解析 GPT tokenizer 的工作原理,并通过大量实例和工具演示,帮助你直观理解 token 的生成过程、奇特现象以及如何在实际开发中应用。内容源自开源技术社区,由 Django 联合创始人 Simon Willison 撰写。

1. tokenizer 是什么?为什么重要?

在 GPT 模型中,tokenization(词元化) 指的是将用户输入的文本分割成 token(词元) 的过程。这是模型理解输入文本的词义、句法和语义的关键预处理步骤,直接影响模型输出的质量和连贯性。

tokenizer(词元生成器) 是执行这一操作的工具或组件。它负责将原始文本转换成模型可以处理的数字形式(即 token ID 序列),为 GPT 的生成与推理提供基础能力。

2. 直观理解 token:使用可视化工具

OpenAI 提供了一个官方 tokenizer 供探索。作者 Simon Willison 则构建了一个更直观的 Observable notebook 工具,可以在其中进行文本与 token 的相互转换,并搜索整个 token 表。

该工具界面如下:

以这段混合语言的文本为例:

The dog eats the apples El perro come las manzanas 片仮名

在该工具中,这段文本被切分为 21 个整数 token:

  • 5 个 token 对应英文文本
  • 8 个 token 对应西班牙文本
  • 6 个 token(每个字符 2 个)对应三个日文字符
  • 2 个换行符也各自对应一个整数 token

小提示: 该工具基于 GPT-2 的 tokenizer 构建,主要作为教育工具使用。GPT-3 及更高版本(如 GPT-4)的 tokenizer 与其存在些许差异。

2.1 常见英语单词的 token

大多数常见的英语单词都分配了一个唯一的 token。在示例中:

  • “The”:464
  • “ dog”:3290(注意前面的空格)
  • “ eats”:25365
  • “ the”:262
  • “ apples”:22514

重要观察: 字母的大小写非常重要!以单词 “the” 为例,大写字母 T 的 “The” 对应的 token 是 464,而小写字母 t 开头且包含前导空格的 “ the” 对应的 token 是 262。许多单词的 token 都包含了前导空格,这样无需为每个空格字符使用一个额外 token,编码效率更高。

2.2 对其他语言(西班牙语)的切分

西班牙语 “El perro come las manzanas” 的编码如下:

  • “El”:9527
  • “ per”:583
  • “ro”:305
  • “ come”:1282
  • “ las”:39990
  • “ man”:582
  • “zan”:15201
  • “as”:292

从以上案例可以看出对英语的明显偏向。因为 “man” 是一个英语单词,其 token ID 较低(582)。而 “zan” 虽然不是一个独立的英语单词,但由于它是常见的字符序列,也拥有自己的 token(15201)。

2.3 对日语字符的切分

某些语言(如日语)的单个字符可能被编码为多个 token:

  • :31965, 229
  • :20015, 106
  • :28938, 235

3. 奇特的“故障 token”

“故障 token”(glitch tokens)是 tokenizer 中一类令人着迷的特殊 token。其中一个有趣的例子是 token 23282,对应字符串 “da vidjl”

Scale AI 的 prompt 工程师 Riley Goodside 指出了与该 token 相关的奇怪行为:

为什么会发生这种情况?

  • token 23282 可能与 Reddit 上的用户 “da vidjl123” 有关。该用户是 /r/counting 子论坛的活跃用户,经常发布递增数字,已发布过 163,000 多次此类帖子。
  • /r/counting 子论坛的数据最终被用于训练 GPT-2 的 tokenizer。由于该用户出现数十万次,最终获得了属于自己的 token。

Hacker News 用户 @londons_explore 给出了最佳解释:

这些故障 token 都位于 token 嵌入空间的中心附近。模型在区分这些 token 和其他位于嵌入空间中心附近的 token 时存在困难,因此当被要求“重复”这些 token 时,模型会选择错误的 token。这种情况发生的原因是,这些 token 在互联网上出现了很多次,但本身并不难以预测(因此在训练过程中,梯度几乎变为零,嵌入向量会衰减到零,这是某些优化器在归一化权重时的操作)。

了解更多:LessWrong 上搜索 “SolidGoldMagikarp (plus, prompt generation)” 可以找到对这种现象的详细说明。

4. 使用 tiktoken 进行 token 计数

OpenAI 的模型都有 token 限制。在将文本传递给 API 之前,经常需要计算字符串中的 token 数量,以确保不超出限制。

一个典型的技术用例是 检索增强生成(Retrieval Augmented Generation, RAG):通过对文档语料库执行搜索来回答用户问题,提取最相关的内容作为上下文包含在 prompt 中。成功实现这种模式的关键是在 token 限制内包含尽可能多的相关上下文,因此准确计算 token 数量至关重要。

OpenAI 提供了名为 tiktoken 的 Python 库来实现这一功能:

tiktoken 目前包含五种不同的切分方案:r50k_basep50k_basep50k_editcl100k_basegpt2

其中 cl100k_base 是最相关的,它是 GPT-4 和当前 ChatGPT 使用的经济型 gpt-3.5-turbo 模型的 tokenizer。text-da vinci-003 则使用 p50k_base。完整的模型与 tokenizer 映射可以在 tiktoken/model.py 的 MODEL_TO_ENCODING 词典中找到。

4.1 tiktoken 代码示例

以下是如何使用 tiktoken 的代码示例:

import tiktoken

encoding = tiktoken.encoding_for_model("gpt-4")
# or "gpt-3.5-turbo" or "text-da vinci-003"
tokens = encoding.encode("Here is some text")
token_count = len(tokens)

现在 token 将是一个包含四个整数 token ID 的数组——在该例中是 [8586, 374, 1063, 1495]

使用 .decode() 方法可以将整数 ID 数组转换回文本:

text = encoding.decode(tokens)
# 'Here is some text'

提示: 第一次调用 encoding_for_model() 时,编码数据会通过 HTTP 从 openaipublic.blob.core.windows.net 的 Azure Blob 存储桶获取。这些数据会被缓存在临时目录中。如果机器重启,缓存将被清除。可以通过设置 TIKTOKEN_CACHE_DIR 环境变量来指定持久化的缓存目录,避免重复下载。

5. 命令行工具 ttok

ttok 是 tiktoken 的命令行封装工具,主要提供两个关键功能

  1. 计算 token 数量:计算输入文本中的 token 数
  2. 文本截断:将文本截断为指定数量的 token

5.1 使用示例

计算 token 数量:

# Count tokens
echo -n "Count these tokens" | ttok
# Outputs: 3 (the newline is skipped thanks to echo -n)

截断文本:

# Truncation
curl 'https://simonwillison.net/' | strip-tags -m | ttok -t 6
# Outputs: Simon Willison’s Weblog

查看整数 token ID:

# View integer token IDs
echo "Show these tokens" | ttok --tokens
# Outputs: 7968 1521 11460 198

可以使用 -m gpt2 或类似选项选择适用于不同模型的编码。

6. 观察 token 生成过程

理解 token 之后,GPT 模型生成文本的方式会更加清晰。GPT-4 的速度略慢于 3.5 版本,可以更容易地观察到其逐 token 生成过程。

以下示例使用 llm CLI 工具从 GPT-4 生成文本的结果,命令是:llm -s 'Five names for a pet pelican' -4

如你所见,不在词典中的名字(如 “Pelly”)占据了多个 token,而 “Captain Gulliver” 作为一个整体输出了 token “Captain”。

常见问题

问题1:为什么故障 token 会导致模型出现奇怪的行为?

答案: 故障 token(如 “da vidjl”)位于词嵌入空间的中心区域,模型难以区分它们与其他中心附近的 token。由于这些 token 在训练数据中间出现频率极高(例如 Reddit 用户发布了超过 16 万次递增数字的帖子),但自身预测难度很低,导致梯度几乎为零,嵌入向量在优化过程中逐渐衰减到零。最终模型在需要“重复”这些 token 时,可能会错误地输出其他 token。

问题2:如何在代码中准确计算 token 数量,避免超出 API 限制?

答案: 必须使用与目标模型一致的 tokenizer。例如,对于 GPT-4 或 gpt-3.5-turbo,应使用 cl100k_base;对于 text-da vinci-003,使用 p50k_base。tiktoken 库提供了 encoding_for_model() 方法自动获取正确的编码器。注意不要依赖简单的字符计数(如OpenAI Tokenizer)或通用规则,因为不同模型中文字符通常需要 2-3 个 token,而英文单词平均约 1.3 个 token。

问题3:ttok 工具中如何设置更持久的缓存?

答案: 设置环境变量 TIKTOKEN_CACHE_DIR 指向一个自定义的持久目录。例如:export TIKTOKEN_CACHE_DIR=/path/to/cache。这样即使机器重启,编码数据也不会被清除,避免重复下载。

来源:https://m.elecfans.com/article/2247025.html

相关热点

继续查看同栏目近期热点。

延伸阅读

补充最近整理过的热点入口。