Gemini API 走中转站:端点、路径与三个专属坑
Gemini 的路径结构和 OpenAI 完全不同;v1 与 v1beta 的区别、generateContent 的调用方式、安全设置的传法。
Gemini 是四种主流协议里最容易被中转站做错的一种。原因是它的 URL 结构和其它三家都不一样:模型名在路径里,而不是在请求体里;密钥放在 query 或 header 里,路径还要区分 v1 和 v1beta。
一、正确的端点形状
POST https://{base}/v1beta/models/{model}:generateContent
三个要点:
- 版本是
v1beta,不是v1。有些模型只在 beta 可用。 - 模型名在路径上,
models/gemini-2.0-flash,冒号后面是动作。 - 动作是
generateContent(非流式)或streamGenerateContent(流式)。
常见的错误拼法是 /v1/models/...、/v1beta/models/{model}/generateContent(多了一个斜杠)、或者把模型名放进 body。这三种都会 404。
二、认证的两种方式
# 方式一:header
x-goog-api-key: YOUR_KEY
# 方式二:query
?key=YOUR_KEY
中转站通常接受 Authorization: Bearer 做统一鉴权,然后自己换成 Google 的格式。如果站点的文档写的是 Bearer,就按 Bearer 发;不要两种都加,有些实现会因为冲突而拒绝。
三、请求体长什么样
{
"contents": [
{"role": "user", "parts": [{"text": "用一句话解释量子纠缠"}]}
],
"generationConfig": {
"maxOutputTokens": 200,
"temperature": 0.7
}
}
注意和 OpenAI 的差别:
| 概念 | OpenAI | Gemini |
|---|---|---|
| 消息数组 | messages | contents |
| 内容 | content(字符串) | parts(数组) |
| 角色 | user / assistant | user / model |
| 输出上限 | max_tokens | generationConfig.maxOutputTokens |
| 系统提示 | system 消息 | systemInstruction |
角色叫 model 不叫 assistant,这是最常写错的一个。
四、三个专属坑
1. v1 与 v1beta 混用
如果你把 base URL 设成 https://relay.example.com/v1,再拼 /models/...,最终请求是 /v1/models/...。而 Gemini 的模型列表和生成接口在 v1beta 下更完整。有些中转站会自动改写,有些不改写,结果就是同一个站点有的模型能用有的不能。
排查方法:拿一个确定存在的模型名,分别请求 /v1/models/{m}:generateContent 和 /v1beta/models/{m}:generateContent,看哪个返回 200。这能立刻暴露路径问题。
2. 安全设置的位置
Gemini 的 safetySettings 是顶层数组,每个元素有 category 和 threshold。如果你按 OpenAI 的习惯放在 generationConfig 里,会被忽略——不报错,但也不生效。
被忽略比报错更危险:你以为设了过滤,实际上没有。
3. 流式的返回格式
streamGenerateContent 返回的是 JSON 数组流,不是 SSE 的 data: 行。有些中转站把它包装成 OpenAI 风格的 SSE,有些直接透传。如果你的客户端只认 SSE,需要确认站点做了转换。
五、怎么验证一个中转站的 Gemini 支持
- 路径:确认
/v1beta/models/{model}:generateContent返回 200。 - 模型名:响应里的
modelVersion是否和请求的一致。 - 参数:设
maxOutputTokens: 16,看输出是否真被截断。 - 错误形状:发一个不存在的模型,看是否返回 Google 风格的错误体(
{"error":{"code":404,"message":...,"status":"NOT_FOUND"}})。 - 流式:
streamGenerateContent是否分块到达。
本站检测台的 Gemini 协议会自动把 base URL 规整到 /v1beta,并把模型名放进路径。如果你在别处调不通,可以先用它确认是路径问题还是站点问题。
六、一个最小可用的 curl
curl -sS "https://relay.example.com/v1beta/models/gemini-2.0-flash:generateContent" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{
"contents":[{"role":"user","parts":[{"text":"说一句话"}]}],
"generationConfig":{"maxOutputTokens":64}
}'
先用这个跑通,再接 SDK。SDK 的默认 base URL 和路径拼接规则各不相同,直接用 curl 能排除掉一半变量。
七、小结
Gemini 的问题九成出在路径上:版本、模型名位置、动作名。剩下一成是角色名和参数位置。把这几个对照清楚,中转站的 Gemini 支持就能验证个七七八八。