Xử lý giới hạn tốc độ và thử lại trên API LLM
Vào lúc 09:12 một ngày thứ Ba, quy trình tóm tắt của chúng tôi có vẻ hoạt động tốt: 96 tiến trình xử lý đang chạy, độ trễ trung vị của mô hình khoảng 2.8 giây, tỷ lệ lỗi 5xx không tăng cao. Sau đó, một khách hàng tải lên lượng tồn đọng gồm 38,000 phiếu hỗ trợ.
Chỉ trong vòng bốn phút, quy trình đã “ngừng hoạt động” dù không có máy chủ nào ngừng chạy. Chúng tôi đồng thời chạm vào hai giới hạn khác nhau:
requests_per_minute: quá nhiều lệnh gọi APItokens_per_minute: tổng lượng prompt và phản hồi quá lớn
Logic thử lại đơn giản khiến tình hình tệ hơn. Mọi tiến trình xử lý đều gặp 429, chờ một giây rồi cùng thử lại. Điều đó tạo ra một làn sóng thử lại, dẫn đến thêm nhiều 429, từ đó tạo ra một làn sóng khác. Hệ thống đã vô tình tạo ra một cuộc tấn công từ chối dịch vụ đồng bộ nhắm vào chính hạn ngạch của mình.
Xử lý giới hạn tốc độ của LLM không chỉ là “thêm cơ chế giãn thời gian chờ theo cấp số nhân”. Trong môi trường vận hành thực tế, bạn cần xem xét token, hàng đợi, mức độ đồng thời, các lần thử lại, tính lũy đẳng, nhà cung cấp dự phòng và cách tính phí như một hệ thống thống nhất.
Hai giới hạn quan trọng: RPM và TPM
Hầu hết API LLM áp dụng một tổ hợp các giới hạn sau:
- RPM: số yêu cầu mỗi phút
- TPM: số token mỗi phút
- RPD / TPD: số yêu cầu hoặc token mỗi ngày
- Giới hạn yêu cầu đồng thời: số lệnh gọi đang xử lý tối đa
- Giới hạn riêng theo mô hình: giới hạn cao hơn cho các mô hình nhỏ hơn, giới hạn thấp hơn cho các mô hình tiên tiến nhất
Điểm quan trọng: RPM và TPM gây lỗi theo những cách khác nhau.
Nếu gửi nhiều prompt rất ngắn, bạn sẽ chạm giới hạn RPM trước. Nếu gửi ít prompt hơn nhưng mỗi prompt lại lớn, bạn sẽ chạm giới hạn TPM trước.
Ví dụ:
Limit:
- 600 requests/minute
- 300,000 tokens/minute
Workload A:
- 1,000 short classification calls/minute
- 200 tokens each
- 200,000 tokens/minute total
Result:
- TPM is fine
- RPM fails
Workload B:
- 100 long document analysis calls/minute
- 5,000 tokens each
- 500,000 tokens/minute total
Result:
- RPM is fine
- TPM fails
Một cạm bẫy thường gặp: nhà phát triển điều tiết số yêu cầu nhưng không điều tiết số token. Cách này hoạt động trong môi trường tiền sản xuất, nơi prompt ngắn. Nhưng khi người dùng thực tế dán nội dung PDF, lịch sử trò chuyện, nhật ký hoặc hợp đồng pháp lý, ngân sách token nhanh chóng cạn kiệt.
Trong thực tế, tôi coi mỗi lệnh gọi LLM là việc dành trước hai loại tài nguyên:
cost = {
requests: 1,
tokens: estimated_prompt_tokens + max_output_tokens
}
Ngay cả khi mô hình trả về ít token đầu ra hơn max_output_tokens, việc dành trước theo giới hạn trên vẫn giúp tránh cấp phát vượt mức.
Điều gì thực sự xảy ra khi bạn bỏ qua TPM
Giả sử bạn có:
TPM limit: 120,000
Average request: 4,000 input tokens + 1,000 max output tokens
Reserved cost: 5,000 tokens
Thông lượng tối đa thực tế của bạn không phải là “càng nhiều tiến trình xử lý càng tốt”. Nó là:
120,000 / 5,000 = 24 requests per minute
Tức là trung bình cứ 2.5 giây mới có một yêu cầu.
Nếu chạy 100 tiến trình xử lý, toàn bộ lô đầu tiên có thể khởi chạy thành công nếu nhà cung cấp cho phép tải tăng đột biến. Sau đó, tài khoản sẽ chạm giới hạn cứng. Mọi yêu cầu tiếp theo đều nhận được 429, và các lần thử lại dồn ứ.
Cách khắc phục không chỉ là giảm số tiến trình xử lý. Bạn cần một bộ lập lịch có tính đến việc dành trước token.
Bộ giới hạn tốc độ tối giản có tính đến token
Với một tiến trình duy nhất, thuật toán token bucket thường là đủ. Bạn bổ sung dung lượng theo thời gian và yêu cầu mỗi yêu cầu phải được cấp cả một suất yêu cầu lẫn một phần dung lượng token.
Dưới đây là một ví dụ Python đã được đơn giản hóa:
import asyncio
import time
from dataclasses import dataclass
@dataclass
class Bucket:
capacity: float
refill_per_second: float
tokens: float
updated_at: float
def refill(self):
now = time.monotonic()
elapsed = now - self.updated_at
self.tokens = min(self.capacity, self.tokens + elapsed * self.refill_per_second)
self.updated_at = now
async def acquire(self, amount: float):
while True:
self.refill()
if self.tokens >= amount:
self.tokens -= amount
return
missing = amount - self.tokens
sleep_for = missing / self.refill_per_second
await asyncio.sleep(min(sleep_for, 1.0))
class LLMRateLimiter:
def __init__(self, rpm: int, tpm: int):
now = time.monotonic()
self.request_bucket = Bucket(
capacity=rpm,
refill_per_second=rpm / 60,
tokens=rpm,
updated_at=now,
)
self.token_bucket = Bucket(
capacity=tpm,
refill_per_second=tpm / 60,
tokens=tpm,
updated_at=now,
)
self.lock = asyncio.Lock()
async def acquire(self, estimated_tokens: int):
async with self.lock:
await self.request_bucket.acquire(1)
await self.token_bucket.acquire(estimated_tokens)
Cách sử dụng:
estimated_tokens = prompt_tokens + max_output_tokens
await limiter.acquire(estimated_tokens)
response = await client.chat.completions.create(
model="gpt-5.5",
messages=messages,
max_tokens=max_output_tokens,
)
Ví dụ này được chủ ý giữ đơn giản. Trong hệ thống phân tán, hãy sử dụng Redis, khóa tư vấn của Postgres hoặc hàng đợi có cơ chế điều phối tập trung. Nguyên tắc quan trọng vẫn như nhau: điều tiết cả số lượng yêu cầu lẫn ngân sách token trước khi gọi API.
Thử lại: giãn thời gian chờ là cần thiết nhưng chưa đủ
Thử lại hữu ích đối với:
- Tạm thời
429phản hồi - Hết thời gian chờ mạng
- Tạm thời
500,502,503, hoặc504lỗi - Quá tải phía nhà cung cấp
- Kết nối bị đặt lại
Thử lại có thể gây nguy hiểm đối với:
- Lỗi kiểm tra tính hợp lệ
- Lỗi độ dài ngữ cảnh
- Lỗi xác thực
- Yêu cầu bị từ chối theo chính sách an toàn
- Prompt không hợp lệ luôn gây ra cùng một lỗi
- Lệnh gọi công cụ không có tính lũy đẳng
Chính sách thử lại cần phân loại lỗi trước.
| Loại lỗi | Thử lại? | Hành động thường dùng |
|---|---|---|
429 rate_limit_exceeded | Có | Giãn thời gian chờ, tuân thủ các header hướng dẫn thử lại, giảm mức độ đồng thời |
500/502/503/504 | Có | Giãn thời gian chờ kèm độ lệch ngẫu nhiên, giới hạn số lần thử |
| Hết thời gian chờ trước khi nhận phần thân phản hồi | Có thể | Thử lại với khóa lũy đẳng nếu được hỗ trợ |
| Vượt quá độ dài ngữ cảnh | Không | Nén, chia nhỏ hoặc định tuyến đến mô hình có ngữ cảnh dài hơn |
| Khóa API không hợp lệ | Không | Vô hiệu hóa khóa, cảnh báo người vận hành |
| Bị từ chối do nội dung hoặc chính sách an toàn | Không | Trả về lỗi có kiểm soát hoặc viết lại yêu cầu |
| Tác động phụ của công cụ đã được thực hiện | Không/Có thể | Cần thiết kế bảo đảm tính lũy đẳng |
Dạng cơ bản của cơ chế giãn thời gian chờ:
import random
def retry_delay(attempt: int, base=0.5, cap=30.0):
exponential = min(cap, base * (2 ** attempt))
return random.uniform(0, exponential)
Phần random.uniform(0, exponential) đó là độ lệch ngẫu nhiên. Đừng bỏ qua nó.
Không có độ lệch ngẫu nhiên:
100 workers fail
100 workers sleep 1s
100 workers retry
100 workers fail
100 workers sleep 2s
100 workers retry
Có độ lệch ngẫu nhiên:
100 workers fail
workers retry across a spread of 0-1s
then 0-2s
then 0-4s
Mẫu thứ hai tạo khoảng trống để nhà cung cấp và hàng đợi của bạn phục hồi.
Tuân thủ các header thử lại khi có
Nhiều API cung cấp gợi ý như:
Retry-After: 12
hoặc các header đặt lại giới hạn riêng của nhà cung cấp. Nếu API cung cấp thời gian chờ cụ thể, hãy dùng thời gian đó làm mức tối thiểu:
delay = max(header_retry_after_seconds, retry_delay(attempt))
await asyncio.sleep(delay)
Trong thực tế, tôi cũng giới hạn tổng thời gian thử lại. Một yêu cầu trò chuyện trực tiếp với người dùng không nên âm thầm thử lại suốt hai phút trong khi người dùng nhìn biểu tượng tải xoay. Một tác vụ xử lý hàng loạt chạy nền có thể chờ lâu hơn nhiều.
Ví dụ về chính sách:
{
"interactive_chat": {
"max_attempts": 3,
"max_total_retry_seconds": 8
},
"batch_summarization": {
"max_attempts": 8,
"max_total_retry_seconds": 300
}
}Dùng hàng đợi hiệu quả hơn để các worker đồng loạt gửi yêu cầu
Nếu khối lượng công việc vượt quá hạn mức, không nên để tất cả worker trực tiếp gọi API LLM. Hãy đặt một hàng đợi ở phía trước.
Một kiến trúc thực tế:
App/API
-> Job queue
-> Rate-aware dispatcher
-> Provider client
-> Result store
Bộ điều phối chịu trách nhiệm về:
- Theo dõi RPM
- Theo dõi TPM
- Lựa chọn mô hình
- chính sách thử lại
- chuyển sang nhà cung cấp dự phòng
- giới hạn số tác vụ đồng thời
- mức ưu tiên trong hàng đợi
Cách này giúp bạn thấy rõ tình trạng quá tải. Thay vì hàng nghìn tác vụ thất bại với 429, bạn sẽ thấy số tác vụ trong hàng đợi tăng lên và thời gian chờ ước tính dài hơn.
Với các hệ thống dùng Redis, tôi thích tách các tác vụ “sẵn sàng chạy” khỏi các tác vụ “chờ thử lại”:
llm:ready
llm:delayed
llm:dead_letter
Một tác vụ thất bại không lập tức quay lại ready. Tác vụ đó được gán mốc thời gian thử lại theo lịch. Một bộ lập lịch nhỏ chuyển các tác vụ đến hạn trở lại hàng đợi sẵn sàng.
{
"job_id": "sum_7f13",
"model": "claude-sonnet-4.6",
"estimated_tokens": 6200,
"attempt": 2,
"not_before": "2026-02-03T09:14:22Z"
}
Phần not_before là trường giúp ngăn các đợt thử lại ồ ạt.
Kiểm soát số tác vụ đồng thời khác với giới hạn tốc độ
Giới hạn số tác vụ đồng thời khống chế lượng công việc đang xử lý. Giới hạn tốc độ khống chế lượng công việc trong mỗi khoảng thời gian.
Bạn cần cả hai.
Giả sử mỗi lệnh gọi mất 20 giây và RPM của bạn là 60. Một bộ giới hạn chỉ dựa trên RPM cho phép một yêu cầu mỗi giây. Sau 20 giây, bạn có khoảng 20 lệnh gọi đồng thời. Nếu độ trễ tăng lên 90 giây, cùng mức RPM đó sẽ tạo ra 90 lệnh gọi đồng thời. Điều này có thể vượt quá giới hạn của nhà cung cấp hoặc tài nguyên cục bộ.
Dùng semaphore để kiểm soát số tác vụ đồng thời:
provider_concurrency = asyncio.Semaphore(20)
async def call_model(job):
async with provider_concurrency:
await limiter.acquire(job.estimated_tokens)
return await send_request(job)
Một lỗi dễ mắc: chiếm semaphore quá sớm khiến các worker không làm gì nhưng vẫn giữ những suất xử lý đồng thời khan hiếm trong lúc chờ token cấp phép từ bộ giới hạn tốc độ. Thông thường, hãy lấy quyền gửi yêu cầu theo giới hạn tốc độ trước, rồi chiếm suất xử lý đồng thời ngay trước khi gọi qua mạng. Nếu thời gian chờ bộ giới hạn có thể kéo dài, hãy tránh chiếm tài nguyên worker trong lúc chờ.
Giảm chất lượng có kiểm soát: Dành chất lượng cho những nơi quan trọng
Khi giới hạn tốc độ bắt đầu ảnh hưởng, bạn có những lựa chọn khác ngoài việc để yêu cầu thất bại.
Ví dụ, một trợ lý hỗ trợ khách hàng có thể giảm chất lượng theo các mức sau:
| Mức áp lực | Chiến lược | Ảnh hưởng đến người dùng |
|---|---|---|
| Bình thường | Dùng mô hình mạnh nhất đã cấu hình | Chất lượng tốt nhất |
| Áp lực TPM nhẹ | Giảm max_tokens, rút gọn ngữ cảnh đã truy xuất | Câu trả lời ngắn hơn một chút |
| Áp lực vừa phải | Chuyển các tác vụ đơn giản sang mô hình nhỏ hơn | Ảnh hưởng tối thiểu nếu việc phân loại/định tuyến dễ dàng |
| Áp lực cao | Đưa các tác vụ không khẩn cấp vào hàng đợi | Công việc chạy nền bị trì hoãn |
| Áp lực nghiêm trọng | Trả về câu trả lời đã lưu trong bộ nhớ đệm hoặc theo mẫu | Chất lượng thấp hơn nhưng vẫn phục vụ được |
Ví dụ cụ thể:
- Định tuyến tác vụ gắn nhãn phiếu hỗ trợ sang Haiku 4.5, Qwen hoặc một biến thể Llama nhỏ thay vì dùng mô hình tiên tiến hàng đầu.
- Dùng Sonnet 4.6 cho suy luận thông thường và dành Opus 4.8 hoặc GPT-5.5 cho các luồng xử lý nâng cấp.
- Chỉ chuyển tác vụ phân tích ngữ cảnh dài sang Fable 5 hoặc Gemini 3 khi prompt thực sự cần cửa sổ ngữ cảnh đó.
- Với các tác vụ xử lý hàng loạt, hãy tạm dừng các tenant có mức ưu tiên thấp trước khi ảnh hưởng đến lưu lượng tương tác.
Đổi lại là độ phức tạp. Mọi luồng dự phòng đều cần kiểm thử, khả năng quan sát và sự chấp thuận từ phía sản phẩm. Trong một số lĩnh vực, câu trả lời kém hơn có thể gây thiệt hại lớn hơn câu trả lời đến muộn.
Dự phòng bằng nhiều khóa và nhiều nhà cung cấp
Định tuyến qua nhiều khóa và nhiều nhà cung cấp có thể cải thiện khả năng chống chịu, nhưng cũng rất dễ triển khai sai.
Có ba mẫu riêng biệt:
| Mẫu | Vấn đề được giải quyết | Rủi ro |
|---|---|---|
| Nhiều khóa, cùng nhà cung cấp/tài khoản | Cô lập vận hành | Có thể vi phạm điều khoản của nhà cung cấp nếu dùng để né giới hạn |
| Nhiều tài khoản/khu vực | Cô lập sự cố | Tăng độ phức tạp trong thanh toán và quản trị |
| Nhiều nhà cung cấp/mô hình | Tính sẵn sàng và sự linh hoạt về chi phí | Đầu ra khác biệt, prompt không tương thích |
Đừng dùng nhiều khóa để lách giới hạn. Hãy dùng chúng để phân tách hợp lệ: tenant, môi trường, sản phẩm hoặc phạm vi thanh toán.
Một chính sách định tuyến rõ ràng có thể như sau:
{
"task": "support_ticket_summary",
"primary": {
"provider": "anthropic",
"model": "claude-sonnet-4.6"
},
"fallbacks": [
{
"provider": "openai",
"model": "gpt-5.5",
"when": ["provider_5xx", "rate_limit_after_retry_budget"]
},
{
"provider": "google",
"model": "gemini-3",
"when": ["context_length_needed", "primary_unavailable"]
}
],
"degrade_to": {
"provider": "open_model_cluster",
"model": "qwen",
"when": ["batch_low_priority"]
}
}
Nếu bạn dùng một dịch vụ tổng hợp hoặc nền tảng như AI Prime Tech để truy cập nhiều mô hình, các nguyên tắc kỹ thuật tương tự vẫn áp dụng: theo dõi rõ ràng tính lũy đẳng, ngân sách, điều kiện chuyển sang phương án dự phòng và quy tắc tính phí cuối cùng.
Tránh bị tính phí hai lần khi chuyển sang phương án dự phòng
Điểm khó của phương án dự phòng là xác định liệu yêu cầu đầu tiên đã hoàn tất hay chưa.
Hãy xem xét chuỗi sự kiện này:
Client sends request to Provider A
Provider A processes it successfully
Network connection drops before client receives response
Client retries with Provider B
Both providers bill
Two completions may exist
Bạn không thể giải quyết hoàn toàn vấn đề này từ phía máy khách, trừ khi nhà cung cấp hỗ trợ khóa lũy đẳng hoặc tra cứu yêu cầu. Nhưng bạn có thể giảm thiệt hại.
Dùng khóa lũy đẳng khi được hỗ trợ
Tạo một khóa ổn định cho mỗi thao tác logic:
import hashlib
import json
def idempotency_key(task_name, tenant_id, input_payload):
canonical = json.dumps(input_payload, sort_keys=True, separators=(",", ":"))
digest = hashlib.sha256(canonical.encode()).hexdigest()
return f"{tenant_id}:{task_name}:{digest}"
Lưu thao tác trước khi gửi:
{
"operation_id": "acme:summarize:9d2a...",
"status": "in_flight",
"provider": "anthropic",
"model": "claude-sonnet-4.6",
"created_at": "2026-02-03T09:12:01Z"
}
Sau đó cập nhật khi hoàn tất:
{
"operation_id": "acme:summarize:9d2a...",
"status": "completed",
"provider_request_id": "req_abc123",
"usage": {
"input_tokens": 4180,
"output_tokens": 612
}
}
Trước khi thử lại ở nơi khác, hãy kiểm tra bảng thao tác. Nếu một worker khác đã hoàn tất thao tác đó, hãy trả về kết quả đã lưu.
Phân biệt các loại hết thời gian chờ
Không phải mọi trường hợp hết thời gian chờ đều giống nhau:
- Hết thời gian chờ kết nối: yêu cầu có thể chưa bao giờ đến được nhà cung cấp
- Hết thời gian chờ đọc trước khi nhận header: không chắc chắn
- Hết thời gian chờ trong khi truyền token theo luồng: gần như chắc chắn nhà cung cấp đã xử lý yêu cầu
- Máy khách hủy yêu cầu: phụ thuộc vào việc lệnh hủy có được truyền đến bên xử lý hay không
Với những trường hợp không chắc chắn, tôi ưu tiên một chính sách thử lại thận trọng:
interactive:
- retry connect timeout
- do not cross-provider retry after partial stream
- show recoverable error if status unknown
batch:
- retry after reconciliation delay
- prefer same provider with idempotency key
- fallback only after retry budget expires
Truyền theo luồng một cách thận trọng
Truyền theo luồng cải thiện độ trễ mà người dùng cảm nhận, nhưng khiến việc thử lại phức tạp hơn. Khi bạn đã gửi một phần đầu ra cho người dùng, việc thử lại bằng mô hình khác có thể tạo ra phần tiếp theo khác biệt.
Với trò chuyện truyền theo luồng, tôi thường coi thời điểm “nhận được token đầu tiên” là mốc không thể thử lại ngầm nữa. Sau đó, lỗi sẽ được hiển thị cho người dùng:
"The response was interrupted. Retry?"
Cách này kém tinh tế hơn việc âm thầm phục hồi, nhưng tránh ghép các đầu ra không tương thích từ những mô hình khác nhau.
Khả năng quan sát: Những chỉ số thực sự hữu ích
Bạn cần nhiều hơn tỷ lệ thành công.
Ít nhất hãy theo dõi:
llm_requests_total{provider,model,status}
llm_tokens_reserved_total{provider,model}
llm_tokens_used_total{provider,model}
llm_retries_total{provider,model,error_type}
llm_queue_depth{priority,task_type}
llm_queue_wait_seconds{priority,task_type}
llm_rate_limit_hits_total{provider,model,limit_type}
llm_fallbacks_total{from_provider,to_provider,reason}
llm_duplicate_suppressed_total{task_type}
Trong các sự cố thực tế, ô thông tin hữu ích nhất trên bảng điều khiển thường không phải là độ trễ. Mà là:
queue_wait_seconds p50 / p95
rate_limit_hits by provider and model
tokens_reserved vs tokens_used
fallback rate by reason
Nếu tokens_reserved luôn cao hơn nhiều so với tokens_used, lượng token bạn dự trù quá dư dả. Nếu lượng này quá sát hoặc thấp hơn mức sử dụng thực tế, bạn đang phân bổ vượt hạn mức và sẽ bất ngờ chạm giới hạn TPM.
Một hàm bao thử lại thiết thực
Dưới đây là một mẫu gọn để chỉ thử lại những lỗi đủ điều kiện:
import asyncio
import random
import time
RETRYABLE_STATUS = {429, 500, 502, 503, 504}
class LLMError(Exception):
def __init__(self, status, message="", retry_after=None):
self.status = status
self.retry_after = retry_after
super().__init__(message)
def jittered_backoff(attempt, base=0.5, cap=20):
return random.uniform(0, min(cap, base * (2 ** attempt)))
async def call_with_retries(fn, max_attempts=4, max_elapsed=20):
started = time.monotonic()
for attempt in range(max_attempts):
try:
return await fn()
except LLMError as error:
elapsed = time.monotonic() - started
if error.status not in RETRYABLE_STATUS:
raise
if attempt == max_attempts - 1 or elapsed >= max_elapsed:
raise
delay = jittered_backoff(attempt)
if error.retry_after is not None:
delay = max(delay, error.retry_after)
remaining = max_elapsed - elapsed
await asyncio.sleep(min(delay, remaining))
Hàm bao này được cố ý giữ đơn giản. Phần phức tạp nên nằm ở việc phân loại, xếp hàng, bảo đảm tính lũy đẳng và định tuyến—chứ không phải trong một vòng lặp thử lại thần kỳ cứ chạy mãi.
Những điểm thực tiễn cần ghi nhớ
- Mô hình hóa giới hạn tốc độ theo cả RPM và TPM. Điều tiết dựa trên lượng token giúp tránh những bất ngờ do prompt lớn gây ra.
- Sử dụng giãn thời gian chờ theo cấp số nhân có thêm độ lệch ngẫu nhiên, và tuân thủ các header hướng dẫn thử lại khi nhà cung cấp trả về chúng.
- Đặt một hàng đợi và bộ điều phối giữa ứng dụng của bạn và các nhà cung cấp LLM cho khối lượng công việc theo lô hoặc có lưu lượng lớn.
- Biện pháp kiểm soát mức độ đồng thời riêng biệt với giới hạn tốc độ; nếu không, độ trễ tăng đột biến có thể khiến quá nhiều lời gọi đang xử lý cùng lúc.
- Thiết kế giảm cấp dịch vụ một cách có kiểm soát một cách có chủ đích: mô hình nhỏ hơn, ngữ cảnh ngắn hơn, công việc nền được đưa vào hàng đợi hoặc phản hồi đã lưu trong bộ nhớ đệm.
- Xem chuyển sang nhà cung cấp dự phòng như một tính năng bảo đảm độ tin cậy, chứ không phải quyền gửi tràn lan các yêu cầu trùng lặp.
- Sử dụng khóa lũy đẳng và bản ghi thao tác để giảm việc tính phí hai lần và ngăn kết quả sinh trùng lặp.
- Thông báo trung thực với người dùng khi phản hồi dạng luồng gặp lỗi sau khi đã phát ra token.
- Xây dựng bảng theo dõi xoay quanh thời gian chờ trong hàng đợi, lượng token dự trù, số lần chạm giới hạn tốc độ, số lần thử lại và lý do chuyển sang phương án dự phòng.
- Giữ logic thử lại đơn giản; công việc thực sự trong môi trường sản xuất là lập ngân sách, lập lịch và biết khi nào không nên thử lại.
Một khóa API cho Claude Opus 5.5, Sonnet 5, Haiku 4.5 và Fable 5.1, cùng GPT-6 mô hình. Thanh toán theo mức sử dụng, không cần đăng ký thuê bao.
Nhận khóa API của bạn →