อัตราจำกัดคำขอและคำขอพร้อมกัน
ลิมิตระดับบัญชีสองตัวที่กำหนดโดยแพ็กเกจ คำขอต่อนาทีใช้หน้าต่างเวลาร่วมกันทุกผลิตภัณฑ์ ส่วนคำขอพร้อมกันนับแยกตามผลิตภัณฑ์ พร้อมวิธีนับของแต่ละลิมิต วิธีอ่านเฮดเดอร์ x-ratelimit และวิธีส่งซ้ำเมื่อเจอ 429
ลิมิตมีสองตัว และแพ็กเกจเป็นตัวกำหนดทั้งคู่ คำขอต่อนาทีนับครั้งเดียวทั้งบัญชี: หน้าต่างเวลาเดียวครอบคลุมทุกผลิตภัณฑ์และทุกคีย์ ส่วนคำขอพร้อมกันนับแยกตามผลิตภัณฑ์: เสียงพูด การถอดเสียง OCR และแปลภาษา มีโควตาแยกของตัวเองขนาดเท่าตัวเลขของแพ็กเกจ และการสกัดข้อมูลจากเอกสารใช้โควตาเดียวกับ OCR เอนด์พอยต์แคตตาล็อก บัญชี และสถานะระบบ ไม่ถูกจำกัด ส่วนความคิดเห็นมีโควตารายวันของตัวเอง ดูตัวเลขของแต่ละแพ็กเกจได้ที่หน้าราคา ปัจจุบันคือ
| แพ็กเกจ | คำขอต่อนาที | คำขอพร้อมกัน |
|---|---|---|
| Free | 10 | 1 |
| Starter | 60 | 5 |
| Standard | 200 | 15 |
| Pro | ไม่จำกัด | 60 |
คำขอพร้อมกันนับแยกตามผลิตภัณฑ์: แพ็กเกจ Standard จึงมีคำขอเสียงพูดค้างอยู่ได้ 15 คำขอ พร้อมกับคำขอถอดเสียงอีก 15 คำขอ คำขอ OCR อีก 15 คำขอ และคำขอแปลภาษาอีก 15 คำขอในเวลาเดียวกัน GET /v1/me รายงานตัวเลขทั้งสองของบัญชีที่ยืนยันตัวตนแล้ว
หน้าต่างคำขอเดียว โควตาพร้อมกันแยกกัน#
ลิมิตสองตัวนี้ตั้งใจให้นับต่างกัน:
- คำขอต่อนาทีใช้ร่วมกัน หน้าต่างเวลาเดียวครอบคลุมทั้งบัญชี: ทุกผลิตภัณฑ์ ทุกคีย์ และทุกรอบสังเคราะห์บนสตรีมสด รวมกัน
- คำขอพร้อมกันแยกจากกัน เสียงพูด การถอดเสียง OCR และแปลภาษา มีโควตาของตัวเองขนาดเท่าตัวเลขของแพ็กเกจ และคำขอสกัดข้อมูลจากเอกสารนับในโควตา OCR งานแปลชุดใหญ่ที่ช้าจึงไม่มีทางขวางเสียงพูด การอ่านเอกสาร หรือการถอดเสียง และกลับกันก็เช่นกัน
- การเชื่อมต่อสดที่เปิดอยู่ถือหนึ่งช่องของฝั่งเสียงพูดตลอดเวลาที่เชื่อมต่อ ไม่ว่าขณะนั้นจะกำลังสังเคราะห์อยู่หรือไม่
หน้าต่างเวลาแบบเลื่อน#
การจำกัดใช้หน้าต่างเวลา 60 วินาทีแบบเลื่อน นาทีก่อนหน้ายังถูกนับตามสัดส่วนเวลาที่เหลืออยู่ การยิงคำขอชุดใหญ่จึงใช้โควตาซ้อนกันสองเท่าตรงรอยต่อของนาทีไม่ได้ และโควตาทยอยคืนอย่างต่อเนื่อง
อ่านเฮดเดอร์#
ในแพ็กเกจที่มีการจำกัด การตอบกลับของคำขอสังเคราะห์ทุกครั้งรายงานโควตาผ่าน x-ratelimit-limit, x-ratelimit-remaining และ x-ratelimit-reset (เวลา Unix เป็นวินาที) ส่วนแพ็กเกจที่ไม่จำกัดจะไม่ส่งเฮดเดอร์ชุดนี้
HTTP/1.1 200 OK
Content-Type: audio/mpeg
x-request-id: 7d9c2b7e-4a41-4c8e-9a35-1f26d8c04b7a
x-credits-charged: 0.86
x-ratelimit-limit: 60
x-ratelimit-remaining: 42
x-ratelimit-reset: 1785762360คำขอพร้อมกัน#
หนึ่งช่องคือหนึ่งคำขอที่ค้างอยู่: คำขอสังเคราะห์ผ่าน HTTP นับตั้งแต่รับเข้าจนการตอบกลับจบ คำขอแปลภาษาหรืออ่านเอกสารนับจนกว่า JSON จะตอบกลับ และการเชื่อมต่อสดนับตั้งแต่อัปเกรดจนปิด เมื่อบัญชีถือครบทุกช่องของผลิตภัณฑ์ใด คำขอใหม่ของผลิตภัณฑ์นั้นตอบ 429 concurrency_limited และไม่มีการคิดค่าบริการ
การตอบกลับ concurrency_limited ไม่มีเฮดเดอร์ retry-after เพราะการรอจะจบเมื่อคำขอของคุณเองเสร็จหนึ่งรายการ ให้ส่งซ้ำหลังมีคำขอเสร็จ หรือปิดการเชื่อมต่อสดที่ไม่ใช้แล้ว สังเกต x-ratelimit-remaining ในตัวอย่าง: หน้าต่างคำขอยังเหลือโควตา และ 429 ครั้งนี้เป็นเรื่องช่องคำขอที่ค้างอยู่
HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
x-ratelimit-limit: 60
x-ratelimit-remaining: 41
x-ratelimit-reset: 1785762420
{"title": "concurrency_limited", "status": 429}อยู่ใต้ลิมิต#
ลิมิตทั้งสองตัวนับจำนวนคำขอ ขนาดของแต่ละคำขอไม่มีผล ควรรวมงานให้เหลือจำนวนคำขอน้อยที่สุด คำขอแปลภาษาที่ส่งอาร์เรย์หลายท่อนนับเป็นหนึ่งคำขอต่อหน้าต่างเวลาและถือหนึ่งช่อง คำขอ TTS ที่ส่งทั้งย่อหน้านับเป็นหนึ่งคำขอ ส่วนการเรียกทีละประโยคนับทีละคำขอ
ทุกคีย์ใช้ลิมิตของบัญชีร่วมกัน การเพิ่มคีย์จึงไม่เพิ่มโควตา ให้เว้นจังหวะส่งซ้ำตาม retry-after การเปิด WebSocket สดก็ถูกปฏิเสธด้วย 429 ได้เหมือนคำขอสังเคราะห์ทั่วไป จากลิมิตตัวใดก็ได้
จัดการการตอบกลับ 429#
สถานะ 429 มีได้สองโค้ด และ title คือตัวแยก rate_limited แปลว่าหน้าต่างต่อนาทีหมดโควตา ให้รอตามเฮดเดอร์ retry-after ส่วน concurrency_limited แปลว่าทุกช่องของผลิตภัณฑ์นั้นถูกถือครบ ให้ส่งซ้ำเมื่อคำขอของคุณเสร็จหนึ่งรายการ ตัวช่วยรอแล้วส่งซ้ำง่าย ๆ ครอบคลุมทั้งสองกรณีสำหรับงานส่วนใหญ่
HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
retry-after: 12
x-ratelimit-limit: 60
x-ratelimit-remaining: 0
x-ratelimit-reset: 1785762420
{"title": "rate_limited", "status": 429}async function withRetry(request: () => Promise<Response>): Promise<Response> {
for (;;) {
const response = await request();
if (response.status !== 429) return response;
// rate_limited sends retry-after. concurrency_limited does not,
// and a short wait covers a slot freeing up.
const seconds = Number(response.headers.get("retry-after") ?? "1");
await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
}
}