Token 计数 vs 字符计数:为什么差异很重要

字符数很容易测量。Token 数才是 LLM 在上下文限制、用量报告以及通常的计费中实际使用的指标。把两者视为可以互换,可能会让提示预算看起来安全,实际上并不安全——或者让你删掉本来完全可以放下的有用上下文。
实用规则很简单:写作和界面限制使用字符数;进行 LLM 规划时使用模型特定的 token 数。 每 token 字符数的比例可以帮助做粗略估算,但它不能替代使用目标模型所对应的分词器或 API 对完整请求进行计数。
本指南解释为什么 token 数与字符数会出现偏差、这种差异在何时重要,以及如何通过可直接粘贴的示例在 TokenTest 中测试其影响。
一张表看懂 token 数与字符数
| 度量 | 统计内容 | 最佳用途 | 主要限制 |
|---|---|---|---|
| 字符 | 可见文本中的 Unicode 字符或码位 | 编辑器限制、UI 校验、存储量估算 | 不能反映分词器词表或请求结构 |
| 字节 | 编码后的数据大小,通常是 UTF-8 字节 | 传输、存储、负载限制 | 多字节字符仍无法与 token 形成可预测映射 |
| Tokens | 模型分词器用于输入和输出的单位 | 上下文规划、用量检查、成本预测 | 取决于模型、分词器以及完整请求格式 |
| 词 | 人类可读的词边界 | 编辑长度和可读性 | 对代码、标点、中文、表情符号以及分词器行为的适用性较弱 |
一个 token 可能是一个完整的短词、较长词的一部分、标点、附着在词上的空白、代码片段,或非拉丁字符序列的一部分。这就是为什么不存在适用于所有输入的固定字符到 token 转换——也正因如此,token 数与字符数的比较必须使用真实示例。
一个 token 有多少个字符?
对于英文散文,每个 token 约四个字符是一个有用的初步经验法则。OpenAI 将其描述为经验性规则,而不是保证。Google 的 Gemini 文档给出了类似的英文估算,并明确指出对于非拉丁脚本,这个比例会更低。
这个注意事项很重要。该比例会随着以下因素变化:
- 模型和分词器;
- 语言和书写系统;
- 常见与不常见的字母序列;
- 空格、换行和标点;
- JSON、代码、表格和日志;
- 表情符号以及其他多字节 Unicode 字符;
- 聊天角色、工具定义、图片、文件以及其他请求结构。
如果将 10,000 个英文字符除以 4,结果——大约 2,500 个 token——只是一个规划估算,而不是实际计数。它对于早期电子表格来说也许足够好,但对于生产环境的上下文限制、每次请求的成本上限或回归测试来说远远不够。这正是 token 数与字符数 会改变工程决策的第一个地方。
为什么相同的字符数会产生不同的 token 数
分词器是围绕可复用的文本模式设计的,而不是围绕等长的字符块。常见模式可以压缩成更少的 token,而不常见的混合内容则会被更细粒度地拆分。
以下以 OpenAI 的 o200k_base 编码作为一个示意性的本地估算,这两个 ASCII 字符串的字符数几乎相同:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aB7!qZ9@kL2#mN4$pR6%tV8&wX0*yC1
第一个有 32 个字符,在这个示例中编码为 4 个 token。第二个有 31 个字符,编码为 27 个 token。字符数几乎没有变化;token 数量却发生了巨大变化。
这并不是对每个模型的承诺。它展示了字符限制对 LLM 预算不可靠的核心原因:分词器词表会高效识别某些序列,而将另一些序列拆成许多片段。token 计数 vs 字符计数之间的差距由模式驱动,而不仅仅由长度决定。
导致字符到 token 估算失真的四个因素
1. 语言和书写系统
英语单词通常会匹配分词器词表中的常见模式。中文不会在每个词之间使用空格,而且其字符使用多个 UTF-8 字节。更新的多语言分词器可以比旧分词器更高效地表示中文,但具体比例仍取决于所用模型。
试试这个语义对应的示例:
Summarize this customer review in three bullet points.
请用三个要点总结这条客户评价。
在同一个示意性的 o200k_base 测试中,英文行有 54 个字符和 11 个 token;中文行有 15 个字符,也有 11 个 token。字符数会让人觉得中文提示短得多,但 token 预算并没有变少。
如果是专门的多语言工作流,请参见为什么中文提示词可能使用与英文提示词不同的 token 预算。
2. 空白字符和请求格式
空白字符并不总是免费。换行、缩进、分隔符以及标点周围的空格都可能改变分词结果。在结构化提示中,即使格式本身没有带来新的业务信息,token 计数 vs 字符计数的差距也可能扩大。比较以下两个 JSON 负载:
{"task":"summarize","limit":3,"language":"en"}
{
"task": "summarize",
"limit": 3,
"language": "en"
}
在这个示意性的本地测试中,紧凑形式有 46 个字符和 15 个 token。格式化后的形式有 59 个字符和 25 个 token。漂亮的格式能提升可读性,但如果在大型工具 schema 或示例中反复出现,就会消耗相当可观的上下文。
不要盲目地压缩每一个提示词。更好的做法是衡量格式是否具有实际意义,并保留人类维护系统所需的结构。
3. 代码、标识符和看起来像随机的文本
源代码混合了关键字、缩进、运算符、路径、哈希值、UUID 和标识符。常见的语言语法可能会被高效地分词;而随机字符串、压缩后的代码、编码数据或很长的标识符则未必如此。
这就是为什么 20,000 个字符的堆栈跟踪和 20,000 个字符的产品文章不应共用一个 token 估算。如果你的应用会发送 diff、日志或文件,请使用组件级预算。我们关于代码提示的 token 计数指南展示了如何区分指令、源文件、补丁、日志和错误输出。
4. 表情符号和 Unicode 细节
两个字符串看起来同样简短,但使用的字节数和 token 数可能不同:
Launch status: ready OK
Launch status: ready ✅🚀
按基本字符计数,两行都包含 23 个字符。在这个示例性的本地测试中,纯文本行使用 5 个 token,而表情符号行使用 7 个 token。有些可见符号由多个 Unicode 码点组成,因此即使是“字符计数”,也可能因编程语言或计数方法而异。
字符计数器看不到的隐藏 token
可见的提示文本可能只是请求的一部分。生产环境调用还可能包含:
- 系统和开发者指令;
- 聊天角色和消息格式;
- 工具名称、说明和 JSON schema;
- 检索到的文档和对话历史;
- 图像、音频、文件或缓存内容;
- 模型生成的推理或其他不可见的输出 token。
OpenAI 的输入 token 计数端点接受与 Responses API 相同的请求输入格式,并包含请求格式化开销。Anthropic 提供了一个 token 计数端点用于 Messages 输入,并指出其估算结果可能与最终用量略有不同。Gemini 提供 countTokens,并且也会在生成后返回 token 用量。
重要的教训不是某个提供商计数“更好”。而是每个提供商都提供了与模型感知相关的计数,因为通用字符计数器看不到整个请求。 因此,任何严肃的 token 计数 vs 字符计数 测试都应从完整的模型输入开始。
为什么这种差异在生产环境中很重要
上下文窗口安全性
请求必须为输入和输出都留出空间。如果你的限制检查使用字符数,那么一个不利于 tokenizer 的输入即使 UI 显示低于文本限制,也可能超出可用上下文。
使用这个预算模型:
可用输入预算
= 模型上下文容量
- 预留输出 token
- 安全边际
- 已知请求开销
然后将特定模型的输入 token 计数——而不是字符计数——与可用输入预算进行比较。更多细节请阅读上下文窗口规划开发者指南。
成本预测
LLM 使用通常按输入和输出 token 进行衡量。基于字符的预测会错误估计多语言流量、重代码工作负载以及工具调用请求的成本。即使粗略的英文比例在月度平均值上可行,它也可能掩盖昂贵的请求片段。按工作负载测量 token 计数 vs 字符计数 可以让这些片段变得可见。
按工作负载类型进行预测:英文支持、中文支持、代码审查、检索、工具调用以及长对话。记录提供商实际报告的使用量,并根据生产数据更新假设。
提示词回归测试
一个小小的文案修改就可能增加一个大型 schema、重复示例或检索字段。字符数可能会捕捉到整体增长,但不一定能捕捉到特定分词器的增长。为具有代表性的请求保存 token 预算固定样本,并在提示词、工具、模型或检索模板发生变化时重新运行这些样本。
多语言产品限制
单一字符限制对文本框来说是公平的,但对于不同语言而言,它不一定是公平的 token 预算。如果业务规则基于 LLM 容量或成本,请针对每种受支持语言验证具有代表性的输入,而不是假设一个全球统一比例。
实用的计数工作流程
- 在写作界面使用字符数。 当这样做能提升可用性时,向用户显示清晰的文本限制。
- 构建完整的模型请求。 包括指令、历史记录、检索、工具 schema 和媒体输入。
- 使用目标提供商和模型进行计数。 如有可用,使用官方 token 计数端点或匹配的分词器。
- 预留输出和安全余量。 不要用输入填满整个上下文窗口。
- 运行请求并记录实际使用量。 将预检估算与提供商返回的输入、输出、缓存和总 token 进行比较。
- 按工作负载和语言分段。 跟踪分布,而不是单一的全局平均值。
- 在变更后重新计数。 模型、分词器、提示词、工具或格式变化都可能使旧比例失效。
将这些示例粘贴到 TokenTest 中
TokenTest 旨在评估在线模型端点,并检查 token 使用情况是否可信。使用下面的配对创建测试用例,在你实际计划使用的模型端点上运行它们,并比较报告的输入 token,而不是假设本地示意性的计数会完全一致。
| 测试 | 可直接粘贴的输入 | 要检查什么 |
|---|---|---|
| 相似字符,不同模式 | 上面重复的 a 字符串 vs 混合字母、数字和标点 |
尽管字符长度相似,输入用量是否会明显变化? |
| 英文 vs 中文 | 上面的双语摘要配对 | 模型特定的 token 比率是否与字符比率不同? |
| 紧凑 vs 格式化 JSON | 上面的两个 JSON 示例 | 缩进会增加多少 token 开销? |
| 纯文本 vs 表情符号 | 上面的两行发布状态文本 | Unicode 符号是否会意外增加 token 或字节? |
TokenTest 还可以帮助验证输入/输出/总用量的一致性,并运行重复的端点测试。它不能替代提供商的分词器定义;它提供的是你准备上线的端点和响应中的实时证据。
token 计数 vs 字符计数:最终规则
字符计数回答的是:“有多少文本是可见的?”Token 计数回答的是:“这次请求消耗了多少模型容量?”这两种度量彼此相关,但这种关系会随着分词器、语言、格式、内容和请求结构而变化。
只有在粗略的英文规划中,才使用“每个 token 约等于四个字符”的经验法则。对于成本控制、上下文限制、多语言预算和生产环境检查,请统计所选模型的完整请求——然后在 TokenTest 中确认端点的真实用量。
常见问题
一个 token 总是等于四个字符吗?
不是。每个 token 对应四个英文字符只是一个粗略经验法则,并不是固定换算。代码、中文、标点、表情符号、非常规字符串以及不同的分词器都可能产生差异很大的比例。
我可以把字符数换算成 token 数吗?
你可以先用英文字符数除以四,作为早期估算。在执行限制或预测支出之前,请使用目标模型的官方 token 计数方法重新统计完整请求。
空格也算作 token 吗?
空格和换行会影响分词,但一个空格并不一定等于一个 token。分词器通常会把空白字符与相邻文本合并,因此影响取决于具体序列。
中文提示词比英文提示词更占 token 吗?
有时是,但并不总是。结果取决于措辞、含义、分词器和模型。请用你计划使用的确切模型,对语义等价的样本进行比较。
为什么 API 的 token 用量会超过我本地的文本计数?
API 可能会统计消息格式、角色、工具 schema、检索到的上下文、媒体、缓存内容,或普通字符串计数器未包含的、不可见的生成 token。
我应该使用哪种 token 计数器?
优先使用与目标模型相关联的官方计数端点或分词器。使用实时请求评估来确认返回的 usage 字段在内部是一致的。