Bỏ qua để vào nội dung chính
Kiểm soát chi phí LLM: ngân sách, fallback và cách đo đúng

Kiểm soát chi phí LLM: ngân sách, fallback và cách đo đúng

Bởi Charlotte Adams
05 thg 11, 20267 phút đọc

Ba lớp chặn hoá đơn LLM vượt trần: đo chi phí mỗi task thành công, kill switch ngân sách bằng Redis, và chuỗi fallback khi provider trả 429 hoặc 500.

Worker của bạn chạy một vòng retry hỏng lúc 2 giờ sáng, và không có ai đứng giữa job đó với API của provider. Đến sáng, hoá đơn đã cộng xong và không ai trong team biết job nào đốt tiền.

Bài này đi qua ba lớp phòng thủ cụ thể: đo chi phí bằng đúng chỉ số, chặn job trước khi nó tiêu token, và dựng chuỗi fallback khi provider sập. Cả ba đều triển khai được trong một sprint.

Đo sai chỉ số thì tối ưu sai chỗ

Hầu hết team so sánh model bằng giá mỗi triệu token. Chỉ số đó không nhìn thấy retry, output sai định dạng, hay job chạy mãi không xong. Chỉ số cần dùng là: chi phí mỗi task thành công — tổng tiền tiêu cho mọi lần thử (kể cả lần hỏng, lần retry, lần timeout) chia cho số lần thử đạt yêu cầu.

Con số đi kèm đến từ một benchmark do Arize và Fireworks chạy: 10 model trên 40 task dòng lệnh thật lấy từ Terminal-Bench, mỗi task 6 lượt, tổng 2.400 lượt chạy, chấm bằng chính test script của task.

ModelPass rate$ mỗi lượt$ mỗi task thành côngSố lượt / 1 lần thành công
gpt-oss-120b33%$0,018$0,0543,0
gemini-3.1-flash-lite40%$0,026$0,0632,5
GPT-5.567%$0,424$0,6361,5
Kimi K366%$0,441$0,6701,5
Claude Sonnet 549%$0,494$1,0142,1
gemini-3.5-flash23%$0,288$1,2334,3

Đọc bảng theo hai chiều. Chiều thứ nhất: model rẻ nhất mỗi lượt không tự động rẻ nhất mỗi kết quả — gemini-3.5-flash tốn $0,288 một lượt nhưng chỉ pass 23%, thành $1,233 cho mỗi task xong. Chiều thứ hai, và đây là chỗ nhiều team bỏ sót: model rẻ thắng ít task hơn. Nếu chỉ tính task mà model giải được ổn định (đạt từ 4/6 lượt trở lên), gpt-oss-120b phủ 8 trên 40 task, GPT-5.5 phủ 25 và Kimi K3 phủ 26.

Nghĩa là đổi model rẻ trên toàn hệ thống thì hoá đơn giảm nhưng tập tính năng cũng co lại. Nguồn cũng tự giới hạn phạm vi: đây là task agent dòng lệnh, không phải phân loại hay trích xuất, và với 6 lượt mỗi ô thì pass rate có sai số khoảng ±6 điểm. Đừng bê số đô-la đó vào dự toán của bạn — bê cách đo.

Cách đo chạy gọn trong một buổi chiều: lấy 100 input thật từ traffic, viết trước luật chấm pass (exact match, JSON schema, hay rubric), đặt ngưỡng chất lượng, rồi chạy model hiện tại cùng hai ba ứng viên rẻ hơn. Ghi chi phí của mọi lời gọi, kể cả lời gọi bị validator loại. Loại hết ứng viên dưới ngưỡng, rồi chọn cái có chi phí mỗi task thành công thấp nhất.

Lớp 1 — Kill switch ngân sách chặn trước khi tiêu token

Đo xong vẫn chưa chặn được đêm 2 giờ sáng. Một hướng dẫn production cho AI worker queue mô tả ba kiểu hỏng mà try/catch không đỡ nổi: TPM limit của provider khiến các worker đồng loạt retry và càng làm rate limit nặng thêm; vòng lặp agent đệ quy tiêu token vô hạn vì không có kill switch toàn cục; và provider 503 làm cả ứng dụng đứng. Tác giả bài đó mô tả hậu quả của một vòng retry hỏng là hoá đơn $2.000 sau một đêm — đó là con số của tác giả, không phải số đo chung.

Lời giải là kiểm tra ngân sách trước khi prompt rời khỏi worker. Mẫu minh hoạ dưới đây theo mô tả của hướng dẫn: ước lượng token, đối chiếu với một counter Redis theo ngày, và từ chối job nếu vượt trần.

// Ví dụ minh hoạ, không phải code production
const estimatedTokens = Math.ceil(job.data.prompt.length / 4) + 500;
const budget = await budgetManager.canExecute(estimatedTokens);
if (!budget.allowed) throw new Error(`[BUDGET_EXCEEDED] ${budget.reason}`);
// sau khi gọi model xong, cộng dồn token thật sự đã dùng
await budgetManager.recordUsage(response.tokensUsed);

Hai chi tiết đáng chép lại. Thứ nhất, counter dùng INCRBY của Redis nên việc cộng dồn là atomic — nhiều worker chạy song song vẫn không ghi đè nhau. Thứ hai, key được set TTL 172800 giây (48 giờ) nên counter cũ tự dọn, không cần cron. Ước lượng prompt.length / 4 chỉ là xấp xỉ thô; nó đủ để chặn job thảm hoạ, không đủ để làm báo cáo tài chính.

Lớp 2 — Chuỗi fallback xếp theo độ giống model chính

Khi provider chính trả 429 hoặc 500, queue không nên chết theo. Một guide về LLM failover (do Control Plane xuất bản — hãy đọc như tài liệu có lợi ích thương mại) đưa ra thứ tự fallback xếp từ giống nhất tới khác nhất so với model chính:

  1. Cùng model, region hoặc deployment khác. Chất lượng gần như không đổi, nhưng dữ liệu có thể sang vùng tài phán khác và latency tăng.
  2. Model tương đương, provider khác. Sống sót qua sự cố toàn provider, đổi lại output khác đi và điều khoản dữ liệu khác.
  3. Model open-weight tự host. Bỏ hẳn phụ thuộc bên ngoài, đổi lại khoảng cách chất lượng lớn nhất và phải nuôi GPU.

Chuyển bậc không miễn phí: model fallback có context window và tokenizer khác, nên prompt vừa với model chính có thể vượt giới hạn của model dự phòng. Prompt cache của provider cũng không mang theo được, nên ngay sau khi failover thì latency và chi phí đều tăng — nghịch lý là sự cố làm hoá đơn phình ra, không phải co lại. Hãy đặt budget riêng cho từng bậc.

Điều kiện để chuỗi này dùng được: mỗi model dự phòng phải qua được một eval set của bạn (JSON hợp lệ, tool-call đúng, độ chính xác, giọng văn, latency) trước khi được đưa vào chuỗi, và quota của provider thứ hai phải được cấp sẵn cho tải production đầy đủ — không phải cấp lúc đang sập.

Lớp 3 — Retry ở đúng một tầng

Đây là lỗi làm hỏng cả hai lớp trên: nếu cả client lẫn gateway cùng retry, số lần thử nhân lên đúng lúc provider đang quá tải. Chọn một tầng, tắt tầng còn lại.

Vài luật cụ thể đáng gắn vào worker:

  • Timeout rõ ràng cho mọi lời gọi, và một timeout riêng cho time-to-first-token khi stream.
  • Backoff theo cấp số nhân kèm jitter, trong một deadline tổng cứng, để tránh bão retry đồng bộ.
  • Tôn trọng Retry-After khi gặp 429. Nhưng 429 báo hết quota hoặc hết hạn mức chi tiêu thì retry không bao giờ hết — OpenAI đánh dấu loại này là insufficient_quota trong body lỗi, còn 429 vì spend limit của Anthropic không kèm retry-after. Gặp hai loại đó thì chuyển thẳng sang bậc fallback.
  • Circuit breaker: sau nhiều lần hỏng liên tiếp thì ngừng gửi traffic tới provider đó trong một khoảng cooldown, và gửi một request thăm dò trước khi mở lại.
  • Idempotency key cho mọi hành động có tác dụng phụ (gửi email, ghi DB, thanh toán), để retry không làm lại lần hai.

Làm gì trong tuần này

Ba việc, theo đúng thứ tự tác động:

  1. Dựng counter ngân sách theo ngày và cho nó quyền từ chối job. Đây là thứ duy nhất chặn được hoá đơn bất ngờ; hai việc còn lại chỉ tối ưu.
  2. Chạy bài đo chi phí mỗi task thành công trên 100 input thật của bạn. Nếu model hiện tại thắng, bạn vừa biết điều đó miễn phí.
  3. Kiểm tra xem có bao nhiêu tầng đang retry trong đường gọi model. Đếm, rồi bỏ bớt còn một.

Việc cần theo dõi tiếp: giá model thay đổi hàng tháng, nên ứng viên bị loại quý trước có thể qua ngưỡng ở lần đo sau. Lịch chạy lại bài đo quan trọng không kém bài đo đầu tiên.

Không spam, hủy đăng ký bất kỳ lúc nào.

Bài viết liên quan