Gemini 原生接口
与 Google Gemini 的原生 generateContent 协议兼容。
它与其余三个协议有三处结构性差异:模型写在路径里、是否流式由动作决定、鉴权头不一样。
/v1beta
该端点已在网关内注册并可用,但边缘反向代理目前只放行 /v1/、
/api/v1/ai/、/api/v1/user/ 等前缀,
从公网直连 /v1beta/* 暂时打不通。
需要调用 Gemini 系模型时,请改用
/v1/chat/completions——
网关会自动做协议转换,能力与计费完全一致。本页内容供边缘放行后参考。
路径参数
平台模型 ID,直接写在路径里,与动作之间用冒号分隔。 模型不写在请求体里——请求体里写了也不生效。
只支持 generateContent 与 streamGenerateContent。
其余动作(如 countTokens、embedContent)会返回
400 40003
unsupported gemini action: …。
鉴权
这个端点接受三种传法,按顺序取第一个非空的:
| 顺序 | 位置 | 写法 |
|---|---|---|
| 1 | 请求头 | x-goog-api-key: sk-rouertcode-… |
| 2 | 查询参数 | ?key=sk-rouertcode-… |
| 3 | 请求头 | Authorization: Bearer sk-rouertcode-… |
?key=密钥出现在 URL 里,会被反向代理、CDN、浏览器历史完整记进访问日志。 能用请求头就用请求头。
请求体
对话内容。每项含 role(user / model)与
parts 数组。助手角色叫 model,不是 assistant。
系统提示,形如 {"parts": [{"text": "..."}]}。
生成参数集合:temperature、topP、topK、
maxOutputTokens、stopSequences。
注意是驼峰命名,且都收在这个对象里,不是平铺在顶层。
工具定义,形如 [{"functionDeclarations": [...]}]。
安全过滤阈值。这是 Gemini 的专属字段—— 跨协议转换时无对应位置,会被丢弃。对它有硬依赖时只能用本端点。
stream 字段
是否流式完全由 URL 决定:动作是 streamGenerateContent,
或查询串带 alt=sse。在请求体里写 "stream": true 不起任何作用。
响应
{
"candidates": [
{
"content": {
"role": "model",
"parts": [{ "text": "你好!有什么可以帮你的吗?" }]
},
"finishReason": "STOP",
"index": 0
}
],
"usageMetadata": {
"promptTokenCount": 12,
"candidatesTokenCount": 11,
"totalTokenCount": 23
}
}
文本在 candidates[0].content.parts[] 里,
可能有多个 part(文本 + 函数调用混排),取的时候要遍历。
调用示例
curl "https://www.apigoto.com/v1beta/models/gemini-2.5-pro:generateContent" \
-H "Content-Type: application/json" \
-H "x-goog-api-key: $APIGOTO_API_KEY" \
-d '{
"systemInstruction": {"parts": [{"text": "你是一个简洁的助手。"}]},
"contents": [
{"role": "user", "parts": [{"text": "用一句话解释什么是 API 网关"}]}
],
"generationConfig": {"maxOutputTokens": 200}
}'
import os
from google import genai
client = genai.Client(
api_key=os.environ["APIGOTO_API_KEY"],
http_options={"base_url": "https://www.apigoto.com"},
)
resp = client.models.generate_content(
model="gemini-2.5-pro",
contents="用一句话解释什么是 API 网关",
)
print(resp.text)
示例里的 gemini-2.5-pro 只是占位——
请以 模型列表里的实际 model_id 为准。
流式返回
用 :streamGenerateContent。强烈建议同时加上 ?alt=sse:
POST /v1beta/models/{model}:streamGenerateContent?alt=sse
data: {"candidates":[{"content":{"role":"model","parts":[{"text":"你"}]}}]}
data: {"candidates":[{"content":{"role":"model","parts":[{"text":"好"}]}}]}
data: {"candidates":[{"content":{"role":"model","parts":[{"text":"!"}]},"finishReason":"STOP"}],"usageMetadata":{"totalTokenCount":23}}
不加 alt=sse 时上游返回的是一个持续写入的 JSON 数组流,
得自己做增量 JSON 解析,麻烦很多。加了就是标准 SSE,每行一个完整片段。
既没有 [DONE] 也没有 message_stop。
判断正常结束的依据是最后一个片段带有 finishReason;
没拿到 finishReason 流就断了,按失败处理。
与其它协议的字段对照
| Chat Completions | Gemini |
|---|---|
| messages | contents |
| role: assistant | role: model |
| content(字符串) | parts[](数组) |
| system 消息 | systemInstruction |
| max_tokens | generationConfig.maxOutputTokens |
| finish_reason: "stop" | finishReason: "STOP" |
| usage.prompt_tokens | usageMetadata.promptTokenCount |
可能的错误
| HTTP | code | 原因 |
|---|---|---|
| 400 | 40002 | 路径里没解析出模型名(冒号或动作写错) |
| 400 | 40003 | 动作不受支持 |
| 401 | 40001 | 三种鉴权位置都没找到密钥 |
| 413 | 41301 | 请求体超 100 MiB |
注意网关错误一律是网关自己的 JSON 结构(error.type = "gateway_error"),
不是 Gemini 的错误格式。完整清单见 错误码总表。