Điểm chính
- Văn bản đến từ ứng dụng khách, vì vậy hãy tái tạo lệnh gọi với curl để xem thân lỗi và trạng thái thực.
- HTTP 429 với mã rate_limited hoặc concurrency là nguyên nhân phổ biến nhất trên tài khoản bận rộn, và một luồng giữ vị trí của nó cho đến khi kết thúc.
- Hãy kiểm tra URL cơ sở, khóa, ID mô hình uncensored, kích thước thân (8 MB) và tổng token (100,000) trước bất cứ thứ gì khác.
- Chỉ thử lại với 429 và mất kết nối mạng, chờ Retry-After, và giữ độ đồng thời dưới giới hạn khóa.
Thông điệp thực sự cho bạn biết điều gì
Nếu bạn đã tìm kiếm lỗi không xác định từ luồng LLM, hãy tìm hiểu thêm, bạn có thể đang xem một thông báo toast hoặc dòng màu đỏ trong giao diện trò chuyện, plugin chỉnh sửa hoặc khung tác nhân. Cách diễn đạt này đến từ ứng dụng khách đó. Điều này có nghĩa là ứng dụng đã yêu cầu một câu trả lời được truyền phát, sự cố xảy ra trước hoặc trong quá trình truyền phát, và ứng dụng không biết cách mô tả nó. API thực tế báo cáo các vấn đề bằng trạng thái HTTP và thân lỗi JSON, còn ứng dụng khách đã loại bỏ chi tiết đó.
Đó là tin tốt, vì nó có nghĩa là bạn có thể lấy lại chi tiết. Hãy gửi cùng một yêu cầu bên ngoài ứng dụng khách, đọc dòng trạng thái và thân, và nguyên nhân thường rõ ràng sau một hoặc hai lần thử. Phần còn lại của trang này đi qua các nguyên nhân theo thứ tự chúng thường xảy ra trên API này, sau đó cung cấp cho bạn một ứng dụng khách nhỏ xử lý luồng in lỗi thực thay vì ẩn nó.
Một điều cần ghi nhớ ngay từ đầu: một yêu cầu stream có hai điểm thất bại. Nó có thể thất bại trước byte đầu tiên, khi máy chủ từ chối yêu cầu (sai khóa, sai URL, giới hạn). Hoặc nó có thể thất bại ở giữa, khi kết nối bị ngắt sau khi một số văn bản đã đến. Các cách sửa khác nhau, vì vậy hãy lưu ý loại nào bạn thấy. Nếu câu trả lời không bao giờ bắt đầu, hãy xem các phần hai đến bốn. Nếu nó bắt đầu rồi sau đó dừng lại, hãy xem phần về proxy và thời gian chờ.
Hãy kiểm tra URL cơ sở, khóa và mô hình trước
Hầu hết các lỗi luồng trên một thiết lập mới đến từ ba lỗi nhỏ. Chúng mất một phút để loại trừ.
- URL cơ sở. Nó phải là
https://api.uncensoredllmhub.com/v1, bao gồm/v1và không có/chat/completionsở cuối. Ứng dụng khách tự thêm đường dẫn. Nếu bạn dán endpoint đầy đủ vào trường mong đợi một URL cơ sở, ứng dụng khách sẽ yêu cầu một đường dẫn không tồn tại và báo một lỗi mơ hồ. - Khóa. Tiêu đề là
Authorization: Bearer YOUR_KEY. Một khoảng trắng lạc, một dòng mới được sao chép cùng khóa, hoặc một khóa từ dịch vụ khác đều thất bại theo cùng một cách. Hãy tạo hoặc sao chép lại khóa từ trang khóa API nếu bạn không chắc chắn. - ID mô hình. Mô hình duy nhất là
uncensored. Các ứng dụng khách có menu thả xuống thường điền trước một tên từ nhà cung cấp khác. Hãy gõ ID bằng tay, và gọiGET /v1/modelsnếu bạn muốn xác nhận những gì máy chủ liệt kê.
Một cách nhanh chóng để kiểm tra cả ba cùng lúc là lệnh gọi models. Nó không phát trực tiếp, vì vậy nó tách vấn đề kết nối hoặc khóa khỏi vấn đề luồng:
curl -i https://api.uncensoredllmhub.com/v1/models -H "Authorization: Bearer $API_KEY"
Nếu kết quả trả về là danh sách bình thường, URL và khóa API của bạn đều ổn và bạn có thể ngừng nghi ngờ hai thứ đó. Nếu kết quả trả về lỗi, hãy sửa lỗi đó trước khi xử lý bất kỳ vấn đề nào liên quan đến truyền phát (streaming). Bạn cũng nên kiểm tra xem tài khoản của bạn còn tín dụng không: API sẽ gửi số dư còn lại của bạn trong tiêu đề X-Balance-USD trên phản hồi, điều này rất hữu ích khi một khóa API ngừng hoạt động đột ngột sau khi sử dụng nhiều. Trang giá cả giải thích cách nạp tiền, và tài khoản mới có thể nhận $0.50 tín dụng dùng thử từ trang khóa API.
Giới hạn tốc độ và luồng giữ vị trí của nó
Nguyên nhân phổ biến tiếp theo là HTTP 429. Có ba loại, và ứng dụng khách của bạn sẽ gộp tất cả chúng vào cùng một thông báo vô dụng.
| Tín hiệu | Ý nghĩa | Những việc cần làm |
|---|---|---|
429, code rate_limited | Quá nhiều yêu cầu mỗi phút cho khóa API | Hãy chậm lại; một khóa đầy đủ cho phép 300 mỗi phút, một khóa dùng thử 60 |
429, code concurrency | Quá nhiều yêu cầu đang chạy cùng lúc | Xếp chúng vào hàng đợi; một khóa đầy đủ cho phép 8 cùng lúc, một khóa dùng thử 2 |
429 với Retry-After: 5 | Quá tải tạm thời ở phía dịch vụ | Hãy đợi 5 giây, sau đó thử lại |
Giới hạn đồng thời là giới hạn gây bất ngờ cho nhiều người, vì cách hoạt động của truyền phát. Một yêu cầu truyền phát chiếm vị trí của nó cho đến khi dòng dữ liệu kết thúc, chứ không phải cho đến khi token đầu tiên đến. Nếu ứng dụng của bạn mở một dòng dữ liệu cho mỗi tin nhắn và không bao giờ đóng dòng cũ, ví dụ vì người dùng đã chuyển hướng và giao diện người dùng quên hủy yêu cầu, các vị trí đó vẫn bị chiếm. Với khóa dùng thử có giới hạn là 2, hai dòng dữ liệu bị bỏ rơi là đủ để làm tin nhắn thứ ba thất bại.
Các triệu chứng nhất quán. Vài tin nhắn đầu tiên hoạt động, sau đó lỗi bắt đầu, sau đó mọi thứ lại hoạt động sau một khoảng thời gian chờ ngắn. Nếu điều đó khớp, hãy hủy các luồng bạn không còn cần nữa (một AbortController trong trình duyệt, đóng phản hồi trên máy chủ), và giới hạn số lượng lệnh gọi đồng thời trong mã của riêng bạn. Các agent là nguyên nhân thường xuyên nhất: một bộ lập kế hoạch bắn mười lệnh gọi công cụ cùng lúc sẽ chạm giới hạn trên một khóa dùng thử ngay lập tức.
Các tiêu đề phản hồi giúp bạn biết mình đang ở đâu. X-RateLimit-Limit-Requests và X-RateLimit-Limit-Concurrency cho biết các giới hạn áp dụng cho khóa API bạn đã sử dụng, và X-Request-Id xác định yêu cầu nếu bạn cần hỏi hỗ trợ về nó.
Kích thước yêu cầu và độ dài ngữ cảnh
Một yêu cầu cũng có thể bị từ chối vì quá lớn. Hai con số quan trọng. Thân có thể tối đa 8 MB, và prompt cùng phần hoàn tất phải vừa trong cửa sổ ngữ cảnh 100,000 token. Các giao diện người dùng chat gửi lại toàn bộ cuộc trò chuyện trên mỗi lượt chạm vào các giới hạn này chậm rồi sau đó tất cả cùng lúc: cuộc trò chuyện hoạt động trong một giờ, sau đó một tin nhắn dài hoặc một tệp dán làm nó vượt quá, và mọi lượt sau đều thất bại vì lịch sử vẫn còn trong yêu cầu.
Nếu lỗi bắt đầu sau một phiên dài, hãy thử với một cuộc trò chuyện mới ngắn. Nếu điều đó hoạt động, lịch sử là nguyên nhân. Hãy cắt ngắn nó bằng cách bỏ các lượt cũ, tóm tắt chúng thành một tin nhắn, hoặc bắt đầu một cuộc trò chuyện mới. Các tài liệu dán lớn là kích hoạt khác. Một tệp văn bản vài trăm kilobyte thì ổn, nhưng các blob base64 hoặc nhật ký rất lớn có thể đạt 8 MB nhanh hơn bạn mong đợi.
Bạn không cần đặt max_tokens, vì phần hoàn thành có thể sử dụng bất cứ thứ gì còn lại của cửa sổ. Nếu bạn có đặt nó, hãy đảm bảo token prompt cộng với max_tokens vẫn dưới 100,000. Một máy khách mã cứng một max_tokens lớn trên một lịch sử dài có thể đẩy tổng vượt quá cửa sổ ngay cả khi prompt đơn lẻ trông ổn.
Proxy, đệm và thời gian chờ
Luồng sử dụng sự kiện do máy chủ gửi: một phản hồi HTTP tồn tại lâu dài cung cấp các chunk nhỏ khi chúng được tạo ra. Bất cứ thứ gì giữa bạn và API chờ phản hồi đầy đủ trước khi chuyển tiếp nó sẽ phá vỡ điều đó. Kết quả là hoặc một sự im lặng dài theo sau bởi một đợt, hoặc một thời gian chờ và lỗi chung chung.
Hãy tìm những thứ này trong thiết lập của riêng bạn:
- Proxy ngược. Nếu bạn định tuyến API thông qua nginx hoặc proxy tương tự, hãy tắt đệm phản hồi cho vị trí đó, và tăng thời gian chờ đọc lên trên câu trả lời dài nhất bạn mong đợi. Các câu trả lời dài từ cửa sổ 100,000 token có thể mất một lúc.
- Proxy doanh nghiệp hoặc chống vi-rút. Một số kiểm tra lưu lượng HTTPS và giữ thân. Hãy thử từ điểm truy cập điện thoại để loại trừ điều này.
- Hàm không máy chủ (Serverless functions). Nhiều nền tảng giới hạn thời gian thực thi hoặc bộ đệm phản hồi trừ khi bạn chọn bật truyền phát (streaming). Nếu luồng truyền phát chết ở cùng một số giây mỗi lần, thì giới hạn thời gian của nền tảng là nguyên nhân có thể xảy ra.
- Tiện ích mở rộng trình duyệt và VPN. Hiếm gặp, nhưng chúng có thể ngắt các kết nối nhàn rỗi.
Mẹo chỉ ra đây là lỗi ở giữa một câu trả lời, với cùng thời gian cắt ngắn trên mọi lần thử. Một giới hạn tốc độ sẽ từ chối yêu cầu ở đầu, vì vậy một lần cắt giữa luồng luôn xảy ra vào, ví dụ, 30 giây hầu như không bao giờ là một giới hạn.
Một máy khách hiển thị lỗi thực
Hãy dùng cái này khi bạn muốn sự thật thay vì thông báo thân thiện. Nó bắt các ngoại lệ SDK OpenAI, in trạng thái và thân lỗi, và đọc gợi ý thử lại khi có một.
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)
Cùng ý tưởng trong Node, với một tín hiệu hủy để các luồng bị bỏ hoang giải phóng vị trí của chúng:
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
Và một lệnh gọi curl thô, loại bỏ mọi máy khách khỏi bức tranh. -N tắt đệm riêng của curl và -i in dòng trạng thái và tiêu đề, bao gồm 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."}]}'
Nếu curl stream văn bản tốt và ứng dụng của bạn không, API hoạt động bình thường và vấn đề nằm ở ứng dụng, proxy hoặc cài đặt của nó. Nếu curl hiển thị 429 hoặc trạng thái khác, bạn đã có nguyên nhân chính xác.
Quy tắc thử lại không làm mọi thứ tệ hơn
Các lần thử lại giúp xử lý các vấn đề tạm thời và gây hại với các vấn đề vĩnh viễn. Một chính sách thử lại ngắn giúp bạn tránh rắc rối.
- Hãy thử lại 429 và kết nối bị đứt. Chờ giá trị
Retry-Afterkhi nó có mặt, nếu không hãy lùi lại vài giây và thêm một chút nhiễu ngẫu nhiên để các worker song song không thử lại cùng lúc. - Không thử lại các lỗi xác thực hoặc yêu cầu quá lớn. Kết quả sẽ không thay đổi, và mỗi lần thử lại chỉ thêm nhiễu.
- Giới hạn số lần thử ở ba hoặc bốn, sau đó hiển thị văn bản lỗi thực cho người dùng.
- Giới hạn độ đồng thời của riêng bạn dưới giới hạn khóa. Một semaphore 6 trên một khóa đầy đủ để lại chỗ cho một công cụ thứ hai dùng cùng khóa.
- Nếu một luồng bị gãy ở giữa, hãy giữ văn bản một phần. Gửi lại với văn bản đó làm một tin nhắn trợ lý và yêu cầu mô hình tiếp tục, thay vì tạo lại từ đầu.
Các yêu cầu bị lỗi hoặc bị từ chối sẽ không bị tính phí, vì vậy việc gỡ lỗi bằng các lệnh gọi thử nghiệm lặp lại sẽ không làm cạn kiệt tín dụng của bạn. Các lệnh gọi thành công được tính phí $0.15 cho mỗi 1 triệu token đầu vào và $0.50 cho mỗi 1 triệu token đầu ra, và một stream chưa hoàn tất nhưng kết thúc bình thường chỉ đơn giản là một câu trả lời ngắn. Thêm chi tiết về định dạng yêu cầu có trong tài liệu API.
Nếu bạn đã làm tất cả những điều trên và vẫn thấy thông báo, hãy gửi X-Request-Id của một lệnh gọi bị lỗi đến trang hỗ trợ, kèm theo thời gian của lần thử nghiệm và liệu lỗi xảy ra trước hay sau token đầu tiên. Thông tin đó là đủ để truy vết những gì đã xảy ra.
