Token Counting

当 LLM 提示你的消息超出最大上下文长度时该怎么办

当 LLM 提示你的消息超出最大上下文长度时,你的请求未必是“字数太多”。请求中也可能包含隐藏指令、对话历史、检索到的文档、工具 schema、图像或预留输出,而这些都会争用同一个上下文窗口。

最快且安全的做法不是随机删除段落。先识别是什么消耗了预算,保护任务所需的输出空间,然后再删除或压缩价值最低的输入。

本指南提供一个你可以立即使用的恢复顺序、一个用于防止该错误的预算公式,以及一个合成响应夹具,你可以将其粘贴到 TokenTest production-reference evaluation console 中,在不输入 API 密钥的情况下检查令牌使用证据。

“消息超出最大上下文长度”是什么意思

模型在一次请求中只能处理有限的上下文。根据提供商和 API 的不同,这个预算可能包括:

实用规则是:

request input + reserved output + serialized overhead + safety margin
<= model context window

如果总量放不下,提供商可能会在生成前直接拒绝请求。有些系统则会裁剪较早的内容、压缩上下文,或返回更短的响应,因此具体行为取决于提供商和端点。请查阅你实际调用的模型和路由文档,不要依赖记忆中的模型上限。

先做这个:60 秒恢复序列

当消息超出最大上下文长度时,按以下顺序处理:

  1. 保存失败请求和错误的完整原样内容。 保留模型 ID、端点、输入、工具 schema、输出上限和原始错误响应。
  2. 统计完整请求结构。 在可用时使用提供商原生的 token 计数方法。只统计可见的用户提示可能会漏掉消息、工具、文件和序列化开销。
  3. 预留输出空间。 在把剩余预算用于输入之前,先决定一个有效答案需要多少空间。
  4. 移除意外重复。 重复的策略、重复的聊天轮次、复制的导航内容以及重复的检索片段通常是最安全的首批删除对象。
  5. 减少低价值上下文。 保留会影响答案的指令和证据;删除无关背景。
  6. 使用相同模型和设置重试。 一次只改一个预算变量,这样你才能判断究竟是什么修复了请求。
  7. 检查返回的 usage 和 finish reason。 即便请求不再报错,如果答案被截断或 token 统计不一致,仍可能失败。

如果你使用的是聊天界面而不是 API,等效的快速修复方法是:用一份简洁的交接摘要开启新的对话,其中包含当前目标、所需约束,以及下一步仅需要的源材料。

计算一个安全的最大上下文长度输入预算

不要把宣传中的上下文窗口当作你可见提示词的目标。应改为计算可用输入预算:

可用输入预算
= 上下文窗口
- 所需输出预留
- 工具和请求开销
- 不确定性余量

例如,假设你选择的路由支持 W 个 token 的上下文窗口。你的任务需要 R 的输出预留,你测得的工具/模式开销为 T,而安全余量为 S

最大计划输入 = W - R - T - S

在你从官方文档中验证当前模型限制之前,请始终使用符号表示。模型名称、别名、路由行为以及限制都可能变化。即使代码本身仍然可用,提示词库中的硬编码表也可能变得不正确。

输出预留中应该包含什么?

预留足够的容量以生成一个有效完成,而不只是任意完成。应包括以下内容的空间:

降低输出上限也许能让请求装得下,但这可能把上下文长度错误变成不完整的答案。如果模型因为达到长度限制而停止,请增加预留,或进一步减少输入。

按正确顺序裁剪最大上下文长度的使用量

最佳的裁剪顺序是在移除浪费的同时保留行为。

1. 删除重复内容

查找重复的系统规则、重复的示例、重复的检索段落、引用的邮件链、样板化标题,以及已经在别处总结过的对话轮次。

2. 移除不相关的检索块

检索增强生成经常失败,是因为包含了太多“可能相关”的块。应改进过滤,去重近似相同的段落,限制每个来源的块数,并优先选择能够回答问题的最小证据集。

3. 总结较早的对话历史

用结构化状态记录替换较早的轮次:

目标:
已经做出的决定:
必须保留的约束:
未解决的问题:
所需的源事实:

只有在措辞本身很重要时,才保留最近的轮次原文。

4. 先缩短示例,再处理核心说明

少样本示例可能很有价值,但长示例的成本很高。删除冗余示例,缩短其输入,并保留能够建立不同行为的案例。不要仅仅因为安全、格式或业务规则出现在提示词顶部附近,就把它们删掉。

5. 减少工具 schema

冗长的工具描述、重复的枚举、过深嵌套的 schema,以及与当前步骤无关的工具,都会消耗大量输入。只暴露本轮可用的工具,并在不改变校验要求的前提下简化描述。

6. 拆分任务

如果证据量确实过大,可以采用分阶段处理:

  1. 从每个部分提取事实;
  2. 合并并去重这些事实;
  3. 基于压缩后的证据集生成最终答案。

这比让一个请求同时阅读所有来源并写出最终答案更安全。

可直接粘贴的测试

测试 1:创建一个紧凑交接

将下面内容粘贴到你的 LLM 中,并替换方括号中的字段:

为新的对话创建一个紧凑交接。

仅保留:
1. 当前目标;
2. 已经做出的决定;
3. 不能改变的约束;
4. 未解决的问题;
5. 下一步行动所需的源事实。

删除问候语、重复解释、已放弃的选项,以及已完成的实现细节。
请用少于 [TARGET] 个词,并按以下标题返回:
Objective, Decisions, Constraints, Open Questions, Required Facts.

Conversation:
[PASTE CONVERSATION]

先使用提供方的原生工具计算结果的词数,然后用它开启一个新的对话。

测试 2:压缩检索到的证据

在不改变可支持事实的前提下,压缩下面的证据。

保留:
- 直接回答 [QUESTION] 的事实;
- 日期、数量、标识符和例外;
- 归因所需的来源标签;
- 来源之间的分歧。

删除:
- 导航和模板性内容;
- 重复的主张;
- 不影响答案的示例;
- 可用更短等价表述替代的叙述。

返回:
1. 关键事实
2. 冲突或不确定性
3. 可安全省略的事实

Evidence:
[PASTE EVIDENCE]

测试 3:在 TokenTest 中检查长度停止响应

TokenTest 目前在其主页上提供一个离线原始响应分析器。粘贴你自己端点的真实响应,或者使用这个合成诊断样本来查看预期结构:

{
  "id": "synthetic-context-test",
  "model": "replace-with-your-model-id",
  "choices": [
    {
      "message": {
        "role": "assistant",
        "content": "响应在完成请求的结构之前就停止了。"
      },
      "finish_reason": "length"
    }
  ],
  "usage": {
    "prompt_tokens": 7800,
    "completion_tokens": 200,
    "total_tokens": 8000
  }
}

这些数字仅用于示意,并非基准。请将它们替换为你的端点实际返回的响应。TokenTest 的产品手册指出,其 D4 检查覆盖使用情况存在性、总一致性、输入单调性、输出合理性、截断关联性以及缓存 token 证据。这使它有助于验证,在你修复最大上下文长度错误之后,兼容路由是否会返回你需要的证据。

在生产环境中防止最大上下文长度错误

统计组装后的请求,而不是模板

Token 计数应在变量、聊天历史、检索结果、工具和附件全部组装完成后再测量。一个很短的模板,在填入生产数据后,可能会生成一个很大的请求,并意外占用最大上下文长度。

为每个组件设置预算

为系统指令、历史记录、检索、工具、用户输入和输出定义明确的限制。在请求超过计划预算之前,就将其拒绝、摘要化或路由到其他处理路径。

保留安全余量

不要刚好运行在公开公布的上限。要为分词差异、序列化变更、提供方封装层以及未来的提示词编辑留出空间。这个余量应基于真实请求进行测量和调整,而不是从其他应用中通用地照搬。

分别测试不同语言

等效的英文和中文提示词并不一定会产生相同的 token 数。分词方式取决于具体模型和 tokenizer,因此多语言应用应在每种受支持语言中统计具有代表性的请求,而不是用固定比例去乘以英文估算值。

记录诊断故障所需的证据

对于每个请求,至少记录:

然后测试确切的生产路由。TokenTest 可以批量评估兼容的模型端点,并检查用量完整性、截断关联性、缓存证据以及其他生产就绪信号。其手册还建议使用专用测试密钥,而不是生产主密钥。

常见但适得其反的修复方法

快速修复 为什么它可能失败 更安全的替代方案
删除系统提示 移除了行为、策略或格式要求 保留不变量;缩短措辞和示例
将输出 token 设得接近零 让请求勉强容纳,但会截断回答 先定义最小有效输出预留
盲目丢弃最早的消息 删除了当前轮次所依赖的决策 将历史总结为结构化状态
保留每个检索到的片段 增加重复且相关性较弱的证据 重新排序、去重并限制证据上限
对所有模型都信任同一个分词器 会在不同提供方之间产生不准确的规划 针对实际路由使用提供方原生计数
原样重试 在没有学习的情况下重复成本和延迟 更改一个预算变量并比较遥测数据

最大上下文长度检查清单

重试之前,请确认:

FAQ

我可以通过开启一个新聊天来修复这个错误吗?

通常可以。新聊天会移除累积的历史记录。请携带一个简洁的交接内容,其中包含目标、决策、约束、未决问题和所需事实,这样你就不会丢失重要状态。

为什么当我可见的消息很短时仍会出现这个错误?

可见消息可能只是其中一个组成部分。系统指令、之前的轮次、检索结果、工具、文件、图像以及预留输出也会消耗上下文。

我应该降低最大输出 tokens 吗?

只有在先定义有效答案所需的最小容量之后才应该这么做。否则,你可能只是把请求错误换成了被截断或无效的响应。

字符数与 token 数足够接近吗?

不够。两者之间的关系会因语言、文本结构、分词器和模型而变化。请使用适合你将要调用的路由的分词器或计数端点。

更大上下文的模型能永久解决这个问题吗?

它可以提供余量,但不能修复重复检索、无上限的聊天历史、过大的工具或缺失的预算。更大的窗口只能推迟同一个架构问题,同时增加延迟或成本风险。

持久的修复是预算,而不是更大的提示

当 LLM 提示你的消息超出最大上下文长度时,可通过测量完整请求、为输出容量留出保护空间,并按价值裁剪上下文来恢复。然后,再通过组件预算、多语言测试、遥测以及生产路由验证,让修复方案长期有效。

使用 上下文窗口规划指南进行架构级预算,查看 为什么你的提示词太长以了解请求计数中的常见错误,并通过预留输出 token指南来保护答案质量。

来源