重點摘要
- 文字來自客戶端,因此請使用 curl 重現呼叫,以查看真實的錯誤主體和狀態。
- HTTP 429 錯誤(代碼為 rate_limited 或 concurrency)是繁忙帳戶最常見的原因,且串流會佔用其槽位直到結束。
- 在進行其他操作之前,先檢查 Base URL、金鑰、模型 ID uncensored、主體大小(8 MB)和總 token 數(100,000)。
- 僅重試 429 錯誤和網路中斷,等待 Retry-After,並將並行請求保持在金鑰限制之下。
該訊息實際告訴您的內容
如果你搜尋了 來自 LLM 串流的未知錯誤 learn more,你很可能是在聊天前端、編輯器外掛或代理框架中看到彈出訊息或紅線。該用語來自該客戶端。它表示應用程式要求了串流輸出,但在串流之前或期間發生錯誤,而應用程式不知道如何描述該錯誤。API 本身會以 HTTP 狀態碼和 JSON 錯誤主體回報問題,而客戶端已丟棄該詳細資訊。
這是好消息,因為這表示您可以找回詳細資訊。在客戶端之外發送相同的請求,讀取狀態行和主體,原因通常在一次或兩次嘗試後就很明顯。本頁其餘部分將按照該 API 上傾向發生的順序列出原因,然後提供一個小型串流客戶端,它會列印真實錯誤而非隱藏它。
從一開始就要記住的一件事:串流請求有兩個失敗點。它可以在第一個位元組之前失敗,當伺服器拒絕請求時(金鑰錯誤、URL 錯誤、限制)。或者它可以在中間失敗,當連線在已收到一些文字後中斷。修復方法不同,因此請注意您看到的是哪一種。如果答案從未開始,請查看第二到第四節。如果它開始然後停止,請查看關於代理伺服器和超時的部分。
首先檢查 Base URL、金鑰和模型
新設定中的大多數串流錯誤來自三個小失誤。排除這些需要一分鐘。
- Base URL。 它必須是
https://api.uncensoredllmhub.com/v1,包含/v1且沒有尾隨的/chat/completions。客戶端會自行附加路徑。如果您將完整端點貼上到期望 Base 的欄位中,客戶端會請求一個不存在的路徑並報告模糊的失敗。 - 金鑰。 標頭是
Authorization: Bearer YOUR_KEY。多餘的空格、連同金鑰複製的換行符,或來自其他服務的金鑰都會以相同方式失敗。如果您不確定,請從 API 金鑰頁面 重新建立或複製金鑰。 - 模型 ID。 唯一的模型是
uncensored。提供下拉選單的客戶端通常會預先填入來自其他供應商的名稱。請手動輸入 ID,並呼叫GET /v1/models以確認伺服器列出的內容。
一次測試三者的快速方法是 models 呼叫。它不會串流,因此可以將連線或金鑰問題與串流問題區分開來:
curl -i https://api.uncensoredllmhub.com/v1/models -H "Authorization: Bearer $API_KEY"
如果返回正常列表,表示 URL 和金鑰都沒問題,你可以停止懷疑它們。如果失敗,請在處理串流輸出之前先修正該問題。此外,請確認帳戶有額度:API 會在回應的 X-Balance-USD 標頭中傳送剩餘餘額,當金鑰在大量使用後突然無法運作時,這很有幫助。定價頁面說明了儲值方式,新帳戶可以從金鑰頁面領取 $0.50 的免費試用額度。
速率限制與佔用槽位的串流
下一個最常見的原因是 HTTP 429。有三種類型,您的客戶端會將它們全部合併為同樣無用的訊息。
| 訊號 | 含義 | 該怎麼辦 |
|---|---|---|
429,程式碼 rate_limited | 每分鐘請求過多 | 放慢速度;完整金鑰允許每分鐘 300 次,試用金鑰每分鐘 60 次 |
429,程式碼 concurrency | 同時執行的請求過多 | 將它們排入佇列;完整金鑰允許同時處理 8 個請求,試用金鑰允許同時處理 2 個請求 |
429 帶有 Retry-After: 5 | 服務端的暫時過載 | 等待 5 秒後再重試 |
並行限制是讓人驚訝的那一個,因為串流的工作方式。串流請求會佔用其槽位直到串流結束,而不僅僅是第一個 token 到達時。如果您的應用程式為每則訊息開啟串流且從未關閉舊的串流(例如,因為使用者導航離開且 UI 忘記取消請求),這些槽位會保持佔用狀態。在限制為 2 的試用金鑰上,兩個被放棄的串流就足以讓第三則訊息失敗。
症狀是一致的。前幾則訊息可以運作,然後開始出現錯誤,然後在短暫等待後一切又恢復正常。如果符合,請中止不再需要的串流(瀏覽器中的 AbortController,伺服器中關閉回應),並在您自己的程式碼中限制並行呼叫的數量。代理程式是常見的肇事者:一次觸發十個函式呼叫的規劃器會立即達到試用金鑰的限制。
回應標頭可幫助您了解目前的狀況。X-RateLimit-Limit-Requests 和 X-RateLimit-Limit-Concurrency 顯示適用於您使用的金鑰的限制,而 X-Request-Id 標識呼叫,如果您需要向 支援 查詢此事。
請求大小與上下文長度
請求也可能因過大而被拒絕。兩個數字很重要。主體最多為 8 MB,提示詞加上補全必須適合 100,000 token 的上下文視窗。每次輪次都重新發送整個對話的聊天前端會緩慢地達到這些限制,然後一次性全部失敗:聊天運作一個小時,然後一個長訊息或貼上的檔案使其超過限制,之後的每個輪次都會失敗,因為歷史記錄仍在請求中。
如果錯誤在長時間會話後開始,請使用新的短對話進行測試。如果這可以運作,則歷史記錄是原因。透過刪除舊輪次、將它們總結為一則訊息或開始新的聊天來縮減它。大型貼上的文件是另一個觸發因素。幾百 KB 的文字檔案沒問題,但 base64 資料塊或非常大的日誌可能比您預期的更快達到 8 MB。
您不必設定 max_tokens,因為補全可以使用視窗中剩餘的任何內容。如果您確實設定了它,請確保提示詞 token 加上 max_tokens 保持在 100,000 以下。在長歷史記錄之上硬編碼大型 max_tokens 的客戶端可能會使總和超過視窗,即使單獨的提示詞看起來沒問題。
代理伺服器、緩衝和超時
串流使用伺服器發送的事件:一個長期的 HTTP 回應,隨著產生的進度交付小區塊。在您和 API 之間的任何等待整個回應再轉發它的東西都會破壞這一點。結果要麼是長時間的沉默後出現爆發,要麼是超時和通用錯誤。
在您自己的設定中尋找這些:
- 反向代理伺服器。 如果您透過 nginx 或類似的代理伺服器路由 API,請關閉該位置的回應緩衝,並將讀取超時提高到您預期的最長答案之上。來自 100,000 token 視窗的長答案可能需要一些時間。
- 企業或防毒軟體代理伺服器。 某些代理伺服器會檢查 HTTPS 流量並保留主體。請使用手機熱點進行測試以排除此問題。
- 無伺服器函式。 許多平台會限制執行時間或緩衝回應,除非您選擇啟用串流。如果串流每次都在相同的秒數死亡,平台時間限制可能是原因。
- 瀏覽器擴充功能和 VPN。 很少見,但它們可以切斷閒置連線。
指向此處的線索是答案中間的錯誤,每次嘗試都有相同的截斷時間。速率限制會在開始時拒絕請求,因此串流中間的截斷(例如總是發生在 30 秒時)幾乎從來不是限制。
顯示真實錯誤的客戶端
當您想要真相而不是友好的訊息時使用此方法。它會捕獲 OpenAI SDK 異常,列印狀態和錯誤主體,並在存在時讀取重試提示。
import time
from openai import OpenAI, APIConnectionError, APIStatusError, RateLimitError
client = OpenAI(
base_url="https://api.uncensoredllmhub.com/v1",
api_key="YOUR_API_KEY",
)
def stream_once(messages):
stream = client.chat.completions.create(
model="uncensored",
messages=messages,
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
if getattr(chunk, "usage", None):
print("\n[usage]", chunk.usage)
messages = [{"role": "user", "content": "Write two sentences about harbours."}]
for attempt in range(4):
try:
stream_once(messages)
break
except RateLimitError as e:
wait = int(e.response.headers.get("retry-after", 5))
print("429:", e.body, "- waiting", wait, "s")
time.sleep(wait)
except APIStatusError as e:
print("status", e.status_code, e.body)
print("request id:", e.response.headers.get("x-request-id"))
break
except APIConnectionError as e:
print("connection problem:", e)
time.sleep(2)
Node 中的相同概念,帶有中止訊號,以便放棄的串流釋放其槽位:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.uncensoredllmhub.com/v1",
apiKey: process.env.API_KEY,
});
const controller = new AbortController();
try {
const stream = await client.chat.completions.create(
{
model: "uncensored",
messages: [{ role: "user", content: "Write two sentences about harbours." }],
stream: true,
},
{ signal: controller.signal }
);
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}
} catch (err) {
console.error("status:", err.status, "body:", err.error);
}
// call controller.abort() when the user leaves the page
以及原始的 curl 呼叫,它從畫面中移除了每個客戶端。-N 關閉 curl 自己的緩衝,-i 列印狀態行和標頭,包括 X-Request-Id:
curl -N -i https://api.uncensoredllmhub.com/v1/chat/completions -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" -d '{"model":"uncensored","stream":true,"messages":[{"role":"user","content":"Say hello."}]}'
如果 curl 順利串流文字而您的應用程式沒有,則 API 健康且問題位於應用程式、其代理伺服器或其設定中。如果 curl 顯示 429 或其他狀態,您現在有了確切的原因。
不會使情況惡化的重試規則
重試有助於解決暫時性問題,但會使永久性問題惡化。採用較短的重試策略可讓你避免麻煩。
- 重試 429 和斷開的連線。當存在時等待
Retry-After,否則退後幾秒鐘並添加一些隨機抖動,以便並行工作程式不會同步重試。 - 不要重試身份驗證失敗或過大的請求。結果不會改變,每次重試只會增加雜訊。
- 將嘗試次數限制為三或四次,然後向使用者顯示真實的錯誤文字。
- 將你自己的並行請求數量控制在金鑰限制以下。在完整金鑰上設定 6 的訊號量,可為使用相同金鑰的第二個工具保留空間。
- 如果串流在中途斷裂,請保留部分文字。將該文字作為助手訊息重新發送,並要求模型繼續,而不是從頭開始重新生成。
失敗或遭拒的請求不會計費,因此使用重複的測試呼叫進行除錯不會耗盡你的額度。成功的請求會以每 1M 輸入 token $0.15 和每 1M 輸出 token $0.50 計費,而正常完成的 部分串流 僅是一個簡短的答案。有關請求格式的更多詳細資訊,請參見 API 文件。
如果您已完成上述所有操作但仍看到該訊息,請將失敗呼叫的 X-Request-Id 發送到 支援頁面,附上嘗試時間以及失敗是在第一個 token 之前還是之後發生的。這些資訊足以追蹤發生了什麼。
