透過 API 整合 AI:實用指南
你有一個 app。你想讓它跟 AI 對話。也許你想要聊天補全,也許是影像生成,也許兩個都要。好消息:如果你用過 OpenAI API,你已經知道怎麼用我們的。更棒的消息:你透過單一端點就能用上 61 家供應商的 367 個模型。
不用學新的 SDK。沒有專有協定。只要換 base URL 跟 API 金鑰。
步驟 1:拿到你的 API 金鑰
在 zubnet.com 註冊,導到你的工作區設定。你的 API 金鑰住在那裡。它會以一個好認的前綴開頭:
zub_live_a1b2c3d4e5f6...
保密。當它是密碼看待。一旦外流,立刻從工作區設定裡輪換 — 一旦你產生新金鑰,舊金鑰就會立即失效。
步驟 2:設定你的 base URL
每個請求都送到:
https://api.zubnet.ai/v1
就這樣。/v1 前綴配合 OpenAI 的慣例,所以任何支援 OpenAI 的函式庫、工具或框架,只要換個 URL 就能用。
步驟 3:發出你的第一個請求
用 curl
最簡單的測試 — 一則訊息的聊天補全:
curl https://api.zubnet.ai/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer zub_live_YOUR_KEY" \
-d '{
"model": "claude-sonnet-4-20250514",
"messages": [
{"role": "user", "content": "What is the capital of France?"}
]
}'
你會拿到一個 JSON 回應,模型的回覆在 choices[0].message.content。跟 OpenAI 的回應結構一模一樣。
用 OpenAI SDK 的 Python
如果還沒裝,先安裝 SDK:
pip install openai
再用我們的 base URL 來用它:
from openai import OpenAI
client = OpenAI(
api_key="zub_live_YOUR_KEY",
base_url="https://api.zubnet.ai/v1"
)
response = client.chat.completions.create(
model="claude-sonnet-4-20250514",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Explain quantum computing in three sentences."}
],
max_tokens=500,
temperature=0.7
)
print(response.choices[0].message.content)
這是一個完整、可運作的範例。複製、貼上、換掉 API 金鑰,執行。
模型參數
model 欄位就是有趣的地方。你不會被綁在某一家供應商,而是從 61 家供應商的 367 個模型裡挑。幾個範例:
• claude-sonnet-4-20250514 — Anthropic Claude Sonnet 4
• gpt-4.1 — OpenAI GPT-4.1
• gemini-2.5-pro-preview-05-06 — Google Gemini 2.5 Pro
• deepseek-r1 — DeepSeek R1 推理模型
• flux-1.1-pro — Black Forest Labs FLUX 影像
• kling-v2.5-master — Kling 影片生成
完整清單在我們的模型頁,可以依類型(LLM、影像、影片、音訊、3D、程式)和供應商篩選。你在那裡看到的模型 ID,就是放進 model 欄位的那串字。
影像生成
影像模型用同一套端點模式。這是透過 Python 的 FLUX:
response = client.images.generate(
model="flux-1.1-pro",
prompt="A serene Japanese garden at dawn, soft morning light",
n=1,
size="1024x1024"
)
image_url = response.data[0].url
print(image_url)
回應裡會包含指向產出影像(託管在我們 CDN)的 URL。下載、顯示、嵌入 — URL 24 小時內有效。
串流回應
對聊天模型,串流是隨著 token 生成就傳送,而不是等整個回應產完。對任何使用者會看到的聊天介面來說,這很關鍵 — 沒人想盯著空白畫面看 10 秒。
stream = client.chat.completions.create(
model="claude-sonnet-4-20250514",
messages=[
{"role": "user", "content": "Write a short poem about code."}
],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
底層用的是 Server-Sent Events(SSE)。每個片段在 HTTP 回應裡以一行 data: 出現。OpenAI SDK 會替你處理解析,但如果你用原始 HTTP,你會看到這樣的行:
data: {"choices":[{"delta":{"content":"Once"},"index":0}]}
data: {"choices":[{"delta":{"content":" upon"},"index":0}]}
data: {"choices":[{"delta":{"content":" a"},"index":0}]}
...
data: [DONE]
串流以 data: [DONE] 結束。解析每一行、取出 delta.content、接到輸出緩衝區。這就是整個協定。
錯誤處理
API 用標準 HTTP 狀態碼。你會真正遇到的是這些:
400 Bad Request — 你的請求主體格式錯誤。檢查 JSON 結構、確定 messages 是陣列、確定 model 是有效的模型 ID。
401 Unauthorized — 你的 API 金鑰遺失、無效或過期。檢查 Authorization: Bearer 標頭。
403 Forbidden — 你的帳號沒有權限使用這個模型或功能。檢查你的工作區訂閱等級。
429 Too Many Requests — 你撞到速率上限。回應會帶一個 Retry-After 標頭告訴你要等幾秒。實作指數退避:
import time
from openai import RateLimitError
max_retries = 3
for attempt in range(max_retries):
try:
response = client.chat.completions.create(
model="claude-sonnet-4-20250514",
messages=[{"role": "user", "content": "Hello"}]
)
break
except RateLimitError:
wait = 2 ** attempt
print(f"Rate limited. Waiting {wait}s...")
time.sleep(wait)
500 / 502 / 503 — 伺服器端問題。很少見,但會發生。帶退避重試。如果持續,檢查我們的 Pulse 狀態頁。
驗證細節
每個請求都需要一個 Authorization 標頭:
Authorization: Bearer zub_live_YOUR_KEY
金鑰的範圍是你的工作區。同一個工作區的所有團隊成員共享同一把金鑰與用量池。如果你要依每位成員分開追蹤,就建立分開的工作區。
• 絕對不要把金鑰寫死在原始碼 — 用環境變數
• 絕對不要把金鑰 commit 到 git — 用 .env 檔,並加進 .gitignore
• 從工作區設定定期輪換金鑰
• 開發與正式環境用不同的金鑰
速率上限
速率上限跟你的方案等級有關。預設對多數使用情境都很寬鬆:
• 每分鐘請求數:依方案而異(60-600 RPM)
• 每分鐘 Token:依模型與方案而異
• 同時請求數:沒有硬上限,但你瞬間塞太多,還是會觸發 429
速率上限標頭會附在每個回應裡:
x-ratelimit-limit-requests: 120
x-ratelimit-remaining-requests: 119
x-ratelimit-reset-requests: 0.5s
讀這些標頭。把你的客戶端寫成會尊重它們。你的使用者會在他們的請求不會莫名失敗時感謝你。
把它們組起來
這是一個可上線的 Python 函式,能處理錯誤、重試與串流:
import os
from openai import OpenAI, APIError, RateLimitError
import time
client = OpenAI(
api_key=os.environ["ZUBNET_API_KEY"],
base_url="https://api.zubnet.ai/v1"
)
def ask(prompt, model="claude-sonnet-4-20250514", stream=False):
for attempt in range(3):
try:
response = client.chat.completions.create(
model=model,
messages=[{"role": "user", "content": prompt}],
stream=stream
)
if stream:
return response # iterate over chunks
return response.choices[0].message.content
except RateLimitError:
time.sleep(2 ** attempt)
except APIError as e:
if attempt == 2:
raise
time.sleep(1)
# Usage
print(ask("Summarize the latest in quantum computing"))
print(ask("Same question, different model", model="gpt-4.1"))
換一個字串,就換一個模型。不用重構程式碼、不用新相依套件、回應格式也一樣。這就是 OpenAI 相容性的重點。
本指南所有程式碼範例截至 2026 年 3 月都測試過、可用。複製、執行、在上面建構。它們就是為此而在。