国内调 GPT/Claude/Gemini API,我实测了 6 个平台只留了 2 个

7 阅读8分钟

上个月接了个私活,甲方要做一个多模型对比的小工具——用户输入一个 prompt,同时调 GPT-4o、Claude 3.5 Sonnet、Gemini 1.5 Pro,把三家结果并排展示。

需求不复杂,但第一个问题就把我卡住了:这三家的 API 在国内都不能直连。

我之前自己用的方案是在服务器上挂代理,但这是给甲方部署的项目,不可能让他们也搞一套代理环境。所以只能找国内能直连的 API 中转/聚合平台。

花了差不多一周时间,前前后后测了 6 个平台,踩了不少坑,这篇把我的实测过程和结论分享出来。

先说结论

平台模型丰富度兼容 OpenAI 协议国内延迟稳定性我的评价
平台 A(某知名大厂转发)⭐⭐⭐一般高峰期偶尔 429模型少,只有 GPT 系列
平台 B(GitHub 上找的开源项目)⭐⭐⭐⭐挂了两次个人项目,不敢用在生产
平台 C(Telegram 群里推荐的)⭐⭐部分兼容没测完就放弃了注册流程劝退
平台 D(某国产聚合站)⭐⭐⭐还行定价不透明
ofox.ai⭐⭐⭐⭐⭐测试期间没挂过最后留下来了
平台 F(朋友推荐的小站)⭐⭐⭐❌ 自定义协议一般还行要改代码适配,懒得搞

最终留了两个:日常开发和这个项目用 ofox.ai(聚合接口,一个 Key 调所有模型),另外保留了平台 D 做备用。

我为什么需要「聚合平台」而不是单独接每家

可能有人会说,直接用各家官方 API 不就行了?

说实话一开始我也是这么想的。但实际做下来发现几个很现实的问题:

1. 鉴权方式不统一

OpenAI 用 Bearer Token,Claude 的 Messages API 用 x-api-key header,Gemini 早期版本甚至是 URL 参数带 key。三家 SDK 都要装,三套鉴权逻辑都要写。

2. 请求/响应格式不一样

Claude 的 messages 接口和 OpenAI 的 chat/completions 长得像但细节不同(比如 system 消息的处理方式)。Gemini 更是完全另一套 JSON 结构。

3. 国内网络问题

这个不多说了,懂的都懂。

所以如果有一个平台,能用统一的 OpenAI 兼容协议调所有模型,改一下 base_urlmodel 参数就能切换,那开发效率直接翻倍。

实测过程

测试方法

我写了一个简单的测试脚本,对每个平台做三件事:

  1. 可用性测试:分别调 GPT-4o、Claude 3.5 Sonnet、Gemini 1.5 Pro(如果平台支持的话)
  2. 延迟测试:同一个 prompt 跑 10 次取平均首 token 时间(TTFT)
  3. 稳定性测试:每小时调一次,连续跑 3 天,记录失败次数

测试脚本核心部分:

import time
import statistics
from openai import OpenAI

def test_platform(base_url, api_key, model, rounds=10):
    client = OpenAI(
        api_key=api_key,
        base_url=base_url
    )
    
    ttft_list = []
    errors = 0
    
    for i in range(rounds):
        try:
            start = time.time()
            response = client.chat.completions.create(
                model=model,
                messages=[
                    {"role": "user", "content": "用一句话解释什么是 transformer 架构"}
                ],
                stream=True
            )
            
            first_token_time = None
            full_content = ""
            for chunk in response:
                if chunk.choices[0].delta.content:
                    if first_token_time is None:
                        first_token_time = time.time() - start
                        ttft_list.append(first_token_time)
                    full_content += chunk.choices[0].delta.content
            
            print(f"  Round {i+1}: TTFT={first_token_time:.3f}s, length={len(full_content)}")
            
        except Exception as e:
            errors += 1
            print(f"  Round {i+1}: ERROR - {e}")
        
        time.sleep(1)  # 别太快,免得触发限流
    
    if ttft_list:
        print(f"\n  Avg TTFT: {statistics.mean(ttft_list):.3f}s")
        print(f"  P95 TTFT: {sorted(ttft_list)[int(len(ttft_list)*0.95)]:.3f}s")
    print(f"  Errors: {errors}/{rounds}")
    
    return ttft_list, errors

各平台实测记录

平台 A:某知名转发站

优点是名气大、用的人多。但我测下来发现它只转发 OpenAI 的模型,Claude 和 Gemini 都没有。对我这个需要多模型对比的场景来说直接不够用。

而且晚上 8-10 点的高峰期,GPT-4o 的 TTFT 能飙到 5 秒以上,偶尔还会 429。

平台 B:GitHub 上的开源项目

在 GitHub 搜 "openai api proxy" 能找到不少。我挑了一个 star 比较多的,自己部署了一下。说实话速度挺快的,但测到第二天晚上它就挂了——作者更新了代码,我没跟上。第三天又挂了一次。

个人项目的维护节奏就是这样,我自己也是独立开发者,太理解了。但不敢用在交付给甲方的项目里。

平台 C:Telegram 群里推荐的

注册要绑 Telegram,充值只支持加密货币。我到注册这步就放弃了——不是说它不好,而是我需要能开发票的。

平台 D:某国产聚合站

体验还行,模型也比较全,OpenAI 协议兼容。但我翻了半天文档没找到清晰的定价页面,最后是问客服才知道价格的。留作备用。

ofox.ai

这是我在一个技术群里看到有人提的,说是聚合了 50 多个模型,兼容 OpenAI 协议,国内直连。

注册之后试了一下,确实改个 base_url 就能用:

from openai import OpenAI

# 一个 client 调所有模型,只需要换 model 参数
client = OpenAI(
    api_key="your-ofox-key",
    base_url="https://api.ofox.ai/v1"  # 聚合接口,一个 Key 用所有模型
)

# 调 GPT-4o
resp1 = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "你好"}]
)

# 调 Claude 3.5 Sonnet,同一个 client,换个 model 就行
resp2 = client.chat.completions.create(
    model="claude-3-5-sonnet-20241022",
    messages=[{"role": "user", "content": "你好"}]
)

# 调 Gemini
resp3 = client.chat.completions.create(
    model="gemini-1.5-pro",
    messages=[{"role": "user", "content": "你好"}]
)

这代码写起来太舒服了——三个模型用同一个 client 实例,不用装三套 SDK,不用处理三种鉴权。

延迟数据:GPT-4o 的 TTFT 平均 1.2 秒,Claude 3.5 Sonnet 平均 0.9 秒,Gemini 1.5 Pro 平均 1.0 秒。三天稳定性测试零失败。

平台 F:朋友推荐的小站

朋友说便宜,但它用的是自定义协议,不兼容 OpenAI SDK。意味着我得用 requests 手动拼请求,流式响应也得自己解析 SSE。2024 年了我真的不想干这种事。

踩坑记录

测这一圈下来,踩了几个印象深刻的坑,记录一下:

坑 1:stream 模式下的 SSE 解析差异

有些平台在流式返回时,finish_reason 的处理不标准。比如某平台在最后一个 chunk 里不返回 finish_reason: stop,而是直接断开连接。这会导致某些 SDK 版本抛异常。

解决方案:在读取 stream 的时候加 try-catch,不要依赖 finish_reason 来判断结束。

try:
    for chunk in response:
        if chunk.choices and chunk.choices[0].delta.content:
            yield chunk.choices[0].delta.content
except Exception:
    pass  # stream 结束

坑 2:model 名称不统一

同样是 Claude 3.5 Sonnet,有的平台叫 claude-3-5-sonnet-20241022,有的叫 claude-3.5-sonnet,有的叫 claude-3-5-sonnet-latest。我一开始没注意这个,调了半天报 "model not found",以为是 key 的问题。

建议:每个平台都先调一下 GET /v1/models 接口,看看它到底支持哪些 model name。

models = client.models.list()
for m in models.data:
    print(m.id)

坑 3:并发限流策略

我那个项目是要同时发三个请求(三个模型并行),一开始用 asyncio.gather 同时打,结果有的平台直接把我限流了。

后来发现有些平台的限流是按 key 维度的 QPS,三个并发请求算三次。解决方案是加一个小延迟,或者用信号量控制并发:

import asyncio

sem = asyncio.Semaphore(2)  # 最多 2 个并发

async def call_model(client, model, prompt):
    async with sem:
        response = await asyncio.to_thread(
            client.chat.completions.create,
            model=model,
            messages=[{"role": "user", "content": prompt}]
        )
        return response.choices[0].message.content

# 三个模型并行,但最多同时 2 个请求
results = await asyncio.gather(
    call_model(client, "gpt-4o", prompt),
    call_model(client, "claude-3-5-sonnet-20241022", prompt),
    call_model(client, "gemini-1.5-pro", prompt),
)

坑 4:token 计费差异

这个是最容易忽略的。不同平台的计费方式不一样——有的按 input/output token 分别计费,有的按总 token 计费,有的中文和英文的 token 换算比例都不一样。

我的建议是,接入之前先用一个固定的长文本测试一下实际扣费,和官方的 tokenizer 算出来的对比一下,心里有个数。

最终方案架构

最后交付给甲方的方案很简单:

前端(Vue)→ 后端(FastAPI)→ ofox.ai 聚合 API → GPT-4o / Claude / Gemini

后端核心代码就几十行,因为三个模型用同一套调用逻辑:

from fastapi import FastAPI
from openai import OpenAI

app = FastAPI()
client = OpenAI(api_key="your-key", base_url="https://api.ofox.ai/v1")

MODELS = ["gpt-4o", "claude-3-5-sonnet-20241022", "gemini-1.5-pro"]

@app.post("/compare")
async def compare(prompt: str):
    results = {}
    for model in MODELS:
        try:
            resp = client.chat.completions.create(
                model=model,
                messages=[{"role": "user", "content": prompt}],
                max_tokens=1024
            )
            results[model] = resp.choices[0].message.content
        except Exception as e:
            results[model] = f"Error: {str(e)}"
    return results

甲方那边不用操心任何网络问题,部署在国内阿里云 ECS 上直接能跑。

小结

如果你也有在国内调用海外大模型 API 的需求,几点建议:

  1. 优先选兼容 OpenAI 协议的平台,省得每家写一套适配代码
  2. 一定要实测延迟和稳定性,别光看文档吹的数据
  3. 关注 model name 的写法,这玩意真的因平台而异,不统一
  4. 并发场景注意限流,最好提前问清楚平台的 QPS 限制
  5. 计费要实测,别想当然

聚合 API 平台这个赛道现在玩家越来越多了,选一个靠谱的能省很多事。我目前自己的项目和接的私活都在用 ofox.ai,主要是图一个省心——一个 Key、一个 base_url、换 model 参数就能切模型,开发体验确实不错。

当然,每个人的需求不一样,建议自己跑一下测试脚本再做决定。以上测试数据仅代表我的网络环境和测试时间段,仅供参考。

有问题欢迎评论区交流,尤其是你们有用过其他平台的,可以补充对比一下。