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 不同,詳見 錯誤處理。