コスト最適化ガイド
Python でプロジェクト別の API 支出を追跡し、予算アラートを受け取る
短い Python スクリプトが使用量ログをプロジェクト別コストレポートに変え、月次予算の 50、75、95、100% で警告します。

このページの内容
API 呼び出しのたびに JSON を 1 行ファイルに追記し、プロジェクト名でタグ付けします。30 行の Python スクリプトがそのファイルをプロジェクト別コストレポートに変え、月次予算の 50、75、95、100% で警告を出します。Anthropic が Claude Enterprise チームに提供したのと同じビューを、自分のログから作るわけです。
1 つの残高がエージェント、ブログ下書きスクリプト、小さなサポートボットを支えているとします。月末になり、残高は思ったより少なく、3 つのどれが原因かは何も教えてくれません。この記事はそのギャップを埋めます。
Anthropic が提供したもの、そしてコピーできるもの#
Anthropic の発表(2026 年 10 月 28 日)は、スマートレポート、アプリ内サーベイ、プール型グループ予算を扱っており、一般提供は Claude Enterprise プラン限定です(source)。ここで重要なのは 2 点です。レポートはチームの作業をワークストリームにまとめ、それぞれの支出を表示します。プール型予算は 1 つの共有月次金額で、請求管理者はその 50%、75%、95%、100% でメールを受け取ります。Anthropic はさらに、レポートは投資計画のためのものであり、個人を評価するためのものではないと付け加えています。
同じ形なら Enterprise プランは不要です。ワークストリームは自分で選ぶラベルにすぎず、4 つのしきい値はコード内の 1 つのリストです。Anthropic が挙げた理由から、人ではなくプロジェクトでグループ化しましょう。
クイックチェック
プリペイド残高はすでにゼロでリクエストを止めます。なぜ 50% と 75% の警告を追加するのでしょうか?
答えを表示
答え: ゼロでは遅すぎるから:まだ調査する余裕があるうちに、暴走ループに気づきたい
残高はハードストップであり、アラームではありません。早めのしきい値があれば、100% での驚きが 9 日目の疑問になります。
ログ:リクエストごとに 1 行#
すべてのチャット補完レスポンスには、prompt_tokens と completion_ を持つ usage オブジェクトが含まれます。レポートに必要なのはこれと、自分で追加するプロジェクトラベルだけです。このラッパーはリクエストを送信し、月次ファイルに 1 行追記します(ファイル名は毎月変わるので、新しい月はゼロから始まります):
import json, os, time
from openai import OpenAI
client = OpenAI(base_url="https://api.cheaptokens.dev/v1",
api_key=os.environ["CHEAPTOKENS_API_KEY"])
def ask(project, model, messages):
r = client.chat.completions.create(model=model, messages=messages)
with open(time.strftime("usage-%Y-%m.jsonl"), "a") as f:
f.write(json.dumps({"project": project, "model": model,
"prompt_tokens": r.usage.prompt_tokens,
"completion_tokens": r.usage.completion_tokens}) + "\n")
return r
ask("support-bot", "zai-org/GLM-5.3-Flash",
[{"role": "user", "content": "Where is my order?"}])CheapTokens docs の完全なモデル ID(deepseek-、zai-)を使ってください。価格表の短い名前は API では受け付けられません。キーは環境変数から取得し、ファイルからは決して取得しません。

スクリプト:プロジェクト別コストとしきい値アラート#
これを report.py として保存します。価格はプレースホルダーです。現在の価格を pricing table からコピーしてください(ここでは計算を読みやすくするためだけに、両モデルが 1 つの例価格を共有しています)。
import json, os, sys, time
from collections import defaultdict
LOG = time.strftime("usage-%Y-%m.jsonl")
BUDGET = float(os.environ.get("BUDGET_USD", "10")) # example, substitute your own
STATE = LOG + ".alert"
LEVELS = [50, 75, 95, 100]
PRICES = { # USD per 1M tokens (input, output): example, substitute current prices
"deepseek-ai/DeepSeek-V4-Flash-0731": (1.0, 2.0),
"zai-org/GLM-5.3-Flash": (1.0, 2.0),
}
spend = defaultdict(float)
with open(LOG) as f:
for line in f:
r = json.loads(line)
p_in, p_out = PRICES[r["model"]]
spend[r["project"]] += (r["prompt_tokens"] * p_in
+ r["completion_tokens"] * p_out) / 1_000_000
total = sum(spend.values())
if total == 0:
sys.exit("log is empty")
for name, usd in sorted(spend.items(), key=lambda kv: -kv[1]):
print(f"{name:<8} ${usd:6.2f} {usd / total:5.0%}")
print(f"{'total':<8} ${total:6.2f} of ${BUDGET:.2f} ({total / BUDGET:.0%})")
last = int(open(STATE).read()) if os.path.exists(STATE) else 0
crossed = [l for l in LEVELS if total >= BUDGET * l / 100 and l > last]
if crossed:
print(f"WARNING: budget passed {crossed[-1]}%")
open(STATE, "w").write(str(crossed[-1]))最後の 4 行が忘れられがちな部分です。小さな状態ファイルがなければ、スクリプトは月の残りずっと実行のたびに「50% を超えました」と叫び続けます。状態ファイルがあれば、各レベルは 1 回だけ発火します。
実行して結果を読む#
4 行のトイログを用意します(実際のログはリクエストごとに 1 行なので数千行になります):
{"project": "agent", "model": "deepseek-ai/DeepSeek-V4-Flash-0731", "prompt_tokens": 2400000, "completion_tokens": 300000}
{"project": "agent", "model": "deepseek-ai/DeepSeek-V4-Flash-0731", "prompt_tokens": 1000000, "completion_tokens": 100000}
{"project": "blog", "model": "zai-org/GLM-5.3-Flash", "prompt_tokens": 800000, "completion_tokens": 400000}
{"project": "bot", "model": "zai-org/GLM-5.3-Flash", "prompt_tokens": 500000, "completion_tokens": 100000}例の価格と予算 10 で、python report.py は次を出力します:
agent $ 4.20 65%
blog $ 1.60 25%
bot $ 0.70 11%
total $ 6.50 of $10.00 (65%)
WARNING: budget passed 50%エージェントが請求のほぼ 3 分の 2 を占めており、警告は最後ではなく 50% で出ました。もう一度実行すると、合計が 75% に達するまで警告は静かなままです。

これを毎月機能させるには、3 つのステップが必要です:
ステップバイステップ
3 つのステップで設定する
すべての呼び出しをログに記録
すべての呼び出しを ask(project, model, messages) 経由にし、短く安定したプロジェクトラベルを選びます。月の途中でラベルを変更すると、1 つのプロジェクトが 2 行に分かれます。
価格と予算を設定
価格表の現在の価格を PRICES に入れ、上限をエクスポートします:export BUDGET_。
スケジュールで実行
毎時の cron 行で十分です:0 * * * * cd ~/。警告をプッシュしたい場合は、出力をメールやチャットのコマンドに送ります。
安価なモデルでの 1 か月#
数字は自分の数字になって初めて役に立ちます。トイログのエージェントが 1 ステップあたり平均 30,000 入力トークンと 2,000 出力トークン、1 タスク 20 ステップ、1 日 2 タスクを使うとします。DeepSeek-V4-Flash の 1 ステップは $0.00065、GLM-5.3-Flash では $0.00068 です。1 日は 40 ステップ、1 か月は 1,200 ステップです。スライダーを自分のエージェントに合わせて動かしてください:
コスト計算機
エージェントの 1 日:1 タスクあたりのステップ数 × 1 日あたりのタスク数
リクエストあたりの入力トークン数: 30,000 · リクエストあたりの出力トークン数: 2,000 · 1日あたりのリクエスト数: 40
| モデル | 1日あたり | 1か月あたり |
|---|---|---|
| GLM-5.3-Flash$0.02$0.04 | $0.0272 | $0.816 |
| DeepSeek-V4-Flash$0.015$0.10 | $0.026 | $0.78 |
| MiniMax-M2.7$0.05$0.15 | $0.072 | $2.16 |
そして 1,200 ステップの 1 か月、入力と出力を合算して:
| モデル | 入力 $/1M | 出力 $/1M | リクエストあたり | 1,200 リクエスト | OpenRouter、1,200 リクエスト |
|---|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.00068 | $0.816 | $1.41 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.00065 | $0.78 | $2.86 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.0018 | $2.16 | $25.92 |
リクエストあたり 30,000 入力トークンと 2,000 出力トークン。100万トークンあたりの価格は現行のもので、当社の料金体系に合わせて変動します。OpenRouter 列は同じワークロードの参考価格を示しています。
合計で、入力と出力を合算すると、両モデルともその表の OpenRouter の参照価格より安くなり、時間帯を問わず 1 つの価格で、ピーク時の割増はありません。DeepSeek-V4-Flash は回答あたり最大 32,768 出力トークンと 380K コンテキストを許可し、GLM-5.3-Flash は 390K コンテキストを持ちます。レポートでどのプロジェクトが重いかがわかったら、そのプロジェクトの model 文字列だけを切り替えるのは 1 行の変更で、1 つの残高がすべてのモデルをカバーします。1 回のリクエストが実際に何トークン使うかは how many tokens an API request uses を、エージェントの実行を途中で止める方法は tracking AI agent token cost を参照してください。価格とモデルは CheapTokens models page にあります。
うまくいかないところ#
PRICESにモデルがない。 スクリプトはモデル名を示すKeyErrorで停止します。追加してください。ゼロをデフォルトにしないでください。そうしないとプロジェクトが無料に見えます。- ストリーミング呼び出し。 最終チャンクは、要求した場合にのみ使用量を含みます(OpenAI SDK では
stream_)。そうでなければログに穴が空きます。options={"include_ usage": True} - 失敗したリクエスト。
usageオブジェクトを持つレスポンスだけをログに記録してください。エラーになったリクエストには数えるものがありません。 - 個人別レポート。 ラベルはプロジェクト名かエージェント名に保ってください。人についてのレポートは誤った結論を招きます。



