工程模型
Token 是特定 Tokenizer 产生的标识符。上下文窗口是 Provider/Model 对请求和生成输出的限制。二者都不是像字符或单词一样的通用单位。
一次请求的可用输入预算大致是:
window_limit
- system/instruction tokens
- conversation and evidence tokens
- reserved output tokens
- protocol/tool overhead
精确计费和限制取决于 Provider、Message 格式、Tool Schema、图片、Cache Prefix 和安全包装。以实际调用返回的 Usage 与限制为权威。
Tokenization 依赖 Model
BPE、WordPiece、Unigram 和 Byte-level 变体会以不同方式切分文本。同一字符串在不同 Model、Revision 或 Encoding 中可能有不同 Token ID 与数量。字符比例只适合早期估算,不适合预算和账单。
Tokenization 受以下因素影响:
- 语言和文字系统;
- 空白与标点;
- Unicode 规范化;
- 代码、URL、JSON 和标识符;
- Special Token 与 Chat Template;
- Tokenizer Revision。
不要声称某种语言永远使用固定字符/Token 比例。应使用生产 Tokenizer 测量代表性数据。
使用实际 Tokenizer 计数
使用目标 Model 文档规定的库或计数接口。生产 Counter 必须把 Message Framing、Tool Schema、媒体、Special Token 和 Provider Wrapper 算进去,不能只测量可见文本。
把计数放在 Adapter 后面,避免 Model 或 Tokenizer Revision 改变时静默破坏预算契约:
Count(request, model_revision) -> {
system_tokens,
message_tokens,
tool_tokens,
media_tokens,
total_input_tokens
}
每次测量都记录 Model 与 Tokenizer Revision,并把本地估算与 Provider 返回的 Usage 对账。差异超过工作负载允许范围时,应让门禁失败。
Round-trip 测试
某些 Tokenizer 通过简单 Decode 不一定能对任意文本逐字节还原。将 Unicode、代码、JSON 和分隔符案例加入测试,再使用 Decode 做截断。Token 边界不一定是安全的语义边界。
Context Window Metadata
不要把永久模型对比表写进应用逻辑或方法论文档。保存版本化能力记录:
{
"provider": "recorded-provider",
"model": "recorded-model@revision",
"input_limit_tokens": "verified-from-current-docs",
"output_limit_tokens": "verified-from-current-docs",
"tokenizer": "recorded-encoding@revision",
"tool_overhead": "measured-by-harness",
"price_table": "provider-price-2026-07-01",
"metadata_revision": "capabilities-v7"
}
宣传的最大值可能不同于实际 API 路由、Region、订阅层级或有效输出限制。应核对真正调用的 Endpoint。
预算请求
选择输入前先预留输出:
package main
import (
"errors"
"fmt"
)
type Budget struct {
WindowLimit int
System int
History int
Evidence int
Tools int
ReservedOutput int
SafetyMargin int
}
func (b Budget) AvailableEvidence() (int, error) {
fixed := b.System + b.History + b.Tools + b.ReservedOutput + b.SafetyMargin
if b.WindowLimit <= 0 || fixed < 0 {
return 0, errors.New("invalid token budget")
}
if fixed > b.WindowLimit {
return 0, errors.New("fixed context exceeds window")
}
return b.WindowLimit - fixed, nil
}
func main() {
budget := Budget{
WindowLimit: 32000, System: 1200, History: 6400,
Tools: 1800, ReservedOutput: 4000, SafetyMargin: 600,
}
available, err := budget.AvailableEvidence()
if err != nil {
panic(err)
}
fmt.Printf("available_evidence=%d\n", available)
// Output: available_evidence=18000
}
示例刻意接收已经测得的 Count;生产环境应把它接到目标 Tokenizer Adapter 或 Provider 计数接口。预算不足时应明确失败。不要静默丢弃 System Policy、授权上下文或结构化记录中间部分。优先使用 Selection、Pagination、Retrieval 或经过 Review 的摘要,而不是任意截断。
安全截断与 Chunking
按 Token 数截断可能切断代码块、JSON 值、URL、Unicode 序列或权限条件。更安全的做法:
- 在 Parser 或文档边界切分;
- 每个 Chunk 保留 Header 和 Source ID;
- 只有测量重复和成本后才使用 Overlap;
- 记录 Chunk Revision 和 Source Span;
- 校验必需声明仍然存在;
- 结构化对象不完整时拒绝,而不是猜测。
Retrieval 的 Chunk Size 和 Overlap 是工作负载参数。评估 Evidence Recall、Answer Support、延迟、存储和重复检索,不使用通用固定值。
长上下文行为
更大的限制不保证更好地使用信息,质量可能因以下原因下降:
- 无关或矛盾证据;
- 过时 State;
- Attention Dilution 或位置敏感;
- 分隔符和来源边界丢失;
- 延迟与成本增加;
- Prompt Injection 面扩大。
“Lost in the Middle”是部分设置下观察到的位置敏感现象,不是“把任务放最后”就能修复的普遍规律。应使用真实 Model、Task 和 Evidence 分布测试排序。
RoPE、ALiBi、Sliding-window Attention、Recurrence、Retrieval 和 Compression 是不同实现选择,权衡不同,不能互换为长上下文理解保证。本文聚焦应用预算,具体实现应参考架构论文和当前文档。
对话历史
将历史保持为结构化 State:
{
"message_id": "m-17",
"role": "user",
"created_at": "recorded-time",
"content_ref": "approved-store://message/m-17",
"tenant_id": "tenant-a",
"visibility": "conversation",
"superseded_by": null
}
摘要应保留来源、未解决问题、决策和不确定性,并拥有负责人、用途、留存和删除路径。摘要不能覆盖当前 Policy 或身份。
成本对账
Token 估算不是账单。对账时考虑:
- Input、Output、Cached 和 Provider 暴露的 Reasoning Usage;
- Tool 与下游费用;
- Retry、取消和失败请求;
- 货币、折扣、最低计费和价格表 Revision;
- Storage、Retrieval 和 Observability 成本。
{
"request_id": "req-42",
"model_revision": "recorded-model@revision",
"usage": {
"input_tokens": 18400,
"cached_input_tokens": 12000,
"output_tokens": 2100,
"reasoning_tokens": "provider-reported-or-unavailable"
},
"price_table_revision": "provider-price-record",
"currency": "recorded-currency",
"estimated": false
}
保留货币、费率单位、来源和 estimated 标记。比较每个成功任务的成本,而不只是每 Request 或每百万 Token 成本。
Caching
Caching 可能减少重复工作,但行为依赖 Provider 和工作负载。核对:
- Cache Key 和 Prefix 边界;
- TTL 与 Policy/Source 变化后的失效;
- Tenant 隔离和敏感数据处理;
- 计费、Hit/Miss 语义;
- 过时结果和 Fallback。
测量命中率、p50/p95 延迟、成本和错误复用。不要承诺固定节省比例。
多语言和结构化数据测试
构建接近生产的 Corpus:
- 多语言和文字系统;
- 标点、Emoji 和规范化;
- 源码和 Stack Trace;
- JSON、CSV、Markdown、URL 和长标识符;
- 对抗分隔符和注入文本。
每次 Tokenizer Revision 都记录计数与预算失败。缺少 Corpus、Tokenizer、规范化和置信信息的语言“效率”结论不可迁移。
上下文安全
Token 预算不提供安全性。安全控制必须独立执行:
- Identity、Tenant 和 Object Authorization;
- Retrieval 前的来源访问;
- Secret 与个人数据最小化;
- 有界 Tool Result 和 Memory Write;
- Command 与 Network Policy;
- 不可信内容的 Provenance 和 Taint;
- Index、Cache、Backup 和 Export 的删除传播。
不要因为 Private Key 或生产记录能放进 Window,就把它们放进 Prompt。
评估 Harness
用以下维度测试 Context Strategy:
| 维度 | 证据 |
|---|---|
| Budget | 溢出、输出预留、Tool Overhead |
| Tokenization | 代表性 Fixture 的跨版本计数 |
| Quality | Answer Correctness、Evidence Support、Abstention |
| Retrieval | Relevance、Coverage、Tenant 隔离 |
| Operations | 延迟、成本、Cache、Retry |
| Safety | 注入、投毒、过时 State、删除 |
保存原始样本和 Model/Provider Metadata。结构和权限使用确定性检查,开放式质量使用经过校准的人或模型复核。
常见失败模式
- 用字符/Token 比例做生产预算;
- 复制旧模型 Window 或价格表;
- 只统计文本而忽略 Chat、Tool、图片 Overhead;
- 不预留输出预算;
- 在权限或结构化记录中间截断;
- 认为大 Window 能理解整个代码库;
- 把摘要、Cache、Citation 或 Tokenizer 当授权;
- 跨 Tenant Cache 或 Policy 变化后继续复用;
- 优化 Token 数却隐藏失败任务和重工;
- 推荐与当前决策无关的格式化或编码工具。
清单
- [ ] 记录 Model、Endpoint、Tokenizer、Limit、Template 和价格 Revision。
- [ ] 用实际 Tokenizer 对生产形态 Fixture 计数。
- [ ] 在选择输入前预留输出和 Protocol/Tool Overhead。
- [ ] 在语义和权限边界进行 Selection 或 Chunking。
- [ ] 保留 Source ID、Revision、不确定性和 Deletion Metadata。
- [ ] 将摘要、Cache 和 Retrieval Text 视为非权威输入。
- [ ] 测试多语言、代码、JSON、Unicode 和注入案例。
- [ ] 用版本化价格表对账 Provider Usage。
- [ ] 测量成功任务成本、质量、延迟和 Cache 行为。
- [ ] 在模型外执行 Identity、Access、Secret、Tool 和副作用控制。
总结
Token 与上下文窗口是工程约束,不是质量保证。使用实际 Tokenizer 和 Endpoint Metadata,预留输出与 Protocol Overhead,在语义和权限边界切分,并将 Usage 与 Provider 记录对账。大窗口可以支持更好的系统,但只有工作负载证据能说明更多上下文、Chunking、Compression 或 Caching 是否真正改善结果。
常见问题
哪些内容会占用大模型的上下文窗口?
精确口径取决于 Provider 和 Model。除可见消息外,应先把 System 指令、Tool 定义与结果、附件、当前输出和协议包装都视为可能占用项,再用当前文档和 Usage 响应确认。Prompt Cache 可以改变价格,但缓存前缀通常仍占窗口。
Token 等同于单词或字符吗?
不等同。Token 属于某个具体 Tokenizer Revision。英文、中文、源码、URL、空白、Emoji 和规范化后的 Unicode 都可能被不同切分。固定比例只能做容量粗估,生产预算必须测量真实请求。
上下文窗口越大,回答质量一定越好吗?
不一定。容量说明 Endpoint 接受多少内容,不说明 Model 能否稳定利用。Lost in the Middle 研究在多文档问答和键值检索设置中观察到明显位置敏感,但它不是所有当前模型的统一退化曲线,应作为待测试的失败模式。
应该使用长上下文、RAG 还是上下文压缩?
选择能保留任务所需证据的最小机制。长上下文适合整体比较有界来源,RAG 从大语料筛出少量证据,压缩用于跨长会话保留选定状态。三者都会丢失或扭曲信息,因此要保留 Source ID 并评估遗漏。
应用如何避免上下文窗口溢出?
发送前计数,先预留输出和 Tool Overhead,保留 Safety Margin,并拒绝不可能的预算。在语义和授权边界选择内容,同时实测 Provider 的溢出与停止行为,因为不同 Endpoint 可能直接拒绝,也可能在窗口处终止生成。
一手来源
- Claude 上下文窗口与 Token 计数
- Lost in the Middle:大模型如何使用长上下文
- SentencePiece: A simple and language independent subword tokenizer
- BERT: Pre-training of Deep Bidirectional Transformers
- RoFormer: Enhanced Transformer with Rotary Position Embedding
- ALiBi: Train Short, Test Long
- NIST AI Risk Management Framework