Context Length Exceeded 怎么解决:上下文超限与裁剪策略
AI API 提示 context length exceeded?本文解释输入、输出、工具结果和图片如何占用上下文,并给出 Token 预估、消息裁剪、摘要、RAG 与 Agent 压缩方案。


context length exceeded、maximum context length、prompt is too long 和 input token limit exceeded 看起来像不同报错,本质上都表示:本次请求需要放进模型上下文窗口的内容,超过了当前模型或接口允许的容量。
最直接的解决办法不是无限调大 max_tokens。你需要先弄清:
输入消息
+ 系统提示
+ 工具定义
+ 工具调用与结果
+ 图片 / 文档
+ 历史回复
+ 为本轮输出预留的空间
≤ 可用上下文窗口
本文给出一套从快速止血到生产级上下文管理的完整方案,适用于聊天应用、RAG、OpenAI 兼容 API 和长时间运行的编程 Agent。
上下文窗口到底包含什么

上下文窗口不是“用户输入框最多能放多少字”。模型在一次推理中需要看到的所有内容都会占用预算:
| 内容 | 常见来源 |
|---|---|
| System / Developer 指令 | 产品规则、角色设定、安全要求 |
| 用户消息 | 当前问题和历史问题 |
| 助手消息 | 之前的回答、推理项目或状态 |
| 工具定义 | JSON Schema、MCP 工具说明、函数参数 |
| 工具调用与结果 | 搜索结果、终端日志、文件内容、API 响应 |
| 检索内容 | RAG 文档片段、引用与元数据 |
| 多模态输入 | 图片、PDF、音频或视频表示 |
| 输出预留 | 本轮答案、工具参数或推理预算 |
因此,一个只有十个对话回合的 Agent,也可能因为读取了大型日志、几十个文件和复杂工具 Schema 而超限。
上下文窗口不等于最大输出
假设一个模型的上下文上限是 W,本次输入占用 I,希望保留的最大输出为 O,还应留出安全余量 S:
I + O + S ≤ W
如果把输出上限从 2,000 调到 8,000,而输入已经接近窗口边界,错误反而更容易发生。不同 API 对输入与输出上限的计算方式可能不同,应以当前模型文档和实际错误响应为准。
为什么明明没输入很多字也会超限
工具定义每轮都会占空间
Agent 可能向模型发送几十个工具及其完整 JSON Schema。参数说明越长、嵌套越深,固定开销越高。即使本轮没有调用某个工具,它的定义也可能进入上下文。
工具输出比聊天记录更容易膨胀
常见高风险内容包括:
- 完整构建日志;
node_modules或依赖锁文件;- 大型 JSON 响应;
- 数据库查询结果;
- Base64 图片;
- 重复读取的同一文件;
- 搜索结果中大量相似片段。
Token 不等于字符数
英文、中文、代码、JSON 和随机字符串的 Token 比例不同。不能用固定的“一个 Token 等于四个字符”作为硬性判断。模型、Tokenizer 和多模态计费方式也可能不同。
服务商的实际限制可能更小
第三方网关可能:
- 为同名模型配置较小的上下文;
- 限制单次输入 Token;
- 对输出另设上限;
- 在路由到备用模型时改变容量;
- 对图片、缓存或工具使用不同计算方式。
不要只看模型营销页。应核对当前 Model ID、Provider 文档和错误响应中的实际限制。
先做这五步快速止血
1. 减少本轮输入
删除无关历史、重复文档、完整日志和不必要附件。只保留解决当前任务需要的内容。
2. 降低输出预留
如果客户端允许,先把最大输出设置为合理值。例如需要简短分类结果时,不要预留数万 Token。
3. 新建会话
当旧对话已经累积大量无关分支时,新会话通常比继续修补更可靠。先生成一份任务交接摘要,再把摘要和必要文件带入新会话。
4. 使用更大且经过确认的上下文模型
切换模型前确认:
- API 中准确的 Model ID;
- 输入和输出限制;
- 工具调用是否兼容;
- 长上下文是否需要特定请求头或方案;
- 第三方网关是否真正提供相同容量。
5. 关闭暂时不需要的工具和附件
为当前任务只提供必要工具。图片、PDF、网页快照和大型工具 Schema 都可能显著增加上下文。
如何在请求前估算 Token
最可靠的方法是使用 Provider 的 Token Counting API 或与目标模型匹配的官方 Tokenizer。不要等请求失败后才处理。
生产代码可建立预算器:
const budget = {
contextWindow: model.contextWindow,
reserveOutput: requestedOutput,
safetyMargin: Math.ceil(model.contextWindow * 0.05),
};
const maxInput =
budget.contextWindow -
budget.reserveOutput -
budget.safetyMargin;
if (estimatedInputTokens > maxInput) {
// compact, retrieve less, or reject before calling the model
}
安全余量用于覆盖消息包装、工具 Schema、Tokenizer 差异和服务端附加内容。不要把窗口用到理论上的最后一个 Token。
记录分项预算
不要只记录总 Token。至少拆分为:
system_tokens
tool_schema_tokens
history_tokens
retrieval_tokens
current_input_tokens
reserved_output_tokens
分项数据能直接告诉你应该裁剪聊天历史、工具还是 RAG 文档。
消息裁剪:不要简单删除最旧消息

最简单的滑动窗口会删除最旧消息,但可能同时删除:
- 用户最初目标;
- 已确认约束;
- 关键错误原因;
- 工具调用与工具结果的配对;
- 尚未完成的计划。
更稳健的方法是分层保留:
固定保留:系统规则、用户目标、安全约束
结构化状态:已完成事项、待办、关键决定、文件列表
压缩历史:较早对话的事实摘要
原始近期消息:最近若干轮
按需检索:旧日志、文件和文档
保持消息语义完整
裁剪时不要留下孤立的工具结果,也不要删除工具调用却保留对应结果。某些协议要求严格的消息顺序;破坏配对可能从“上下文过长”变成“请求格式无效”。
摘要应保留事实,而不是文风
好的任务摘要包含:
- 当前目标;
- 已确认约束;
- 已做决定及原因;
- 重要路径、对象 ID 与错误码;
- 已完成和下一步;
- 仍未解决的问题。
不要把长对话机械压缩成一段模糊叙述。结构化摘要更容易验证,也更适合再次压缩。
RAG:只检索真正需要的片段
把整个知识库、手册或代码仓库塞进 Prompt 既昂贵又容易超限。RAG 应控制:
top_k;- 单片段长度;
- 总检索 Token;
- 相似内容去重;
- 元数据和引用开销;
- 当前问题与片段的相关性阈值。
一种实用流程是:
- 先检索少量高相关片段;
- 对结果去重并按文档分组;
- 必要时二次重排;
- 只发送能支持答案的段落;
- 缺少证据时再扩大检索,而不是一开始就取大量内容。
长上下文不是替代检索质量的理由。无关内容越多,模型找到关键事实的难度也可能增加。
编程 Agent 如何控制上下文
文件先搜索,再读取局部
不要默认读取整个仓库。推荐顺序:
搜索文件名或符号
→ 读取命中位置附近
→ 确认相关后扩大范围
→ 修改后只返回差异和验证结果
截断并摘要终端输出
对测试和构建日志保留:
- 退出码;
- 首个关键错误;
- 相关堆栈;
- 失败测试名;
- 必要的前后文。
成功日志通常只需命令、退出码和摘要,不需要把数千行构建产物再次发送给模型。
对工具结果设置硬上限
工具层应支持:
max_bytes
max_lines
pagination
field selection
server-side filtering
超出上限时返回“内容已截断”以及继续读取的方法,而不是静默丢失尾部。
将长期状态放在上下文之外
任务数据库、工作区文件、向量库和可查询日志比无限增长的聊天历史更适合保存长期状态。模型需要时再检索相关部分。
OpenAI、Claude 与 Gemini 的上下文管理差异
OpenAI
对话可以由客户端手动重放,也可以使用 Responses API 的会话状态能力。官方同时提供 compaction 和 token counting 相关功能。无论由谁保存状态,进入下一轮模型上下文的内容仍受窗口限制;引用前一响应不代表历史免费或无限。
Claude
Claude 文档明确说明,长会话和 Agent 工作流最终会接近上下文限制,并将 server-side compaction 作为主要管理策略。工具使用、扩展思考和历史内容都需要按当前模型规则计入或管理。
Gemini
Gemini 支持长上下文,但官方仍建议理解输入 Token、模型限制和长上下文性能。大窗口不代表应发送所有内容;缓存、文件处理和检索策略仍然影响延迟、成本与答案质量。
跨 Provider 应建立统一的业务预算,再由适配层映射各自 Token 计数、会话状态和压缩功能。
常见错误做法
只调大 max_tokens
这通常增加输出预留,不能减少已有输入。应先确认错误描述和参数语义。
每次请求重发全部历史
实现简单,但成本和上下文会线性增长。应引入摘要、滑动窗口或服务端会话压缩。
超限后随机删除消息
这会破坏目标、工具配对和关键约束。裁剪策略必须可预测、可测试。
只换一个“更大上下文”的模型
若应用继续无限积累日志和文件,新窗口迟早也会用完,且调用成本和延迟可能显著增加。
自动重试完全相同的请求
上下文超限是确定性配置问题。原样重试不会缩短输入,只会浪费时间和请求额度。
一套生产级处理流程

1. 请求前估算输入和输出预算
2. 超过软阈值时先压缩历史与工具结果
3. 限制 RAG 总 Token 和工具输出
4. 保留目标、约束、决定及工具配对
5. 再次计数
6. 仍超限则切分任务或新建会话
7. 最后才考虑切换更大上下文模型
8. 记录压缩前后 Token 与被删除内容类型
建议设置两个阈值:
- 软阈值:例如窗口的一定比例,触发预防性压缩;
- 硬阈值:超过后拒绝发送,避免 API 返回错误。
比例需要根据模型、输出需求和业务风险测试,不应把某个固定百分比当成所有模型的标准。
通过 Nbility 处理上下文超限
从 Nbility 模型广场复制准确 Model ID,并核对当前模型的上下文和输出限制。OpenAI 兼容客户端通常使用:
https://api.nbility.ai/v1
出现上下文错误时,提交工单前准备脱敏信息:
Model ID
API 路径
错误 code 和 message
输入 Token 估算
输出上限参数
是否包含工具、图片或文档
是否经过第三方客户端
请求 ID 与发生时间
可通过 Nbility 工单提交。不要附带真实 API Key、完整 Prompt 或敏感文件。
如果错误同时涉及状态码或 Endpoint,可参考 AI API 错误排查指南;若模型返回成功但正文为空,可阅读 AI API 返回空内容排查。
FAQ
context length exceeded 是输入太长还是输出太长?
两者都可能影响总预算。检查错误信息、输入 Token、输出预留和模型对两者的独立限制。
换成更大上下文模型就能彻底解决吗?
不能。它只能推迟超限。没有裁剪、摘要和工具输出控制的长会话仍会继续增长。
可以直接删除最早的消息吗?
可以作为简单滑动窗口,但应保留用户目标、系统约束、关键决定及工具调用配对。重要历史更适合先摘要。
为什么图片或 PDF 很快占满上下文?
多模态输入会按 Provider 规则转换并计入输入预算,页数、分辨率和处理方式都可能影响 Token。应只发送必要页面或区域。
Prompt Cache 能扩大上下文窗口吗?
通常不能。缓存主要减少重复输入的延迟或费用;内容仍需符合模型上下文限制。以 Provider 当前文档为准。
总结
解决 Context Length Exceeded 的核心不是盲目增加参数,而是管理预算:
- 计算系统提示、历史、工具、检索和输出的总占用;
- 在请求前计数并保留安全余量;
- 分层保留目标、结构化状态、摘要和近期消息;
- 限制 RAG 片段与工具输出;
- 对长 Agent 任务使用压缩、新会话和外部状态;
- 只有在需求确实需要时才切换更大上下文模型。
上下文是一种有限资源。把它当作可观测、可分配、可压缩的预算,才能让聊天、RAG 和 Agent 在长任务中保持稳定。


