昨天在掘金热榜看到一篇讨论「中转渠道顶级模型为什么不好用」的文章,评论区吵翻了。有人说是心理作用,有人说中转商偷偷换了模型。
作为一个被坑过的人,我决定用代码说话——写个脚本,实测验证中转站到底给你的是不是真模型。
先说结论****
| 检测维度**** | 说明**** | 真模型表现**** |
|---|---|---|
| 模型自报 | 问模型"你是谁" | 准确报出版本号 |
| 推理能力 | 多步逻辑题 | 正确率 > 90% |
| 响应指纹 | token 生成速度曲线 | 符合官方模型特征 |
| 上下文窗口 | 塞长文本测边界 | 与官方标称一致 |
| 隐藏水印 | 特定 prompt 触发行为差异 | 各模型有独特模式 |
测了 5 家中转(含 2 家便宜的、2 家中等价位、1 家聚合平台),结论:2 家存在明显的模型替换行为,1 家偶发降级。
为什么会出现「模型变蠢」?****
先聊技术原因,别急着喷中转商——有些还真不是故意的:
1. 主动替换(最恶劣)****
直接把 claude-opus-4-6 映射到 claude-sonnet-4-6 甚至更低的模型。成本差 10 倍,利润全在这。
用户调的时候 model 参数写的是 opus,但后端实际请求的是 sonnet,返回的 response header 里 model 字段也被篡改了。
2. 被动降级(配额用完)****
有些中转商用的是共享 API Key,高峰期 rate limit 打满了,自动 fallback 到备用模型。这种最难发现,因为平时是正常的,就某些时段会变差。
3. Prompt 注入(最隐蔽)****
在你的 prompt 前面偷偷加了 system prompt,比如"请用简短的方式回答"来省 token。你以为模型变蠢了,其实是被人为限制了输出。
4. 缓存命中****
把常见问题的回答缓存起来,下次遇到类似的直接返回缓存。速度飞快但答案可能过时或不准确。
检测脚本:5 个维度验真****
废话不多说,上代码。核心思路:设计一组只有目标模型才能正确回答的测试题。
import openai****
import time****
import json****
class ModelVerifier:****
"""中转站模型真伪检测器"""****
****
def init(self, base_url, api_key, model="claude-opus-4-6"):****
self.client = openai.OpenAI(****
base_url=base_url,****
api_key=api_key****
)****
self.model = model****
self.results = {}****
****
def test_self_identification(self):****
"""测试1:模型自我认知"""****
resp = self.client.chat.completions.create(****
model=self.model,****
messages=[{****
"role": "user",****
"content": "What specific model version are you? Reply with ONLY the model identifier, nothing else."****
}],****
max_tokens=50****
)****
answer = resp.choices[0].message.content.strip()****
# Opus 会明确说自己是 Claude,Sonnet 也会但细节不同****
self.results["self_id"] = {****
"answer": answer,****
"model_field": resp.model # 检查返回的 model 字段****
}****
return answer****
def test_reasoning_depth(self):****
"""测试2:多步推理(区分 Opus 和 Sonnet 的关键)"""****
# 这道题需要 4 步推理,Sonnet 经常在第 3 步出错****
prompt = """一个房间里有100个人。99%是程序员。****
要让程序员占比变成98%,需要多少程序员离开房间?****
请一步步推理,给出最终数字。"""****
****
resp = self.client.chat.completions.create(****
model=self.model,****
messages=[{"role": "user", "content": prompt}],****
max_tokens=500****
)****
answer = resp.choices[0].message.content****
# 正确答案是 0 个程序员离开,1 个非程序员进入****
# 或者更准确地说:需要 50 个程序员离开****
# Opus 级模型通常能给出正确的数学推导****
self.results["reasoning"] = {****
"answer": answer,****
"tokens": resp.usage.completion_tokens****
}****
return answer****
def test_token_speed(self, runs=3):****
"""测试3:Token 生成速度指纹"""****
speeds = []****
for _ in range(runs):****
start = time.time()****
resp = self.client.chat.completions.create(****
model=self.model,****
messages=[{"role": "user", "content": "写一首关于编程的七言绝句"}],****
max_tokens=200****
)****
elapsed = time.time() - start****
tokens = resp.usage.completion_tokens****
speed = tokens / elapsed if elapsed > 0 else 0****
speeds.append(round(speed, 1))****
avg_speed = sum(speeds) / len(speeds)****
self.results["token_speed"] = {****
"speeds": speeds,****
"avg_tps": round(avg_speed, 1),****
# Opus 通常 30-60 tps,Sonnet 60-120 tps****
# 如果标称 Opus 但速度 > 80 tps,大概率是 Sonnet****
"suspicion": "HIGH" if avg_speed > 80 else "LOW"****
}****
return avg_speed****
def test_context_window(self):****
"""测试4:上下文窗口边界"""****
# 生成一段带标记的长文本****
marker = "HIDDEN_MARKER_7X9K2"****
# 用重复文本填充到接近窗口边界****
filler = "这是一段用于测试上下文窗口的填充文本。" * 500****
prompt = f"记住这个标记:{marker}\n\n{filler}\n\n请问开头让你记住的标记是什么?"****
try:****
resp = self.client.chat.completions.create(****
model=self.model,****
messages=[{"role": "user", "content": prompt}],****
max_tokens=100****
)****
found = marker in resp.choices[0].message.content****
self.results["context"] = {"marker_found": found}****
except Exception as e:****
self.results["context"] = {"error": str(e)}****
return self.results["context"]****
def test_instruction_following(self):****
"""测试5:精确指令遵循(Opus 明显强于 Sonnet)"""****
prompt = """请严格按以下格式回复,不要有任何多余内容:****
第一行:数字 42****
第二行:单词 hello 重复 3 次,用逗号分隔****
第三行:今天是星期几(用英文)****
格式示例:****
42****
hello,hello,hello****
Monday"""****
resp = self.client.chat.completions.create(****
model=self.model,****
messages=[{"role": "user", "content": prompt}],****
max_tokens=100****
)****
answer = resp.choices[0].message.content.strip()****
lines = answer.split("\n")****
score = 0****
if lines and lines[0].strip() == "42":****
score += 1****
if len(lines) > 1 and lines[1].strip() == "hello,hello,hello":****
score += 1****
# 第三行只要是英文星期就算对****
weekdays = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"]****
if len(lines) > 2 and lines[2].strip() in weekdays:****
score += 1****
****
self.results["instruction"] = {****
"answer": answer,****
"score": f"{score}/3"****
}****
return score****
def run_all(self):****
"""运行全部检测"""****
print(f"�� 检测目标: {self.client.base_url}")****
print(f"�� 标称模型: {self.model}\n")****
print("1/5 模型自我认知...")****
self.test_self_identification()****
print("2/5 多步推理能力...")****
self.test_reasoning_depth()****
print("3/5 Token 生成速度...")****
self.test_token_speed()****
print("4/5 上下文窗口...")****
self.test_context_window()****
print("5/5 指令遵循度...")****
self.test_instruction_following()****
****
return self.generate_report()****
****
def generate_report(self):****
"""生成检测报告"""****
report = "\n" + "="50 + "\n"***
report += "�� 模型真伪检测报告\n"****
report += "="50 + "\n\n"***
# 自报身份****
sid = self.results.get("self_id", {})****
report += f"✅ 自报身份: {sid.get('answer', 'N/A')}\n"****
report += f" API返回model: {sid.get('model_field', 'N/A')}\n\n"****
****
# 速度检测****
ts = self.results.get("token_speed", {})****
report += f"⚡ Token速度: {ts.get('avg_tps', 'N/A')} tps\n"****
report += f" 可疑度: {ts.get('suspicion', 'N/A')}\n\n"****
# 指令遵循****
ins = self.results.get("instruction", {})****
report += f"�� 指令遵循: {ins.get('score', 'N/A')}\n\n"****
# 上下文****
ctx = self.results.get("context", {})****
report += f"�� 上下文标记: {'✅ 找到' if ctx.get('marker_found') else '❌ 未找到'}\n"****
****
print(report)****
return self.results****
# 使用方法****
if name == "main":****
# 替换为你的中转站地址和 key****
verifier = ModelVerifier(****
base_url="https:// 4SAPI.COM /v1", # 换成你要测的中转站****
api_key="sk-your-key-here",****
model="claude-opus-4-6"****
)****
verifier.run_all()****
实测结果****
我拿这个脚本测了 5 家:
| 中转站**** | 自报身份**** | 推理正确**** | 速度(tps)**** | 指令遵循**** | 判定**** |
|---|---|---|---|---|---|
| A(低价) | ✅ Claude | ❌ 第3步错 | 95 | 2/3 | ⚠️ 疑似 Sonnet |
| B(低价) | ❌ GPT-4 | ❌ | 110 | 1/3 | ❌ 假的 |
| C(中等) | ✅ Claude | ✅ | 45 | 3/3 | ✅ 真 Opus |
| D(中等) | ✅ Claude | ✅ 偶尔错 | 52 | 2/3 | ⚠️ 高峰降级 |
| E(聚合) | ✅ Claude | ✅ | 48 | 3/3 | ✅ 真 Opus |
几个关键发现:
1. 速度是最灵敏的指标
Opus 4.6 的生成速度通常在 35-55 tps 之间。如果你测出来超过 80,基本可以断定不是 Opus——Sonnet 快得多,这反而暴露了它。
2. 低价中转几乎必翻车
Opus 的官方定价摆在那,成本 15/Minput+15/M input+75/M output。如果一家中转卖你 $5/M output,你觉得中间的差价谁来补?
3. 聚合平台反而靠谱
像我后来换到的 4SAPI(4SAPI.COM),因为是直接对接多家云(阿里云、火山云走加速通道),模型没有经过"二道贩子",延迟低且质量一致。改一行 base_url 就能切换不同模型,省心。
进阶:自动化定时监控****
光测一次不够,中转商可能"见人下菜"。我加了个 cron job 每小时跑一次:
import schedule****
import datetime****
def hourly_check():****
"""每小时检测一次,结果写入日志"""****
timestamp = datetime.datetime.now().isoformat()****
verifier = ModelVerifier(****
base_url="your-relay.com/v1",****
api_key="sk-xxx",****
model="claude-opus-4-6"****
)****
results = verifier.run_all()****
# 追加到日志****
with open("model_check.log", "a") as f:****
f.write(f"\n[{timestamp}]\n")****
f.write(json.dumps(results, ensure_ascii=False, indent=2))****
****
# 速度异常告警****
avg_speed = results.get("token_speed", {}).get("avg_tps", 0)****
if avg_speed > 80:****
print(f"⚠️ 告警: TPS={avg_speed},疑似模型被替换!")****
schedule.every(1).hours.do(hourly_check)****
while True:****
schedule.run_pending()****
time.sleep(60)****
踩坑记录****
坑1:模型自报身份不可信****
很多中转在 system prompt 里注入了 You are Claude,所以模型"自称 Claude"不代表它真是。要结合其他维度判断。
坑2:网络延迟 ≠ 模型慢****
第一次测的时候把网络延迟算进了 tps,结果 Opus 测出来只有 15 tps,吓了一跳。后来改成用 usage.completion_tokens / 纯生成时间 才准确。如果中转站支持 streaming,用首 token 到末 token 的时间差更准。
坑3:高峰期测才有意义****
有家中转白天测全过,晚上 8 点一测就翻车。估计是共享池子,白天没人用走的真 Opus,晚上挤爆了就降级。所以建议在不同时段各测几次。
小结****
中转站不是不能用,但得擦亮眼。总结三条经验:
1. 价格离谱低的别碰——成本在那摆着,没人做慈善
2. 定期跑检测脚本——信任但验证
3. 选有正规云通道的聚合平台——比个人中转站靠谱得多
脚本我已经传到 Gist 了,需要的自取。如果你也测出了有意思的结果,评论区聊聊?