Google Gemini API
Google Gemini API 是 Google 的原生生成式 AI 协议。如果你的客户端已经按 Google GenAI SDK 规范开发,把 Base URL 和 API Key 换成 RouteAPI 即可直接使用,不需要改写请求结构。
Gemini API 使用 URL 路径包含模型名称的独特设计,请求体用 contents 数组表达对话,每条消息的角色是 user 或 model(注意不是 assistant)。响应结构用 candidates 数组包装,支持安全过滤和多候选生成。
适用场景:
| 场景 | 说明 |
|---|---|
| Google GenAI SDK | google-generativeai Python / Node.js SDK,改 base_url 即可 |
| Gemini REST 客户端 | 已经按 Gemini REST API 开发的应用 |
| 多模态应用 | 需要原生支持图像、视频、音频输入的场景 |
| Google AI Studio 导出 | 从 AI Studio 导出的代码可直接迁移 |
如果你的客户端只支持 OpenAI 协议,请改用 Chat Completions。RouteAPI 会在内部完成必要的格式适配,但优先选择客户端原生支持的协议,兼容性最好。
Gemini API 的端点设计与众不同:模型名称直接嵌入 URL 路径。
POST /v1beta/models/{model}:generateContent完整地址示例:
https://api.routeapi.ai/v1beta/models/gemini-1.5-pro:generateContent流式端点:
https://api.routeapi.ai/v1beta/models/gemini-1.5-pro:streamGenerateContent{model} 部分替换为实际模型名称,如 gemini-1.5-pro、gemini-1.5-flash、gemini-2.0-flash-exp 等。注意冒号前的模型名和冒号后的方法名之间没有空格。
请求头:
Authorization: Bearer sk-your-routeapi-tokenContent-Type: application/json所有协议都使用同一类 RouteAPI Token。请在服务端保存 Token,不要把 Token 暴露到浏览器、移动端或公开仓库中。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
contents | array | 是 | 对话内容列表,至少一条 |
generationConfig | object | 否 | 生成配置参数 |
safetySettings | array | 否 | 安全过滤设置 |
systemInstruction | object | 否 | 系统指令,独立字段 |
tools | array | 否 | 函数调用工具定义 |
toolConfig | object | 否 | 工具调用配置 |
基础请求示例:
{ "contents": [ { "role": "user", "parts": [ { "text": "请用一句话介绍 RouteAPI" } ] } ], "generationConfig": { "temperature": 0.7, "maxOutputTokens": 1024 }}contents 结构的特殊性
Section titled “contents 结构的特殊性”Gemini API 使用三层嵌套结构:
contents数组包含多条消息- 每条消息有
role和parts字段 parts数组包含实际内容块
关键差异:
role只能是user或model(不是assistant)- 内容必须放在
parts数组里,每个元素是一个 part 对象 - 支持多模态 parts:文本、图像、视频、音频可以混合在同一条消息的
parts中
{ "contents": [ { "role": "user", "parts": [ { "text": "分析这张图片" }, { "inlineData": { "mimeType": "image/jpeg", "data": "base64编码的图像数据..." } } ] }, { "role": "model", "parts": [ { "text": "这是一张展示..." } ] } ]}generationConfig 参数
Section titled “generationConfig 参数”| 参数 | 类型 | 说明 |
|---|---|---|
temperature | number | 采样温度,取值 0 到 2,默认 1.0 |
topP | number | nucleus sampling 参数,默认 0.95 |
topK | integer | 只从概率最高的 K 个 token 中采样 |
maxOutputTokens | integer | 最大输出 token 数 |
stopSequences | array | 自定义停止序列,最多 5 个 |
candidateCount | integer | 生成候选数量,默认 1 |
responseMimeType | string | 响应格式,如 "application/json" |
responseSchema | object | JSON Schema 约束输出结构 |
示例:
{ "generationConfig": { "temperature": 0.9, "topP": 0.95, "topK": 40, "maxOutputTokens": 2048, "stopSequences": ["END", "STOP"] }}systemInstruction
Section titled “systemInstruction”系统指令是独立字段,不放在 contents 里:
{ "systemInstruction": { "parts": [ { "text": "你是一个严谨的技术助手,回答保持简洁。" } ] }, "contents": [ { "role": "user", "parts": [{ "text": "解释什么是 API 网关" }] } ]}safetySettings
Section titled “safetySettings”控制内容安全过滤级别:
{ "safetySettings": [ { "category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_MEDIUM_AND_ABOVE" }, { "category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_MEDIUM_AND_ABOVE" } ]}常见类别:HARM_CATEGORY_HARASSMENT、HARM_CATEGORY_HATE_SPEECH、HARM_CATEGORY_SEXUALLY_EXPLICIT、HARM_CATEGORY_DANGEROUS_CONTENT。
阈值选项:BLOCK_NONE、BLOCK_LOW_AND_ABOVE、BLOCK_MEDIUM_AND_ABOVE、BLOCK_ONLY_HIGH。
Gemini API 原生支持多模态输入,通过 parts 数组的不同类型实现。
{ "text": "这是文本内容" }内联图像(base64)
Section titled “内联图像(base64)”{ "inlineData": { "mimeType": "image/jpeg", "data": "/9j/4AAQSkZJRgABAQAAAQ..." }}支持的图像格式:image/jpeg、image/png、image/webp、image/heic、image/heif。
图像 URL(fileData)
Section titled “图像 URL(fileData)”{ "fileData": { "mimeType": "image/jpeg", "fileUri": "https://example.com/image.jpg" }}{ "fileData": { "mimeType": "video/mp4", "fileUri": "gs://bucket-name/video.mp4" }}视频支持:video/mp4、video/mpeg、video/mov 等。
音频支持:audio/wav、audio/mp3、audio/aac 等。
混合多模态示例
Section titled “混合多模态示例”{ "contents": [ { "role": "user", "parts": [ { "text": "分析这段视频和这张图片的关联性" }, { "fileData": { "mimeType": "video/mp4", "fileUri": "gs://my-bucket/video.mp4" } }, { "inlineData": { "mimeType": "image/jpeg", "data": "base64..." } } ] } ]}{ "candidates": [ { "content": { "parts": [ { "text": "RouteAPI 是一个统一管理多家 AI 模型供应商的 API 网关。" } ], "role": "model" }, "finishReason": "STOP", "safetyRatings": [ { "category": "HARM_CATEGORY_HARASSMENT", "probability": "NEGLIGIBLE" } ] } ], "usageMetadata": { "promptTokenCount": 12, "candidatesTokenCount": 18, "totalTokenCount": 30 }}响应字段说明
Section titled “响应字段说明”| 字段 | 说明 |
|---|---|
candidates | 候选响应数组,默认只有一个 |
candidates[].content | 生成的内容,结构与请求中的 contents 元素相同 |
candidates[].content.role | 始终是 "model" |
candidates[].finishReason | 结束原因 |
candidates[].safetyRatings | 安全评级详情 |
usageMetadata | token 用量统计 |
finishReason 取值
Section titled “finishReason 取值”| 值 | 含义 |
|---|---|
STOP | 模型自然结束 |
MAX_TOKENS | 达到 maxOutputTokens 上限 |
SAFETY | 触发安全过滤被阻止 |
RECITATION | 检测到内容重复被阻止 |
OTHER | 其他原因 |
usageMetadata 字段
Section titled “usageMetadata 字段”| 字段 | 说明 |
|---|---|
promptTokenCount | 输入 token 数 |
candidatesTokenCount | 输出 token 数(所有候选的总和) |
totalTokenCount | 总 token 数 |
cachedContentTokenCount | 缓存命中 token 数(如果使用了上下文缓存) |
使用 streamGenerateContent 端点实现流式响应:
POST /v1beta/models/{model}:streamGenerateContent流式响应使用 SSE(Server-Sent Events)格式,每个事件是一个 JSON 对象:
data: {"candidates":[{"content":{"parts":[{"text":"RouteAPI"}],"role":"model"},"finishReason":""}],"usageMetadata":{"promptTokenCount":12,"candidatesTokenCount":1,"totalTokenCount":13}}
data: {"candidates":[{"content":{"parts":[{"text":" 是一个"}],"role":"model"},"finishReason":""}],"usageMetadata":{"promptTokenCount":12,"candidatesTokenCount":3,"totalTokenCount":15}}
data: {"candidates":[{"content":{"parts":[{"text":"统一管理"}],"role":"model"},"finishReason":""}],"usageMetadata":{"promptTokenCount":12,"candidatesTokenCount":5,"totalTokenCount":17}}
data: {"candidates":[{"content":{"parts":[{"text":""}],"role":"model"},"finishReason":"STOP","safetyRatings":[{"category":"HARM_CATEGORY_HARASSMENT","probability":"NEGLIGIBLE"}]}],"usageMetadata":{"promptTokenCount":12,"candidatesTokenCount":18,"totalTokenCount":30}}流式特点:
- 每个 chunk 都是完整的 JSON 对象,包含完整的
candidates结构 finishReason为空字符串表示继续,有值表示结束- 最后一个 chunk 包含完整的
safetyRatings和最终的usageMetadata - 流式响应没有显式的
[DONE]标记,靠finishReason判断结束
函数调用(Function Calling)
Section titled “函数调用(Function Calling)”Gemini API 支持函数调用,用于让模型调用外部工具。
{ "tools": [ { "functionDeclarations": [ { "name": "get_weather", "description": "查询指定城市的当前天气。城市名使用中文全称。", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名,如 北京" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"] } }, "required": ["city"] } } ] } ]}函数调用响应
Section titled “函数调用响应”模型返回函数调用请求:
{ "candidates": [ { "content": { "parts": [ { "functionCall": { "name": "get_weather", "args": { "city": "北京", "unit": "celsius" } } } ], "role": "model" }, "finishReason": "STOP" } ]}回传函数结果
Section titled “回传函数结果”把函数执行结果作为新的 user 消息回传:
{ "contents": [ { "role": "user", "parts": [{ "text": "北京现在天气怎么样?" }] }, { "role": "model", "parts": [ { "functionCall": { "name": "get_weather", "args": { "city": "北京", "unit": "celsius" } } } ] }, { "role": "user", "parts": [ { "functionResponse": { "name": "get_weather", "response": { "content": "北京,晴,气温 23 摄氏度,湿度 45%。" } } } ] } ]}与 OpenAI 格式对比
Section titled “与 OpenAI 格式对比”结构差异对比表
Section titled “结构差异对比表”| 项目 | Gemini API | OpenAI Chat Completions |
|---|---|---|
| 端点格式 | /v1beta/models/{model}:generateContent | /v1/chat/completions |
| 模型指定 | URL 路径中 | 请求体 model 字段 |
| 对话数组字段 | contents | messages |
| 消息结构 | role + parts 数组 | role + content 字符串/数组 |
| 角色名称 | user / model | user / assistant / system |
| 系统指令 | systemInstruction 对象 | messages 中 role: "system" |
| 响应包装 | candidates 数组 | choices 数组 |
| 响应内容位置 | candidates[0].content.parts[0].text | choices[0].message.content |
| 结束原因字段 | finishReason | finish_reason |
| 用量统计字段 | usageMetadata | usage |
| Gemini API | OpenAI Chat Completions | 备注 |
|---|---|---|
generationConfig.temperature | temperature | Gemini 上限 2,OpenAI 也是 2 |
generationConfig.topP | top_p | 命名风格不同 |
generationConfig.topK | 无对应 | OpenAI 不支持 |
generationConfig.maxOutputTokens | max_tokens / max_completion_tokens | 字段名不同 |
generationConfig.stopSequences | stop | 名称不同 |
generationConfig.candidateCount | n | 语义相同 |
generationConfig.responseMimeType | response_format.type | 控制方式不同 |
generationConfig.responseSchema | response_format.json_schema | 层级不同 |
safetySettings | 无对应 | OpenAI 使用内容审核 API |
tools[].functionDeclarations | tools[].function | 包装层级不同 |
toolConfig | tool_choice | 字段名和结构不同 |
迁移注意事项
Section titled “迁移注意事项”从 OpenAI 迁移到 Gemini API 时,按以下顺序检查:
- 模型名称移到 URL 路径:
/v1beta/models/gemini-1.5-pro:generateContent messages改名为contents,每条消息的结构改为role+parts数组- 所有
assistant角色改为model content字段改为parts数组,文本内容包装为{ "text": "..." }- 系统提示词从
messages数组移到systemInstruction对象 - 生成参数包装到
generationConfig对象中,并调整字段名(如maxOutputTokens、stopSequences) - 响应解析改为从
candidates[0].content.parts[0].text提取内容 - 流式端点改为
streamGenerateContent,每个 chunk 是完整 JSON - 工具定义改为
functionDeclarations包装,参数字段改为parameters
角色名称对照
Section titled “角色名称对照”| Gemini | OpenAI | Claude |
|---|---|---|
user | user | user |
model | assistant | assistant |
| 无独立角色 | system | 无独立角色 |
| 无独立角色 | tool | 无独立角色 |
Gemini 和 Claude 都把系统指令提到顶层字段,不作为消息角色。
基础对话(curl)
Section titled “基础对话(curl)”curl https://api.routeapi.ai/v1beta/models/gemini-1.5-pro:generateContent \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "contents": [ { "role": "user", "parts": [ { "text": "请用一句话介绍 RouteAPI" } ] } ], "generationConfig": { "temperature": 0.7, "maxOutputTokens": 1024 } }'基础对话(Python SDK)
Section titled “基础对话(Python SDK)”使用 Google GenAI Python SDK,只需改 client_options:
import osimport google.generativeai as genaifrom google.api_core.client_options import ClientOptions
# 配置 RouteAPI 端点genai.configure( api_key=os.environ["ROUTEAPI_KEY"], transport="rest", client_options=ClientOptions( api_endpoint="https://api.routeapi.ai/v1beta" ))
model = genai.GenerativeModel("gemini-1.5-pro")
response = model.generate_content( "请用一句话介绍 RouteAPI", generation_config={ "temperature": 0.7, "max_output_tokens": 1024 })
print(response.text)print(f"输入 tokens: {response.usage_metadata.prompt_token_count}")print(f"输出 tokens: {response.usage_metadata.candidates_token_count}")图像输入示例(curl)
Section titled “图像输入示例(curl)”# 将图像转为 base64IMAGE_BASE64=$(base64 -w 0 screenshot.jpg)
curl https://api.routeapi.ai/v1beta/models/gemini-1.5-pro:generateContent \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "contents": [ { "role": "user", "parts": [ { "text": "这张图里有哪些界面控件?" }, { "inlineData": { "mimeType": "image/jpeg", "data": "'"$IMAGE_BASE64"'" } } ] } ], "generationConfig": { "maxOutputTokens": 2048 } }'图像输入示例(Python SDK)
Section titled “图像输入示例(Python SDK)”import osimport google.generativeai as genaifrom google.api_core.client_options import ClientOptionsfrom PIL import Image
genai.configure( api_key=os.environ["ROUTEAPI_KEY"], transport="rest", client_options=ClientOptions( api_endpoint="https://api.routeapi.ai/v1beta" ))
model = genai.GenerativeModel("gemini-1.5-pro")
image = Image.open("screenshot.jpg")
response = model.generate_content( ["这张图里有哪些界面控件?", image], generation_config={"max_output_tokens": 2048})
print(response.text)流式输出示例(curl)
Section titled “流式输出示例(curl)”curl https://api.routeapi.ai/v1beta/models/gemini-1.5-pro:streamGenerateContent \ -H "Authorization: Bearer $ROUTEAPI_KEY" \ -H "Content-Type: application/json" \ -d '{ "contents": [ { "role": "user", "parts": [ { "text": "逐步解释什么是 API 网关" } ] } ] }'流式输出示例(Python SDK)
Section titled “流式输出示例(Python SDK)”import osimport google.generativeai as genaifrom google.api_core.client_options import ClientOptions
genai.configure( api_key=os.environ["ROUTEAPI_KEY"], transport="rest", client_options=ClientOptions( api_endpoint="https://api.routeapi.ai/v1beta" ))
model = genai.GenerativeModel("gemini-1.5-pro")
response = model.generate_content( "逐步解释什么是 API 网关", stream=True)
for chunk in response: print(chunk.text, end="", flush=True)
print()函数调用完整示例(Python SDK)
Section titled “函数调用完整示例(Python SDK)”import osimport google.generativeai as genaifrom google.api_core.client_options import ClientOptions
genai.configure( api_key=os.environ["ROUTEAPI_KEY"], transport="rest", client_options=ClientOptions( api_endpoint="https://api.routeapi.ai/v1beta" ))
# 定义工具get_weather_declaration = { "name": "get_weather", "description": "查询指定城市的当前天气。城市名使用中文全称。", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "城市名,如 北京" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"] } }, "required": ["city"] }}
model = genai.GenerativeModel( "gemini-1.5-pro", tools=[get_weather_declaration])
chat = model.start_chat()
# 第一轮:用户提问response = chat.send_message("北京现在天气怎么样?")
# 检查是否有函数调用if response.candidates[0].content.parts[0].function_call: function_call = response.candidates[0].content.parts[0].function_call
# 模拟函数执行 if function_call.name == "get_weather": city = function_call.args["city"] weather_result = f"{city},晴,气温 23 摄氏度,湿度 45%。"
# 第二轮:回传函数结果 response = chat.send_message( genai.protos.Content( parts=[ genai.protos.Part( function_response=genai.protos.FunctionResponse( name="get_weather", response={"content": weather_result} ) ) ] ) )
print(response.text)- 参数的实际支持程度取决于所选模型和上游服务能力,部分高级特性(如上下文缓存、代码执行)建议先在测试环境验证。
- 明确传入
0或false的可选参数会被视为用户显式设置,不会当作缺省值丢弃。 - 生产环境建议固定模型 ID,不要依赖临时别名或展示名称。
- 记录每次请求的模型 ID、状态码和 token 用量,便于排查延迟与成本异常。
fileUri使用gs://协议时需要确保文件可被上游访问,或使用inlineData直接传输。- 错误响应格式可能与 OpenAI/Claude 不同,详见 错误处理。