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

当 LLM 提示你的消息超出最大上下文长度时,你的请求未必是“字数太多”。请求中也可能包含隐藏指令、对话历史、检索到的文档、工具 schema、图像或预留输出,而这些都会争用同一个上下文窗口。
最快且安全的做法不是随机删除段落。先识别是什么消耗了预算,保护任务所需的输出空间,然后再删除或压缩价值最低的输入。
本指南提供一个你可以立即使用的恢复顺序、一个用于防止该错误的预算公式,以及一个合成响应夹具,你可以将其粘贴到 TokenTest production-reference evaluation console 中,在不输入 API 密钥的情况下检查令牌使用证据。
“消息超出最大上下文长度”是什么意思
模型在一次请求中只能处理有限的上下文。根据提供商和 API 的不同,这个预算可能包括:
- 系统和开发者指令;
- 当前用户消息;
- 之前的对话轮次;
- 检索到的文档或文件内容;
- 工具定义和 JSON schema;
- 图像、音频或文档表示;
- 模型可见的输出;
- 提供商或模型特定的内部 token。
实用规则是:
request input + reserved output + serialized overhead + safety margin
<= model context window
如果总量放不下,提供商可能会在生成前直接拒绝请求。有些系统则会裁剪较早的内容、压缩上下文,或返回更短的响应,因此具体行为取决于提供商和端点。请查阅你实际调用的模型和路由文档,不要依赖记忆中的模型上限。
先做这个:60 秒恢复序列
当消息超出最大上下文长度时,按以下顺序处理:
- 保存失败请求和错误的完整原样内容。 保留模型 ID、端点、输入、工具 schema、输出上限和原始错误响应。
- 统计完整请求结构。 在可用时使用提供商原生的 token 计数方法。只统计可见的用户提示可能会漏掉消息、工具、文件和序列化开销。
- 预留输出空间。 在把剩余预算用于输入之前,先决定一个有效答案需要多少空间。
- 移除意外重复。 重复的策略、重复的聊天轮次、复制的导航内容以及重复的检索片段通常是最安全的首批删除对象。
- 减少低价值上下文。 保留会影响答案的指令和证据;删除无关背景。
- 使用相同模型和设置重试。 一次只改一个预算变量,这样你才能判断究竟是什么修复了请求。
- 检查返回的 usage 和 finish reason。 即便请求不再报错,如果答案被截断或 token 统计不一致,仍可能失败。
如果你使用的是聊天界面而不是 API,等效的快速修复方法是:用一份简洁的交接摘要开启新的对话,其中包含当前目标、所需约束,以及下一步仅需要的源材料。
计算一个安全的最大上下文长度输入预算
不要把宣传中的上下文窗口当作你可见提示词的目标。应改为计算可用输入预算:
可用输入预算
= 上下文窗口
- 所需输出预留
- 工具和请求开销
- 不确定性余量
例如,假设你选择的路由支持 W 个 token 的上下文窗口。你的任务需要 R 的输出预留,你测得的工具/模式开销为 T,而安全余量为 S。
最大计划输入 = W - R - T - S
在你从官方文档中验证当前模型限制之前,请始终使用符号表示。模型名称、别名、路由行为以及限制都可能变化。即使代码本身仍然可用,提示词库中的硬编码表也可能变得不正确。
输出预留中应该包含什么?
预留足够的容量以生成一个有效完成,而不只是任意完成。应包括以下内容的空间:
- 所需答案长度;
- 必需的 JSON 键或 XML 标签;
- 引用、代码块或表格;
- 简单输入与困难输入之间的差异;
- 在适用时,提供方特定的推理或结构性占用;
- 用于严格输出的一小段重试或修复余量。
降低输出上限也许能让请求装得下,但这可能把上下文长度错误变成不完整的答案。如果模型因为达到长度限制而停止,请增加预留,或进一步减少输入。
按正确顺序裁剪最大上下文长度的使用量
最佳的裁剪顺序是在移除浪费的同时保留行为。
1. 删除重复内容
查找重复的系统规则、重复的示例、重复的检索段落、引用的邮件链、样板化标题,以及已经在别处总结过的对话轮次。
2. 移除不相关的检索块
检索增强生成经常失败,是因为包含了太多“可能相关”的块。应改进过滤,去重近似相同的段落,限制每个来源的块数,并优先选择能够回答问题的最小证据集。
3. 总结较早的对话历史
用结构化状态记录替换较早的轮次:
目标:
已经做出的决定:
必须保留的约束:
未解决的问题:
所需的源事实:
只有在措辞本身很重要时,才保留最近的轮次原文。
4. 先缩短示例,再处理核心说明
少样本示例可能很有价值,但长示例的成本很高。删除冗余示例,缩短其输入,并保留能够建立不同行为的案例。不要仅仅因为安全、格式或业务规则出现在提示词顶部附近,就把它们删掉。
5. 减少工具 schema
冗长的工具描述、重复的枚举、过深嵌套的 schema,以及与当前步骤无关的工具,都会消耗大量输入。只暴露本轮可用的工具,并在不改变校验要求的前提下简化描述。
6. 拆分任务
如果证据量确实过大,可以采用分阶段处理:
- 从每个部分提取事实;
- 合并并去重这些事实;
- 基于压缩后的证据集生成最终答案。
这比让一个请求同时阅读所有来源并写出最终答案更安全。
可直接粘贴的测试
测试 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,因此多语言应用应在每种受支持语言中统计具有代表性的请求,而不是用固定比例去乘以英文估算值。
记录诊断故障所需的证据
对于每个请求,至少记录:
- 提供方、路由以及返回的模型 ID;
- 在提供时记录输入、输出、缓存和总 token 用量;
- 请求的输出上限;
- 结束或停止原因;
- 历史记录和检索结果的大小;
- 工具数量和 schema 大小;
- 语言和请求类型;
- 响应是否通过结构验证。
然后测试确切的生产路由。TokenTest 可以批量评估兼容的模型端点,并检查用量完整性、截断关联性、缓存证据以及其他生产就绪信号。其手册还建议使用专用测试密钥,而不是生产主密钥。
常见但适得其反的修复方法
| 快速修复 | 为什么它可能失败 | 更安全的替代方案 |
|---|---|---|
| 删除系统提示 | 移除了行为、策略或格式要求 | 保留不变量;缩短措辞和示例 |
| 将输出 token 设得接近零 | 让请求勉强容纳,但会截断回答 | 先定义最小有效输出预留 |
| 盲目丢弃最早的消息 | 删除了当前轮次所依赖的决策 | 将历史总结为结构化状态 |
| 保留每个检索到的片段 | 增加重复且相关性较弱的证据 | 重新排序、去重并限制证据上限 |
| 对所有模型都信任同一个分词器 | 会在不同提供方之间产生不准确的规划 | 针对实际路由使用提供方原生计数 |
| 原样重试 | 在没有学习的情况下重复成本和延迟 | 更改一个预算变量并比较遥测数据 |
最大上下文长度检查清单
重试之前,请确认:
- [ ] 已知确切的模型和端点。
- [ ] 已对完整请求形态进行计数。
- [ ] 在输入之前已预留输出容量。
- [ ] 已移除重复指令和检索片段。
- [ ] 旧历史已被总结,而不是被盲目删除。
- [ ] 已排除无关工具。
- [ ] 在已验证的限制以下仍保留安全余量。
- [ ] 重试会记录用量和结束原因。
- [ ] 英文、中文和其他受支持语言分别进行了测试。
- [ ] 生产兼容路由报告了看似合理的 token 证据。
FAQ
我可以通过开启一个新聊天来修复这个错误吗?
通常可以。新聊天会移除累积的历史记录。请携带一个简洁的交接内容,其中包含目标、决策、约束、未决问题和所需事实,这样你就不会丢失重要状态。
为什么当我可见的消息很短时仍会出现这个错误?
可见消息可能只是其中一个组成部分。系统指令、之前的轮次、检索结果、工具、文件、图像以及预留输出也会消耗上下文。
我应该降低最大输出 tokens 吗?
只有在先定义有效答案所需的最小容量之后才应该这么做。否则,你可能只是把请求错误换成了被截断或无效的响应。
字符数与 token 数足够接近吗?
不够。两者之间的关系会因语言、文本结构、分词器和模型而变化。请使用适合你将要调用的路由的分词器或计数端点。
更大上下文的模型能永久解决这个问题吗?
它可以提供余量,但不能修复重复检索、无上限的聊天历史、过大的工具或缺失的预算。更大的窗口只能推迟同一个架构问题,同时增加延迟或成本风险。
持久的修复是预算,而不是更大的提示
当 LLM 提示你的消息超出最大上下文长度时,可通过测量完整请求、为输出容量留出保护空间,并按价值裁剪上下文来恢复。然后,再通过组件预算、多语言测试、遥测以及生产路由验证,让修复方案长期有效。
使用 上下文窗口规划指南进行架构级预算,查看 为什么你的提示词太长以了解请求计数中的常见错误,并通过预留输出 token指南来保护答案质量。