Token 到底是什么:大模型计费与上下文窗口的基础知识

给完全不懂的人讲透 token 的概念:tokenizer 怎么切词、上下文窗口是什么、4K/8K/128K 的实际含义,以及 Hermes 各版本的上下文长度对比。

目录

  1. 一个你早晚要搞懂的概念
  2. Token 不是字,也不是词
  3. Tokenizer 是怎么工作的
    1. 为什么不能直接用字符
    2. BPE:最主流的分词方法
    3. 中文的 tokenization
  4. 上下文窗口是什么
    1. 定义
    2. 常见的上下文窗口大小
    3. 上下文窗口的实际影响
  5. Hermes 各版本的上下文长度
  6. Token 和 API 计费
    1. 输入 token 和输出 token
    2. 典型的价格量级
    3. 怎么估算你的 token 消耗
    4. 省 token 的技巧
  7. 关于 token 的几个常见误解
    1. 误解1:token 数量 = 字数
    2. 误解2:上下文窗口越大越好
    3. 误解3:token 数量相同 = 内容相同
    4. 误解4:所有模型的 tokenizer 都一样
  8. 特殊 token
  9. 和 Hermes 使用相关的实际建议
    1. 本地使用时
    2. API 调用时
  10. 写在最后

一个你早晚要搞懂的概念

如果你在用大模型——不管是在线聊天还是调用 API——你一定会反复遇到一个词:Token

「这个模型支持 128K token 的上下文」
「API 按 token 数量计费」
「你的对话已经超出了 token 上限」

但 token 到底是什么?它和「字」有什么区别?为什么不直接用字数来衡量?

这篇文章就把这件事给你讲透。不需要任何技术背景,只要你认识字就行。

Token 不是字,也不是词

先说结论:Token 是大语言模型处理文本时使用的最小单位,它既不等于一个字,也不等于一个词,而是介于两者之间的某种东西。

举个例子,英文句子 “Hello, world!” 在不同的 tokenizer 下可能被切成:

1
["Hello", ",", " world", "!"]  → 4 个 token

而中文句子「你好世界」可能被切成:

1
["你", "好", "世界"]  → 3 个 token

或者:

1
["你好", "世界"]  → 2 个 token

具体怎么切,取决于使用的 tokenizer(分词器)。不同的模型可能使用不同的 tokenizer,所以同一段文本在不同模型下的 token 数量可能不同。

Tokenizer 是怎么工作的

为什么不能直接用字符

你可能会想:为什么不直接把每个字符当作一个处理单位呢?

原因很简单:效率太低。

英文有26个字母。如果每个字母是一个处理单位,模型在处理一个长单词(比如 “understanding”)时需要逐个字母去理解。这就像让你一个字母一个字母地阅读英文,效率很差。

反过来,如果每个完整的单词是一个处理单位呢?问题是英语中有超过几十万个不同的单词(加上各种变形、专有名词),词表太大了。而且你没见过的新词怎么办?

Token 是一种折中方案:把文本切成比字符大、比完整单词小(或等于完整单词)的片段。常用的词保留为完整的 token,不常用的词被切成更小的子片段。

BPE:最主流的分词方法

目前大语言模型最常用的分词方法叫 BPE(Byte Pair Encoding,字节对编码)

BPE 的训练过程是这样的:

  1. 从单个字符(或字节)开始
  2. 统计所有相邻片段对的出现频率
  3. 把出现频率最高的一对合并成新的 token
  4. 重复步骤2和3,直到词表达到预设大小

举个简化的例子,假设训练数据中 “th” 这个组合出现了1万次,那 BPE 就会把 “t” 和 “h” 合并成一个新 token “th”。然后可能 “the” 出现了8千次,就把 “th” 和 “e” 合并成 “the”。

这样做的结果是:

  • 常用的词(如 “the”, “is”, “are”)会被保留为完整的 token
  • 不常用的词会被切成更小的子片段
  • 全新的词(模型没见过的)也能被表示——虽然可能需要更多的 token

中文的 tokenization

中文的处理和英文不太一样。中文没有空格分隔,一个汉字本身就是一个意义单位。

在早期的 tokenizer 中(比如 GPT-2 的),中文字符经常被切得很碎——一个汉字可能需要 2-3 个 token 来表示。这导致中文在 token 消耗上非常吃亏:同样的内容,中文需要的 token 数量远多于英文。

后来的 tokenizer(比如 GPT-4、Llama 3、Qwen 使用的)对中文做了专门的优化,很多常用汉字和词组被加入了词表,一个汉字通常只需要 1 个 token,常用词组甚至可以被整体编码为 1 个 token。

一个粗略的估算:在现代 tokenizer 下,1个中文字大约等于 1-1.5 个 token,1个英文单词大约等于 1-2 个 token。

上下文窗口是什么

搞清楚了 token 的概念,接下来说一个和它直接相关的概念:上下文窗口(Context Window)

定义

上下文窗口就是模型一次能处理的最大 token 数量。你可以把它理解为模型的「工作记忆容量」。

如果一个模型的上下文窗口是 4K(4096 个 token),那它一次最多能看到大约 4096 个 token 的内容。这包括了你的所有输入(system prompt + 对话历史 + 当前问题)和模型的输出。

常见的上下文窗口大小

大小 大约相当于 典型代表
2K (2048) 约1500中文字 早期模型(GPT-2)
4K (4096) 约3000中文字 GPT-3.5 初版、Llama 1
8K (8192) 约6000中文字 GPT-4 初版
32K (32768) 约24000中文字 一些中期模型
128K (131072) 约10万中文字 Llama 3.1、Hermes 3、GPT-4 Turbo
200K+ 约15万+中文字 Claude 3、Gemini 1.5

10万中文字是什么概念?大概是一本中等篇幅的小说。128K 上下文意味着你可以把整本小说喂给模型,让它理解内容后回答问题。

上下文窗口的实际影响

上下文太短的时候

  • 长对话聊到后面,模型会「忘记」前面的内容(因为早期的对话已经被截断了)
  • 无法处理长文档
  • 复杂的多轮任务容易中途断线

上下文够长的时候

  • 可以维持很长的连贯对话
  • 可以分析整篇论文、整个代码文件
  • 复杂任务的完成率更高

但注意:上下文窗口越大不一定越好。更大的上下文窗口意味着更多的计算量和更高的延迟。如果你的任务只需要几百个 token 的上下文,128K 的窗口就是浪费。

Hermes 各版本的上下文长度

把 Hermes 各版本的上下文窗口整理一下:

版本 上下文窗口 说明
Hermes 1 (Llama 1/2) 2K-4K 早期限制,现在已经不够用了
Hermes 2 (Mistral 7B) 8K-32K 有了明显提升
Hermes 2 Pro 8K-32K 和 Hermes 2 相当
Hermes 3 (Llama 3.1) 128K 大幅跃升,基本够用了
Hermes 4/4.3 128K+ 保持高水位

从 Hermes 3 开始,128K 的上下文窗口已经能满足绝大多数使用场景。如果你想了解 Hermes 各版本的更多差异,可以参考 Hermes 模型版本怎么看 这篇。

Token 和 API 计费

如果你通过 API 调用大模型(不管是 OpenAI、Anthropic 还是 OpenRouter 上的 Hermes),费用通常是按 token 数量来计算的。

输入 token 和输出 token

API 计费一般区分两种 token:

  • 输入 token(Input / Prompt tokens):你发送给模型的内容。包括 system prompt、对话历史、当前问题等。
  • 输出 token(Output / Completion tokens):模型生成的回复内容。

通常输出 token 比输入 token 贵。原因是生成输出需要更多的计算量(每个 output token 都需要一次完整的模型前向传播)。

典型的价格量级

不同模型和平台的定价差异很大,但给你一个大致的量级感知:

模型类型 输入价格 (每百万token) 输出价格 (每百万token)
小模型 (7B-8B) $0.03 - $0.10 $0.05 - $0.15
中等模型 (70B) $0.50 - $1.00 $0.75 - $1.50
大模型 (405B+) $2.00 - $5.00 $3.00 - $10.00

Hermes 通过 OpenRouter 调用的话,因为是开源模型,通常价格会比闭源商业模型便宜不少。

怎么估算你的 token 消耗

几个实用的估算方法:

方法1:粗略估算

  • 英文:1 个 token ≈ 4 个字符 ≈ 0.75 个单词
  • 中文:1 个 token ≈ 1-1.5 个汉字

方法2:在线工具
很多平台提供 token 计算工具,比如 OpenAI 的 Tokenizer 页面,可以粘贴文本直接查看 token 数量。

方法3:代码计算

1
2
3
4
5
6
from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("NousResearch/Hermes-3-Llama-3.1-8B")
text = "你好,请帮我解释一下什么是token"
tokens = tokenizer.encode(text)
print(f"Token数量: {len(tokens)}")

省 token 的技巧

如果你在意 API 费用,可以注意以下几点:

1. 精简 system prompt
system prompt 在每次 API 调用中都会被发送,所以一个冗长的 system prompt 会在每次请求中都消耗 token。保持 system prompt 简洁精准。

2. 控制对话历史长度
多轮对话中,整个对话历史都会作为输入发送。如果对话很长,可以考虑只保留最近的 N 轮对话,或者做摘要压缩。

3. 设置 max_tokens 限制
在 API 调用中设置输出的最大 token 数量,防止模型生成过长的回复。

4. 选择合适大小的模型
不是每个任务都需要用最大最贵的模型。简单的问答用 8B 模型就够了,没必要上 405B。

关于 token 的几个常见误解

误解1:token 数量 = 字数

前面已经说了,token 和字数不是一回事。特别是中文,一个 token 的对应关系比较复杂。不要简单地用字数来估算 token。

误解2:上下文窗口越大越好

更大的上下文窗口确实提供了更多的灵活性,但也有代价:

  • 计算量增加:处理 128K token 比处理 4K token 需要多得多的计算资源
  • 延迟增大:上下文越长,模型生成第一个 token 的时间越长
  • 注意力稀释:一些研究表明,当上下文太长时,模型对中间部分内容的注意力会下降(所谓的 “Lost in the Middle” 问题)

实际使用中,根据任务需要选择合适的上下文长度就好。

误解3:token 数量相同 = 内容相同

两段不同的文本可能碰巧有相同数量的 token,但内容完全不同。token 数量只是一个长度度量,不包含语义信息。

误解4:所有模型的 tokenizer 都一样

不同模型家族使用不同的 tokenizer。Llama 系列的 tokenizer、Qwen 的 tokenizer、GPT 系列的 tokenizer 各不相同。同一段文本在不同 tokenizer 下的 token 数量可能有不小的差异。

这在实际中意味着:你不能用一个模型的 tokenizer 来估算另一个模型的 token 消耗。

特殊 token

除了表示文本内容的普通 token 之外,还有一些特殊 token,用来标记特殊的含义。

常见的特殊 token:

  • <|im_start|><|im_end|>:ChatML 格式中的消息起止标记。关于 ChatML 的详细说明,可以看 ChatML 是什么 那篇。
  • <s></s>:序列的开始和结束标记
  • <|endoftext|>:文本结束标记
  • <pad>:填充标记,用于将不等长的序列对齐

这些特殊 token 也占用上下文窗口的空间,虽然数量很少,但在你精确计算 token 消耗时需要考虑在内。

和 Hermes 使用相关的实际建议

本地使用时

如果你用 Ollama 之类的工具在本地跑 Hermes,token 本身不花钱(你已经在用自己的硬件了)。但上下文窗口的大小仍然有影响:

  • 上下文越长,推理越慢
  • 上下文越长,需要的显存越多
  • 8B 模型在 4K 上下文下很流畅,128K 上下文下会明显变慢

所以本地使用时,根据实际需要调整上下文窗口的大小是有意义的。大多数工具都允许你设置最大上下文长度。

API 调用时

通过 OpenRouter 或其他平台调用 Hermes API 时,费用直接和 token 挂钩。按照上面说的省 token 技巧来优化就好。

在 cocoloop 社区有开发者分享过他们的 API 成本优化经验——有人通过精简 system prompt 和合理截断对话历史,把每月的 API 费用降低了 40% 以上。这些实战经验很有参考价值。

写在最后

Token 的概念其实并不复杂,但它在大模型的使用中无处不在。搞懂它,你就:

  1. 理解了上下文窗口的含义和限制
  2. 能估算 API 调用的费用
  3. 知道怎么优化 token 消耗
  4. 不会在看到「128K context」之类的说法时一头雾水

这些都是日常使用大模型的基本功。不用一次记住所有细节,但核心概念——token 是模型处理文本的最小单位,上下文窗口是模型的工作记忆容量——这两点记住就够应付大多数场景了。

参与讨论

对这篇文章有疑问或想法?cocoloop 社区有不少开发者在讨论 Hermes 相关话题,欢迎加入交流。

前往 cocoloop 社区 →