Token 到底是什么
前端工程师第一次接触 LLM API 时,很容易把输入理解成“传一段字符串给模型”。从 JavaScript 代码看,确实只是一个字符串、一个 messages 数组,或者一段 JSON。
但模型真正处理的不是字符,也不是中文词语或英文单词,而是 Token。
理解 Token,是理解上下文窗口、成本、延迟、截断、Streaming、记忆和 RAG 的起点。如果你不知道 Token 是什么,就很难解释为什么同样是一段文字,有的请求很便宜,有的请求很贵;为什么聊天记录不能无限传;为什么中文、英文、代码、JSON 的消耗不一样;为什么一次看似简单的 AI 功能会突然变慢或超出模型限制。
Token 是模型处理文本的基本单位
Token 可以粗略理解为模型读写文本时使用的“片段单位”。
它不完全等于字符,也不完全等于单词。一个 Token 可能是:
- 一个常见英文单词。
- 一个英文单词的一部分。
- 一个中文字符或几个中文字符。
- 一个标点符号。
- 一段空格。
- 一段代码片段。
- JSON 里的引号、冒号、字段名或值。
例如,英文里的 hello 可能是一个 Token,unbelievable 可能被拆成几个 Token。中文里,“前端工程师”可能被拆成多个 Token。代码里的 useEffect、const、=>、} 也会被 Tokenizer 拆成模型能理解的片段。
所以 Token 不是人类自然语言里的“词”,而是模型词表里的文本片段。
Tokenizer 负责把文本切成 Token
Tokenizer 是把原始文本转换为 Token 序列的工具。
在一次 LLM 请求里,大致会发生这样的过程:
- 应用层把用户输入、系统提示词、历史消息、工具结果等组装成文本或消息结构。
- Tokenizer 把这些内容编码成 Token。
- 模型基于输入 Token 预测接下来的输出 Token。
- 输出 Token 再被解码成人类可读的文本。
你在代码里看到的是字符串,模型内部看到的是 Token ID 序列。
这有点像前端里的 DOM 和渲染树:开发者写的是 HTML、CSS 和 JS,但浏览器内部会解析、构建、布局、绘制。Token 就是 LLM 处理文本时绕不过去的内部表示。
Token 不同于字符长度
很多工程师会下意识用 string.length 估算输入长度,但这在 AI 应用里通常不够。
原因是字符数和 Token 数没有稳定的一一对应关系。
例如:
- 一段英文自然语言可能每几个字符才形成一个 Token。
- 一段中文可能更接近“一个或几个字符一个 Token”。
- 一段 JSON 因为字段名、引号、冒号、逗号很多,Token 消耗可能比想象中高。
- 一段代码因为符号密集、命名复杂,也可能切出很多 Token。
- 重复的模板文案、系统提示词、工具描述,每次请求都会继续消耗 Token。
所以“这段文本只有 2000 个字符”不等于“它只会占很少上下文”。真正影响模型限制和成本的是 Token 数。
输入 Token 和输出 Token 都要计算
一次模型调用通常包含两类 Token:
- 输入 Token:你传给模型的内容。
- 输出 Token:模型生成的内容。
输入 Token 包括用户当前问题,也包括系统提示词、开发者提示词、历史消息、检索结果、工具定义、工具返回值、结构化输出约束等。
输出 Token 是模型回复的内容。如果你要求模型写一篇长文、生成大段 JSON、输出完整代码文件,输出 Token 就会明显增加。
很多人只关注用户输入,却忽略了“应用自己塞给模型的上下文”。在真实 AI 应用里,用户只输入一句话,但后端可能拼进去:
- 系统角色说明。
- 产品行为规则。
- 历史对话。
- 用户资料。
- 当前页面状态。
- 检索出来的文档片段。
- 可调用工具列表。
- 输出格式 Schema。
这些都算输入 Token。
上下文窗口限制的是 Token 总量
上下文窗口指模型一次请求最多能处理多少 Token。
这个窗口不是只限制用户输入,也不是只限制聊天记录,而是限制一次请求里的输入和输出预算。你可以把它理解为模型本次“工作台”的容量。
如果上下文窗口是一个固定大小的容器,那么里面要同时放:
- 系统提示词。
- 当前用户消息。
- 需要保留的历史消息。
- 检索结果。
- 工具描述。
- 工具执行结果。
- 模型即将生成的回答空间。
如果输入已经把窗口占满,模型就没有足够空间生成输出。应用层可能会遇到报错、截断、输出不完整,或者被迫裁剪历史上下文。
这就是为什么“把所有聊天记录都传给模型”不是长期可行的策略。
Token 会影响成本、延迟和稳定性
Token 不是一个抽象概念,它直接影响工程结果。
首先是成本。很多模型按输入 Token 和输出 Token 计费。请求越长,成本越高。输出越长,成本也越高。
其次是延迟。模型需要处理更多输入 Token,并生成更多输出 Token,请求时间自然会变长。即使使用 Streaming,首字延迟和总生成时间也会受到 Token 数影响。
再次是稳定性。上下文越长,无关信息越多,模型越容易被干扰。历史消息里旧的指令、过期数据、用户随口说的话,都可能影响当前回答。
所以 Token 管理不是省钱小技巧,而是 AI 应用架构的一部分。
对前端工程师的工程影响
前端工程师做 AI 应用时,Token 会影响多个看得见的产品细节。
聊天界面里,用户可能需要知道为什么某些历史被折叠、某些文件太大、某次回答被截断。
编辑器插件里,选中的代码范围会影响请求大小。传整个项目和只传当前函数,Token 消耗完全不同。
文档问答里,检索返回多少片段、每个片段多长、是否包含标题和元数据,都会影响上下文预算。
结构化输出里,JSON Schema、字段说明和示例也会占 Token。Schema 越复杂,请求越重。
工具调用里,每个工具的名称、描述、参数定义都可能进入模型上下文。工具越多,不代表效果越好,也可能增加成本并干扰选择。
这些并不只是后端问题。前端负责用户输入、文件选择、上下文入口、交互反馈和结果展示,所以也必须理解 Token 的影响。
实践建议
第一,开发阶段就接入 Token 估算或用量统计。
不要等账单异常才开始看 Token。至少要在日志里记录每次请求的输入 Token、输出 Token、模型、功能入口、用户 ID 或会话 ID。
第二,把上下文当成预算管理。
每次请求都应该问:这次任务真正需要什么上下文?哪些是必须的?哪些只是看起来有帮助?哪些可以总结、裁剪或延迟加载?
第三,避免无意识地重复塞入大段模板。
系统提示词、工具描述、Schema、固定示例如果每次都很长,会形成隐性成本。它们通常不出现在用户界面里,但会稳定消耗预算。
第四,为不同功能设计不同上下文策略。
一句话润色、长文总结、代码审查、文档问答、多轮聊天、Agent 工作流,不应该共用同一套粗暴的 messages 拼接方式。
第五,在 UI 上给用户明确边界。
当文件太大、上下文不足、历史被压缩、输出可能截断时,界面要让用户知道发生了什么。AI 产品的不确定性需要被产品体验承接。
常见误区
误区一:Token 等于字符。
Token 不是字符数。用字符长度只能做非常粗略的前端提示,不能作为严肃的成本和上下文判断。
误区二:只要模型上下文窗口足够大,就不用管理 Token。
大窗口能缓解问题,但不能消除成本、延迟和干扰。把大量无关内容塞进上下文,仍然会让系统更贵、更慢、更不稳定。
误区三:用户输入很短,请求就一定很便宜。
用户输入可能只有一句话,但应用层附加的历史、检索内容、工具定义和格式约束可能很长。成本来自完整请求,不只来自输入框里的文字。
误区四:输出越详细越好。
长输出会增加成本和等待时间,也可能让用户更难使用结果。很多产品场景需要的是可操作、可验证、可继续编辑的输出,而不是无限展开。
误区五:Token 管理是后端或模型平台的事。
Token 会影响前端交互、文件上传限制、编辑器选择范围、加载状态、错误提示和用户对产品的信任。前端工程师必须参与上下文设计。
小结
Token 是 LLM 处理文本的基本单位。它不是字符,也不是传统意义上的词,而是 Tokenizer 把文本切分后得到的模型输入输出片段。
一次 AI 请求的输入 Token 和输出 Token 共同决定成本、延迟、上下文限制和稳定性。对于前端工程师来说,理解 Token 不是为了记住一个模型内部术语,而是为了能设计更可靠的 AI 交互:知道传什么、少传什么、什么时候裁剪、什么时候提示用户,以及如何让应用在真实使用中可控。