Chuyển đến nội dung
16/30Chương 16 trên 30

Context window, token và hóa đơn, đo bằng số liệu

Một cuộc trò chuyện 40 lượt tốn input token gấp 22 lần độ dài của nó. Cache giảm 68%; đặt sai timestamp tăng 20%.

Trên trang này

Đây là một cuộc trò chuyện hỗ trợ bốn mươi lượt, được tính phí theo từng lượt. Không có gì bất thường trong đó: một lập trình viên hỏi về một API, một assistant trả lời trong một hoặc hai đoạn. Toàn bộ trao đổi dài 5,090 token văn bản — khoảng tám trang.

lượttoken promptvăn bản mớioutputchi phí lượt nàytổng lũy kế
121318183$0.002622$0.002622
589214123$0.003260$0.014354
101,65619114$0.004680$0.035530
202,86818103$0.006972$0.094426
303,9412099$0.009070$0.174170
404,94717142$0.011598$0.274386

Hãy đọc cột thứ hai và thứ ba cùng nhau. Ở lượt 40, người dùng gõ mười bảy token và bị tính phí cho 4,947 token. Câu hỏi không khó hơn câu đầu tiên; nó còn ngắn hơn. Điều thay đổi là request mang theo toàn bộ cuộc trò chuyện, một lần nữa, đến lần thứ bốn mươi.

Tổng input token bị tính phí trên bốn mươi call đó: 112,617. Cuộc trò chuyện dài 5,090 token. Bạn đã trả tiền cho nó hơn hai mươi hai lần.

Chương này nói về lý do điều đó xảy ra, nó được gọi là gì trên hóa đơn của từng provider, và trong năm thứ bạn đang bị tính phí, thứ nào bạn có thể tác động.

Hiện chi tiết

Chương này cần gì từ Phần II.

  • Chương 7 đã xây tokenizer. Một token cũng là đơn vị ở đây — cùng một đơn vị, giờ đã có giá.
  • Chương 9 đã suy ra self-attention và chi phí O(n2)O(n^2) của nó, trong hộp ký hiệu tiệm cận. Chi phí đó là lý do vì sao giới hạn tồn tại, và ở đây nó được liên kết thay vì giải thích lại.
  • Chương 13 đã đo prefill so với decode và tính một KV cache chiếm bao nhiêu. Hai pha đó chính là thứ các cột input và output ở trên đang mua.

Mọi thứ còn lại là TypeScript, vì đây là kế toán cho một remote call chứ không phải toán học về một model.

Ngộ nhận đắt đỏ nhất trong lĩnh vực này là nghĩ rằng model nhớ một cuộc trò chuyện.

Nó không nhớ, và cơ chế ở Chương 13 nói chính xác vì sao. Trạng thái của một transformer trong khi generation là KV cache: các key và value được tính cho mọi token trong chuỗi. Cache đó sống trong thời lượng của một request. Khi request kết thúc, process giữ nó có thể tự do phục vụ người khác, và cache biến mất. Không có kho lưu trữ theo từng người dùng ở phía bên kia, và cũng không có session.

Vì vậy request tiếp theo phải tự mang theo mọi thứ mà model cần biết, và model dựng lại trạng thái đó bằng cách chạy một forward pass trên toàn bộ prompt trước khi phát ra một token mới duy nhất. Chương 15 gọi prompt là “toàn bộ trạng thái”. Đây là lý do vật lý: prompt là trạng thái hoàn chỉnh vì không có gì khác sống sót sau call.

context window là độ dài tối đa của prompt đó cộng với câu trả lời của nó. Nó là trần cho lượng trạng thái bạn có thể dựng lại, không phải một container giữ bất cứ thứ gì giữa các request. Gọi nó là “bộ nhớ của model” là đảo ngược quan hệ nhân quả — bạn không đang lấp đầy một bộ nhớ, bạn đang trả tiền để tái lập một bộ nhớ.

Đó là nguồn gốc của con số hai mươi hai. Lượt nn mang theo toàn bộ n1n-1 lượt trước đó, nên tổng input trong một cuộc trò chuyện nn lượt là tổng của một chuỗi tăng dần, tức là bậc hai:

total input  =  i=1n(s+hi)  =  Θ(n2)\text{total input} \;=\; \sum_{i=1}^{n} \big(s + h_i\big) \;=\; \Theta(n^2)

trong đó ss là system prompt và hih_i là lịch sử ở lượt ii. Khớp input tích lũy đo được với an2+bnan^2 + bn trên bốn mươi lượt cho 60.22n2+432.25n60.22\,n^2 + 432.25\,n, dự đoán 113,645 token ở lượt 40 so với 112,617 đo được. Thành phần bậc hai chi phối, còn thành phần tuyến tính là phần người dùng thật sự gõ.

Hệ quả là câu cần nhớ từ chương này: hóa đơn của bạn tăng theo bình phương của cuộc trò chuyện, không theo câu hỏi cuối cùng. Cùng bốn mươi câu hỏi đó, nếu không gửi lịch sử, tốn $0.066036. Giữ lịch sử tốn $0.274386. Lịch sử nhân hóa đơn lên 4.2 lần, và nó sẽ tiếp tục nhân lên, vì hệ số nhân chính là độ dài cuộc trò chuyện.

Window là hữu hạn vì hai lý do cùng kéo về một hướng. Lý do thứ nhất là của Chương 9: attention so sánh mọi token với mọi token khác, nên công việc của layer đó tăng theo bình phương độ dài chuỗi. Lý do thứ hai là bộ nhớ: KV cache tăng tuyến tính theo độ dài chuỗi, và Chương 13 đã làm phép tính đó — ở các chuỗi dài, nó lớn hơn weights.

Cả hai giới hạn đều đã bị tấn công và chưa giới hạn nào bị xóa bỏ. FlashAttention1 tổ chức lại phép tính để nó đọc và ghi ít hơn rất nhiều vào high-bandwidth memory, khiến các chuỗi dài trở nên thực tế mà không thay đổi chi phí tiệm cận. Position Interpolation2 và YaRN3 mở rộng window dùng được của một model đã train bằng cách co giãn positional encodings từ Chương 9 thay vì retrain. Cùng nhau, chúng là lý do window đi từ 2K lên 1M trong năm năm.

Điều chúng không làm là biến context dài thành miễn phí. Chúng nâng trần lên cao hơn và làm độ dốc dịu hơn. Độ dốc vẫn còn đó, và đó là thứ các price tier về sau trong chương này đang đo.

Gần như mọi cost calculator trên internet mô hình hóa một API call bằng input token nhân với giá input cộng output token nhân với giá output. Điều đó đúng vào năm 2023. Bây giờ nó sai theo cách khiến hóa đơn lệch hai lần hoặc hơn theo cả hai hướng.

năm nhóm token tính phí:

bucketnó là gìgiá điển hình, so với input
uncached inputtoken prompt mà model phải xử lý mới
cache readtoken prompt được phục vụ từ một prefix đã lưu0.1×
cache writetoken prompt được lưu vào cache trong call này1.25× đến 2×
outputtoken model đã tạo và gửi cho bạn5× đến 6×
reasoningtoken model đã tạo và không gửi cho bạngiá output

Ba trong năm nhóm đó không tồn tại như các dòng riêng cách đây hai năm, và hai dòng cache là thứ mọi người hay hiểu sai, vì một cache write tốn nhiều hơn input thông thường, không phải ít hơn. Bạn trả premium để lưu một thứ, để sau đó có thể trả giá chiết khấu khi đọc lại nó, và giao dịch đó có lợi hay không phụ thuộc hoàn toàn vào số lần bạn đọc nó.

Bucket reasoning là của Chương 12, giờ đã có giá, và nó mang một chi tiết đáng nói thẳng: tài liệu của Google nói pricing “dựa trên toàn bộ thought tokens mà model cần generate, dù chỉ summary được output từ API.”4 Bạn bị tính phí cho những token không bao giờ được truyền đến bạn. Đây là bucket duy nhất có nội dung bạn không thể đếm, kiểm tra hoặc xác minh.

Bây giờ là phần khiến đây thành vấn đề chuẩn hóa thay vì vấn đề nhân số. Mỗi provider báo các bucket này bằng những tên khác nhau, và — đây là cái bẫy — hai provider dùng cùng một từ cho hai đại lượng khác nhau.

Lấy một call: 4,837 token đọc từ cache, 110 token mới, 142 token output hiển thị, 300 token reasoning.

three usage payloads, one callJSON
// OpenAI-compatible
{ "usage": { "prompt_tokens": 4947,
             "prompt_tokens_details": { "cached_tokens": 4837 },
             "completion_tokens": 442,
             "completion_tokens_details": { "reasoning_tokens": 300 } } }

// Anthropic
{ "usage": { "input_tokens": 110,
             "cache_read_input_tokens": 4837,
             "cache_creation_input_tokens": 0,
             "output_tokens": 442 } }

// Gemini
{ "usageMetadata": { "promptTokenCount": 4947,
                     "cachedContentTokenCount": 4837,
                     "candidatesTokenCount": 142,
                     "thoughtsTokenCount": 300 } }

Hãy nhìn prompt_tokens: 4947input_tokens: 110. Cả hai field đều là số input token cho cùng một prompt. Của OpenAI bao gồm token đã cache; của Anthropic loại trừ chúng — tài liệu của họ nêu identity đó rõ ràng, total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens.5 input_tokens của Anthropic nghĩa là “các token sau cache breakpoint cuối cùng của bạn”.

Và hãy nhìn output. OpenAI và Anthropic đều báo 442, trong đó đã chứa 300 token reasoning. Gemini báo 142 và đặt 300 vào một field riêng. Chương 12 đã đánh dấu đây là sự không tương thích giữa hai cách đếm cùng một công việc; đây là chi phí của nó.

Một normaliser dài ba mươi dòng và không phải tùy chọn:

normalise.tsTS
export interface Usage {
  promptTokens?: number;        // input, NOT cached
  cachedInputTokens?: number;   // read from cache
  cacheWriteTokens?: number;    // written to cache on this call
  completionTokens?: number;    // output
  reasoningTokens?: number;     // billed apart from output (Gemini only)
}

const num = (v: unknown) => (typeof v === "number" && isFinite(v) ? v : 0);

export const fromOpenAI = (raw: any): Usage => {
  const u = raw.usage ?? {}, d = u.prompt_tokens_details ?? {};
  const cached = num(d.cached_tokens), write = num(d.cache_write_tokens);
  return {
    promptTokens: Math.max(0, num(u.prompt_tokens) - cached - write), 
    cachedInputTokens: cached,
    cacheWriteTokens: write,
    completionTokens: num(u.completion_tokens),   // reasoning already inside
    reasoningTokens: 0,
  };
};

export const fromAnthropic = (raw: any): Usage => {
  const u = raw.usage ?? {};
  return {
    promptTokens: num(u.input_tokens),            // already excludes cache
    cachedInputTokens: num(u.cache_read_input_tokens),
    cacheWriteTokens: num(u.cache_creation_input_tokens),
    completionTokens: num(u.output_tokens),
    reasoningTokens: 0,
  };
};

export const fromGemini = (raw: any): Usage => {
  const m = raw.usageMetadata ?? {}, cached = num(m.cachedContentTokenCount);
  return {
    promptTokens: Math.max(0, num(m.promptTokenCount) - cached),
    cachedInputTokens: cached,
    cacheWriteTokens: 0,
    completionTokens: num(m.candidatesTokenCount), // EXCLUDES thinking
    reasoningTokens: num(m.thoughtsTokenCount),    // billed at output rate
  };
};

Chạy ba payload ở trên qua ba reader và cả ba đều tạo cùng một Usage, do đó cùng một con số: $0.006491. Sự khớp nhau đó là toàn bộ lý do để viết layer này.

Làm sai thì đây là chi phí, trên cùng call đó:

lỗibị tínhsai lệch
coi cached_tokensbổ sung cho prompt_tokens$0.0161652.49× — bạn tính tiền prompt hai lần
coi cache read là miễn phí thay vì 0.1×$0.0055240.85× — bạn nuốt mất 15 %
đọc candidatesTokenCount và bỏ qua thoughtsTokenCount$0.00289155 % của call biến mất

Lỗi thứ ba là lỗi nguy hiểm, vì nó thất bại âm thầm theo hướng tin tốt. Dashboard của bạn cho thấy một reasoning model tốn chưa đến một nửa chi phí thật, và không nơi nào báo lỗi.

Khi các bucket đã được chuẩn hóa, cost function rất ngắn. Phần duy nhất không hiển nhiên là tra tier, phần mà mục tiếp theo sẽ giải thích:

cost.tsTS
export interface Tier { maxPromptTokens: number | null; price: number }
export interface Pricing {
  input: Tier[]; output: Tier[];
  cachedInput?: Tier[]; cacheWrite?: Tier[]; reasoning?: Tier[];
}

const tierPrice = (tiers: Tier[] | undefined, contextSize: number, fallback?: Tier[]) => {
  const table = tiers ?? fallback;
  if (!table?.length) return 0;
  const sorted = [...table].sort(
    (a, b) => (a.maxPromptTokens ?? Infinity) - (b.maxPromptTokens ?? Infinity));
  for (const t of sorted)
    if (t.maxPromptTokens === null || contextSize <= t.maxPromptTokens) return t.price;
  return sorted[sorted.length - 1].price;
};

export function computeCost(pricing: Pricing, usage: Usage): number {
  const fresh = usage.promptTokens ?? 0;
  const read  = usage.cachedInputTokens ?? 0;
  const write = usage.cacheWriteTokens ?? 0;
  const out   = usage.completionTokens ?? 0;
  const think = usage.reasoningTokens ?? 0;
  const contextSize = fresh + read + write;   // the tier depends on the WHOLE prompt
  return fresh * tierPrice(pricing.input, contextSize)
       + read  * tierPrice(pricing.cachedInput, contextSize, pricing.input)
       + write * tierPrice(pricing.cacheWrite,  contextSize, pricing.input)
       + out   * tierPrice(pricing.output, contextSize)
       + think * tierPrice(pricing.reasoning, contextSize, pricing.output);
}

Có hai quyết định thiết kế ở đó đáng được bảo vệ. Các fallback — giá cache fallback về input, reasoning về output — mã hóa ý nghĩa của một bảng thiếu: reasoning token trên Gemini được tính theo giá output, nên giá reasoning vắng mặt không phải là zero, mà là giá output. Và contextSize cộng cả ba bucket input thay vì chỉ bucket mới, vì tier được chọn theo độ dài của prompt, không theo bao nhiêu phần trong đó bị tính giá đầy đủ.

Một prompt cache lưu trạng thái đã tính của model cho một prefix của prompt, để request sau với cùng prefix bỏ qua việc tính lại nó. Bốn tính chất đi theo từ “prefix”, và cả bốn đều khiến người ta ngạc nhiên.

Cache match từ đầu prompt đã render trở đi, và dừng ở byte đầu tiên khác biệt. Không có điểm một phần cho nội dung xuất hiện sau đó theo thứ tự khác. OpenAI nói thẳng: “cache reuse requires the entire rendered prefix to match.”6

Dưới mức đó, không có gì được cache và không có lỗi nào được trả về. Trên OpenAI, mức tối thiểu là 1,024 token cho GPT-5.6 trở lên và 2,048 cho các model cũ hơn. Trên Anthropic, nó dao động từ 512 đến 4,096 tùy model — 1,024 cho Claude Sonnet 4.5, 4,096 cho Claude Haiku 4.5. Nếu cả hai field cache trả về zero, thường đây là lý do.

Trên OpenAI và Anthropic, một cache write là 1.25× giá uncached input cho cache ngắn hạn, và cache một giờ của Anthropic là 2×. Một read là 0.1×. Google không tính phí write nhưng cho thuê storage: $4.50 mỗi triệu token mỗi giờ trên Gemini 2.5 Pro.

Entry mặc định của Anthropic sống năm phút, được refresh miễn phí ở mỗi hit. Của OpenAI ít nhất ba mươi phút sau lần write hoặc reuse gần nhất. Và OpenAI lưu ý rằng trạng thái đã cache sống trên từng máy riêng, nên một request chỉ hit nếu nó được route đến máy đang giữ entry — đó là thứ prompt_cache_key ảnh hưởng, nhưng không bảo đảm.

Điểm hòa vốn đủ nhỏ để nhớ trong đầu, và tài liệu của OpenAI làm phép tính: write một prefix một lần và reuse nó một lần tốn 1.35× chi phí input thông thường của nó, so với 2× nếu xử lý nó hai lần mà không cache; qua mười request, một write và chín read tốn 2.15× so với 10×. Một lần reuse đã trả đủ chi phí write. Anthropic đi đến cùng chỗ: một read cho cache năm phút, hai read cho cache một giờ.

Giờ quay lại cuộc trò chuyện bốn mươi lượt, với caching bật và prefix ổn định:

uncached inputcache readscache writestổng
không cache112,617$0.274386
caching2,887104,7834,947$0.088250

Rẻ hơn sáu mươi tám phần trăm, và ba con số trong bảng đó đáng chú ý.

Cache không hoạt động cho đến lượt 6. prompt chưa đạt 1,024 token cho đến lúc đó, nên năm lượt đầu bị tính phí y như trước — và lượt thứ sáu bị tính tệ hơn, với premium write 1.25×, vì đó là lượt lấp đầy cache. Lần read đầu tiên đến ở lượt 7. 2,887 uncached token trong bảng là phép tính đó: giá trị của năm lượt, không phải sáu. Caching là chiết khấu cho prompt dài, và một cuộc trò chuyện ngắn không nhận được gì từ nó.

Premium write là $0.002474, tức 2.8 % của hóa đơn đã cache. Mỗi lượt write phần đuôi mới của nó, bốn mươi lần, và toàn bộ premium write chỉ là sai số làm tròn so với những gì read tiết kiệm. Phí write đáng được hiểu chính xác để bạn ngừng lo về nó.

Chỉ 2,887 token bị tính theo giá input đầy đủ trong tổng 112,617. Đó là hình dạng của một cache hoạt động: gần như mọi thứ là read.

Thứ tự của prompt quyết định liệu điều này có xảy ra hay không

Liên kết đến mục: Thứ tự của prompt quyết định liệu điều này có xảy ra hay không

Đây là lỗi gây tốn tiền thật, và nó là bug một dòng.

Đặt thứ gì đó thay đổi ở mỗi call gần đầu prompt — timestamp, request id, tên người dùng, dòng “hôm nay là”, một tài liệu vừa retrieval — và prefix khác ngay từ byte một. Không có gì match. Mọi call đều miss. Và vì mọi call trình ra một prefix mới, mọi call cũng write.

Cùng cuộc trò chuyện, cùng bốn mươi lượt, caching bật, với timestamp theo từng call ở đầu system prompt:

tổngso với
không caching gì cả$0.274386
caching, prefix ổn định$0.088250−67.8 %
caching, prefix biến động$0.329251+20.0 %

Bật prompt caching khiến cuộc trò chuyện đắt hơn hai mươi phần trăm so với không bật. Bạn trả premium write 1.25× trên 109,730 token và đọc lại zero. Không có lỗi, không có cảnh báo, và tính năng đang bật.

Vậy quy tắc, và cũng là toàn bộ prompt caching trong một dòng: nội dung ổn định ở trước, nội dung biến đổi ở sau. System instructions, tool definitions và tài liệu tham chiếu trước; timestamps, danh tính người dùng và câu hỏi hiện tại sau. Anthropic nêu thứ bậc rõ ràng — cache đi theo toolssystemmessages, và một thay đổi ở bất kỳ cấp nào làm mất hiệu lực cấp đó và mọi thứ sau nó, nên sửa một mô tả tool duy nhất làm mất hiệu lực toàn bộ cache.5

Hai hệ quả khiến người ta vấp. Thay đổi tool nào được enabled sẽ thay đổi tool definitions, nên một feature flag thêm tool cho một số người dùng sẽ tách cache của bạn làm hai. Và trên Anthropic, bật tắt web search hoặc citations sửa system prompt, làm mất hiệu lực system và message cache mà bạn không chạm vào dòng text nào của chính mình.

Phản ứng hiển nhiên trước một hóa đơn bậc hai là ngừng gửi toàn bộ lịch sử: giữ khoảng một tá message gần nhất và bỏ phần còn lại. Nó có giảm hóa đơn, và thường là nước đi sai, và số đo cho thấy vì sao.

chiến lượctổngso với full history + cache
full history, không cache$0.274386+211 %
full history, caching$0.088250
12 message cuối, không cache$0.118712+35 %
12 message cuối, bật caching$0.122546+39 %

Cắt còn window mười hai message rẻ hơn 57 % so với gửi mọi thứ không cache — phép so sánh mà ai cũng làm, và là lý do kỹ thuật này phổ biến. Nhưng nó đắt hơn 39 % so với gửi mọi thứ với một cache hoạt động, và bật caching cùng với truncation làm nó hơi tệ hơn thay vì tốt hơn.

Cơ chế vẫn là prefix. Một sliding window bỏ message cũ nhất ở mỗi lượt, nên prompt không còn bắt đầu ở nơi nó đã bắt đầu lần trước và mỗi lượt đưa ra một prefix mới. Hướng dẫn của OpenAI nói đúng điều này: “summarisation, compaction, or context truncation can change the prefix and reset cache reuse.”6 Đến lượt 40, prompt dạng window còn 813 token, dưới mức tối thiểu 1,024 token, nên hoàn toàn không thể được cache.

Và tiền chỉ là nửa chi phí rẻ hơn. Thứ bạn bỏ đi là chỉ dẫn người dùng đã đưa ở lượt 2 mà model cần ở lượt 40. Truncation đổi một hóa đơn bạn thấy được lấy một failure bạn không thấy, và làm đúng việc đó — compaction, structured notes giữ ngoài window, retrieval lịch sử theo nhu cầu — là chủ đề của Chương 24.

Vượt một tier sẽ định giá lại toàn bộ request

Liên kết đến mục: Vượt một tier sẽ định giá lại toàn bộ request

Context dài không chỉ đắt hơn vì chúng dài hơn. Sau một ngưỡng, chúng đắt hơn theo từng token, và ngưỡng đó áp dụng ngược lại cho toàn bộ prompt.

Trang model của OpenAI cho gpt-5.6-terra nói trong một câu: “Prompts with >272K input tokens are priced at 2x input and 1.5x output for the full request.”7 Không phải cho phần vượt. Cho toàn bộ.

the most expensive token you will ever sendTEXT
prompt 271,999 + 500 output  ->  $0.5500
prompt 272,000 + 500 output  ->  $0.5500
prompt 272,001 + 500 output  ->  $1.0970

Một token, năm mươi lăm cent. Nếu service của bạn xây prompt từ các tài liệu retrieved mà bạn không kiểm soát kích thước, bạn có một vách đá trong cost model tại một ranh giới không ai trong team đã ghi xuống.

Pricing của Google hoạt động tương tự với ngưỡng 200,000-token: Gemini 2.5 Pro là $1.25 mỗi triệu input token cho prompt đến 200K và $2.50 khi vượt, với output tăng từ $10.00 lên $15.00.8 Anthropic đi hướng ngược lại — tính đến ngày 6 tháng 9 năm 2026, tài liệu của họ nói Claude 4.6 trở lên bao gồm toàn bộ one-million-token window ở pricing chuẩn, nên “một request 900k-token được tính cùng per-token rate như request 9k-token.”9 Các model trước đó vẫn giữ surcharge.

Đây là lý do một mức giá không phải là một con số. Một mức giá là bảng tier được key theo độ dài prompt, đó là mục đích của Tier[] trong cost function, và là lý do computeCost chọn tier bằng toàn bộ prompt thay vì từng bucket riêng.

Prefill, decode, và vì sao output đắt gấp sáu lần input

Liên kết đến mục: Prefill, decode, và vì sao output đắt gấp sáu lần input

Năm bucket ánh xạ lên hai pha của Chương 13, và một khi bạn thấy phép ánh xạ đó, các tỷ lệ giá không còn trông tùy tiện.

Input token là prefill. Toàn bộ prompt đi qua model trong một pass, được xử lý song song — các phép nhân ma trận lớn, compute-bound. Chi phí trên mỗi token thấp, và đây là pha quyết định time to first token: một prompt 4,947-token có 4,947 token prefill cần làm trước khi chữ đầu tiên xuất hiện.

Output token là decode. Chúng được tạo từng token một, mỗi token là một forward pass đầy đủ đọc toàn bộ KV cache, trong khi GPU chủ yếu chờ bộ nhớ thay vì tính toán. Đây là pha quyết định tokens per second, nó không thể được song song hóa trong một response, và đó là lý do output đắt hơn input khoảng sáu lần trên model được định giá ở đây: $12.00 so với $2.00 mỗi triệu token.

Ba hệ quả đi thẳng từ đó. Một cache read thay thế công việc prefill, nên nó mua cả latency lẫn tiền cùng lúc — cùng một chiết khấu xuất hiện dưới dạng hóa đơn thấp hơn và thời gian chờ token đầu tiên ngắn hơn. Reasoning token là decode bạn không bao giờ thấy, đó là lý do một reasoning model không stream gì trong vài giây rồi trả lời nhanh: Chương 12 đã cảnh báo hệ quả giao diện, còn đây là hệ quả hóa đơn. Và aborting một stream không dừng generationChương 14 đã xây cancellation và để phần giá cho chương này, và giá là toàn bộ số output, vì token được tạo và tính phí dù có ai đang nghe hay không. Câu trả lời không ai giữ cũng vậy: regenerate một câu trả lời lượt 40 năm lần tốn $0.057990 cho câu duy nhất còn lại trên màn hình.

Tokenizer của Chương 7 là Python và ở lại đó. Budgeting diễn ra trong server xây request, nên nó phải diễn ra ở đây, và chỉ có đúng ba mức độ chính xác.

Mức một: đếm cục bộ. js-tiktoken ship cùng các BPE merge table như Python tiktoken, nên có số đếm byte-for-byte giống hệt cho OpenAI encodings, không cần network call:

count.tsTS
import { getEncoding } from "js-tiktoken";

const enc = getEncoding("o200k_base");
const PER_MESSAGE = 4;   // role and delimiters added by the chat template
const PER_REPLY = 3;     // priming for the assistant turn

export function promptTokens(messages: { role: string; content: string }[]) {
  return messages.reduce(
    (sum, m) => sum + enc.encode(m.content).length + PER_MESSAGE, PER_REPLY);
}

Hai hằng số quan trọng và chúng là nơi số đếm cục bộ bị lệch. Text của bạn không phải thứ được tokenized — chat template của Chương 11 bọc mọi message trong role markers trước, và đó là các token bạn phải trả tiền. Bốn token mỗi message và ba token cho reply priming là ước lượng quy ước cho OpenAI chat models; trên tám mươi mốt message của cuộc trò chuyện ở trên, chúng cộng lại thành 324 token, 6.4 % độ dài của nó. Các số đếm ở đây được kiểm tra chéo với Python tiktoken từ Chương 7 trên toàn bộ tám mươi mốt string và giống hệt.

Mức hai: hỏi provider. Anthropic expose /v1/messages/count_tokens và Google expose count_tokens, cả hai nhận cùng request shape như một call thật và trả về số input token miễn phí. Dùng chúng khi bạn không thể đếm cục bộ — và bạn không thể đếm cục bộ cho Anthropic, whose tokenizer không được công bố. Tài liệu của Anthropic cẩn thận về thứ họ cung cấp: số đếm “là một estimate”, và nó “có thể bao gồm token được Anthropic tự động thêm cho system optimizations”, mà bạn “không bị tính phí”.10

Mức ba: đọc usage trong response. Đó là sự thật, và nó đến sau khi tiền đã được tiêu. Chính vì vậy hai mức đầu tồn tại — để quyết định có gửi request hay không, không phải để tính hóa đơn cho nó.

Những thứ bạn trả tiền mà không ai cho bạn thấy

Liên kết đến mục: Những thứ bạn trả tiền mà không ai cho bạn thấy

Bốn line item không xuất hiện như line item.

System prompt, trả ở mọi call. Prompt ở trên là 192 token cùng template overhead. Qua bốn mươi call, đó là 7,680 token — 5.6 % toàn bộ hóa đơn của cuộc trò chuyện này, cho tám dòng được viết một lần. Nó cũng là ứng viên cache tốt nhất có thể, vì vừa ổn định vừa ở đầu.

Tool definitions. Tên, mô tả và JSON schema của mọi tool được gửi đi ở mọi request, và provider thêm scaffolding bên trên. Anthropic công bố con số: bật tools đã thêm một hidden system prompt 496 token trên Claude Sonnet 4.5 với tool_choice đặt thành auto, hoặc 588 với any hay một named tool.9 Đó là trước schemas của riêng bạn. Chương 18 xây catalogue; Chương 24 đo nó ăn bao nhiêu.

Mọi generation, kể cả những cái bạn discard. Năm regenerations tốn gấp năm lần. Chat chỉ hiển thị một.

Thoughts bạn không được thấy. Billing dựa trên toàn bộ thought tokens dù chỉ summary được trả về, và không hệ kế toán nào của bạn có thể audit con số đó.

Một cảnh báo để kết thúc, vì đó là suy nghĩ tiếp theo tự nhiên và câu trả lời không hiển nhiên.

Một million-token window không có nghĩa là một triệu token dùng được. Độ chính xác retrieval suy giảm theo vị trí: Liu et al. phát hiện rằng model định vị thông tin đáng tin cậy ở đầu và cuối một input dài, và kém đáng tin hơn nhiều ở giữa.11 Window lớn hơn mua khả năng gửi nhiều hơn, không phải sự chắc chắn rằng nó được đọc.

Hiện tượng đó được đo một lần trong course này — retrieval rate ở chín vị trí trong cùng prompt 853-token — và nó thuộc về Chương 24, nơi nó thay đổi việc một agent làm. Nó được trích ở đây vì nó thay đổi thứ bạn nên mua: token rẻ nhất là token bạn không gửi.

Bây giờ bạn có thể dự đoán một call sẽ tốn bao nhiêu trước khi tạo nó, đọc sau đó nó đã tốn bao nhiêu, và phân biệt hai con số. Điều đó bao phủ mọi thứ về request ngoại trừ phần bạn chưa chạm tới: các knob.

Chương 17 là sampling — temperature, top-p, top-k, các penalty, và determinism mà bạn không có. Nó bắt đầu bằng việc tháo dỡ lỗi phổ biến nhất trong lĩnh vực này, rằng temperature là núm chỉnh creativity. Không phải: temperature chia các logit từ Chương 4 trước softmax, và tăng nó không làm model giàu tưởng tượng hơn, nó tăng xác suất của những token mà chính model đã chấm là tệ hơn. Từ đó, vì sao greedy decoding tạo ra text đo được là tệ hơn sampling, vì sao top-k và top-p thất bại trên hai hình dạng phân phối đối nghịch, và thí nghiệm kết thúc chương: hai mươi forward pass giống hệt ở temperature 0 trả về giống nhau từng bit khi model chạy một mình, và đặt cùng prompt vào một batch cùng request của người khác làm dịch chuyển 97 % logit của nó.

Chúng không khớp hết. Lý do bắt đầu với hộp floating-point từ Chương 2.


Tất cả giá, threshold và multiplier trong chương này được đọc từ chính các trang của provider vào 6 tháng 9 năm 2026 và được nêu kèm ngày đó vì chúng sẽ thay đổi. Phương pháp quan trọng hơn các con số: bucket, quy tắc prefix và số học tier đã ổn định trong hai năm trong khi mọi con số bên trong chúng đều đã dịch chuyển.

Stanford CS336 lecture 2, Resource accounting, là xử lý học thuật gần nhất của material này và là bài đọc tiếp theo đúng hướng: nó làm cùng phép tính ở phía training mà chương này làm ở phía inference. Token count ở đây được tạo bằng js-tiktoken 1.0.21 dùng các encoding o200k_basecl100k_base, trên một cuộc trò chuyện bốn mươi lượt dài 5,090 token; per-message template overhead là ước lượng quy ước four-plus-three và được nêu ở bất cứ đâu nó được bao gồm. Các số liệu cache, tier và truncation là các quy tắc pricing đã document được áp vào những token count đã đo đó, không phải quan sát từ live API responses — không paid call nào được thực hiện để tạo chương này, đó cũng là lý do trung thực khiến các tuyên bố latency là định tính còn các tuyên bố chi phí thì không.

  1. Dao, T., Fu, D. Y., Ermon, S., Rudra, A. and Ré, C. FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness. arXiv:2205.14135 (2022). Vì sao trần dịch chuyển mà chi phí tiệm cận không đổi.

  2. Chen, S., Wong, S., Chen, L. and Tian, Y. Extending Context Window of Large Language Models via Positional Interpolation. arXiv:2306.15595 (2023).

  3. Peng, B., Quesnelle, J., Fan, H. and Shippole, E. YaRN: Efficient Context Window Extension of Large Language Models. arXiv:2309.00071 (2023).

  4. Google, Thinking, ai.google.dev/gemini-api/docs/thinking, và Token counting, ai.google.dev/gemini-api/docs/tokens, cả hai truy cập 2026-09-06. “Pricing is based on the full thought tokens the model needs to generate, despite only the summary being output from the API.” Usage object báo total_input_tokens, total_output_tokens, total_thought_tokens, total_cached_tokens, total_tool_use_tokenstotal_tokens — sáu bucket, với thoughts và tool use nằm ngoài output count. Tên field trước đó cho cùng đại lượng, vẫn được generateContent surface trả về, là thoughtsTokenCount, được document trên trang thứ ba, ai.google.dev/gemini-api/docs/generate-content/thinking.

  5. Anthropic, Prompt caching, docs.anthropic.com/en/docs/build-with-claude/prompt-caching, truy cập 2026-09-06. Nguồn của thứ bậc invalidation toolssystemmessages và bảng của nó; độ dài tối thiểu có thể cache theo từng model; identity total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens; và vòng đời mặc định năm phút được refresh miễn phí ở mỗi hit. 2

  6. OpenAI, Prompt caching, platform.openai.com/docs/guides/prompt-caching, truy cập 2026-09-06. Nguồn của: quy tắc entire-rendered-prefix; prefix tối thiểu có thể cache (1,024 visible input token trên GPT-5.6 trở lên, 2,048 trên các model trước); multiplier write 1.25× và read 0.1×, và việc không có phí write nào trên GPT-5.5 trở về trước; vòng đời 30 phút; giới hạn four-writes-per-request và fifty-breakpoint; ghi chú machine-affinity và prompt_cache_key; các ví dụ hòa vốn 1.35×, 2.15× và 10×; và tuyên bố rằng summarisation, compaction hoặc truncation reset cache reuse. 2

  7. OpenAI, Pricing (platform.openai.com/docs/pricing) và trang model cho gpt-5.6-terra, cả hai truy cập 2026-09-06. gpt-5.6-terra, standard service tier, mỗi triệu token: input $2.00, cached input $0.20, cache writes $2.50, output $12.00; long context input $4.00, cached $0.40, writes $5.00, output $18.00; “prompts with >272K input tokens are priced at 2x input and 1.5x output for the full request”; context window 1,050,000 token với tối đa 922,000 input token. Cùng bảng liệt kê gpt-6-astra ở $10.00/$1.00/$12.50/$50.00 và gpt-5.6-luna ở $0.20/$0.02/$0.25/$1.20. Mọi chi phí worked trong chương này dùng standard short-context rates của gpt-5.6-terra.

  8. Google, Gemini Developer API pricing, ai.google.dev/gemini-api/docs/pricing, truy cập 2026-09-06. Gemini 2.5 Pro, mỗi triệu token: input $1.25 cho prompt đến 200K và $2.50 khi vượt; output $10.00 và $15.00, trong cả hai trường hợp được gắn nhãn “including thinking tokens”; context caching $0.125 và $0.25, cộng phí storage $4.50 mỗi triệu token mỗi giờ. Gemini 3.1 Pro Preview dùng cùng threshold 200K ở input $2.00/$4.00 và output $12.00/$18.00.

  9. Anthropic, Pricing, docs.anthropic.com/en/docs/about-claude/pricing, truy cập 2026-09-06. Mỗi triệu token, base input / 5-minute cache write / 1-hour cache write / cache read / output: Claude Sonnet 4.5 $3 / $3.75 / $6 / $0.30 / $15; Claude Haiku 4.5 $1 / $1.25 / $2 / $0.10 / $5; Claude Opus 5 $5 / $6.25 / $10 / $0.50 / $25. Multiplier: 1.25× cho write năm phút, 2× cho write một giờ, 0.1× cho một read. Cũng là nguồn của tuyên bố long-context (“Claude 4.6 and later models... include the full 1M token context window at standard pricing”), số token system prompt của tool-use (496 token trên Claude Sonnet 4.5 với tool_choiceauto hoặc none, 588 với any hoặc một named tool), và ghi chú rằng Claude 4.7 trở lên dùng tokenizer mới hơn tạo ra “approximately 30 % more tokens for the same text”. 2 3

  10. Anthropic, Token counting, docs.anthropic.com/en/docs/build-with-claude/token-counting, truy cập 2026-09-06. Endpoint /v1/messages/count_tokens nhận cùng inputs như một message và trả về input token count; tài liệu nói rằng số đếm là estimate, rằng nó có thể bao gồm token Anthropic thêm cho system optimisations, và những token đó không bị tính phí.

  11. Liu, N. F., Lin, K., Hewitt, J., Paranjape, A., Bevilacqua, M., Petroni, F. and Liang, P. Lost in the Middle: How Language Models Use Long Contexts. arXiv:2307.03172 (2023). Được trích ở đây, đo trong Chương 24.

Sẵn sàng để LIA chọn giúp bạn chưa?

Xây dựng cùng mọi mô hình AI ở một nơi — bắt đầu miễn phí ngay hôm nay.