拒绝 Token 焦虑:OpenCode 上下文超限的终极指南
你是否遇到过 "Input length xx exceed" 的报错?或者发现 AI 好像"忘记"了之前的对话?
如果在 OpenCode 中遇到这类问题,往往是因为触发了模型的上下文限制。本文说明如何核对模型额度与配置。修改本地数值不会增加提供商实际允许的上下文,也不会改变订阅权益。
# 为什么会报错?#
首先要澄清一个误区:Input 不等于你输入的这段话。
当你按下回车时,OpenCode 实际发送给大模型的内容包含:
- System Prompt:OpenCode 的核心指令(定义了它是谁,能做什么)。
- Conversation History:之前的对话记录(为了保持上下文连贯)。
- Tool Outputs:工具调用的返回结果(比如读取的文件内容、终端输出)。
- User Input:你刚刚输入的这段话。
如果这些内容的总和超过了模型允许的 input limit,接口可能拒绝请求;OpenCode 的压缩机制会尝试减少后续请求的历史占用,但不能保证所有超限请求都能恢复。
# 核心策略:先核对模型额度,再按需覆盖#
核验日期:2026-10-12。 以下配置结构适用于 OpenCode 1.x,结合官方 自定义提供商示例↗ 与 v1.19.0 源码核验;不要直接套用到 OpenCode 2 的配置。
标准提供商的模型额度通常由 OpenCode 从 models.dev 自动读取,不需要为每个模型手填 limit。只有接入自定义模型,或确认模型元数据与服务端实际限制不一致时,才需要按提供商文档补充或覆盖。
## 配置位置与字段#
在项目的 opencode.jsonc 或全局 ~/.config/opencode/opencode.jsonc 中,模型额度的完整路径是 provider.<提供商 ID>.models.<模型 ID>.limit。limit 不是顶层字段;顶层 model 使用 提供商 ID/模型 ID。更多位置规则见 配置文档。
| 字段 | 含义 | 填写依据 |
|---|---|---|
context | 模型上下文窗口上限,单位为 token | 提供商对应模型与接口的文档 |
output | 模型最大输出 token 数 | 提供商的输出限制 |
input | 可选的独立输入上限 | 仅在提供商明确给出输入上限时填写 |
定义 limit 时需要包含 context 和 output。不要为了“留空间”凭空填写 input,也不要通过调大数字尝试突破服务端限制。
## 完整 JSONC 结构示例#
下面是采用 OpenAI Chat Completions 兼容接口的自定义提供商结构示例。域名、模型 ID 和额度均为占位示例,使用前需替换为真实服务的参数,并设置对应环境变量;此示例不代表任何具体模型的额度。
jsonc1{ 2 "$schema": "https://opencode.ai/config.json", 3 "model": "myprovider/my-model", 4 "provider": { 5 "myprovider": { 6 "npm": "@ai-sdk/openai-compatible", 7 "name": "My Provider", 8 "options": { 9 "baseURL": "https://api.example.com/v1", 10 "apiKey": "{env:MY_PROVIDER_API_KEY}" 11 }, 12 "models": { 13 "my-model": { 14 "name": "My Model", 15 "limit": { 16 // 示例值:必须按实际服务端限制替换 17 "context": 200000, 18 "output": 65536 19 } 20 } 21 } 22 } 23 } 24}
配置后使用 /models 核对模型名称。对于已内置的提供商,应使用其真实 ID,并仅覆盖需要调整的模型字段,不必照搬上面的自定义接口配置。
## 与压缩阈值的关系#
在 v1.19.0 的阈值实现↗ 中,有独立 input 上限时会再预留缓冲;没有时则根据 context 和有效最大输出量计算可用额度。因此,省略 input 不等于不能压缩,也不能据此断言模型会退回 4096 或 8192 的小窗口。
# OpenCode 如何减少上下文占用#
即使配置了正确的 Limit,长对话还是容易超限。OpenCode 内置了三套机制来对抗这个问题,而不是简单粗暴地报错。
OpenCode 对 Input 超过 Limit 的处理方式不是切分(Split),而是通过 压缩(Compaction)、修剪(Pruning) 和 截断(Truncation) 来减少上下文的大小。
## 1. 压缩 (Compaction) —— 让 AI 帮你做笔记#
启用自动压缩时,OpenCode 会依据模型额度与 token 使用量判断是否需要压缩任务。阈值和保留策略随版本变化,以下为机制概述。
- 原理:通过压缩 Agent 将较早的对话整理为摘要。
- 效果:后续请求使用摘要及保留的近期内容,减少历史占用;摘要可能遗漏细节,不能保证固定的压缩比例。
- 代码位置:
packages/opencode/src/session/compaction.ts
## 2. 修剪 (Pruning) —— 遗忘不重要的细节#
在编程过程中,工具调用的输出往往非常长(比如 ls -R 的结果,或者大文件的内容)。
- 原理:OpenCode 会修剪较早的工具输出,减少后续请求携带的详细内容,并保留近期结果;这不等于删除磁盘上的原始文件。
- 效果:防止历史中的工具调用(Tool Calls)像滚雪球一样占满上下文。
- 代码位置:
packages/opencode/src/session/compaction.ts中的prune函数
## 3. 截断 (Truncation) —— 最后的安全防线#
这是针对单次工具调用的硬性安全限制。
- 场景:比如你让 AI 读取一个 10MB 的日志文件。
- 处理:工具可限制单次返回的内容,向模型提供部分输出,并在支持时附上完整输出的存储路径。具体阈值和保存方式取决于工具及 OpenCode 版本。
- 注意:工具输出限制与模型额度是不同层次的控制;调高
provider.<id>.models.<id>.limit.input不会自动扩大每个工具的输出。
# 总结#
如果你的输入(包括历史记录)超过了 Limit,OpenCode 会尝试通过总结历史来腾出空间。它不会将你的单次长输入切分成多个块分批发送给模型(这通常需要 RAG 或其他复杂架构支持)。
因此,如果经过压缩后,单次请求的内容仍然超过模型的上下文限制,请求通常会直接被 Provider 拒绝(报错)。
先确认选中的模型与服务端额度一致,再按需修正 provider.<id>.models.<id>.limit。请求仍然超限时,应缩小单次输入或工具输出,而不是继续调高本地额度。