Token 可能是这两年开发者圈子里最容易被误解的单词。同样是token后端工程师在排查 JWT 过期和token exchange failed登录错误AI 应用开发者却在盯着 API 账单计算每一次调用消耗了多少词元。同一个单词两套完全不同的语义却可能同时出现在同一份技术方案里。这种命名碰撞不是巧合它反映了 AI 开发正在快速融入传统软件工程体系旧的术语体系和新的模型术语体系撞在了一起。如果你正在做 LLM 应用那需要关注的是词元意义上的 token。它不是一段加密字符串而是大模型理解和生成文本的基本单位。更重要的是token 在今天的 LLM 生态里至少承担了三重角色计费单位、上下文窗口的容量单位、模型推理质量的预算单位。不理解 token就很难真正掌控一个 AI 应用的成本和体验。这篇文章不从登录鉴权的角度讲 token而是从零开始讲清楚 LLM 语境下的 token模型是怎么切词的、token 数量怎么算、为什么处理中文通常更耗 token、怎么在不损失效果的前提下优化消耗以及越来越长的上下文窗口会带来哪些新问题。读完你不需要成为分词算法专家但会建立一套关于 token 的工程直觉拿到一段文本能估算出量级看到账单异常知道从哪里排查设计提示词时知道如何给模型留出足够的思考空间。1. 同一个 Token两个世界先把概念对齐先解决一个容易劝退初学者的问题你搜token 详解搜出来的一半是Cookie、Session 和 Token 详解另一半是JWT 实现 token 续签。这些文章没有错但它们讲的不是大模型语境下的 token。鉴权领域的 token 是身份凭证。它的来源是认证服务器用途是证明你是谁、你有没有权限形态通常是一串加密字符串。你反复遇到的sign-in could not be completed token exchange failed、token expired、401 invalid token都属于这一类问题。这类 token 的生命周期很短过期了要刷新作用域变了要重新换取本质上是一次授权流程的状态载体。LLM 领域的 token 是文本处理单元。它来自分词器对原始文本的切分用途是让模型能够把自然语言转换成可以计算的向量序列形态是一串数字编号。每次调用大模型 API输入的 prompt 和输出的结果都会被切分成 token账单上的费用就是由这些 token 的数量和类型算出来的。两者的共同点其实只有这个名字以及都通过某种形式在网络请求中传递这个表面现象。底层机制、生成方式、生命周期完全不同。维度鉴权 TokenLLM Token词元生成来源认证服务器、密钥签名分词器对文本的切分表达内容身份、权限、会话状态文本的基本语义单元典型形态加密字符串如 JWT数字编号组成的序列生命周期短期有效可刷新、可撤销每次调用独立生成不跨请求复用常见报错401、403、token expiredcontext length exceeded、账单异常这里想给一个明确判断学习 LLM 时如果被鉴权 token 的资料带偏会浪费大量时间。搜索资料时建议直接加限定词比如LLM token 是什么大模型 token 计算token 上下文窗口而不是单独搜token。两个世界在概念上没有任何交叉后续所有内容都只围绕 LLM 词元展开。2. 从字符到词元LLM 眼中的文本长什么样大模型本质上是一个基于概率的文本处理系统但它并不直接读取字符。模型接收的输入是一个整数序列每一个整数对应词表中的一个词元。这个过程叫做 Tokenization分词。一个 token 可以是一个完整的单词比如hello可以是半个单词比如unbelievable被切成un、believ、able几段可以是一个汉字也可以是一个标点符号。关键在于模型不会像人一样按字或单词来理解文本它按词元来理解文本。这里可以用集装箱来做类比。港口运输货物时不会把散装货物一件一件搬上船而是先把货物装进规格统一的集装箱再用吊机整体装卸。Token 就是大模型世界里的集装箱。模型本身不关心集装箱内部的具体摆放方式它只按照箱子的序号去计算语义关联。分词器负责把任意文本装进这些箱子每个箱子有一个固定编号。拿一段最简单的文本举例Hello, world!在常见的编码器下可能被切成[Hello, ,, world, !]这样的组合。unbelievable这种长单词因为完整出现的频率不够高很可能被拆成几个子词单元。中文字符通常一个字就是一个词元但也可能一个字被拆成多个更细的单元具体取决于分词器。由此可以引出第一个重要结论token 数量不等于字符数除以某个固定系数它完全取决于分词器的设计和词表内容。同样一句话用不同的模型处理token 数可能差出一倍。这也是为什么不能用一个固定公式去估算所有模型的 token 消耗。3. 分词器原理BPE 与主流 Tokenizer 的差异LLM 最常用的分词算法是 BPEByte Pair Encoding字节对编码。这个算法最初是 1994 年 Gage 提出的一种数据压缩方法后来被 GPT-2 引入 NLP 领域并成为大模型分词的主流方案。BPE 的核心思想并不复杂从字节或字符级别开始统计训练语料中相邻字符对的出现频率把最高频的相邻对合并成一个新的符号然后反复迭代这个过程直到词表达到预设大小。最终得到的词表里高频单词会以完整形式存在低频单词会被拆成子词单元。用一个非常简化的思路演示# 以简化方式演示 BPE 的合并思路 text low low low low low lower lowest words text.split() # 统计相邻字符对的出现频率 pairs {} for word in words: symbols list(word) for i in range(len(symbols) - 1): pair (symbols[i], symbols[i 1]) pairs[pair] pairs.get(pair, 0) 1 print(出现最多的相邻字符对, sorted(pairs.items(), keylambda x: -x[1])[:3])在这个例子里l和o的组合出现次数最高会被合并成lo然后lo和w又会因为高频继续合并成low。真实训练中分词器面对的是几十 GB 甚至更大的语料反复迭代几万次之后就形成了模型固定的词表Vocabulary。不同模型使用的分词器并不一样BERT 系列常用 WordPiece它按频率选择合并的规则略有不同。T5 等模型使用 SentencePiece把空格也当作普通字符处理适合多语言场景。GPT-3.5、GPT-4 系列使用 cl100k_base 编码器词表约 10 万个词元。更新的 GPT-4o 等模型使用 o200k_base 编码器词表约 20 万个词元对中文、代码等场景的切分效率更高。词表里的词元数量是分词器质量的一个直接体现。词表越大模型能直接表示的 token 越多切分后的 token 数通常越少。但这也会带来词表嵌入层参数量的增加所以模型设计者需要在词表大小和模型体积之间做权衡。理解 BPE 的意义在于当你发现一段中文被切出大量 token 时不要觉得是模型笨。这是分词器在训练语料上统计高频组合后的必然结果。如果一个中文字符在训练语料中出现频率不够高它就可能被拆成两个甚至更多字节级 token消耗自然就上去了。4. Token 为什么重要成本、容量、质量三重影响Token 并不是一个孤立的技术概念。它在实际工程中直接决定了三件事账单金额、上下文容量和输出质量。4.1 计费单位几乎所有主流 LLM API 都按 token 计费。调用一次接口输入部分按 input token 计价输出部分按 output token 计价两者单价往往不同通常输出比输入更贵。此外不同模型的价格差异可能达到一个数量级以上。很多平台还引入了缓存机制。如果 prompt 的一部分在短时间内重复出现服务商可以把这部分内容缓存起来。缓存读取一般比正常输入便宜得多但缓存写入往往会额外收费。也就是说缓存并不是无条件省钱配置不当反而可能让 token 消耗更多。这里先给一个判断在 API 调用中token 就是钱。一个不关心 token 消耗的开发者和一个把 token 纳入核心度量指标的开发者写出的应用成本可能相差 5 到 10 倍。4.2 上下文窗口的容量单位模型的上下文窗口Context Window用 token 衡量。常见的模型有 4K、8K、32K、128K 甚至 1M 的窗口。窗口是一段共享预算输入 prompt 占用的 token 加上输出需要生成的 token两者之和不能超过窗口上限。实际开发中max_tokens参数就是给输出预留的空间。如果 prompt 太长挤占了输出空间模型可能只写了一半就被截断。这也是很多应用回答越来越短的直接原因。处理这个问题不能只调参数要从输入侧做压缩。4.3 输出质量的预算这是很多人忽略的一点。模型的推理输出是有节奏的尤其是带有思维链能力的模型它需要在输出 token 里完成思考过程。如果输出预算被压缩到很小模型就没有足够的空间展开推理回答质量会明显下降。从这个角度看token 更像是模型的思考预算。系统提示词占用太多相当于让模型在狭小的空间里思考给输出预留太少相当于做卷子时只发给半张答题纸。调优一个 LLM 应用本质上是在调整这三部分 token 的分配比例系统提示词、对话历史、输出空间。很多产品还会在 token 之上再包装一层 credits。Credits 是平台自定义的结算点数1 次请求消耗多少 credits由平台在底层 token 数的基础上乘以系数、加上功能溢价得出。你不需要精确推算 credits 和 token 的换算公式但应该知道二者不是固定汇率不同模型、不同时段、不同功能都可能不同。4.4 一天消耗多少 token 才算入门这是一个常被问到的问题但没有标准答案。可以按量级来估算一个日常用 ChatGPT 辅助写代码、偶尔调 API 的开发者一天消耗几万到十几万 token 很正常一个重度依赖 AI 编程助手、同时跑自动化测试和多轮 Agent 任务的开发者一天消耗百万 token 并不夸张。真正值得关注的不是绝对数字而是你对自己的应用有没有用量感知。如果你完全不知道一次请求消耗多少 token大概率也没有做好成本控制。5. Token 数量计算方法tiktoken 实践与 usage 字段解读工程上需要精确计算 token不能靠猜。最常用的方式是使用 OpenAI 开源的 tiktoken 库。它的作用就是复现 OpenAI 各模型的 tokenizer 逻辑在本地完成切分。先安装依赖pip install tiktoken然后写一个最简单的 token 统计脚本# 示例使用 tiktoken 统计 token 数量 import tiktoken # 直接用编码器名称获取 enc tiktoken.get_encoding(cl100k_base) text Hello, world! This is a token counting demo. tokens enc.encode(text) print(原始文本, text) print(Token 数量, len(tokens)) print(Token ID 列表, tokens) print(解码还原, enc.decode(tokens))这段代码的核心是enc.encode(text)它把文本切分成 token 数量每个 token 对应一个整数 ID。decoder可以把 ID 序列还原成原始文本用于校验切分是否可逆。更推荐的方式是按模型名获取编码器避免选错 tokenizerimport tiktoken def count_tokens(text: str, model: str gpt-4) - int: 根据模型返回对应的编码器并统计 token 数 try: enc tiktoken.encoding_for_model(model) except KeyError: # 找不到对应模型时回退到 cl100k_base enc tiktoken.get_encoding(cl100k_base) return len(enc.encode(text)) def check_context_budget( prompt: str, max_context: int 8192, reserved_output: int 1024 ) - int: 检查 prompt 是否超出上下文预算 prompt_tokens count_tokens(prompt) available max_context - reserved_output if prompt_tokens available: print(f[警告] prompt 占用 {prompt_tokens} token超出可用预算 {available}) print(f需要压缩 {prompt_tokens - available} token) else: print(f[正常] prompt 占用 {prompt_tokens} token可用预算 {available}) return prompt_tokens prompt 你是一名资深 Java 架构师请根据用户需求给出代码方案并解释关键设计。 check_context_budget(prompt)encoding_for_model会读取该模型对应的编码器配置。如果模型名称很新、本地库还没收录就回退到通用编码器做估算。这里要注意本地估算只是近似值最终以服务端返回的 usage 字段为准。大多数 LLM API 的响应体里都带有用量信息。以类 OpenAI 协议为例{ id: chatcmpl-xxx, model: gpt-4, usage: { prompt_tokens: 156, completion_tokens: 89, total_tokens: 245 } }prompt_tokens是输入消耗completion_tokens是输出消耗两者相加就是total_tokens。生产环境的日志系统应当记录每一次请求的这个字段这是成本监控的数据基础。如果只是快速验证某个文本的 token 量不想写代码可以使用各种在线的 token 计数工具或者用浏览器里的可视化 tokenizer 页面。不过线上工具未必能覆盖最新模型正式项目还是建议在代码里集成 tiktoken 或同类型库。# 以 curl 调用大模型 API 为例响应体中包含 usage 字段 curl -X POST https://api.example.com/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer ${API_KEY} \ -d { model: gpt-4, messages: [ {role: user, content: 用一句话解释什么是 token} ], max_tokens: 200 }注意把 API 密钥放在环境变量里不要硬编码到代码中。实际接入时请以你所使用服务商的接口文档为准这里的例子只演示通用思路。6. 中英文 Token 消耗差异为什么中文感觉更贵很多开发者第一次算中文 token 时会惊讶明明只有几十个字符怎么算出上百个 token这不是幻觉而是分词器的真实表现。原因要从 BPE 的训练语料说起。早期模型的训练语料以英文为主导词表里英文单词和子词的覆盖度很高而中文字符出现的频率相对分散。在 cl100k_base 这类编码器上一部分常用汉字可以一个字符对应一个 token但生僻字、组合词或特殊符号可能需要多个 token 才能表示。同样表达大型语言模型这个意思英文large language model可能只要 3 到 5 个 token中文却可能超过 10 个 token。可以写一个对比脚本直观感受import tiktoken enc tiktoken.get_encoding(cl100k_base) english_text Large language models process text by splitting it into tokens. chinese_text 大型语言模型通过分词技术将文本切分为词元序列。 en_tokens enc.encode(english_text) cn_tokens enc.encode(chinese_text) print(f英文字符数: {len(english_text)}) print(f英文 Token 数: {len(en_tokens)}) print(f中文字符数: {len(chinese_text)}) print(f中文 Token 数: {len(cn_tokens)}) print(f中文 Token 明细: {[enc.decode([t]) for t in cn_tokens]})运行这段代码大概率会看到英文句子的 token 数明显少于同义中文句子的 token 数具体数值取决于 tiktoken 版本和编码器细节。中文 Token 明细那一行会显示中文被切成了什么样的片段有些是完整汉字有些是奇怪的组合这就是字节级拆分的痕迹。这个差异带来的工程影响很直接同样的成本预算英文应用能处理更多内容。中文提示词要更注意精简避免无意义的客套话。设计多语言产品时中英文版本的 token 消耗要分开评估。不过要提醒一句不要为了省 token 牺牲语义表达。中文信息密度本身很高短句可能表达丰富含义。优化的方向是删掉冗余、合并重复信息而不是把中文硬翻译成英文再喂给模型——翻译本身也消耗 token而且可能丢失原意。7. 常见 Token 问题与排查思路实际开发中token 相关的问题通常集中在几个固定场景。下面这张表可以直接用作排查清单问题现象可能原因排查方式解决方案请求报错 maximum context length exceededprompt 太长超出上下文窗口查看错误信息中的 token 数和窗口上限压缩历史消息、截断早期对话、改用更大窗口模型输出突然变短或经常中断max_tokens 设置太小或输入挤占输出预算检查请求参数和 usage 字段调高 max_tokens压缩输入侧内容账单金额比预期高很多多轮对话历史不断累加或触发缓存写入费用分析日志中 total_tokens 的趋势实现滑动窗口、对历史做摘要、合理配置缓存本地 tiktoken 计算和官方 usage 不一致本地用错了 tokenizer确认 encoding_for_model 是否匹配模型按模型名称获取编码器以服务端 usage 为准接口报 token exchange failed / 401这是鉴权 token 问题不属于词元问题检查认证配置、密钥、请求头重新获取访问凭证确认权限范围配置缓存后 token 反而增加缓存写入本身有额外计费对比缓存命中前后的 usage只对稳定不变的 system prompt 启用缓存多语言场景费用差异大不同语言 token 切分效率不同用 tiktoken 分别统计各语言文本调整文案长度或换用对中文更友好的新编码器模型排查 token 问题有一个基本原则先看日志里的 usage再看参数配置。usage字段是服务端给出的最终裁决本地估算只能作为辅助判断。很多为什么这么贵的问题打开一次请求的 usage 日志答案就出来了。这里要特别区分两类报错。如果你的应用在登录、鉴权阶段报token exchange failed、401 invalid token那和 LLM 词元完全没有关系不要按照上下文窗口去排查应该回到认证服务配置。这个区分在团队协作中尤其重要避免把时间花在错误的排查路径上。8. 降低 Token 消耗的工程实践与最佳实践控制 token 消耗并不是一味地压缩输入而是把有限的 token 预算花在最有价值的地方。以下实践按优先级排列。8.1 精简系统提示词很多应用的 system prompt 动辄上千字包含大量背景说明、文体约定、示例输出。压缩空间通常很大删掉模型已经内隐知道的常识、合并重复的规则、把长句子改写为短指令。建议每过一段时间就 review 一次 system prompt观察它对 token 的占用比例。一个值得养成的习惯是把 system prompt 与用户输入分开统计。如果 system prompt 占总 token 消耗的一半以上说明固定成本过高压缩它带来的收益最大。8.2 多轮对话的滑动窗口与摘要多轮对话是 token 消耗的大户。每轮追加的新对话都会连同历史一起发送对话次数越多token 增长越快。常见优化方案有两种滑动窗口只保留最近 N 轮对话超出部分直接丢弃。摘要压缩对早期对话做一次摘要用一两句话代表整段历史再和新对话拼接。更复杂的方案是为摘要单独维护一个记忆 token 预算当摘要内容超过阈值时再压缩一次摘要。这种递归压缩的开销远低于每次都发送完整历史。8.3 合理使用缓存这里回应一个常见疑问缓存越多消耗的 token 越多吗严格说缓存写入会额外计费但缓存读取通常远低于正常输入价格。关键在于命中率。如果你的 system prompt 固定不变、对话历史前 N 轮反复出现缓存命中率高整体成本会下降。如果每次请求的 prompt 都完全不同缓存反而可能增加成本。建议只对稳定部分启用缓存并且观察命中率后再调整。8.4 使用结构化输出让模型以 JSON 等结构化格式输出表面上看是多消耗了一些格式 token但在实际工程项目里它能显著减少后续解析重试的次数。一次失败的解析可能需要重新调用模型一次重试的成本远超几个格式 token。如果结构固定还可以用严格的 JSON Schema 约束输出避免模型输出冗余说明文字。8.5 任务分级与模型选择不是所有请求都需要大模型的最强能力。简单的分类、抽取、格式转换可以交给更小的模型小模型往往更便宜、token 限制也低。把复杂任务分配给大模型、简单任务分配给小模型是成本优化最有效的手段之一。这也解释了为什么很多聚合平台既要提供旗舰模型又要保留轻量模型成本模型决定了应用能否规模化。8.6 日志、监控与预算上限生产环境一定要记录每一次请求的prompt_tokens、completion_tokens、模型名和耗时按用户、按场景、按天聚合。有了数据才能知道优化方向。同时要设置预算告警比如单日 token 消耗超过阈值时通知负责人。成本失控从来不是瞬间发生的而是从没有监控开始的。9. 从 Token 到 Token 工程LLM 应用的必修课最后聊一个更大的趋势token 正在从一个技术概念变成一类工程体系。一方面模型的上下文窗口越来越大1M、2M 甚至更长的窗口不再是理论目标。但更长的窗口不等于更低的成本。当你可以把整本书塞进上下文时单次请求的 token 数也会成倍增长计费模型会让长上下文变成一种需要管理的资源而不是可以随意挥霍的福利。未来的模型应用会面临一个有趣的问题能力上限提升了但成本模型要求你仍然保持克制。另一方面行业里已经开始出现面向词元计量计费的管理规范讨论。从公开信息看国内也在推进人工智能词元计量计费相关的管理能力要求标准这意味着 token 不只是开发者圈子的技术话题还会逐步进入工程规范、运维体系和商业结算流程。对开发者来说早点把 token 纳入应用的度量体系就是在为这些规范落地做准备。还有一个容易被低估的方向Agent 应用的 token 消耗。传统 API 调用是一次性的用户问一句模型答一句。Agent 应用则不同它会自主规划步骤、调用工具、观察结果、反思修正。每一步都在消耗 token而且中间步骤的错误还会导致重试。从这个角度看Agent 本质上是 token 的自动化消耗器。设计 Agent 时如果不给 token 预算设定边界一次任务跑出天价账单是完全可能的。落到工程实践上可以给自己立三条规矩每次接入模型 API第一件事就是把 usage 日志接好否则后续所有优化都没有依据。任何 prompt 上线前先用 tiktoken 计算固定部分和动态部分的 token 占比确认模型窗口能稳定容纳最坏情况。把 token 消耗当作和延迟、错误率同等重要的核心指标而不是事后的账单焦虑。Token 这个概念看似简单但它连接着分词算法、计费模型、上下文管理和产品体验。把从模型如何切词到应用如何分配预算这条链路想清楚你就真正理解了 LLM 应用的成本本质。建议下一步找一个在线 tokenizer 页面亲手把一段中文和一段英文放进去对比建立自己的体感再回到项目里看一眼 usage 日志你的 token 工程之旅就从这里开始了。