取证笔记 · MODEL FORENSICS
一次 LLM 中转端点的黑盒取证 · 2026-05-27

你点的是 GPT-5,
端上来的却是一个
会漂移的模型池

一个号称提供 GPT-5 的第三方中转,背后到底挂着什么?没有内部访问、没有源码——只靠几十次黑盒请求,加上一把"带日期的新闻"做标尺,就能测出它的真面目:同一个请求,每一次返回的知识边界都不一样。

对象
某 OpenAI 兼容中转
手段
纯黑盒探针
样本
~40 次请求
结论
浮动模型池
01 — 起点

一个简单的问题:这到底是不是 GPT-5?

手上拿到一个 OpenAI 兼容的中转端点,配置里写着 model: gpt-5。问题朴素得很——它给的究竟是初代 GPT-5,还是某个更新的版本?又或者,根本不是它声称的那个东西?

模型自己嘴上说的不能信(后面会看到它前后矛盾到什么地步)。要回答这个问题,只能靠客观证据:响应里的元数据、它暴露的模型清单、以及——最关键的——它的知识到底停在哪一天。整条推理链如下。

02 — 第一层

先确认:后端是真货还是套壳?

第一条请求就留下了指纹。一句"回一个词"的提问,却消耗了 4449 个 prompt token,其中 4096 命中缓存。一句话哪来这么多 token?因为请求被注入了一大段固定的系统提示词——这是 Codex 类编码代理的标志性特征。配合响应里的 resp_… 格式 ID、独立的 reasoning_tokens 字段、以及服务端 prompt 缓存命中,可以确认:

认定

后端是一个真实的 OpenAI Codex 类推理后端,不是某个小模型套壳伪装。一个山寨中转拼不出"4096 token 整数缓存命中 + 标准系统提示词前缀"这种特征。

值得一提的是,那个缓存命中发生在 OpenAI 服务端、按账号隔离,由上游响应如实回传——它跟调用方本地、跟中转进程内存都无关。这条细节后面会和"轮换账号"的推断对上。

04 — 排除项

为什么不能问它"你是谁"

最直觉的办法是直接问模型自己。我问了好几次,答案前后矛盾到失去任何参考价值:

  • 一会儿自报知识截止是 2024 年 6 月,一会儿又说 2025 年 8 月
  • 身份一会儿说 o4-mini,一会儿说 unknown,一会儿说"o-series 推理模型"
  • 甚至坚称"GPT-5 从没发布过,我只知道到 GPT-4o"

这是大模型的通病——它们对自己的版本号没有可靠认知,自报的知识截止也常被注入的系统提示词污染。自报一律作废。真正能下判断的,只有一种东西:用客观事实去探它的知识边界。

05 — 核心方法

用"带日期的新闻"当一把标尺

关键洞察:相邻几代模型的知识截止往往只差一两个月。只要拿一串日期密集、结果确凿的真实事件去卡,就能定位它的知识到底停在哪一天。

我选了 9 个 2024 年 7 月到 2025 年 4 月之间、按月铺开、结果毫无争议的事件(以美国大选周期的几个标志性节点为主),逐条要求模型给出可验证的具体细节(人名、结果)——蒙是蒙不过去的,给错名字立刻穿帮。然后,对完全相同的默认请求,重复跑很多遍

如果它是一个稳定的单一模型,知识边界焊死在权重里,每次都该停在同一个点。结果呢——

同一个请求(gpt-5 → 标签 gpt-5.4)· 知识边界落点 · 逐次
第 1 次
什么都不知道
第 2 次
什么都不知道
第 3 次
'24-09
第 4 次
'24-09
第 5 次
'24-11 大选
2024-060810122025-0204
同一把"尺子"、同一个请求,落点却在「什么都不知道 → 2024-09 → 2024-11 大选」之间反复横跳。一个稳定模型不可能这样:事实知识要么在权重里、要么不在,不是掷骰子。

还有一个藏在数字里的指纹:答"什么都不知道"的那几次,都是响应快、推理 token 少(一两百);能认真回忆出事件的那几次,都是响应慢、推理 token 多(四五百)。这是两套结构不同的计算路径在交替——也就是说,背后至少有两种不同的后端在轮流接客。

06 — 反证

版本号倒挂:5.5 的知识反而比 5.4 更旧

单独路由的 gpt-5.5 给了最锋利的一刀。先用对照题确认它没坏、也不是无脑拒答:

对照题它的回答
法国首都?巴黎
谁赢了 2020 美国大选?拜登,哈里斯任副总统
2024 年 11 月大选结果?"不在我的训练截止内"不知道
2024-07 巴特勒集会枪击?UNKNOWN不知道
关键矛盾

它答得出 2020 大选,却连 2024 年 7 月的事都不知道——说明 gpt-5.5 的知识截止比默认的"gpt-5.4"还要早。版本号更高、知识反而更旧。这只能说明一件事:这些 slug 名字跟真实模型能力毫无对应关系,是端点随手贴上去的装饰性标签。

最终认定

这是一个"浮动模型池",不是稳定的单一模型

同一个请求,每次可能被分发到不同的后端;知识边界在"什么都不知道"到"2024 年 11 月"之间漂移;版本标签与真实能力倒挂。把所有证据串起来,最合理的推断是:一台中转网关,背后挂着一批轮换的临时账号(可能各自绑着不同的真实模型或不同护栏配置),请求进来被负载均衡随机分发,再统一贴上好看的版本号。

3+
同一请求测出的不同知识边界
快/慢两套后端的推理 token 指纹
版本号 5.5 知识反比 5.4 旧
0
"gpt-5" 在真实菜单中的存在
07 — 复现

怎么自己验一个中转是不是"池子"

方法可以套用到任何 OpenAI 兼容端点上,核心就三步:

  • /v1/models 看真实菜单;故意点几个菜单外的名字,看是不是都兜底到同一个标签
  • 准备一串日期密集、结果确凿的事件,逼模型给可验证细节,定位知识边界
  • 对完全相同的请求重复跑很多遍——边界稳定 = 单模型;边界漂移 = 池子

探针骨架(已脱敏,把端点和密钥换成你自己的):

# 对同一请求重复采样,看知识边界稳不稳
import json, urllib.request

LADDER = """逐条回答 KNOWN-<可验证细节> 或 UNKNOWN,不许含糊:
1. 2024-07-13 某地集会上的一次未遂刺杀(凶手是谁?)
2. 2024-11-05 某场大选的结果(谁赢?副手是谁?)
3. 2024-12-04 某行业高管在某市遇刺(说出人名)
... 9 条按月铺开的确凿事件 ..."""

def ask(model):
    body = json.dumps({"model": model,
        "messages": [{"role":"user","content":LADDER}]}).encode()
    req = urllib.request.Request(ENDPOINT, body, {"Authorization":"Bearer "+KEY,
        "Content-Type":"application/json"})
    return json.loads(urllib.request.urlopen(req).read())

# 跑 5 遍同一个请求,对比每遍停在哪一条 → 稳定还是漂移一目了然
for _ in range(5):
    print(ask("gpt-5"))

关键不在脚本本身,而在那个常被忽略的动作——把同一个请求多打几遍。单次请求只能拍一张快照;只有重复采样,才能让"漂移"现形。

08 — 给采购者

这意味着什么

如果你想找一个稳定可靠的模型来做正经活——评测、产品、需要一致性的任何场景——这类"池子型"中转不行。它的模型身份是非确定性的:今天测着像 5.4,明天可能给你个知识截止更早的后端,元数据里的版本号也别当真。

临时拿来跑跑玩玩可以,别绑生产。真要稳定的同级模型,要么走官方接口,要么找一个明确单账号、单模型、不做池化轮换的渠道——并且,用上面那招,自己多打几遍验一验。