Kembali ke blog

API & SDKPanduan

Lacak biaya token agen AI di Python: usage, anggaran, stop

Catat field usage setiap permintaan, jumlahkan per tugas dan hentikan agen pada anggaran dolar. Contoh Python yang berfungsi untuk API yang kompatibel dengan OpenAI.

Oleh CheapTokens TeamDiterbitkan 6 menit baca

Kartu kode bergaya terminal: log usage per langkah dan pemeriksaan anggaran yang menghentikan agen AI
Di halaman ini
  1. Di mana angkanya: objek usage
  2. Meter yang menghentikan agen
  3. Berapa total dari proses 40 langkah
  4. Saat model sedang thinking
  5. Streaming: usage datang terakhir
  6. Jika angkanya terlihat salah

Agen Anda berjalan selama sepuluh menit dan tagihannya lebih besar daripada tugasnya. Untuk melihat penyebabnya, baca objek usage di setiap respons API, jumlahkan per tugas dan kalikan dengan harga model per 1 juta token. Untuk membatasinya, bandingkan total berjalan itu dengan anggaran setelah setiap langkah dan hentikan loop saat terlampaui. Di bawah ini adalah kelas Python kecil yang melakukan hal tersebut.

Contoh ini menggunakan endpoint yang kompatibel dengan OpenAI https://api.cheaptokens.dev/v1 dan id model deepseek-ai/DeepSeek-V4-Flash-0731 (konteks 380K, hingga 32.768 token output per jawaban). Jika Anda ingin memperkirakan biaya sebuah proses sebelum memulainya, itu pekerjaan yang berbeda, dan Cara memperkirakan biaya agen AI membahasnya. Artikel ini tentang mengukur dan membatasi saat proses berjalan.

Di mana angkanya: objek usage#

Setiap chat completion non-streaming dikembalikan dengan objek usage. Referensi API DeepSeek (diperiksa 26 Oktober 2026) mencantumkan field-field ini:

  • prompt_tokens — semua yang Anda kirim kali ini: system prompt, riwayat, hasil tool.
  • completion_tokens — apa yang ditulis model sebagai balasan.
  • total_tokens — keduanya dijumlahkan.

DeepSeek juga mendokumentasikan tambahan opsional: prompt_cache_hit_tokens dan prompt_cache_miss_tokens (keduanya berjumlah prompt_tokens), dan completion_tokens_details.reasoning_tokens untuk model thinking. Halaman tersebut tidak menunjukkan tanggal publikasi, dan tambahan ini adalah ekstensi dari format OpenAI, jadi kode di bawah memperlakukannya sebagai opsional dan hanya mengandalkan dua field pertama.

Mengapa mencatat setiap langkah dan bukan hanya yang terakhir? Karena agen mengirim ulang konteksnya yang terus bertambah setiap kali. Langkah 1 mungkin mengirim 2.000 token input, langkah 30 mungkin mengirim 9.000, dan tagihannya adalah jumlah dari semuanya. Alasannya dijelaskan di mengapa obrolan panjang lebih mahal, dan pembagian input/output di token input vs output.

Meter yang menghentikan agen#

Inilah keseluruhannya: sebuah meter yang menjumlahkan token, mencetak satu baris per langkah dan memunculkan error saat anggaran terlampaui, plus loop agen sederhana di sekitarnya. Instal SDK dengan pip install openai dan letakkan kunci Anda di CHEAPTOKENS_API_KEY.

python
import os
from openai import OpenAI

client = OpenAI(
    base_url='https://api.cheaptokens.dev/v1',
    api_key=os.environ['CHEAPTOKENS_API_KEY'],
)
MODEL = 'deepseek-ai/DeepSeek-V4-Flash-0731'

# example prices, USD per 1M tokens: use the current ones from the pricing table
PRICE_IN = 0.10
PRICE_OUT = 0.40


class BudgetExceeded(Exception):
    pass


class TaskMeter:
    def __init__(self, budget_usd):
        self.budget = budget_usd
        self.steps = 0
        self.tokens_in = 0
        self.tokens_out = 0
        self.reasoning = 0

    @property
    def cost(self):
        return (self.tokens_in * PRICE_IN + self.tokens_out * PRICE_OUT) / 1_000_000

    def add(self, usage):
        self.steps += 1
        self.tokens_in += usage.prompt_tokens
        self.tokens_out += usage.completion_tokens
        details = getattr(usage, 'completion_tokens_details', None)
        self.reasoning += getattr(details, 'reasoning_tokens', 0) or 0
        print(f'step {self.steps}: in={usage.prompt_tokens} '
              f'out={usage.completion_tokens} task=${self.cost:.4f}')
        if self.cost > self.budget:
            raise BudgetExceeded(
                f'budget ${self.budget:.2f} crossed at step {self.steps}: '
                f'${self.cost:.4f}')


def run_task(goal, budget_usd=0.50, max_steps=40):
    meter = TaskMeter(budget_usd)
    messages = [
        {'role': 'system', 'content': 'Work step by step. Reply DONE when finished.'},
        {'role': 'user', 'content': goal},
    ]
    for _ in range(max_steps):
        resp = client.chat.completions.create(
            model=MODEL, messages=messages, max_tokens=1024)
        meter.add(resp.usage)  # log first, then decide
        reply = resp.choices[0].message.content or ''
        messages.append({'role': 'assistant', 'content': reply})
        if 'DONE' in reply:
            break
        messages.append({'role': 'user', 'content': 'Continue.'})
    return meter


try:
    meter = run_task('Summarise the main risks of a database migration.')
    print(f'finished: {meter.steps} steps, ${meter.cost:.4f}')
except BudgetExceeded as err:
    print('stopped:', err)

Tiga pilihan di dalamnya layak untuk ditiru.

Catat sebelum memutuskan. meter.add mencatat langkah terlebih dahulu dan baru kemudian memeriksa anggaran, sehingga proses yang dihentikan tetap meninggalkan jejak yang lengkap. Pemeriksaan terjadi setelah panggilan yang melewati batas, jadi Anda bisa melebihi paling banyak satu langkah. max_tokens=1024 membatasi output dari langkah terakhir itu.

Dua penghentian keras, bukan satu. max_steps menangkap agen yang berulang tanpa banyak menghabiskan biaya; anggaran dolar menangkap agen yang menghabiskan banyak per langkah. Anda memerlukan keduanya.

Harga berada di satu tempat. PRICE_IN dan PRICE_OUT adalah angka placeholder. Salin nilai terkini untuk model Anda dari halaman harga; saat ini DeepSeek-V4-Flash adalah $0.015 per 1 juta token input dan $0.10 per 1 juta token output.

Berapa total dari proses 40 langkah#

Misalkan agen Anda mengambil 40 langkah, dan karena konteks bertambah, rata-rata langkah mengirim 6.000 token input dan menerima 400 token kembali. Itu berarti 40 × 6.000 = 240.000 token input dan 40 × 400 = 16.000 token output untuk tugas tersebut.

Langkah 1 mengirim 2.000 token input, langkah 30 mengirim 9.000; total tugas adalah jumlah dari semua langkah
Ilustrasi dengan asumsi artikel, bukan hasil proses

Pada DeepSeek-V4-Flash biayanya $0.0052. Tabel menjalankan beban kerja yang sama pada model lain dan menempatkan harga referensi OpenRouter di samping harga kami:

Model Biaya OpenRouter
GLM-5.3-Flash $0.0054 $0.0111
DeepSeek-V4-Flash $0.0052 $0.0139
MiniMax-M2.7 $0.0144 $0.0912

Total 240.000 token input dan 16.000 token output. Harga per 1 juta token adalah harga saat ini dan berubah seiring tarif kami; kolom OpenRouter menunjukkan harga referensi untuk beban kerja yang sama.

Secara total, dengan input dan output dihitung bersama, DeepSeek-V4-Flash lebih murah daripada OpenRouter untuk tugas ini. Perhatikan juga di mana tokennya berada: 240.000 dari 256.000 adalah input. Konteks yang dibawa agen Anda adalah tagihannya, itulah sebabnya angka in= per langkah di log Anda adalah yang perlu diperhatikan. Anggaran $0,50 per tugas dalam contoh di atas adalah batas untuk mencegah pembengkakan, bukan target.

Mengganti model hanya berarti mengubah MODEL. Pilih id dari dokumentasi CheapTokens: namanya berbeda antar penyedia, dan id pendek dari label harga tidak akan berfungsi di API. Untuk loop agen yang panjang, DeepSeek-V4-Flash memiliki satu harga pada jam berapa pun, jadi sebuah tugas berbiaya sama pada tengah hari dan pukul 3 pagi. Lihat halaman DeepSeek untuk batasannya.

Saat model sedang thinking#

Jika jawaban jauh lebih panjang dalam token daripada teks yang Anda lihat, periksa reasoning_tokens. Token thinking dihitung sebagai output, jadi langkah yang berat penalaran dapat menghasilkan token output jauh lebih banyak daripada yang disarankan teks yang terlihat, dan token tersebut ditagih sebagai output. Meter di atas mengumpulkannya di meter.reasoning saat API mengembalikan field tersebut dan membiarkannya 0 saat tidak, sehingga tidak pernah crash karena key yang hilang. Cetak di samping out= jika Anda ingin melihat berapa banyak output yang merupakan thinking. Upaya penalaran dan token thinking menjelaskannya.

Streaming: usage datang terakhir#

Jika agen Anda melakukan streaming, tidak ada usage di chunk normal. Dalam format OpenAI Anda memintanya dengan stream_options={'include_usage': True}. Referensi DeepSeek (diperiksa 26 Oktober 2026) menyatakan opsi tersebut hanya berfungsi bersama stream=True (jika tidak, API menjawab 400), bahwa usage adalah null di setiap chunk kecuali satu, dan bahwa chunk terakhir sebelum data: [DONE] membawa total untuk seluruh permintaan. Jadi dalam loop streaming, panggil meter.add sekali, pada chunk di mana usage tidak kosong. Loop non-streaming di atas adalah tempat paling sederhana untuk memulai; streaming di Python memiliki loop itu sendiri.

Jika angkanya terlihat salah#

  • usage adalah None. Anda melakukan streaming tanpa include_usage. Tambahkan, atau beralih ke panggilan non-streaming.
  • Totalnya lebih rendah daripada penurunan saldo. Periksa bahwa setiap panggilan melewati meter: percobaan ulang, panggilan peringkasan atau panggilan pemilihan tool yang dilakukan di luar run_task mudah terlewat. Bungkus client.chat.completions.create dalam satu fungsi dan arahkan semuanya melaluinya.
  • Biaya per langkah terus naik. Itu normal untuk loop yang menambahkan semuanya ke messages. Pangkas output tool lama atau ringkas riwayat; output tool di luar konteks menunjukkan idenya.
  • BudgetExceeded menyala pada langkah 2. Anggaran Anda lebih kecil daripada satu langkah. Periksa bahwa PRICE_IN adalah per 1 juta token, bukan per 1.000.

Untuk menyimpan angkanya, tulis meter.steps, meter.tokens_in, meter.tokens_out dan meter.cost sebagai satu baris JSON per tugas. Seminggu baris-baris tersebut memberi tahu Anda token nyata per langkah untuk agen Anda, yang merupakan angka untuk dimasukkan ke setiap estimasi setelahnya. Model, harga dan permintaan pertama ada di dokumentasi; panggilan tool dibahas di function calling di Python.