OpenAI 将于 10 月 14 日下线 GPT-5.5:一份不留坑的迁移清单

·阅读约11分钟·Evergreen Tools Team

模型下线这件事,最危险的从来不是模型本身,而是它在你系统里留下的指纹。OpenAI 已经明确:2026 年 10 月 14 日,GPT-5.5 将从 ChatGPT、ChatGPT Work 和 Codex 中退役,覆盖消费版、Business、Enterprise 和 Edu 全部计划。官方文档里同时给了两句关键信息:这次退役不适用于 OpenAI API;如果你在 Codex 里用 ChatGPT 登录,请在 10 月 14 日前切到 GPT-5.6 Sol(gpt-5.6-sol)。

"模型版本与发布"

"模型退役考验的是纪律,不是技术"

一、到底什么会消失,什么不会

先把边界划清楚,能省掉一半的恐慌。会消失的是 GPT-5.5 在 ChatGPT、ChatGPT Work 与 Codex 这三个产品里的可用性——普通用户基本无感,会话会平滑地挪到新的默认模型上。不会消失的是 API:官方明确写着这次退役不适用于 OpenAI API,也就是说任何直接调用 API 的服务不受影响。真正的风险集中在两类人身上:在 Codex 里用 ChatGPT 登录的开发者,以及那些把 gpt-5.5 这个名字写进了配置和代码的人。这种不对称就是全部问题所在:产品内的退役是产品决策、按产品的节奏走,而 API 保持契约不变。如果你的架构本来就把模型选择当成配置,这只是一次两行的改动;如果不是,它就变成一个项目。

# 1) Find every hardcoded reference, then split explicit from implicit.
#    Model names hide in configs, not just in source.
rg -n --hidden --no-ignore -g '!node_modules' -g '!.git'    'gpt-5.5|gpt-5-5|"gpt-5.5"' . | tee /tmp/model-refs.txt

grep -E '.(json|ya?ml|toml|env)$' /tmp/model-refs.txt   # config surface
grep -vE '.(json|ya?ml|toml|env)$' /tmp/model-refs.txt   # source surface

二、硬编码藏在哪:六个常见的角落

官方建议非常具体:把工作区默认值、保存的模型设置、托管配置、自定义 Agent、定时任务和脚本里所有还指向 GPT-5.5 的地方换掉。这份清单之所以长,是因为模型名会以多种形态生存:有时是一个显式字符串,有时是一个「保存的模式」下拉项,有时是某个自定义 GPT 的隐式默认值。经验做法是先做一次全仓库与全配置面的字符串扫描,把「显式引用」和「隐式依赖」分开处理,前者机械替换,后者需要逐个跑一遍。

# 2) One source of truth. Retired names should be unrepresentable.
RETIRED = {"gpt-5.5", "gpt-5.5-turbo"}

MODELS = {
    "chat_default": "gpt-5.6-sol",     # was gpt-5.5 for Codex sign-in users
    "codex_signin": "gpt-5.6-sol",
    "heavy": "gpt-6-astra",
    "cheap": "gpt-6-mini",
}

def model(key: str) -> str:
    name = MODELS[key]
    if name in RETIRED:
        raise ValueError(f"retired model selected: {name}")
    return name

print(model("codex_signin"))

三、Codex 的那条岔路

Codex 用户要区分自己是怎么登录的。用 ChatGPT 登录的,需要在 10 月 14 日前切到 gpt-5.6-sol;用 API key 的则不受这次退役影响,但也不该继续用老模型,因为版本落差会在长任务上体现出来。切换时别只改一个下拉框:把仓库里的 CI 脚本、`.codex` 之类的本地配置、团队共享的模板都过一遍。这件事最容易出错的地方是「本地改了、CI 没改」,于是一个人切好了,流水线还在跑旧模型。一个实用技巧:把鉴权方式打进日志。如果从一次运行记录里看不出它用的是 ChatGPT 登录还是 API key,你就无法判断这次退役是否影响它,最后会把同一件事迁移两遍。

// 3) Shadow pass: same requests, two models, three metrics that matter.
async function shadow(requests, oldModel, newModel) {
  const results = { parse: [0, 0], tools: [0, 0], evals: [0, 0] };
  for (const req of requests) {
    const [a, b] = await Promise.all([
      call(oldModel, req), call(newModel, req),
    ]);
    results.parse[0] += a.parsed ? 1 : 0;   results.parse[1] += b.parsed ? 1 : 0;
    results.tools[0] += a.toolArgsOk ? 1 : 0; results.tools[1] += b.toolArgsOk ? 1 : 0;
    results.evals[0] += a.passed ? 1 : 0;   results.evals[1] += b.passed ? 1 : 0;
  }
  return results;   // decide with numbers, not vibes
}

四、别直接切,先影子跑一轮

模型换代时最贵的错误是「直接换掉,等用户投诉」。稳妥做法是双跑:把同一批真实请求同时发给新旧模型,比较输出差异。重点不是看哪个「更好」,而是看三类指标——结构化输出的解析成功率、工具调用的参数正确率、以及你的评估集通过率。如果解析成功率掉了,说明提示词依赖了旧模型某种格式习惯;如果工具参数错得更多,说明需要补 few-shot 示例。这些都应该在 10 月 14 日之前跑完。

# 4) A CI guard so a retired identifier can never ship again.
import pathlib, re, sys

RETIRED = re.compile(r"gpt-5.[45](-turbo)?")

def scan(root=".", allow=("docs/", "CHANGELOG.md")):
    bad = []
    for p in pathlib.Path(root).rglob("*"):
        if not p.is_file() or "node_modules" in p.parts:
            continue
        if any(str(p).startswith(a) for a in allow):
            continue
        try:
            text = p.read_text(encoding="utf-8", errors="ignore")
        except OSError:
            continue
        for i, line in enumerate(text.splitlines(), 1):
            if RETIRED.search(line):
                bad.append(f"{p}:{i}")
    return bad

problems = scan()
if problems:
    print("retired model identifier found:")
    print("
".join(problems)); sys.exit(1)

五、提示词会漂移,这不是玄学

同一个提示词在新模型上行为不同,是正常现象:指令遵循的倾向、对格式的偏好、输出长度的默认值都可能变化。应对方式不是重写全部提示词,而是把它当成一次小版本升级:先用评估集定位哪几条提示词受影响,再针对性地加约束(明确 JSON schema、给出示例、限定输出长度)。做完之后把评估集固化进 CI,这样下一次模型换代时,你只需要跑一遍,而不是重新做一次考古。两个实现上的小结省能省不少钱:把响应缓存下来,重跑时不必再付一次;把差异按请求而不是按批次保存,这样你能直接看最差的那十个案例,而不是一个汇总数字。排查哪些提示词出问题有个好用的经验法则:失效的通常是那些依赖隐式格式约定、而不是显式 schema 的提示词。你写下来的约束会活下来,你养成的习惯不会。

// 5) Rollback in one switch. A migration without an exit is a gamble.
const MIGRATED = process.env.MODEL_MIGRATED === "1";

const ROUTES = {
  migrated: { chat: "gpt-5.6-sol", heavy: "gpt-6-astra" },
  legacy:   { chat: "gpt-5.5",     heavy: "gpt-5.5" },   // API-only fallback
};

export function pick(kind) {
  const table = MIGRATED ? ROUTES.migrated : ROUTES.legacy;
  return table[kind];
}

// Flip MODEL_MIGRATED=0 in the environment to roll back in seconds.
console.log("chat model:", pick("chat"));

六、迁移清单与回滚

五条规则。第一,先把模型名集中到一个常量或配置项,任何地方都不再出现字面量。第二,扫全仓库与配置面,把显式引用与隐式依赖分开处理。第三,影子双跑,用解析率、工具参数正确率、评估集通过率三项指标决策。第四,CI 里加一条守卫,禁止出现已退役的模型标识。第五,准备好回滚开关,让它在 30 秒内可切换。10 月 14 日不是一个技术难题,而是一次纪律测验:硬编码越少、评估越全的团队,感受到的变化就越小。还有一点:现在就开始排期,别拖到 10 月 13 日。日期是已知的、模型是已知的,剩下的唯一变量只有「你的团队在多少个地方硬编码了那个字符串」。

"配置与代码审查"

"硬编码散落在配置与脚本里"

"CI 流水线"

"用守卫禁止已退役模型标识"

📌 常见问题 FAQ

GPT-5.5 具体什么时候下线,影响哪些产品?

2026 年 10 月 14 日,从 ChatGPT、ChatGPT Work 和 Codex 中退役,覆盖消费版、Business、Enterprise 与 Edu 全部计划。

API 会受影响吗?

不会。官方文档明确说明这次退役不适用于 OpenAI API,直接调用 API 的服务不受影响。

Codex 用户该做什么?

用 ChatGPT 登录的 Codex 用户需要在 10 月 14 日前切换到 GPT-5.6 Sol(gpt-5.6-sol);记得同时更新工作区默认值、保存的模式、CI 脚本与团队模板。

为什么不能直接换成新模型?

因为提示词会漂移:指令遵循倾向、格式偏好与默认输出长度都可能变化。稳妥做法是先做影子双跑,用解析成功率、工具参数正确率与评估集通过率三项指标决策。

最该先做的一件事?

把模型名集中到一个常量或配置项,然后在 CI 里加守卫禁止出现已退役标识。硬编码越少,下次换代越轻松。