3.1 编码、字符、字节和Token
字符是我们看到的字母、汉字或符号。Unicode为字符提供统一的编码体系;UTF-8是把这些编码值表示为字节的一种方式。字节是存储和传输单位;Token则是模型词表中的单位,二者不是一回事。
一个Token可能是一个字、一个词的一部分、标点或若干字节的组合。中文一字不一定对应一个Token,英文一词也不一定对应一个Token。不同模型采用不同词表,不能把固定的"字数×系数"当成精确计数。预算应使用目标模型的Tokenizer,或服务返回的实际统计。
3.2 Tokenization怎样工作
传统方法可能先用词典和规则分词。子词方法则把常见片段作为单位,把不常见的词拆开。BPE可以理解为根据训练语料不断合并常见相邻片段;WordPiece和Unigram是其他常见方案,它们的训练和切分方式不同。
以"维修预约"为例,某个词表可能切成"维修/预约",另一个可能切成"维/修/预约"。这里只展示可能形式,不代表任何具体模型的真实切分。无论如何切分,最终每个单位都映射到一个整数ID。
Token ID只是索引,不是大小等级。编号8000的Token并不比编号80的Token"语义更强"。ID通过查表得到向量,模型才对这些向量做计算。词表、特殊Token和模型参数必须匹配,随意换Tokenizer会导致输入含义错位。
3.3 特殊Token和聊天模板
模型可能用特殊Token标记序列开始、结束、角色边界、工具调用或其他结构。聊天模板把system、user、assistant等消息组织成模型训练时熟悉的格式。模板不是装饰,它影响模型判断"谁在说话"和"应该从哪里开始续写"。
同一模型权重使用错误模板,可能出现复读、角色混乱、提前结束或工具调用解析失败。但出现这些现象时,不能只凭现象认定模板有错,还要检查输出限制、停止标记、输入内容和原始响应。
3.4 上下文窗口到底装了什么
上下文窗口是一次推理能够处理的Token范围。对常见解码器模型,输入和已经生成的输出共同占用序列长度预算。输入不只是用户当前一句话,还可能包括系统提示词、历史消息、检索资料、工具说明、工具结果和模板标记。
教学预算:假设可用总预算为32768,系统与工具占4000,历史占6000,检索资料占12000,当前问题占500,计划输出占4000,则合计26500,尚有6268的余量。这个例子只说明加法关系;不同服务对输出上限、隐藏推理Token和自动压缩的计算口径必须分别核实。
"预留输出空间"不是增加总窗口,而是减少可以放入输入的空间。预留越大,不一定越稳定:如果原本输入已经很长,过大的预留反而可能提前触发压缩或拒绝请求。模型声明支持的长度,也不等于本地运行时实际配置的长度。
3.5 截断、压缩、分块与检索
截断是直接删除部分内容;压缩是把旧内容改写成更短摘要;分块是把长文拆开分别处理;检索是只选与当前问题有关的部分。它们解决的问题不同,也各有代价。压缩可能丢细节,检索可能漏证据,分块可能割裂跨段关系。
如果任务要求精确引用原文,不应仅依赖历史摘要。可以把原文保存在外部存储中,用段落ID重新取回。把所有文件一次塞入上下文通常既慢又不利于定位证据。
3.6 本章检查点
问:"我只问了一句话,为什么输入Token却很多?"答:模型可能同时收到系统提示、历史和工具等内容。检查时应看实际请求组成和计数,而不是只看聊天框里最后一条消息。