用大模型时,几乎所有讨论都绕不开 token:上下文窗口是 20 万 token,输入 3 元每百万 token,回复超过 8000 token 会被截断。这篇讲清楚 token 到底是什么,以及它为什么决定了你的账单。

Token 是大模型读写文本的最小单位。模型不认识“字符”也不认识“单词”,它只认识 token。

一段文本进入模型前,会先被切成若干个 token;模型生成回复时,也是一个 token 一个 token 往外吐。上下文窗口的长度、API 的定价、生成的速度,全部按 token 计。

token 不是字,也不是词

一个常见误解是“token = 单词”,或“一个汉字一个 token”。实际都不是。

以 GPT 系列使用的 BPE(Byte Pair Encoding)为例,一段文本会被拆成“高频子串”。频繁出现的字符组合会合并成一个 token,罕见的组合则被拆碎。

看几个例子(用 GPT-4 的分词器):

原文 token 数 拆分方式
hello 1 hello
unbelievable 3 un / bel / ievable
你好 2 /
你好世界 4 每个汉字一个 token
🍥 3~4 一个 emoji 会占多个字节,拆成多个 token

规律是:训练语料里越常见的片段,越容易独占一个 token;越冷门的字符,越会被切碎。因为主流分词器都以英语语料为主,中文、日文、代码里的罕见符号,token 数普遍多于英语。

为什么设计成这样

模型的词表大小是固定的,通常在 5 万到 20 万之间。如果按单词切,光是英语就远远超过这个规模;按字符切,模型要处理的序列又太长,学习效率低。

BPE 的做法是折中:先按字节切,然后统计哪些相邻字节最常一起出现,把它们合并成新的 token。这个过程反复迭代,直到词表满了为止。得到的词表里,theingtion 这种高频组合独占一个 token,罕见的字符组合则保留细粒度。

结果就是一段英文文本平均下来每个 token 覆盖大约 4 个字符或 0.75 个单词,中文平均一个字占 1~2 个 token。

你可以自己数

OpenAI 提供了在线工具(platform.openai.com/tokenizer),也可以用官方库本地跑:

import tiktoken

enc = tiktoken.encoding_for_model("gpt-4o")

text = "MCP 是一个开放协议"
tokens = enc.encode(text) 

print(len(tokens), tokens)
# 11 [78241, 5745, 42648, 21043, 45114, 92795, 40792, 29102, 45383, 32574, 30298]

高亮的那一行就是从字符串到 token id 列表的转换。每个 id 对应词表里的一个位置,模型看到的是这串数字,不是原文。

想反过来看每个 id 对应的字符片段:

for tid in tokens:
    print(tid, repr(enc.decode([tid])))

跑一下就能直观看到 BPE 是怎么把中文一个字拆成一两个字节 token 的。

Token 和账单

主流 API 全部按 token 计费,输入和输出通常价格不同(输出往往是输入的 3~5 倍)。一次调用的成本可以粗略估算:

成本 = 输入 token 数 × 输入单价 + 输出 token 数 × 输出单价

一次看似普通的对话,token 消耗可能远超预期,因为:

  • 每一轮都要重发历史。多轮对话里,前面所有 turn 都会作为输入再次传入。第 10 轮的输入 token 数是第 1 轮的十几倍。
  • 系统提示词也算钱。system prompt 每次调用都要传,长 prompt 是持续开销。
  • 工具定义也算钱。挂了 10 个工具,它们的 schema 每次调用都要放进上下文。

一个常见的坑是把日志、文档、代码全塞进 prompt。看着方便,账单会翻倍。

上下文窗口

模型能“看到”的 token 总数就是上下文窗口。2026 年主流模型的窗口大小:

模型 上下文窗口
GPT-4o 128k
Claude Sonnet 4.5 200k
Gemini 2.5 Pro 1M~2M

窗口不是越大越好。原因有几个:

  • 中间部分容易被忽略。长上下文里,模型对开头和结尾的内容记得清楚,中间段落经常“读了但没记住”。这现象叫 Lost in the Middle。
  • 成本线性上涨。100k token 的输入是 10k 的十倍钱,还没算生成。
  • 延迟明显增加。输入越长,首 token 出来越慢。

真正需要长上下文时才用长上下文,其他情况该做 RAG 就做 RAG。

Token 决定了什么

除了账单和窗口,token 还悄悄影响了几件事:

  • 流式响应的粒度。API 的 stream 返回是按 token 推的,一次通常一个 token。中文往往几个字符才凑出一个 token,所以中文流式看起来比英文“卡”一点。
  • 模型的空间感知。让模型“每段 300 字”,它其实数的是 token 数(大致对应),不是精确字数。
  • 生成速度。厂商公布的 “80 tokens/秒” 是 token 速度,中文实际字符速度会更低。
  • 提示词的调整方向。同样意思用更少 token 的表达(比如英文关键词代替长中文短语)在极端场景下确实能省钱,但可读性下降,通常不划算。

一些工程经验

  • 调用前先估 token。用官方分词器算一遍输入 token 数,可以避免 prompt 意外超长。
  • 压缩历史。多轮对话到一定长度后,让模型自己写一段摘要替换掉旧 turn,能显著降本。
  • 区分输入和输出定价。有些优化只降输入 token 没用,输出 token 才是大头。
  • 别用字符数估算。中英混合、含代码的文本,字符数和 token 数比例波动很大。
  • 系统提示词值得优化。它每次调用都要传,砍掉一句话就是每次都省钱。

写在最后

Token 不是一个 AI 使用者能绕开的抽象。上下文窗口、API 账单、生成速度、模型的“记忆力”,本质上都是 token 的表达。理解它怎么切、怎么算,比死背哪个模型多大窗口有用得多。

下次看到一个 200k token 的模型时,先算一下这够写多少中文、多少代码、能塞下多少文档,再决定值不值这个价。