跳至主要内容

錯誤

每次失敗都會回傳一個 JSON 本文和一個 HTTP 狀態碼。這是沒帶 Key 的請求收到的回應:

{
"error": {
"message": "Missing API key. Send it as: Authorization: Bearer <your OceanToken key>.",
"type": "authentication_error",
"param": null,
"code": "invalid_api_key"
}
}

請依 code 分支處理。它是一組固定且保持穩定的詞彙;message 是給人看的,措辭可能改變。type 把處理方式相同的錯誤碼歸為一類。HTTP 狀態碼表達的是同一件事,只是更粗略,所以依狀態碼分支的既有用戶端仍可正常運作。

錯誤碼​

HTTPtypecode發生了什麼怎麼處理
400invalid_request_errorinvalid_request請求格式有誤:缺少欄位、模型不接受的值、損壞的圖片。修正請求。不要原樣重試。
400not_found_errormodel_not_foundmodel 名稱不存在。從 GET /v1/models 中選一個名稱。
400insufficient_creditsinsufficient_credits可用額度已用完。沒有執行,也沒有扣款。儲值後重試。
400insufficient_creditskey_budget_exceeded這個 Key 自己的額度上限已用完(帳號可能仍有餘額)。提高這個 Key 的上限、等它重置,或改用其他 Key。
400insufficient_creditsrequest_exceeds_balance餘額大於 $0,但扣掉進行中請求預留的部分後,剩下的不足以支付這個請求最多可能的費用。最壞情況的算法:輸入按完整輸入價,加上 max_tokens 的輸出(不超過模型的輸出上限;沒有 max_tokens 時取該上限,最多 16,384 個 token),乘以 n,再加上任何按次或搜尋費用,並以該模型所有通道中可能計費的最高價格計算,包含長上下文和推理價格。沒有執行,也沒有扣款。降低 max_tokens 或縮短輸入,或儲值。
400content_policy_violationcontent_filtered模型執行前,安全檢查拒絕了請求。不收費。修改輸入。同樣的輸入重試會得到同樣的結果。
401authentication_errorinvalid_api_key沒有 Key、未知的 Key 或已刪除的 Key。檢查 Authorization: Bearer sk-... 標頭。
401authentication_errorkey_expiredKey 已過期。建立新的 Key。
403permission_errormodel_not_allowedKey 有效,但這個模型不在帳號允許的範圍內。改用 GET /v1/models 中的模型。
403permission_errorforbidden這個 Key 不能執行此操作。管理 API Key 就是一例:API Key 不能建立、修改、輪替或刪除 Key。在主控台管理 Key;其他情況請改用權限合適的 Key。
404not_found_errornot_found未知的路徑,或不存在的影片 / 任務 id。檢查 URL 和 id。
409idempotency_erroridempotency_key_reused這個 Idempotency-Key 已用於另一個不同的請求本文。新請求請用新的 Key。見重試。
409idempotency_erroridempotency_key_in_progress使用這個 Key 的第一個請求仍在執行中。等待 Retry-After 秒後,重試同一個請求。
429rate_limit_errorrate_limited超過了這個 Key 每分鐘請求數或 token 數的上限。等到 Retry-After 後再試;見限制。
429rate_limit_errorprovider_overloaded這個模型的所有通道目前都滿載。見重試與故障轉移。退避後重試,或換模型。
501invalid_request_errornot_supported不提供此端點:批次(/v1/batches)、微調(/v1/fine_tuning),以及在 /v1/files 下列出、讀取或刪除檔案。不要重試。改把每個請求送到對應的一般端點。
503api_errortemporarily_unavailable閘道剛才無法查核接受請求所需的資訊,例如組織的餘額。沒有執行,也沒有扣款。等 Retry-After 秒後重試。
5xxapi_errorprovider_error閘道自行重試和故障轉移後,模型仍然失敗。不收費。退避後重試;若持續發生,請換模型。
408api_errortimeout串流開始後 120 秒內沒有收到模型的任何內容。退避後重試。
504api_errortimeout請求超過了 240 秒的時限。改用串流、縮短請求,或使用非同步端點。

不在表中的錯誤都是 api_error。之後可能新增錯誤碼;既有的錯誤碼不會改名或移除。

請求 ID​

模型請求的回應帶有標頭 x-oceantoken-request-id。請把它和錯誤一起記錄,聯絡我們時附上。因 Key 被拒(401)的請求沒有到達模型,因此沒有這個 ID。

成功的回應在本文中也有 id,串流的每個區塊都帶有相同的 id。它就是主控台 Logs 中顯示的 Request ID(附請求的狀態、延遲和費用),也是 GET /v1/usage/{request_id} 用來查詢的 id。

重試​

錯誤傳到你這裡之前,閘道已經重試過;如果模型還有其他通道,也已把請求轉過去。重試與故障轉移 說明它處理了什麼、留給你處理什麼。

只在以下情況重試:429;除 501 以外的任何 5xx;timeout 錯誤;網路失敗(連線中斷、用戶端逾時)。所有 400 段的錯誤和 501 not_supported,在請求或帳號改變之前都會以同樣方式再次失敗。

使用帶隨機抖動的指數退避,從約一秒開始,上限約三十秒;回應帶有 Retry-After(秒數)時,至少等待那麼久。 Retry-After 只在 409 idempotency_key_in_progress 上保證出現;429 或 503 可能沒有,此時請用你自己的退避策略。

# Retry only what can succeed on a second try: 429, 408 (timeout), every 5xx
# except 501 (an endpoint that is not offered) and network failures,
# with exponential backoff and jitter, honouring Retry-After when it is sent.
import os
import random
import time

from openai import APIConnectionError, APIStatusError, OpenAI

client = OpenAI(
base_url=os.getenv("OCEANTOKEN_BASE_URL", "https://api.oceantoken.ai/v1"),
api_key=os.environ["OCEANTOKEN_API_KEY"],
max_retries=0, # the loop below does the retrying
)


def with_retries(call, attempts=5):
for attempt in range(attempts):
try:
return call()
except APIConnectionError:
if attempt == attempts - 1:
raise
delay = None # network failure: back off and try again
except APIStatusError as e:
retryable = e.status_code in (408, 429) or (e.status_code >= 500 and e.status_code != 501)
if not retryable or attempt == attempts - 1:
raise
retry_after = e.response.headers.get("retry-after")
delay = float(retry_after) if retry_after else None
time.sleep(delay if delay is not None else min(30, 2**attempt) + random.random())


models = with_retries(lambda: client.models.list())
print(len(models.data), "models")

重試會花錢的請求​

圖片、影片和語音合成請求在執行時就會扣款。網路逾時後重試,原本會讓它們再執行一次。請在 POST /v1/images/generations、/v1/images/edits、/v1/videos 和 /v1/audio/speech 上傳送 Idempotency-Key 標頭(任何唯一字串,最多 255 個字元,例如 UUID):

  • 第一個請求正常執行,其回應保留 24 小時。
  • 用相同 Key 且相同本文重試,會拿回那個回應,並帶有標頭 Idempotency-Replayed: true。不會執行,也不會扣款。
  • 相同 Key 但本文不同,會被拒絕並回傳 409 idempotency_key_reused。
  • 第一個請求仍在執行時重試,會得到帶 Retry-After 的 409 idempotency_key_in_progress。
  • 5xx 回應不會保留,所以供應端失敗後的重試會重新執行。

Key 的範圍限於你的 API Key。其他端點會忽略這個標頭;在上述端點上,不帶它的請求行為和以前完全一樣。超過 8 MB 的回應不會保留;請求照常執行,只是不適用重放。

串流中的錯誤​

使用 "stream": true 時,在第一個 token 之前發生的錯誤,是一般的 JSON 錯誤回應,狀態碼如上。串流開始後發生的錯誤,會以最後一個 data: 區塊送達,內容是同樣的 error 物件,然後串流結束。

提前結束的串流(連線中斷、你主動斷線,或被錯誤中斷),按模型的一般價格計費:

  • 提示全部計費;
  • 到那時為止已串流的輸出。推理模型串流出的推理內容算作輸出,即使還沒收到任何回答文字。

串流停止後模型可能繼續生成的輸出不計費。還沒產生任何輸出就結束的串流完全不計費。

餘額用盡​

餘額小於或等於 $0 時,所有付費模型的請求都會被拒絕並回傳 400 insufficient_credits。不會執行,也不會扣款。儲值後重試。模型 ID 以 :free 結尾的模型在餘額為 $0 時仍可呼叫。

餘額大於 $0 但少於某個請求最多可能的費用時,只有那個請求會被拒絕並回傳 400 request_exceeds_balance;較小的請求仍會執行。 錯誤訊息會說明這個請求最多可能花多少,以及你的餘額是多少。 降低 max_tokens 或縮短輸入,讓它在餘額內執行,或者儲值。

從 OpenAI 遷移​

錯誤本文的 error 物件與 OpenAI 相同。 有兩種情況的狀態碼或錯誤碼不同:

情況OpenAIOceanToken
餘額用完429 insufficient_quota400 insufficient_credits
未知模型404 model_not_found400 model_not_found

code 的值全部是我們自己的,見錯誤碼。 有幾個狀態碼帶有我們自己的含義:模型滿載是 429 provider_overloaded(OpenAI 回 503),408 timeout 是串流沒了動靜,409 是冪等衝突,501 not_supported 是我們不提供的端點。 如果你的程式把 429 insufficient_quota 當作沒錢了,請改看 400 insufficient_credits;它不是 429,所以重試迴圈不會在它上面空轉。 未知模型是 400,所以等待 404 的處理器看不到它;依 code 分支,兩邊都適用。

內容政策​

觸發安全檢查的請求會被拒絕並回傳 400 content_filtered。檢查在呼叫模型前進行,所以不收費。

找到失敗的請求​

每次失敗都會記錄在主控台的 Logs 中,附狀態碼和回應本文。依時間和模型找到它,聯絡我們時附上它的 x-oceantoken-request-id。