
Cắt chi phí token: prompt caching và đếm token cho đúng
Prefix sai thứ tự làm cache không bao giờ hit, còn quy tắc 4 ký tự/token lệch tới 55%. Giá, ngưỡng tối thiểu và checklist cắt chi phí token.
Mục lục
- Vì sao mỗi request đều trả tiền lại từ đầu
- Thứ tự prefix quyết định cache hit hay không
- Bật cache: automatic hay explicit breakpoint
- Giá thực tế, không phải giá cảm tính
- Cơ chế TTL khiến bạn hụt cache mà không biết
- Ngưỡng tối thiểu: chỗ cache im lặng không chạy
- Đếm token: quy tắc 4 ký tự sai ở đâu
- Với Claude và Gemini, mọi con số local đều là ước lượng
- Checklist áp dụng
Bạn deploy một con agent, một tuần sau hoá đơn API tăng gấp đôi mà traffic không đổi. Mở dashboard ra thì input tokens chiếm gần hết, còn output thì nhỏ xíu.
Hai chỗ rò tiền phổ biến nhất nằm ở đây: prefix lặp lại không bao giờ được cache, và số token bạn ước lượng sai ngay từ đầu. Bài này chỉ cách bịt cả hai, bằng con số từ tài liệu thay vì cảm tính.
Vì sao mỗi request đều trả tiền lại từ đầu
Gốc của vấn đề là API stateless. Theo bài phân tích prompt caching trên Dev.to: "Every API request is stateless: the model re-reads your system prompt, your tool definitions, and the whole conversation history each time."
Prompt caching là cách Anthropic xử lý phần lãng phí đó — nó cho API dùng lại một prefix đã xử lý trước đó thay vì xử lý lại. Nó chỉ là cách bạn đánh dấu phần nào trong request có thể tái sử dụng.
Thứ tự prefix quyết định cache hit hay không
Đây là phần nhiều team làm sai. Bài viết dẫn tài liệu Anthropic: prefix được dựng theo thứ tự cố định — "tool definitions first, then the system prompt, then the message history". Mọi thứ từ token đầu tiên đến hết breakpoint của bạn trở thành một khối cacheable duy nhất.
Hệ quả rất thẳng: phần ít đổi phải nằm trước, phần đổi mỗi request nằm sau. Nếu biến động lọt vào trong prefix, "the prefix is different on every request and nothing is ever reused".
Thứ hay phá cache nhất là timestamp, request id hoặc user context nhét vào system prompt. Nếu bạn đang chèn thời gian hiện tại vào đó, cache gần như chưa bao giờ hit.
Bật cache: automatic hay explicit breakpoint
Có hai đường. Automatic caching là thêm một field cache_control ở top level, hệ thống tự đặt breakpoint vào block cacheable cuối cùng; khi hội thoại dài ra, breakpoint tự tiến lên.
Explicit breakpoint cho bạn kiểm soát từng block. Hai con số cần nhớ: bạn đặt được tối đa 4 breakpoint trong một request, và tài liệu mô tả một cửa sổ lookback 20 block. Mỗi breakpoint có một lần tìm ngược riêng để tìm cache entry cũ.
Breakpoint không tốn phí. Bạn chỉ trả cho cache write, cache read và phần token chưa cache.
Giá thực tế, không phải giá cảm tính
Theo bảng giá mà bài viết dẫn từ tài liệu Anthropic:
- Cache write (TTL 5 phút) đắt hơn base input token 25%.
- Cache read bằng 10% giá base input với phần lớn model, trừ một số ngoại lệ: 0.025x cho Claude Fable 5.1 và Claude Mythos 5.1, 0.05x cho Claude Opus 5.5 và Claude Sonnet 5.5.
- TTL 1 giờ có giá write gấp 2x base input.
Ví dụ cụ thể trong bảng giá, với Claude Sonnet 4.6: base input 3 USD/triệu token, cache write 5 phút 3,75 USD, write 1 giờ 6 USD, còn cache read 0,30 USD.
Caching chỉ có lãi khi prefix thực sự được dùng lại: request đầu đắt hơn, các request sau rẻ hơn hẳn.
Cơ chế TTL khiến bạn hụt cache mà không biết
Mặc định một cache entry sống 5 phút, và đọc nó sẽ gia hạn miễn phí. Nhưng mốc đếm là lúc request bắt đầu, không phải lúc response kết thúc.
Bài viết nêu đúng cái bẫy: một response stream mất 4 phút thì chỉ còn khoảng 1 phút cho request kế tiếp dùng lại prefix. Nếu agent của bạn có bước suy luận dài, mặc định 5 phút có thể không đủ.
Ngưỡng tối thiểu: chỗ cache im lặng không chạy
Không phải prompt nào cũng đủ điều kiện cache. Tài liệu có ngưỡng độ dài tối thiểu và ngưỡng này khác nhau theo model: ví dụ 1.024 token cho Claude Sonnet 4.6 và Sonnet 4.5, 512 token cho các model mới hơn như Claude Sonnet 5.5, Opus 5.5 và Haiku 5.5.
Một system prompt ngắn sẽ không bao giờ được cache, và nó fail im lặng — không lỗi, không cảnh báo. Trước khi debug cache miss, hãy kiểm tra prefix có vượt ngưỡng của đúng model đó chưa.
Hai luật nữa đáng nhớ. Cache gắn theo model, nên đổi model giữa chừng là bắt đầu lại từ lạnh. Và nếu block cuối đã có explicit breakpoint với TTL khác, API trả về lỗi 400; khi đã dùng hết 4 explicit breakpoint thì không còn chỗ cho automatic caching.
Đếm token: quy tắc 4 ký tự sai ở đâu
Phần thứ hai của hoá đơn là số token bạn tưởng mình gửi. Một bài đo trên Dev.to đưa ra con số rất rõ: cùng một đoạn 192 ký tự tiếng Trung cho ra 111 token trong DeepSeek V4, 133 trong o200k_base, 172 trong cl100k_base — chênh lệch 55%. Quy tắc bốn ký tự một token dự đoán 48.
Tiếng Anh thì gần như không lệch: câu hỏi 22 ký tự ra 7 token ở cả ba tokenizer. Kích thước vocabulary cũng khác nhau: cl100k_base có 100.277 entry, o200k_base 200.019, DeepSeek V4 129.280.
Bài viết đưa dải ước lượng theo ngôn ngữ: tiếng Anh khoảng 4 ký tự/token; tiếng Trung khoảng 0,5–1,0 token/ký tự; tiếng Nhật 0,6–1,0; tiếng Hàn 0,5–1,0. Nguồn này không đo tiếng Việt, nên đừng suy ra tỉ lệ cho tiếng Việt từ các con số trên — hãy tự đo trên chính prompt của bạn.
Với Claude và Gemini, mọi con số local đều là ước lượng
Chi tiết này tiết kiệm cho bạn vài giờ debug. Claude và Gemini không công bố tokenizer để chạy local, nên "any local count for them is an estimate". Endpoint count_tokens của Anthropic nhận cùng body như message request, và tài liệu gọi kết quả là estimate.
Thêm một điểm ảnh hưởng trực tiếp tới chi phí: tài liệu nói Claude 4.7 trở lên sinh ra nhiều hơn khoảng 30% token cho cùng một đoạn text so với các bản Claude cũ hơn. Với GPT-6 thì lý do khác: tiktoken 0.14.0 không có entry cho nó.
Và nhớ rằng tokenizer local chỉ đo một chuỗi. Một request thật còn có role marker, separator, system prompt, tool definitions, ảnh và file — đó là lý do OpenAI có /v1/responses/input_tokens để đếm cả request.
Checklist áp dụng
- Sắp xếp request: tool definitions, system prompt, tài liệu nền trước; phần biến động để cuối.
- Bắt đầu bằng automatic caching; chỉ dùng explicit breakpoint khi các phần đổi với tần suất khác nhau.
- Không bao giờ đặt breakpoint lên block chứa timestamp hay dữ liệu theo từng request.
- Kiểm tra prefix tĩnh có vượt ngưỡng tối thiểu của đúng model đang dùng chưa.
- Nếu mỗi lượt dài, thêm breakpoint thứ hai để cache write không bị đẩy ra ngoài cửa sổ 20 block.
- Đo token thật bằng endpoint của provider trước khi chốt ngân sách, nhất là với prompt tiếng Việt.
Giá và ngưỡng có thể thay đổi — bài gốc khuyến cáo kiểm tra lại tài liệu trước khi dựa vào một con số. Việc cần làm tuần này rất gọn: log tỉ lệ cache read trên tổng input token, và nếu tỉ lệ đó gần 0 thì lỗi nằm ở thứ tự prefix, không phải ở model.
Không spam, hủy đăng ký bất kỳ lúc nào.
Bài viết liên quan

Prompt caching ghi mà không đọc: vì sao bill tăng 25%
12 thg 9, 2026
