דלג לתוכן
16/30פרק 16 מתוך 30

ה-context window, ה-tokens והחשבון — במדידה

שיחה של 40 תורות עולה פי 22 מאורכה ב-input tokens. caching מקצץ 68%; timestamp במקום שגוי מוסיף 20%.

בעמוד הזה

הנה שיחת תמיכה בת ארבעים תורות, מחויבת turn אחר turn. אין בה שום דבר חריג: מפתח שואל על API, assistant עונה בפסקה או שתיים. כל החילוף הוא 5,090 tokens של טקסט — בערך שמונה עמודים.

turnprompt tokensטקסט חדשoutputעלות ה-turn הזהסך מצטבר
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

קראו יחד את העמודות השנייה והשלישית. ב-turn 40 המשתמש הקליד שבעה-עשר tokens וחויב על 4,947. השאלה לא הייתה קשה יותר מהראשונה; היא הייתה קצרה יותר. מה שהשתנה הוא שהבקשה נשאה איתה את כל השיחה, שוב, בפעם הארבעים.

סך ה-input tokens שחויבו לאורך ארבעים הקריאות האלה: 112,617. אורך השיחה הוא 5,090 tokens. שילמתם עליה פי עשרים ושניים.

הפרק הזה עוסק בשאלה למה זה קורה, איך זה נקרא בחשבונית של כל ספק, ועל אילו מחמשת הדברים שאתם מחויבים עליהם אתם יכולים להשפיע.

הצגת פרטים

מה הפרק הזה צריך מחלק II.

  • פרק 7 בנה את ה-tokenizer. גם כאן token הוא היחידה — אותה יחידה, עכשיו עם מחיר.
  • פרק 9 גזר את self-attention ואת עלות O(n2)O(n^2) שלו, בתיבת הסימון האסימפטוטית. העלות הזאת היא הסיבה לכך שקיים בכלל גבול, והיא מקושרת כאן במקום להיות מוסברת מחדש.
  • פרק 13 מדד prefill מול decode וחישב כמה מקום תופס KV cache. שני השלבים האלה הם מה שעמודות ה-input וה-output למעלה קונות בפועל.

כל השאר הוא TypeScript, כי זה חשבונאות של קריאה מרחוק ולא מתמטיקה על מודל.

הטעות היקרה ביותר בתחום הזה היא לחשוב שמודל זוכר שיחה.

הוא לא, והמנגנון מפרק 13 מסביר בדיוק למה. המצב של transformer בזמן יצירה הוא ה-KV cache: ה-keys וה-values שחושבו לכל token ברצף. ה-cache הזה חי למשך בקשה אחת. כשהבקשה מסתיימת, התהליך שהחזיק אותו פנוי לשרת מישהו אחר, וה-cache נעלם. אין בצד השני מאגר פר-משתמש, ואין session.

לכן הבקשה הבאה צריכה להגיע כשהיא נושאת כל מה שהמודל אמור לדעת, והמודל בונה מחדש את המצב הזה באמצעות forward pass על כל ה-prompt לפני שהוא פולט token חדש אחד. פרק 15 קרא ל-prompt ״כל המצב״. זו הסיבה הפיזית: ה-prompt הוא המצב המלא כי שום דבר אחר לא שורד את הקריאה.

ה-context window היא האורך המקסימלי של ה-prompt הזה יחד עם התשובה שלו. היא תקרה לכמות המצב שאפשר לבנות מחדש, לא מיכל שמחזיק משהו בין בקשות. לקרוא לה ״הזיכרון של המודל״ הופך את כיוון הסיבתיות — אתם לא ממלאים זיכרון, אתם משלמים כדי להקים אחד מחדש.

מכאן מגיע ה-22. turn nn נושא את כל n1n-1 ה-turns הקודמים, ולכן סך ה-input לאורך שיחה של nn turns הוא סכום של סדרה גדלה, כלומר ריבועי:

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

כאשר ss הוא ה-system prompt ו-hih_i הוא ההיסטוריה ב-turn ii. התאמת ה-input המצטבר שנמדד ל-an2+bnan^2 + bn לאורך ארבעים ה-turns נותנת 60.22n2+432.25n60.22\,n^2 + 432.25\,n, שחוזה 113,645 tokens ב-turn 40 מול 112,617 שנמדדו. האיבר הריבועי שולט, והאיבר הליניארי הוא מה שהמשתמש באמת הקליד.

זו השורה שכדאי לקחת מהפרק הזה: החשבון שלכם גדל עם ריבוע השיחה, לא עם השאלה האחרונה. אותן ארבעים שאלות, אם נשאלו בלי היסטוריה בכלל, עלו $0.066036. שמירת ההיסטוריה עלתה $0.274386. ההיסטוריה הכפילה את החשבון פי 4.2, והיא תמשיך להכפיל אותו, כי המכפיל הוא אורך השיחה.

ה-window סופית משתי סיבות שמושכות לאותו כיוון. הראשונה היא של פרק 9: attention משווה כל token לכל token אחר, ולכן העבודה של השכבה הזאת גדלה עם ריבוע אורך הרצף. השנייה היא זיכרון: ה-KV cache גדל ליניארית עם אורך הרצף, ופרק 13 עשה את החשבון הזה — ברצפים ארוכים הוא גדול יותר מהמשקלים.

שני הגבולות הותקפו ואף אחד מהם לא הוסר. FlashAttention1 מארגן מחדש את החישוב כך שהוא קורא וכותב הרבה פחות לזיכרון ברוחב פס גבוה, מה שהופך רצפים ארוכים למעשיים בלי לשנות את העלות האסימפטוטית. Position Interpolation2 ו-YaRN3 מרחיבים את ה-window השימושית של מודל מאומן באמצעות שינוי קנה המידה של positional encodings מפרק 9 במקום לאמן מחדש. יחד הם הסיבה לכך ש-windows עברו מ-2K ל-1M בחמש שנים.

מה שהם לא עשו הוא להפוך contexts ארוכים לחינמיים. הם העלו את התקרה והפכו את השיפוע למתון יותר. השיפוע עדיין שם, וזה מה שמדרגות המחיר בהמשך הפרק מודדות.

כמעט כל מחשבון עלויות באינטרנט ממדל קריאת API כ-input tokens כפול מחיר input ועוד output tokens כפול מחיר output. זה היה נכון ב-2023. עכשיו זה שגוי באופן שמייצר חשבונות שסטו פי שניים או יותר לשני הכיוונים.

יש חמש קטגוריות token לחיוב:

דלימה זהמחיר טיפוסי, יחסית ל-input
uncached inputprompt tokens שהמודל היה צריך לעבד מחדש
cache readprompt tokens שסופקו מתוך prefix שמור0.1×
cache writeprompt tokens שנשמרו ב-cache בקריאה הזאת1.25× עד 2×
outputtokens שהמודל יצר ושלח לכם5× עד 6×
reasoningtokens שהמודל יצר ולא שלח לכםתעריף output

שלוש מתוך החמש האלה לא היו קיימות כשורות נפרדות לפני שנתיים, ושתי שורות ה-cache הן אלה שאנשים טועים בהן, כי cache write עולה יותר מ-input רגיל, לא פחות. אתם משלמים פרמיה כדי לשמור משהו כדי שתוכלו לשלם הנחה כשאתם קוראים אותו חזרה, והאם זו עסקה טובה תלוי לחלוטין בכמה פעמים תקראו אותו.

דלי ה-reasoning הוא של פרק 12, עכשיו עם מחיר, ויש בו פרט שכדאי לומר במפורש: התיעוד של Google אומר שהתמחור ״מבוסס על מלוא thought tokens שהמודל צריך ליצור, אף שרק התקציר יוצא מה-API.״4 אתם מחויבים על tokens שלעולם לא מועברים אליכם. זה הדלי היחיד שאת תוכנו אינכם יכולים לספור, לבדוק או לאמת.

אותה קריאה, שלושה דיאלקטים

קישור למקטע: אותה קריאה, שלושה דיאלקטים

עכשיו החלק שהופך את זה לבעיית נרמול ולא לבעיית כפל. כל ספק מדווח על הדליים האלה בשמות שונים, ו—זו המלכודת—שניים מהם משתמשים באותה מילה לשתי כמויות שונות.

קחו קריאה אחת: 4,837 tokens שנקראו מ-cache, 110 חדשים, 142 output tokens גלויים, 300 reasoning tokens.

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 } }

הסתכלו על prompt_tokens: 4947 ועל input_tokens: 110. שני השדות הם ספירת ה-input tokens עבור אותו prompt. אצל OpenAI היא כוללת את ה-cached tokens; אצל Anthropic היא מחריגה אותם — התיעוד שלה מציין את הזהות במפורש, total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens.5 המשמעות של input_tokens אצל Anthropic היא ״ה-tokens אחרי נקודת ה-cache האחרונה שלכם״.

ועכשיו הסתכלו על ה-output. OpenAI ו-Anthropic מדווחות שתיהן 442, שכבר כולל את 300 ה-reasoning tokens. Gemini מדווחת 142 ושמה את ה-300 בשדה משלה. פרק 12 סימן את זה כאי-תאימות בין שתי דרכים לספור את אותה עבודה; כאן רואים כמה זה עולה.

normaliser הוא שלושים שורות והוא לא אופציונלי:

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
  };
};

הריצו את שלושת ה-payloads שלמעלה דרך שלושת הקוראים, ושלושתם מייצרים את אותו Usage, ולכן את אותו מספר: $0.006491. ההסכמה הזאת היא כל הסיבה לכתוב את השכבה.

טעו בזה, וזה מה שזה עולה באותה קריאה:

טעותחיובשגיאה
להתייחס ל-cached_tokens כתוספת ל-prompt_tokens$0.0161652.49× — מחייבים את ה-prompt פעמיים
להתייחס ל-cache reads כחינמיים במקום 0.1×$0.0055240.85× — אתם סופגים 15 %
לקרוא את candidatesTokenCount ולהתעלם מ-thoughtsTokenCount$0.00289155 % מהקריאה נעלמים

השלישית היא המסוכנת, כי היא נכשלת בשקט בכיוון של חדשות טובות. הדשבורד שלכם מראה שמודל reasoning עולה פחות מחצי ממה שהוא באמת עולה, ושום דבר בשום מקום לא מעלה שגיאה.

אחרי שהדליים נורמלו, פונקציית העלות קצרה. החלק היחיד שאינו מובן מאליו הוא חיפוש המדרגה, שהסעיף הבא מסביר:

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);
}

שתי החלטות תכנון שם ראויות להגנה. ה-fallbacks — מחירי cache שנופלים חזרה ל-input, reasoning ל-output — מקודדים מה המשמעות של טבלה חסרה: reasoning tokens ב-Gemini מחויבים בתעריף output, ולכן מחיר reasoning חסר אינו אפס, אלא מחיר ה-output. ו-contextSize מסכם את כל שלושת דליי ה-input ולא רק את החדשים, כי המדרגה נבחרת לפי אורך ה-prompt, לא לפי כמה ממנו חויבו במחיר מלא.

Prompt caching, ומה עולה לכתוב אותו

קישור למקטע: Prompt caching, ומה עולה לכתוב אותו

prompt cache שומר את המצב המחושב של המודל עבור prefix של ה-prompt שלכם, כך שבקשה מאוחרת יותר עם אותו prefix מדלגת על החישוב מחדש שלו. ארבע תכונות נובעות מהמילה ״prefix״, וכל הארבע מפתיעות אנשים.

ה-cache מתאים מתחילת ה-prompt המרונדר והלאה, ועוצר ב-byte הראשון ששונה. אין קרדיט חלקי על תוכן שמופיע מאוחר יותר בסדר אחר. OpenAI אומרת זאת ישירות: ״cache reuse requires the entire rendered prefix to match.״6

מתחתיו, שום דבר לא נשמר ב-cache ולא מוחזרת שגיאה. אצל OpenAI המינימום הוא 1,024 tokens עבור GPT-5.6 ואילך ו-2,048 עבור מודלים ישנים יותר. אצל Anthropic הוא נע בין 512 ל-4,096 בהתאם למודל — 1,024 עבור Claude Sonnet 4.5, 4,096 עבור Claude Haiku 4.5. אם שני שדות ה-cache חוזרים אפס, זו בדרך כלל הסיבה.

כתיבה עולה יותר מקריאה, ויותר מלא להשתמש ב-cache

קישור למקטע: כתיבה עולה יותר מקריאה, ויותר מלא להשתמש ב-cache

ב-OpenAI וב-Anthropic, cache write הוא 1.25× מתעריף ה-uncached input עבור ה-cache קצר-החיים, וה-cache לשעה אחת של Anthropic הוא 2×. read הוא 0.1×. Google לא גובה על כתיבה אבל משכירה את האחסון: $4.50 למיליון tokens לשעה ב-Gemini 2.5 Pro.

הוא פג תוקף, והוא חי על מכונה אחת

קישור למקטע: הוא פג תוקף, והוא חי על מכונה אחת

רשומת ברירת המחדל של Anthropic חיה חמש דקות, ומתרעננת בחינם בכל hit. של OpenAI היא לפחות שלושים דקות אחרי הכתיבה או השימוש החוזר האחרונים. ו-OpenAI מציינת שמצבים שמורים חיים על מכונות ספציפיות, ולכן בקשה פוגעת רק אם היא מנותבת למכונה שמחזיקה את הרשומה — וזה מה ש-prompt_cache_key משפיע עליו, בלי להבטיח.

נקודת האיזון קטנה מספיק כדי לזכור בראש, והתיעוד של OpenAI עושה את החשבון: כתיבת prefix פעם אחת ושימוש חוזר בו פעם אחת עולה 1.35× מעלות ה-input הרגילה שלו, מול 2× לעיבוד שלו פעמיים ללא cache; לאורך עשר בקשות, כתיבה אחת ותשע קריאות עולות 2.15× מול 10×. שימוש חוזר אחד משלם על הכתיבה. Anthropic מגיעה לאותו מקום: קריאה אחת ל-cache של חמש דקות, שתיים ל-cache של שעה.

עכשיו שוב השיחה בת ארבעים ה-turns, עם caching פעיל ו-prefix יציב:

uncached inputcache readscache writesסך הכול
בלי cache112,617$0.274386
caching2,887104,7834,947$0.088250

זול יותר בשישים ושמונה אחוזים, ושלושה מספרים בטבלה הזאת שווים תשומת לב.

ה-cache לא נכנס לפעולה עד turn 6. ה-prompt לא מגיע ל-1,024 tokens עד אז, ולכן חמשת ה-turns הראשונים מחויבים בדיוק כמו קודם — וה-sixth מחויב גרוע יותר, בפרמיית כתיבה של 1.25\u00d7, כי זה ה-turn שממלא את ה-cache. הקריאה הראשונה מגיעה ב-turn 7. 2,887 ה-uncached tokens בטבלה הם החשבון: חמישה turns, לא שישה. caching הוא הנחה על prompts ארוכים, ושיחה קצרה לא מקבלת ממנו כלום.

פרמיית הכתיבה היא $0.002474, שהם 2.8 % מהחשבון עם cache. כל turn כותב את הזנב החדש שלו, ארבעים פעמים, וכל פרמיית הכתיבה היא טעות עיגול לעומת מה שהקריאות חסכו. כדאי להבין את חיוב הכתיבה במדויק כדי להפסיק לדאוג ממנו.

רק 2,887 tokens חויבו במחיר input מלא מתוך 112,617. כך נראה cache שעובד: כמעט הכול הוא read.

סדר ה-prompt קובע אם משהו מזה יקרה

קישור למקטע: סדר ה-prompt קובע אם משהו מזה יקרה

הנה הכשל שעולה כסף אמיתי, והוא באג של שורה אחת.

שימו משהו שמשתנה בכל קריאה קרוב לתחילת ה-prompt — timestamp, request id, שם המשתמש, שורת ״היום הוא״, מסמך שאוחזר עכשיו — וה-prefix שונה כבר מה-byte הראשון. שום דבר לא מתאים. כל קריאה היא miss. וכיוון שכל קריאה מציגה prefix חדש, כל קריאה גם כותבת.

אותה שיחה, אותם ארבעים turns, caching מופעל, עם timestamp לכל קריאה בראש ה-system prompt:

סך הכוללעומת
בלי caching בכלל$0.274386
caching, prefix יציב$0.088250−67.8 %
caching, prefix תנודתי$0.329251+20.0 %

הפעלת prompt caching הפכה את השיחה ליקרה בעשרים אחוזים יותר מאשר לא להפעיל אותו. שילמתם את פרמיית הכתיבה 1.25× על 109,730 tokens וקראתם חזרה אפס. אין שגיאה, אין אזהרה, והפיצ׳ר מופעל.

אז הכלל, והוא כל prompt caching בשורה אחת: תוכן יציב מקדימה, תוכן משתנה מאחור. הוראות מערכת, הגדרות tools וחומרי עזר קודם; timestamps, זהות משתמש והשאלה הנוכחית אחרונים. Anthropic הופכת את ההיררכיה למפורשת — ה-cache עוקב אחרי toolssystemmessages, ושינוי בכל רמה מבטל את הרמה הזאת ואת כל מה שאחריה, כך שעריכה של תיאור tool יחיד מבטלת את כל ה-cache.5

שתי השלכות שאנשים נתקלים בהן. שינוי אילו tools מופעלים משנה את הגדרות ה-tools, ולכן feature flag שמוסיף tool לחלק מהמשתמשים מפצל את ה-cache לשניים. וב-Anthropic, הפעלה או כיבוי של חיפוש web או citations משנה את ה-system prompt, מה שמבטל את cache המערכת וההודעות בלי שנגעתם בשורה אחת מהטקסט שלכם.

קיצור ההיסטוריה אינו התיקון

קישור למקטע: קיצור ההיסטוריה אינו התיקון

התגובה המתבקשת לחשבון ריבועי היא להפסיק לשלוח את כל ההיסטוריה: לשמור את תריסר ההודעות האחרונות ולזרוק את השאר. זה אכן מקטין את החשבון, ובדרך כלל זו התנועה הלא נכונה, והמדידה אומרת למה.

אסטרטגיהסך הכוללעומת היסטוריה מלאה + cache
היסטוריה מלאה, בלי cache$0.274386+211 %
היסטוריה מלאה, caching$0.088250
12 ההודעות האחרונות, בלי cache$0.118712+35 %
12 ההודעות האחרונות, caching פעיל$0.122546+39 %

קיצור ל-window של שתים-עשרה הודעות זול ב-57 % משליחת הכול ללא cache — ההשוואה שכולם עושים, והסיבה שהטכניקה פופולרית. אבל הוא יקר ב-39 % משליחת הכול עם cache עובד, והפעלת caching לצד קיצור הופכת אותו למעט גרוע יותר, לא טוב יותר.

המנגנון הוא שוב ה-prefix. window נגררת זורקת את ההודעה הישנה ביותר בכל turn, ולכן ה-prompt כבר לא מתחיל איפה שהתחיל בפעם הקודמת וכל turn מציג prefix חדש. ההנחיה של OpenAI אומרת בדיוק את זה: ״summarisation, compaction, or context truncation can change the prefix and reset cache reuse.״6 ב-turn 40 ה-prompt בחלון הוא 813 tokens, מתחת למינימום 1,024-token, ולכן אי אפשר לשמור אותו ב-cache בכלל.

והכסף הוא החצי הזול של העלות. מה שזרקתם הוא ההוראה שהמשתמש נתן ב-turn 2 שהמודל היה צריך ב-turn 40. Truncation מחליף חשבון שאתם יכולים לראות בכשל שאינכם יכולים לראות, ולעשות את זה נכון — compaction, הערות מובנות שמוחזקות מחוץ ל-window, אחזור היסטוריה לפי דרישה — הוא הנושא של פרק 24.

חציית מדרגה מתמחרת מחדש את כל הבקשה

קישור למקטע: חציית מדרגה מתמחרת מחדש את כל הבקשה

contexts ארוכים אינם יקרים יותר רק כי הם ארוכים יותר. מעבר לסף מסוים הם יקרים יותר לכל token, והסף חל רטרואקטיבית על כל ה-prompt.

דף המודל של OpenAI עבור gpt-5.6-terra אומר זאת במשפט אחד: ״Prompts with >272K input tokens are priced at 2x input and 1.5x output for the full request.״7 לא על העודף. על הכול.

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

token אחד, חמישים וחמישה סנט. אם השירות שלכם בונה prompts ממסמכים שאוחזרו וגודלם אינו בשליטתכם, יש לכם צוק במודל העלויות בגבול שאף אחד בצוות לא כתב.

התמחור של Google עובד באותו אופן עם סף של 200,000-token: Gemini 2.5 Pro עולה $1.25 למיליון input tokens עבור prompts עד 200K ו-$2.50 מעליו, כשה-output עולה מ-$10.00 ל-$15.00.8 Anthropic הלכה לכיוון השני — נכון ל-6 בספטמבר 2026, התיעוד שלה מציין ש-Claude 4.6 ואילך כוללים את מלוא ה-window של מיליון token במחיר סטנדרטי, כך ש-״a 900k-token request is billed at the same per-token rate as a 9k-token request.״9 מודלים מוקדמים יותר שמרו על התוספת.

לכן מחיר אינו מספר. מחיר הוא טבלת מדרגות שממופתחות לפי אורך prompt, וזה התפקיד של Tier[] בפונקציית העלות, ולכן computeCost בוחר את המדרגה באמצעות כל ה-prompt ולא כל דלי בנפרד.

Prefill, decode, ולמה output עולה פי שישה מ-input

קישור למקטע: Prefill, decode, ולמה output עולה פי שישה מ-input

חמשת הדליים ממופים לשני השלבים של פרק 13, וכשרואים את המיפוי יחסי המחירים מפסיקים להיראות שרירותיים.

Input tokens הם prefill. כל ה-prompt עובר דרך המודל במעבר אחד, מעובד במקביל — הכפלות מטריצות גדולות, מוגבלות-חישוב. העלות ל-token נמוכה, וזה השלב שקובע את time to first token: prompt של 4,947-token כולל 4,947 tokens של prefill לפני שהמילה הראשונה מופיעה.

Output tokens הם decode. הם נוצרים אחד-אחד, כל אחד forward pass מלא שקורא את כל ה-KV cache, כשה-GPU בעיקר ממתין לזיכרון במקום לחשב. זה השלב שקובע tokens per second, אי אפשר למקבל אותו בתוך תשובה אחת, וזו הסיבה ש-output עולה בערך פי שישה מ-input במודל שמתומחר כאן: $12.00 מול $2.00 למיליון tokens.

מכאן נובעות ישירות שלוש השלכות. cache read מחליף עבודת prefill, ולכן הוא קונה latency וכסף יחד — אותה הנחה מופיעה גם כחשבון נמוך יותר וגם כהמתנה קצרה יותר ל-token הראשון. Reasoning tokens הם decode שאינכם רואים, ולכן מודל reasoning לא מזרים כלום למשך כמה שניות ואז עונה מהר: פרק 12 הזהיר מההשלכה הממשקית, וזו ההשלכה בחשבונית. ו-ביטול stream אינו עוצר את ה-generationפרק 14 בנה cancellation והשאיר את המחיר לפרק הזה, והמחיר הוא ספירת ה-output המלאה, כי ה-tokens נוצרים ומחויבים בין אם מישהו מאזין ובין אם לא. אותו דבר נכון לגבי התשובה שאף אחד לא שומר: יצירה מחדש של תשובת turn 40 חמש פעמים עולה $0.057990 עבור זו שנשארת על המסך.

לספור tokens לפני ששולחים אותם

קישור למקטע: לספור tokens לפני ששולחים אותם

ה-tokenizer של פרק 7 היה Python ונשאר שם. תקצוב קורה בשרת שבונה את הבקשה, ולכן הוא צריך לקרות כאן, ויש בדיוק שלוש רמות דיוק זמינות.

רמה אחת: לספור מקומית. js-tiktoken מגיע עם אותן טבלאות מיזוג BPE כמו tiktoken של Python, ולכן נותן ספירה זהה byte-for-byte עבור encodings של OpenAI, בלי קריאת רשת:

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);
}

שני הקבועים חשובים, ושם ספירות מקומיות נסחפות. הטקסט שלכם אינו מה שעובר tokenization — תבנית ה-chat של פרק 11 עוטפת כל הודעה קודם בסימוני role, ואלה tokens שאתם משלמים עליהם. ארבעה לכל הודעה ושלושה ל-reply priming הם הקירוב המקובל למודלי chat של OpenAI; לאורך שמונים ואחת ההודעות של השיחה למעלה הם מסתכמים ב-324 tokens, 6.4 % מאורכה. הספירות כאן הוצלבו מול tiktoken של Python מפרק 7 על כל שמונים ואחד המחרוזות והן זהות.

רמה שתיים: לשאול את הספק. Anthropic חושפת את /v1/messages/count_tokens ו-Google חושפת את count_tokens, ושניהם מקבלים את אותה צורת בקשה כמו קריאה אמיתית ומחזירים ספירת input token בחינם. השתמשו בהם כשאי אפשר לספור מקומית — ואי אפשר לספור מקומית עבור Anthropic, שה-tokenizer שלה אינו מפורסם. התיעוד של Anthropic זהיר לגבי מה שהוא נותן לכם: הספירה ״is an estimate״, והיא ״may include tokens added automatically by Anthropic for system optimizations״, שעליהם ״you are not billed״.10

רמה שלוש: לקרוא את usage בתגובה. זו האמת, והיא מגיעה אחרי שהכסף כבר הוצא. בדיוק לכן שתי הרמות הראשונות קיימות — כדי להחליט אם לשלוח את הבקשה, לא כדי לחייב עליה.

הדברים שאתם משלמים עליהם ושאף אחד לא מראה לכם

קישור למקטע: הדברים שאתם משלמים עליהם ושאף אחד לא מראה לכם

ארבע שורות שאינן מופיעות כשורות.

ה-system prompt, משולם בכל קריאה. זה שלמעלה הוא 192 tokens עם תקורת התבנית שלו. לאורך ארבעים קריאות אלה 7,680 tokens — 5.6 % מכל חשבון השיחה הזאת, עבור שמונה שורות שנכתבו פעם אחת. הוא גם מועמד ה-cache הטוב ביותר האפשרי, כי הוא גם יציב וגם ראשון.

הגדרות tools. השם, התיאור ו-JSON schema של כל tool יוצאים בכל בקשה, והספקים מוסיפים מעליהם scaffolding. Anthropic מפרסמת את המספר: עצם הפעלת tools מוסיפה system prompt נסתר של 496 tokens ב-Claude Sonnet 4.5 כש-tool_choice מוגדר ל-auto, או 588 עם any או tool בשם.9 וזה עוד לפני ה-schemas שלכם. פרק 18 בונה את הקטלוג; פרק 24 מודד כמה הוא אוכל.

כל generation, כולל אלה שאתם זורקים. חמש יצירות מחדש עולות פי חמש. ה-chat מציג אחת.

מחשבות שלא מוצגות לכם. החיוב מבוסס על מלוא thought tokens אף שרק תקציר מוחזר, ושום חשבונאות שלכם לא יכולה לבקר את המספר הזה.

זה שיש לכם 200K tokens לא אומר שאתם משתמשים בהם

קישור למקטע: זה שיש לכם 200K tokens לא אומר שאתם משתמשים בהם

אזהרה אחת לסיום, כי זו המחשבה הטבעית הבאה והתשובה אינה המובנת מאליה.

window של מיליון token אינה אומרת מיליון tokens שימושיים. דיוק retrieval יורד לפי מיקום: Liu ואחרים מצאו שמודלים מאתרים מידע באופן אמין בתחילת input ארוך ובסופו, והרבה פחות אמין באמצע.11 window גדולה יותר קונה את היכולת לשלוח יותר, לא את הוודאות שיקראו את זה.

התופעה הזאת נמדדת פעם אחת בקורס הזה — שיעור ה-retrieval בתשעה מיקומים באותו prompt בן 853-token — והיא שייכת לפרק 24, שם היא משנה את מה ש-agent עושה. היא מצוטטת כאן כי היא משנה את מה שכדאי לכם לקנות: ה-token הזול ביותר הוא זה שלא שלחתם.

עכשיו אתם יכולים לחזות כמה קריאה תעלה לפני שתבצעו אותה, לקרוא כמה היא עלתה אחר כך, ולהבדיל בין השניים. זה מכסה כל מה שקשור לבקשה חוץ מהחלק שעוד לא נגעתם בו: הכפתורים.

פרק 17 הוא sampling — temperature, top-p, top-k, ה-penalties, והדטרמיניזם שאין לכם. הוא מתחיל בפירוק הטעות הנפוצה ביותר בתחום, שלפיה temperature הוא חוגת יצירתיות. הוא לא: temperature מחלק את ה-logits מ-פרק 4 לפני ה-softmax, והעלאה שלו לא הופכת את המודל לדמיוני, היא מעלה את ההסתברות של tokens שהמודל עצמו דירג כגרועים יותר. משם, למה greedy decoding מייצר טקסט גרוע יותר באופן מדיד מ-sampling, למה top-k ו-top-p נכשלים בצורות התפלגות הפוכות, והניסוי שסוגר את הפרק: עשרים forward passes זהים ב-temperature 0 חוזרים זהים bit-for-bit כשהמודל רץ לבדו, ושימת אותו prompt ב-batch לצד בקשות של מישהו אחר מזיזה 97 % מה-logits שלו.

לא כולם תואמים. הסיבה מתחילה בתיבת ה-floating-point מ-פרק 2.


כל המחירים, הספים והמכפילים בפרק הזה נקראו מדפי הספקים עצמם ב-6 בספטמבר 2026 ומצוינים עם התאריך הזה כי הם ישתנו. השיטה חשובה יותר מהמספרים: הדליים, כלל ה-prefix וחשבון המדרגות יציבים כבר שנתיים, בעוד שכל מספר בתוכם זז.

הרצאה 2 של Stanford CS336, Resource accounting, היא הטיפול האקדמי הקרוב ביותר לחומר הזה והקריאה הבאה הנכונה: היא עושה את אותו חשבון בצד האימון שהפרק הזה עושה בצד ה-inference. ספירות ה-token כאן הופקו עם js-tiktoken 1.0.21 באמצעות encodings o200k_base ו-cl100k_base, על שיחה בת ארבעים turns של 5,090 tokens; תקורת התבנית לכל הודעה היא קירוב הארבע-ועוד-שלוש המקובל ומצוינת בכל מקום שבו היא כלולה. נתוני ה-cache, המדרגות וה-truncation הם כללי התמחור המתועדים שהוחלו על ספירות ה-token שנמדדו, לא תצפיות של תגובות API חיות — לא בוצעה קריאה בתשלום כדי להפיק את הפרק הזה, וזו גם הסיבה הכנה לכך שטענות ה-latency הן איכותניות וטענות העלות אינן.

  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). למה התקרה זזה בלי שהעלות האסימפטוטית השתנתה.

  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, ו-Token counting, ai.google.dev/gemini-api/docs/tokens, שניהם ניגשו ב-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 מדווח על total_input_tokens, total_output_tokens, total_thought_tokens, total_cached_tokens, total_tool_use_tokens ו-total_tokens — שישה דליים, עם thoughts ו-tool use מחוץ לספירת ה-output. שם השדה הקודם לאותה כמות, שעדיין מוחזר על ידי generateContent surface, הוא thoughtsTokenCount, ומתועד בדף שלישי, ai.google.dev/gemini-api/docs/generate-content/thinking.

  5. Anthropic, Prompt caching, docs.anthropic.com/en/docs/build-with-claude/prompt-caching, ניגש ב-2026-09-06. מקור להיררכיית הביטול toolssystemmessages ולטבלה שלה; האורכים המינימליים לשמירה ב-cache לפי מודל; הזהות total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens; ואורך החיים המוגדר כברירת מחדל של חמש דקות שמתרענן ללא חיוב בכל hit. 2

  6. OpenAI, Prompt caching, platform.openai.com/docs/guides/prompt-caching, ניגש ב-2026-09-06. מקור ל: כלל ה-entire-rendered-prefix; ה-prefix המינימלי שאפשר לשמור ב-cache (1,024 visible input tokens ב-GPT-5.6 ואילך, 2,048 קודם); מכפילי הכתיבה 1.25× והקריאה 0.1×, והיעדר כל חיוב כתיבה ב-GPT-5.5 וקודם; אורך חיים של 30 דקות; מגבלות ארבע הכתיבות לבקשה וחמישים ה-breakpoints; הערת ה-machine-affinity ו-prompt_cache_key; דוגמאות נקודת האיזון המחושבות 1.35×, 2.15× ו-10×; והאמירה ש-summarisation, compaction או truncation מאפסים cache reuse. 2

  7. OpenAI, Pricing (platform.openai.com/docs/pricing) ודף המודל עבור gpt-5.6-terra, שניהם ניגשו ב-2026-09-06. gpt-5.6-terra, standard service tier, למיליון tokens: 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 tokens עם מקסימום 922,000 input tokens. אותה טבלה מציגה את gpt-6-astra ב-$10.00/$1.00/$12.50/$50.00 ואת gpt-5.6-luna ב-$0.20/$0.02/$0.25/$1.20. כל חישוב עלות בפרק הזה משתמש בתעריפי ה-standard short-context של gpt-5.6-terra.

  8. Google, Gemini Developer API pricing, ai.google.dev/gemini-api/docs/pricing, ניגש ב-2026-09-06. Gemini 2.5 Pro, למיליון tokens: input $1.25 עבור prompts עד 200K ו-$2.50 מעל; output $10.00 ו-$15.00, בשני המקרים עם התווית ״including thinking tokens״; context caching $0.125 ו-$0.25, בתוספת חיוב אחסון של $4.50 למיליון tokens לשעה. Gemini 3.1 Pro Preview משתמש באותו סף 200K עם input $2.00/$4.00 ו-output $12.00/$18.00.

  9. Anthropic, Pricing, docs.anthropic.com/en/docs/about-claude/pricing, ניגש ב-2026-09-06. למיליון tokens, 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. מכפילים: 1.25× לכתיבה של חמש דקות, 2× לכתיבה של שעה, 0.1× לקריאה. גם המקור לאמירת ה-long-context (״Claude 4.6 and later models... include the full 1M token context window at standard pricing״), ספירות ה-tool-use system prompt tokens (496 tokens ב-Claude Sonnet 4.5 עם tool_choice של auto או none, 588 עם any או tool בשם), וההערה ש-Claude 4.7 ואילך משתמשים ב-tokenizer חדש שמייצר ״approximately 30 % more tokens for the same text״. 2 3

  10. Anthropic, Token counting, docs.anthropic.com/en/docs/build-with-claude/token-counting, ניגש ב-2026-09-06. endpoint /v1/messages/count_tokens מקבל אותם inputs כמו message ומחזיר ספירת input token; התיעוד מציין שהספירה היא estimate, שהיא עשויה לכלול tokens ש-Anthropic מוסיפה עבור system optimisations, ושעל אלה לא מחויבים.

  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). מצוטט כאן, נמדד בפרק 24.


נוצר על ידי

David Vicente Campos

מייסד NeuraLIA Labs ושותף-מייסד MyRealFood

אני מהנדס מחשבים, בוגר אוניברסיטת לאון. הייתי שותף בהקמת MyRealFood, שם, כסמנכ״ל טכנולוגיות, בניתי את האפליקציה שמיליוני אנשים השתמשו בה כדי לאכול בריא יותר, והקמתי את NeuraLIA Labs, שם אני בונה מוצרי בינה מלאכותית. כאן אני כותב על מה שהייתי צריך להבין לאורך הדרך, כפי שהייתי רוצה שמישהו היה מסביר לי בזמנו.

עוד על המחבר

פורסם על ידי NeuraLIA Labs.

פוסטים חדשים ישירות לתיבת הדואר

חדשות AI, מדריכים ועדכוני מוצר — מייל קצר כשאנחנו מפרסמים משהו ששווה את הזמן שלך.

תוכן הקורס

Abstract software decision engine with branching paths, probability nodes, and glowing gates.
jev10 דקות קריאה

מודל ה-AI Jev נבנה להחלטות, לא לפרוזה

Jev של TypeSafe AI מושך תשומת לב כי הוא מתייחס לאינטליגנציית תוכנה כאל בעיית הסתברות: לבחור את ההסתעפות הנכונה, להצמיד ביטחון, ולהימנע מתשלום ל-LLM כדי שיכתוב טקסט כשהקוד צריך החלטה.

Abstract agent runtime sorting documents, memory blocks and pointer nodes inside a bounded context frame.
context-engineering10 דקות קריאה

הנדסת הקשר לסוכני AI ארוכי־טווח

סוכנים שרצים לאורך זמן לא נכשלים רק כי החלון קטן. הם נכשלים כשקבצים, פלטי כלים והיסטוריה מיושנת דוחקים החוצה את המשימה שהסוכן היה אמור להשלים.

מוכנים לתת ל-LIA לבחור?

בנו עם כל מודלי ה-AI במקום אחד — התחילו בחינם עוד היום.