---
title: "中转站模型真假怎么验证：五项自己能做的一致性检查"
description: "通过 API 中转站调用模型，无法百分之百证明背后是哪个模型，但能做一致性检查。本文给出 token 计数、上下文边界、工具调用、延迟吞吐、固定提示五项检查做法，并用 OpenRouter 快照解释同名模型为何表现不同。"
url: https://cdnping.org/blog/verify-model-authenticity-relay
language: zh-CN
published: 2026-10-18
category: "模型观察"
tags: ["模型验证","API 中转","模型量化","推理供应商","OpenRouter"]
source: cdnping.org
license: Free to quote and summarize with a link to the url above.
---
# 中转站模型真假怎么验证：五项自己能做的一致性检查

中转站模型真假，没有一种方法能百分之百确认：你只能看到请求和响应，响应里的 `model` 字段、错误信息、甚至“你是谁”的回答都可以被中间层改写。能做的是一致性检查，把同样的请求分别发给官方接口和中转接口，比较 token 计数、上下文边界、工具调用格式、延迟吞吐和固定提示的输出分布，几项都对得上，掉包的可能性就很低；有一项明显对不上，就值得追问。

## 为什么不能直接问模型“你是谁”？

模型的自我介绍来自训练数据和系统提示，不是运行时读取的身份信息。几个常见情况：

- 中转层可以在系统提示里写“你是某某模型”，大部分模型会照说。
- 很多模型训练语料里混有其他模型的对话，自己会报错名字。
- 响应 JSON 里的 `model` 字段是服务端填的，中转层改一个字符串就行。

所以“问一句看回答”只能排除特别粗糙的替换。真正有用的信号来自模型难以伪装的部分：分词器、上下文上限、协议细节和推理速度。

## 中转站常见的“不一致”有哪几种？

先分清楚问题类型，检查才有方向。读者遇到的“不像官方”，大致是下面四种，只有第一种是真正的掉包：

| 类型 | 说明 | 能否用一致性检查发现 |
|---|---|---|
| 换成了另一个模型 | 请求名是 A，实际调用 B（通常更便宜） | 大多能，分词器和上下文上限差异明显 |
| 同一模型，不同量化 | 开源模型由不同推理供应商部署，fp8、fp4、int4 都有 | 部分能，输出分布和速度会有差别 |
| 同一模型，改了参数 | 压低了最大输出长度、改了 temperature、截断了上下文 | 能，边界测试可以测出来 |
| 加了系统提示或缓存 | 中转层注入提示词，或对相同请求返回缓存结果 | 部分能，token 计数会多出来 |

第二种情况在开源模型上很普遍，而且不一定是有意为之。cdnping 在 2026-10-17 采集的 OpenRouter 公开数据快照里（窗口为当天单次采集，数据见 [/models](/models)），一个 DeepSeek 轻量模型的 id 下有 36 个供应商端点，其中 17 个标注 fp8、3 个 fp4、1 个 mxfp4，另外 15 个没有标注精度；一个 Kimi 新模型的 id 下有 26 个端点，9 个 fp4、7 个 mxfp4、2 个 fp8、8 个未标注。同一个模型名，背后可能是精度差别很大的部署。量化对输出的影响和怎么锁定精度，可以看[模型变笨还是换了供应商：推理供应商与 fp8、fp4 模型量化](/blog/llm-quantization-fp8-fp4-providers)。

闭源模型的情况不同。同一份快照里，Anthropic、OpenAI、Google、xAI 的模型端点精度全部是“unknown”，供应商只有官方自己和几家大云厂商。闭源模型的权重不对外发布，第三方无法自行部署。中转站如果声称提供某个闭源模型，不管中间转了几手，最终的推理只能来自官方或这类授权云平台，这一点是检查的出发点。

## 五项一致性检查怎么做？

准备工作：拿到一个官方 API Key 作为基准（下面的检查请求量不大），再拿中转站的 Key。下面的命令以 OpenAI 兼容格式为例，`<模型 id>` 换成你要验证的模型名。中转站的接口地址怎么配，可参考 [Claude Code 自定义 API 与 Codex、OpenCode 接口地址配置](/blog/configure-custom-api-endpoint-claude-code-codex)。

先写一个小函数，后面反复用：

```bash
# 用法：ask <BASE_URL> <API_KEY> <JSON 请求体文件>
ask() {
  curl -s "$1/v1/chat/completions" \
    -H "Authorization: Bearer $2" \
    -H "Content-Type: application/json" \
    -d @"$3"
}
```

### 检查一：输入 token 计数对得上吗？

不同模型家族用不同的分词器，同一段文本切出来的 token 数不一样。这是最难伪装的一项，因为中转层要伪造就得重新实现目标模型的分词器。

做法：

1. 准备一段固定文本，最好中英文、代码、emoji 混合，长度一千字左右，保存为 `probe.txt`。
2. 构造请求体，`max_tokens` 设为 1，只看输入计数：

```bash
jq -n --arg t "$(cat probe.txt)" --arg m "<模型 id>" \
  '{model:$m, max_tokens:1, messages:[{role:"user",content:$t}]}' > req.json

ask https://官方地址 $OFFICIAL_KEY req.json | jq '.usage.prompt_tokens'
ask https://中转地址 $RELAY_KEY req.json | jq '.usage.prompt_tokens'
```

3. 两个数字应该完全相同或只差几个 token（消息模板的固定开销）。如果中转返回的数字多出几十上百，通常是中转层注入了系统提示；如果差出一个比例（比如多了 20%），很可能分词器根本不是同一家。

Anthropic 官方还提供不消耗额度的 token 计数接口（Messages API 的 `count_tokens`），OpenAI 系模型可以用官方开源的 tiktoken 在本地算。注意 `usage` 字段本身也可以被改写，所以要配合下面几项一起看。

### 检查二：上下文长度的边界在哪里？

每个模型有公开的上下文上限。中转站如果换成了上限更小的模型，或者在中间截断了长对话，边界测试能直接测出来。

1. 查官方文档里该模型的上下文上限。
2. 构造一个接近上限（例如上限的 90%）的输入，在开头写一个随机字符串，最后问“开头的字符串是什么”。
3. 再构造一个明显超过上限的输入。

判断：官方接口在超限时会返回明确的错误；如果中转对超限请求也能正常回答，说明它悄悄截断了内容。如果 90% 的请求答不出开头的字符串，说明实际可用上下文比宣称的小。

### 检查三：工具调用的格式和行为一致吗？

工具调用（function calling）的细节各家不同：参数 JSON 的写法、并行调用时一次返回几个、`tool_call` 的 id 格式、`stop_reason` 或 `finish_reason` 的取值。这些是协议层面的东西，模型换了很容易露出来。

做法：定义两个简单工具（例如查天气、查时间），发一个需要同时调用两者的问题，各跑 5 次，记录：

- 是否一次返回两个调用，还是分两轮
- 调用 id 的前缀和长度
- 结束原因字段的值
- 参数里有没有多余的字段或格式错误

官方和中转的结果放在一起对比，结构上的差异比内容差异更说明问题。

### 检查四：延迟和吞吐像不像？

不同模型、不同部署的生成速度有明显特征。用流式输出测两个数：首 token 时间（TTFT）和每秒输出 token 数。

```bash
# 记录首字节时间和总耗时；BASE、KEY 分别换成官方或中转的地址与 Key
jq '. + {stream:true, max_tokens:500, stream_options:{include_usage:true}}' req.json > stream.json
curl -s -N "$BASE/v1/chat/completions" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d @stream.json -o out.txt \
  -w "首字节 %{time_starttransfer}s 总耗时 %{time_total}s\n"
# 最后一个数据块里的 usage.completion_tokens 是输出 token 数
grep -o '"completion_tokens":[0-9]*' out.txt | tail -1
```

吞吐大致等于输出 token 数 ÷（总耗时 − 首字节时间）。有些服务会先返回响应头再开始生成，首字节时间只能近似看作 TTFT。`stream_options` 是 OpenAI 兼容格式的参数，个别中转可能不支持，这时可以去掉它，改用非流式请求的 `usage` 来数输出 token。

TTFT 会受网络影响，中转多一跳，慢几百毫秒是正常的，不能单凭这个下结论。连接建立、网关往返和首 token 怎么拆开看，见 [AI API 延迟拆解：连接建立、网关往返与首 token 时间](/blog/api-latency-connect-rtt-ttft)。更有区分度的是吞吐：网络只影响开头，不影响生成过程中的速度。如果中转的每秒 token 数比官方快很多，反而要怀疑是更小的模型。

网络这一段可以先用 cdnping 的[在线测速](/)看一下你本地到各家官方 API 入口的首次连接和往返时间，把网络因素和模型因素分开。

### 检查五：固定提示的输出分布一致吗？

单次回答没有可比性，但多次回答的分布有。选几个有确定答案、又有一定难度的题（例如一道需要多步推理的算术题、一段有固定输出的代码题），temperature 设为 0，各跑 10 次：

- 统计正确率
- 看输出长度的范围
- 看措辞习惯，比如是否习惯用列表、开头是否有固定句式

同一个模型在 temperature 为 0 时输出通常高度相似（不一定完全一致）。中转的结果如果正确率明显偏低、或者风格完全不同，结合前几项一起看。这一项受量化影响较大，开源模型出现小幅差异不一定是掉包。

## 结果怎么判断？

| 检查项 | 一致 | 轻微差异 | 明显不一致 |
|---|---|---|---|
| 输入 token 计数 | 正常 | 多出固定数量：可能注入了系统提示 | 按比例偏差：分词器不同，高度怀疑换模型 |
| 上下文边界 | 正常 | 实际上限略低 | 超限不报错或长文本失忆：存在截断 |
| 工具调用 | 正常 | 个别字段不同：可能是协议转换 | 结构不同：怀疑换模型 |
| 吞吐 | 正常 | 首 token 慢：多一跳网络 | 吞吐明显更快或更慢：怀疑换模型或换部署 |
| 固定提示 | 正常 | 开源模型小幅波动：可能是量化 | 正确率和风格都偏离：结合前几项判断 |

经验上，前三项最可靠，后两项用来佐证。只要 token 计数和工具调用都对得上，基本可以排除换模型；剩下的问题多半是量化、参数或网络。

## 检查完之后还要持续关注什么？

一次检查只说明当下。中转站的上游可能随时调整，官方模型本身也会更新。几个低成本的做法：

- 把上面的脚本保存下来，每周或每次觉得“变笨”时跑一遍，和第一次的结果对比。
- 在 [/models](/models) 看开源模型在各推理供应商上的量化精度和可用率变化。同一份 2026-10-17 快照里，那个 DeepSeek 轻量模型的 36 个端点，过去 24 小时可用率最低约 88.1%，有 4 个低于 90%，22 个为 100%，详细分析见[同一模型换个 OpenRouter 供应商，可用率能差多少](/blog/same-model-different-providers-uptime)。
- 在 [/changes](/changes) 跟踪官方更新日志和价格页。官方换了默认版本，你看到的差异可能来自上游而不是中转。
- 遇到“突然变笨”，先在 [/down](/down) 看有没有其他人报告“变笨了”或故障，再判断是不是自己的通道有问题。

选中转站时能提前问清楚的事，比事后检测更省事：上游是谁、是否注入系统提示、是否做缓存、用量怎么计。完整的检查清单见 [AI API 中转站怎么选：可用率、计费、数据政策 8 项检查](/blog/api-relay-how-to-evaluate)，Claude 相关的风险点见 [Claude API 中转靠谱吗：主要风险与自查方法](/blog/is-claude-api-relay-safe)。

最后提醒一点：通过任何第三方渠道使用模型，都应该遵守上游服务的使用条款和当地法规，这些检查只用来核实你买到的服务是否名实相符。
