

当 OpenAI 分组使用本地 Codex 模型目录,且账号已有同步的上游模型元数据时,上游 max_context_window 会在同步/重新生成目录的过程中丢失。实测 gpt-6-astra 的上游最大窗口为 872000,经 Sub2API 本地目录返回后变成 272000,导致 Codex 中显式配置的长上下文被限制到约 258k。
环境
- Sub2API:
0.2.4,部署 commit:5de5e2bed035d43591a2e10e51f420ef6a84eb98。
- 部署方式:Linux / systemd。
- 客户端:macOS Codex 桌面端,内置 CLI
0.154.0-alpha.6.2;模型发现请求使用 client_version=0.154.0。
- 上游账号:OpenAI OAuth;分组内单账号,存在模型自身到自身的映射,例如
gpt-6-astra -> gpt-6-astra。
- 分组的“固定账号获取模型列表”关闭,模型白名单过滤关闭。
- 检查时主分支
4726bdd08b6201d426a80529b79be123a4008d20 仍保留下文所述逻辑;主分支仅做源码检查,未部署验证。
复现条件与步骤
使用一个上游 Codex manifest 同时返回 context_window=272000、max_context_window=872000 的模型。本次实测模型为 gpt-6-astra,同账号的 gpt-5.6-sol 也出现相同字段变化。
将该 OpenAI OAuth 账号加入 OpenAI 分组,配置上述同名模型映射,并确保账号存在已同步的 extra.upstream_model_metadata。本次发现问题时,快照中对应模型只有 context_window=272000,没有单独保存 max_context_window。
关闭分组的“固定账号获取模型列表”,使请求走本地模型目录生成路径。
Codex 使用指向该分组的自定义 provider(Responses),并配置:
model = "gpt-6-astra"
model_context_window = 1000000
model_auto_compact_token_limit = 900000
请求 Sub2API 的 GET /models?client_version=0.154.0,检查对应模型字段;刷新客户端模型缓存后检查会话声明的上下文窗口。
实际结果与期望结果
以下为同一上游账号、同一模型的实测字段:
模型列表来源 |
context_window |
max_context_window |
|---|
直接请求上游 Codex manifest |
272000 |
872000 |
Sub2API 本地生成目录 |
272000 |
272000 |
开启固定账号获取后的 Sub2API 接口 |
272000 |
872000 |
客户端在上述配置下将配置窗口限制到 manifest 声明的最大窗口,再按有效窗口比例 95% 计算:
- 出现问题时,会话日志记录
model_context_window=258400,即 272000 × 95%。
- 切换为固定账号获取、刷新模型缓存后,下一轮会话日志记录
model_context_window=828400,即 872000 × 95%。
期望本地目录保留上游的两个独立字段:默认窗口仍为 272000,最大窗口为 872000,由客户端按显式配置在最大值以内选择窗口。
代码定位
以下链接固定到实际部署 commit:
UpstreamModelMetadata 只保存 ContextWindow,没有独立的 MaxContextWindow。
upstreamMetadataFromCapabilityEntry 优先读取 entry.ContextWindow,只有其非正时才读取 entry.MaxContextWindow。当两个值同时存在时,较大的最大窗口没有被单独保留。
applyUpstreamModelMetadataToCodexDescriptor 随后把同一个值写入两个字段:
if metadata.ContextWindow > 0 {
descriptor.ContextWindow = metadata.ContextWindow
descriptor.MaxContextWindow = metadata.ContextWindow
}
这条路径使 context_window=272000, max_context_window=872000 变成两个字段均为 272000。
已做验证与临时解决方式
- 清理并重新获取 Codex 模型缓存,原问题仍存在。
- 外部接口的普通请求、禁用缓存请求和带随机查询参数请求均返回同样的错误字段,
CF-Cache-Status 为 DYNAMIC。
- 绕过 Cloudflare 和 Nginx,直接请求 Sub2API 本机监听接口,也返回同样的
max_context_window=272000。
- 开启分组的“固定账号获取模型列表”,选择原来的同一上游账号并保存后,接口恢复返回
max_context_window=872000,客户端下一轮会话声明的窗口恢复为 828400。
验证范围为模型发现接口、客户端缓存和会话声明窗口;未进行超过 272k tokens 的实际长输入压测。
建议修复
在上游元数据快照、账号能力合并和 Codex descriptor 生成过程中分别保存、处理 context_window 与 max_context_window。多账号场景继续分别执行保守的能力交集合并,并为旧快照缺少最大窗口字段的情况定义回退/重新同步策略。
建议增加回归用例:上游同时提供 272000/872000 时,完成同步并生成本地目录后仍输出 272000/872000;同时覆盖旧快照缺少 max_context_window 的情况。
相关讨论:#6745 涉及默认窗口和最大窗口的语义。本 issue 提供的是同步快照及本地目录生成路径丢失最大窗口的复现和代码定位。