Token計費怎麼算:把一次大模型 API 呼叫的賬單逐項拆開

部落格 / 模型觀察

Token計費怎麼算:把一次大模型 API 呼叫的賬單逐項拆開

大模型 API 的 token計費,公式本身很簡單:費用 = 輸入 token 數 × 輸入單價 + 輸出 token 數 × 輸出單價,有快取的平臺再把命中快取的那部分輸入按快取價單獨計算。難的是“輸入 token 數”往往比你以為的大得多,因為它不只是你這一輪打的字,還包括系統提示詞、全部對話歷史和工具定義。這篇文章從介面返回的 usage 欄位講起,把一次呼叫的賬單拆開,最後給一張可以照著填的估算表。

一次呼叫到底按什麼收費?

幾乎所有主流介面都會在響應裡帶一個 usage 物件,它就是計費的原始依據。欄位名各家略有不同,常見的有兩套:

含義OpenAI 相容格式Anthropic 格式
輸入 tokenprompt_tokens(含快取命中部分)input_tokens(不含快取部分)
快取讀取prompt_tokens_details.cached_tokenscache_read_input_tokens
快取寫入一般不單列cache_creation_input_tokens
輸出 tokencompletion_tokensoutput_tokens
其中推理 tokencompletion_tokens_details.reasoning_tokens計入 output_tokens

注意兩點。第一,OpenAI 相容格式裡 prompt_tokens 通常已經包含了快取命中的部分,算錢時要先減掉 cached_tokens,再分別乘單價;Anthropic 格式則是三項分開給。第二,推理模型“想”的那部分 token 不一定顯示給你,但按輸出價計費。欄位的確切含義以各家官方 API 文件為準,接入前先核對一遍。

輸入 token 裡裝了哪些東西?

實際賬單裡,你自己這一輪輸入的內容常常只佔很小一部分。一次請求的輸入通常由這幾塊拼成:

  1. 系統提示詞:每次請求都會完整傳送。Agent 類工具的系統提示詞可能有幾千 token。
  2. 工具定義:開了函式呼叫或 MCP,每個工具的名稱、描述和引數 JSON Schema 都算輸入。工具一多,這部分很容易超過系統提示詞。
  3. 對話歷史:介面是無狀態的,模型“記得”上文,是因為客戶端把之前所有輪次重新發了一遍。工具呼叫的返回結果(比如讀進來的整個檔案)也在歷史裡。
  4. 當前輸入:你這一輪打的字、貼的程式碼、上傳的圖片(圖片也會折算成 token)。

輸出部分則是:

  1. 可見輸出:你看到的回答。
  2. 推理輸出:推理模型內部的思考過程,按輸出價計費。

一個標註為“示例”的計算

下面用假設的數字算一遍。單價取輸入 2 美元 / 百萬 token、輸出 10 美元 / 百萬 token,這個組合落在 cdnping 於 2026 年 10 月 17 日從 OpenRouter 公開 API 取得的價格快照區間內;快取讀取價假設為輸入價的十分之一,實際倍率請看各家價格頁。

組成token 數(示例)計價方式費用(美元)
系統提示詞1,500輸入
工具定義3,000輸入
對話歷史12,000輸入
當前輸入500輸入
輸入合計17,000無快取時 × 2 / 1M0.034
可見輸出800輸出
推理輸出1,200輸出
輸出合計2,000× 10 / 1M0.020
單次合計0.054

假如前 15,000 個輸入 token(系統提示詞、工具定義和大部分歷史)命中快取:

  • 快取讀取:15,000 × 0.2 / 1M = 0.003
  • 未命中輸入:2,000 × 2 / 1M = 0.004
  • 輸出不變:0.020
  • 合計 0.027,大約是無快取時的一半。

這個例子裡,你這一輪真正“說的話”只有 500 token,不到輸入的 3%。

為什麼多輪對話越聊越貴?

因為每一輪都要把之前的全部歷史重新發一遍並重新計費。假設固定字首(系統提示詞 + 工具定義)是 4,500 token,每輪問答新增 1,000 token 歷史:

  • 第 1 輪輸入約 4,500
  • 第 10 輪輸入約 13,500
  • 第 20 輪輸入約 23,500

20 輪的累計輸入是 4,500 × 20 + 1,000 × (0 + 1 + … + 19) = 90,000 + 190,000 = 280,000 token。其中歷史部分按平方級增長:輪數翻倍,歷史帶來的累計輸入接近翻四倍。程式設計 Agent 讀檔案、跑命令、看日誌,每次工具返回都塞進歷史,增長更快。

能做的事情:

  • 一個任務完成就開新會話,別在一個視窗裡聊一整天。
  • 用客戶端的壓縮或摘要功能,把舊歷史換成短摘要。
  • 只啟用當前任務需要的工具,減少每次都要傳送的工具定義。
  • 把不變的內容放在請求前部,讓快取能命中,具體做法見 Claude API 提示快取怎麼用才省錢。

max_tokens 管什麼,不管什麼?

max_tokens(有的介面叫 max_output_tokens 或 max_completion_tokens)只限制輸出的上限,不限制輸入。

  • 能做到:防止模型一次輸出過長,給單次請求的輸出費用設一個上限。
  • 做不到:減少輸入費用。歷史有 10 萬 token,設多小的 max_tokens 輸入照樣按 10 萬算。
  • 對推理模型,推理 token 一般也佔用這個額度。設得太小,可能推理還沒結束就被截斷,可見回答是空的,但已經生成的 token 仍然計費。
  • 截斷也收錢:響應裡 finish_reason 為 length(或 stop_reason 為 max_tokens)時,說明被截斷了,這次的輸出照常計費。

想控制總成本,要管的是輸入那一側:歷史長度、工具數量、快取命中率。

怎麼用 usage 欄位自己對賬?

平臺後臺的賬單是按天或按月彙總的,出了偏差很難定位到某次請求。最可靠的辦法是在自己的程式碼裡把每次的 usage 記下來。

第一步:看一次請求的原始 usage

curl -s https://你的介面地址/v1/chat/completions \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"你的模型","messages":[{"role":"user","content":"你好"}],"max_tokens":50}' \
  | jq '.usage'

流式請求(stream: true)預設可能不返回 usage,OpenAI 相容介面通常要加 "stream_options": {"include_usage": true},usage 會出現在最後一個資料塊裡。

第二步:每次呼叫落一行日誌

import json, time

PRICE = {"in": 2.0, "cache": 0.2, "out": 10.0}  # 示例單價,美元/百萬 token,換成你實際的

def log_usage(model, usage, path="usage.jsonl"):
    cached = (usage.get("prompt_tokens_details") or {}).get("cached_tokens", 0)
    prompt = usage.get("prompt_tokens", 0)
    out = usage.get("completion_tokens", 0)
    cost = ((prompt - cached) * PRICE["in"] + cached * PRICE["cache"] + out * PRICE["out"]) / 1e6
    row = {"ts": int(time.time()), "model": model, "prompt": prompt,
           "cached": cached, "out": out, "est_cost": round(cost, 6)}
    with open(path, "a") as f:
        f.write(json.dumps(row) + "\n")

Anthropic 格式把欄位換成 input_tokens、cache_read_input_tokens、cache_creation_input_tokens、output_tokens,快取寫入要按寫入價單獨算。

第三步:按天彙總,和後臺賬單比

jq -s 'group_by(.ts / 86400 | floor) | map({day: (.[0].ts/86400|floor), cost: (map(.est_cost)|add), prompt: (map(.prompt)|add), out: (map(.out)|add)})' usage.jsonl

對賬時的檢查表:

  • 自己記錄的請求數和後臺的請求數是否一致(重試、超時後客戶端重發都算請求)
  • 流式請求是否都拿到了 usage,有沒有漏記
  • 快取命中的 token 有沒有按快取價算,快取寫入有沒有單獨算
  • 推理 token 有沒有計入輸出
  • 單價是否是最新的,平臺有沒有調價
  • 偏差明顯時,挑幾條請求逐條核對

如果對不上,常見原因和逐條核對方法在 AI API 賬單對不上:token 計數口徑與核對方法 裡有更細的講法。單價會變,可以在 cdnping 的 官網動態 頁面跟蹤各家價格頁的逐行變化,模型監測 頁面會記錄 OpenRouter 目錄裡的調價;完整的追蹤思路見 大模型 API 價格變了怎麼第一時間知道。

單價差多少,值得在意嗎?

以 cdnping 在 2026 年 10 月 17 日從 OpenRouter 公開 API 取得的快照為例(單日快照,不代表長期價格),我們跟蹤的 16 個重點模型裡,輸入單價從 0.1 到 4 美元 / 百萬 token,輸出單價從 0.47 到 12 美元 / 百萬 token,上下文視窗在約 26 萬到 105 萬 token 之間。同樣一次請求,選不同的模型,費用可以差出幾十倍。

另外兩個規律:

  • 輸出通常比輸入貴。快照裡多數模型的輸出單價是輸入的 3 到 5 倍,個別模型的差距更大。所以推理模型“想得多”,費用漲得快。
  • 便宜的模型不一定省錢。如果它要多試幾次才能做對,重試的輸入和輸出都要再付一遍。

按任務難度把請求分到不同價位的模型,是比壓提示詞更有效的省錢方式,做法見 多模型路由怎麼做;比較價格時容易踩的坑見 大模型 API 價格怎麼比。

不按 token 計費的方式怎麼換算?

有些平臺不直接按 token 報價,而是用自己的計量單位。以 AGI Plan 為例(AGI Plan 是 cdnping 的商業合作方):計量單位是 CU,1 CU = 基準模型 1,000 個輸出 token;按量付費時 1 元 = 500 CU。其他模型和輸入 token 如何折算成 CU,以 https://agiplan.dev/pricing 和 https://agiplan.dev/models 為準。

遇到這類計量方式,換算思路是一樣的:先弄清楚單位對應的是輸入還是輸出、是哪個基準模型,再用自己日誌裡的 usage 去核對實際扣減。

成本估算表模板

上線一個功能前,把下面這張表填一遍,基本能估出量級。

專案填寫說明
系統提示詞 token用介面發一次只含系統提示詞的請求,看 usage
工具定義 token帶工具和不帶工具各發一次,相減
平均每輪新增歷史 token使用者輸入 + 模型輸出 + 工具返回
平均每會話輪數 n
每會話累計輸入字首 × n + 每輪新增 × n(n−1)/2
預計快取命中比例沒開快取填 0
平均每輪輸出(含推理)看 completion_tokens / output_tokens
輸入 / 快取 / 輸出單價抄官方價格頁,記下日期
每會話費用按上文公式
每日會話數 × 30月度估算
重試率月度估算 × (1 + 重試率)

估完之後,上線第一週用日誌裡的真實 usage 回填這張表,如果歷史和工具定義比預估的大,先從這兩項最佳化。

相關文章

繼續閱讀