跳到正文
DEV Community· Mayur Agnani·· 2 小時前精選AI 評分76

如何比較 token 計數方式各異的 AI 模型價格

How to Compare Model Prices When Each Model Counts Tokens Differently

AI 導讀

要比較 AI 模型價格,應以各模型的 tokenizer 測量自有文本的 token 數,而非只看每 token 單價。

推薦理由

文章提供以自有文本測量各模型每千個字元的 token 數、換算任務成本並重設 token 限制的流程,呈現 tokenizer 差異對價格比較的影響。

正文 · 繁體中文

工程師觀點。這就像按每個 vCPU 的價格比較雲端機器,但其中一家供應商的 vCPU 是一個完整核心,另一家的則只有半個核心。單位名稱相同,大小卻不同。token 也是這類單位:每個模型都有自己的定義。

簡要摘要。每個模型都用自己的詞彙表把文字切分成 token,因此同一段提示詞在不同模型中會有不同的 token 數量。只有量度自己的文字每個字元對應多少個 token,才能按每個 token 的價格作比較。同一效應亦會悄悄縮減上下文視窗和輸出上限。

用 5 歲小孩也能明白的方式説明

兩間店都按「長度」賣繩。在第一間店,一個「長度」就是你的手臂長度;在第二間店,一個「長度」是店主的手臂長度,比你的短。兩間店的標價都是每個「長度」10 枚硬幣。你需要足夠長的繩子橫渡一條河。在第二間店,你需要買更多個「長度」,所以要付更多錢。價目牌上的價格相同,帳單金額卻不同。要作比較,先用自己的步伐量度一次河寬,再問每間店這相當於多少個「長度」。

問題

你以前已在沒有 AI 的系統中發布過這個 bug。

你的團隊按每個 vCPU 的價格挑選雲端機器。供應商 A 的每個 vCPU 價格較低,所以批次工作改到那裏執行。工作執行得更慢,每月帳單也增加了。在供應商 B,vCPU 是一個完整核心;在供應商 A,vCPU 則是一個超執行緒,約等於半個核心。兩個單位都叫 vCPU,大小卻不同,因此比較從一開始就錯了,根本不用等到執行工作才發現。

模型定價也有同樣的問題。每家供應商都列出每百萬個token的價格;token 是模型讀取和生成的文字片段。比較網站把這些價格列在同一張表上。你的用量儀錶板和方案限制也以 token 計算,看起來像是共用同一個單位。

其實不是。每個模型都用自己的方式切分文字。2026 年 4 月,Anthropic 推出 Opus 4.7,定價與 Opus 4.6 相同,但採用了新的分詞器。OpenRouter 隨後研究了轉換模型的用戶所提出的逾一百萬次真實請求。現在,他們的提示詞換算成 token 後長了 32% 至 45%。Simon Willison 把同一段系統提示詞貼到兩個模型中,token 數由 5,039 變成 7,335。標價沒有變,帳單卻變了。

解決方法:比較之前,先按自己的文字換算所有價格,然後重新檢查所有以 token 設定的限制。

解決方法:量度自己的文字每個字元對應多少個 token

token 究竟是甚麼?

模型讀取文字之前,分詞器會先把文字轉換成 token。分詞器會在模型訓練前預先訓練一次。訓練從單一字元開始,然後不斷把訓練文本中最常出現的一對合併,形成一個新的較長 token。經過足夠次合併後,常見詞語各自會成為一個 token。罕見詞語、不常見的程式碼和不熟悉的文字系統,則仍會拆分成較小片段。這種方法稱為位元組對編碼。

How a price per token becomes your bill

為甚麼兩個模型對同一段文字的切分結果不同?

在code_example.py中,兩個示範用的分詞器進行了相同數目的合併操作。一個以散文訓練,另一個則以散文加程式碼訓練。一行 80 個字元的 Python 程式碼,在第一個分詞器中會佔用 70 個 token,在第二個則佔用 44 個。兩者處理散文樣本時都會佔用 33 個 token。程式碼、JSON 及英語以外的語言,差異最大。

那麼,我可以比較甚麼數字?

其中一項工作的成本:每個 token 的價格,乘以每個字元對應的 token 數,再乘以傳送的字元數。假設模型 B 標示的價格便宜 17%,但會把你的文字切分成多 35% 個 token,那麼每項工作的成本便會高 13%。

35% 的 token 增幅,是否一定代表帳單增加 35%?

如果其他條件不變,是的。已快取和未快取的 token 都會按相同比例變化。不過,新模型也會改變輸出內容的長度。OpenRouter 發現,短提示詞下答案的中位長度縮短了 62%,因此帳單維持不變。超過 2,000 tokens 時,成本則上升 12% 至 27%。

這對你有甚麼影響

哪些情況會受影響。你根據價格頁面選擇模型,在 Cursor、Claude Code 或自己的應用程式中切換預設模型,或遇到供應商推出「價格不變」的新版本。你也可能接近上下文上限、用量上限,或預算緊絀的max_tokens。在這些情況下,你設定或比較的數字,都是以該模型的 token 計算。

對你的影響。帳單是最明顯的部分,較容易忽略的是各種上限。以 token 設定的上限,只對設定上限時所用的模型而言,才代表文字量。若改用 token 數多出 35% 的 tokenizer,200,000-token 視窗可容納的程式碼庫內容便會少 26%。800-token 的答案上限,現在大約在 2,370 個字元時就會截停,而不是 3,200 個字元。長答案會更早被截斷,而且不會顯示任何錯誤。Agent 會更早開始壓縮歷史記錄。每週 token 配額也會更早用完,即使完成的是相同工作。

What a 200,000-token context window holds

這又是 vCPU 的老問題。標籤上的數字沒有錯,只是它採用一個你從未核實過大小的單位計算。

應對方法。從自己的記錄中挑選 20 至 50 組真實提示詞和答案,並用各候選模型自己的 token 計數器計算。將 token 數除以字元數,得出每千個字元的 token 數;再乘以各自的價格,計算每項任務的成本。每當模型更換版本時,即使價格不變,也要重新檢查。之後重新計算所有以 token 設定的上限。

實際操作

要作出的改變。

這涉及三個角色:挑選模型的人、追蹤開支的人,以及設定上限的人。

角色 1:挑選模型。用各供應商的計數器計算自己的樣本。每個計數器都會按相應模型的 tokenizer 計算,因此所得比例才準確:

import tiktoken, anthropic
from google import genai

def tokens_per_kchar(samples, count):
    return 1000 * sum(count(s) for s in samples) / sum(len(s) for s in samples)

enc = tiktoken.get_encoding("o200k_base")          # check which encoding your model uses
openai_tpk = tokens_per_kchar(samples, lambda s: len(enc.encode(s)))

claude = anthropic.Anthropic()
claude_tpk = tokens_per_kchar(samples, lambda s: claude.messages.count_tokens(
    model=CLAUDE_MODEL, messages=[{"role": "user", "content": s}]).input_tokens)

gem = genai.Client()
gemini_tpk = tokens_per_kchar(samples, lambda s: gem.models.count_tokens(
    model=GEMINI_MODEL, contents=s).total_tokens)

使用真實提示詞,並包括系統提示詞和工具定義。這些內容往往佔每個請求的最大部分。只採用簡短用戶訊息的樣本會令你得出錯誤結論。將樣本儲存為檔案,確保日後每次比較都使用相同文字。切勿以「每個 token 四個字元」估算。這個經驗法則是按某個 tokenizer 的英文散文調校而成。

角色 2:追蹤開支。記錄每項任務的成本,而非每日 token 數。不同模型的 token 數無法直接比較,但費用可以。讀取每個回應已提供的用量欄位:

u = resp.usage                                      # Anthropic Messages API
dollars = (u.input_tokens * P_IN + u.cache_read_input_tokens * P_CACHE_READ
           + u.cache_creation_input_tokens * P_CACHE_WRITE + u.output_tokens * P_OUT) / 1e6
log.info("task_cost", task=task_id, model=MODEL, dollars=dollars, chars=len(prompt))

OpenAI 則會回報 prompt_tokens、completion_tokens 和 prompt_tokens_details.cached_tokens。Gemini 會在 usage_metadata 中回報這些資料。按任務類型分類,再以相同任務比較不同模型。每筆記錄都要儲存模型名稱,否則切換模型看起來就像流量有變。

角色 3:設定上限。所有以 token 設定的上限,原本都是按某個 tokenizer 調校的。先列出這些上限:在程式碼和設定檔中搜尋 max_tokens、上下文預算、歷史記錄截斷設定和壓縮門檻。切換模型時,再重新換算:

import math

def rescale(limit_tokens, tpk_old, tpk_new):
    return math.ceil(limit_tokens * tpk_new / tpk_old)

MAX_TOKENS = rescale(800, 250, 338)                 # 1082: same answer length in text
COMPACT_AT = min(rescale(150_000, 250, 338),        # 202,800 would pass a 200k window,
                 int(0.8 * NEW_WINDOW))             # so cap at the model's real limit

視窗本身不會變大。重新換算後的數字超出視窗容量時,可容納的文字便會減少,你要預先作好安排。

如何確認做法奏效。切換模型前後,按任務計算的成本圖表仍會平順銜接。若出現跳升,代表實際變化,而非計量單位改變。切換後的截斷率維持不變。如果答案突然更常觸及 max_tokens,代表某項限制沒有重新調整。最後,你的筆記中應記有各模型每千字元 token 數的實測值。下次比較價格應只需五分鐘。

何時不應使用按字元比較

質素比價格重要時。一次便能完成任務的模型,勝過需要嘗試三次但價格較低的模型。計算每項任務的成本時,必須計入重試;按字元計算則無法反映這一點。

按席位收取固定費用,而且沒有 token 上限時。這樣一來,tokenizer 的變化不會影響你支付的費用,但仍會影響上下文視窗可容納的內容量。

輸入主要是圖片或音訊時。這些內容會按大小、解像度或時長計算,各有不同規則。請分開量度。

差距很小時。每個字元的 token 數相差 5%,仍在大多數樣本的雜訊範圍內。不要因此更換模型。

工作負載即將改變時。每個字元的 token 數取決於你提交的內容。在聊天提示詞上量度的比率,不適用於程式碼 Agent。

採用之前,請先問:

  • 每個模型處理我自己的文字時,每千字元會使用多少個 token?
  • 我的系統中有哪些限制以 token 設定?
  • 上次切換模型後,答案長度有否改變?

詞彙表

  • token — 模型讀取或生成的一段文字;每個模型都有自己的 token 定義。
  • tokenizer — 模型讀取文字前,將文字切分為該模型 token 的程式。
  • byte-pair encoding — 透過反覆合併出現頻率最高的符號配對來訓練 tokenizer 的方法。
  • tokens per thousand characters — 模型處理你提供的 1,000 個字元時所使用的 token 數。
  • context window — 模型在單次請求中可讀取的 token 數上限。

延伸閲讀


最初刊載於 theaicommit.com;該網站是為軟件工程師而設的每日 AI 工程實驗室。原文提供可供你互動操作的互動版本,完整的可執行程式碼則載於 GitHub。

來源:DEV Community · dev.to