同样调的 Claude 4 .6 Opus,为什么中转站回答明显变蠢了?我写了个检测脚本

0 阅读7分钟

 

昨天在掘金热榜看到一篇讨论「中转渠道顶级模型为什么不好用」的文章,评论区吵翻了。有人说是心理作用,有人说中转商偷偷换了模型。

作为一个被坑过的人,我决定用代码说话——写个脚本,实测验证中转站到底给你的是不是真模型

先说结论****

检测维度****说明****真模型表现****
模型自报问模型"你是谁"准确报出版本号
推理能力多步逻辑题正确率 > 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步错952/3⚠️ 疑似 Sonnet
B(低价)❌ GPT-41101/3❌ 假的
C(中等)✅ Claude453/3✅ 真 Opus
D(中等)✅ Claude✅ 偶尔错522/3⚠️ 高峰降级
E(聚合)✅ Claude483/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 了,需要的自取。如果你也测出了有意思的结果,评论区聊聊?