Bloga dön

API ve SDKKılavuz

Python'da AI ajanı token maliyetini izleme: usage, bütçe, durdurma

Her isteğin usage alanını günlüğe kaydedin, görev başına toplayın ve ajanı bir dolar bütçesinde durdurun. OpenAI uyumlu bir API için çalışan Python örneği.

Yazan: CheapTokens TeamYayınlanma tarihi: 5 dk okuma

Terminal tarzı kod kartı: adım başına usage günlüğü ve bir AI ajanını durduran bütçe kontrolü
Bu sayfada
  1. Sayılar nerede: usage nesnesi
  2. Ajanı durduran bir sayaç
  3. 40 adımlık bir çalıştırma neye varır
  4. Model düşünürken
  5. Akış (streaming): usage en sonda gelir
  6. Sayılar yanlış görünüyorsa

Ajanınız on dakika çalıştı ve fatura görevden daha büyük. Nedenini görmek için her API yanıtındaki usage nesnesini okuyun, görev başına toplayın ve modelin 1M token başına fiyatıyla çarpın. Bunu sınırlamak için, bu çalışan toplamı her adımdan sonra bir bütçeyle karşılaştırın ve aşıldığında döngüyü durdurun. Aşağıda tam olarak bunu yapan küçük bir Python sınıfı var.

Örnek, OpenAI uyumlu https://api.cheaptokens.dev/v1 uç noktasını ve deepseek-ai/DeepSeek-V4-Flash-0731 model kimliğini kullanır (380K bağlam, yanıt başına 32.768'e kadar çıktı token'ı). Bir çalıştırmayı başlatmadan önce tahmin etmek istiyorsanız, bu farklı bir iştir ve Bir AI ajanının maliyeti nasıl tahmin edilir bunu ele alır. Bu makale, çalışma sürerken ölçme ve sınırlama hakkındadır.

Sayılar nerede: usage nesnesi#

Akış (streaming) olmayan her sohbet tamamlama, bir usage nesnesiyle döner. DeepSeek'in API referansı (26 Ekim 2026'da kontrol edildi) şu alanları listeler:

  • prompt_tokens — bu sefer gönderdiğiniz her şey: sistem istemi, geçmiş, araç sonuçları.
  • completion_tokens — modelin geri yazdığı.
  • total_tokens — ikisinin toplamı.

DeepSeek ayrıca isteğe bağlı ekstraları belgeler: prompt_cache_hit_tokens ve prompt_cache_miss_tokens (toplamları prompt_tokens eder) ve düşünen modeller için completion_tokens_details.reasoning_tokens. Sayfada yayın tarihi yok ve bu ekstralar OpenAI formatının uzantılarıdır, bu nedenle aşağıdaki kod onları isteğe bağlı olarak ele alır ve yalnızca ilk iki alana dayanır.

Neden sadece son adımı değil de her adımı günlüğe kaydetmelisiniz? Çünkü bir ajan her seferinde büyüyen bağlamını yeniden gönderir. 1. adım 2.000 girdi token'ı gönderebilir, 30. adım 9.000 gönderebilir ve fatura hepsinin toplamıdır. Nedeni uzun bir sohbet neden daha pahalıdır ve girdi/çıktı ayrımı girdi ve çıktı token'ları içinde açıklanmıştır.

Ajanı durduran bir sayaç#

İşte tamamı: token'ları toplayan, adım başına bir satır yazdıran ve bütçe aşıldığında hata veren bir sayaç, artı etrafında basit bir ajan döngüsü. SDK'yı pip install openai ile kurun ve anahtarınızı CHEAPTOKENS_API_KEY içine koyun.

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)

Oradaki üç seçim kopyalanmaya değer.

Karar vermeden önce günlüğe kaydedin. meter.add önce adımı kaydeder ve ancak sonra bütçeyi kontrol eder, böylece durdurulan bir çalıştırma yine de eksiksiz bir iz bırakır. Kontrol, çizgiyi aşan çağrıdan sonra gerçekleşir, bu nedenle en fazla bir adım aşabilirsiniz. max_tokens=1024 o son adımın çıktısını sınırlar.

İki sert durdurma, bir değil. max_steps çok harcamadan döngüye giren bir ajanı yakalar; dolar bütçesi adım başına çok harcayanı yakalar. İkisini de istersiniz.

Fiyatlar tek bir yerde yaşar. PRICE_IN ve PRICE_OUT yer tutucu sayılardır. Modeliniz için güncel değerleri fiyatlandırma sayfasından kopyalayın; şu anda DeepSeek-V4-Flash 1M girdi token'ı başına $0.015 ve 1M çıktı token'ı başına $0.10.

40 adımlık bir çalıştırma neye varır#

Diyelim ki ajanınız 40 adım atıyor ve bağlam büyüdüğü için ortalama bir adım 6.000 girdi token'ı gönderip 400 token geri alıyor. Bu, görev için 40 × 6.000 = 240.000 girdi token'ı ve 40 × 400 = 16.000 çıktı token'ıdır.

1. adım 2.000 girdi token'ı gönderir, 30. adım 9.000 gönderir; görev toplamı tüm adımların toplamıdır
Makalenin varsayımlarıyla illüstrasyon, bir çalıştırma sonucu değil

DeepSeek-V4-Flash'te bu $0.0052 tutar. Tablo aynı iş yükünü diğer modellerde çalıştırır ve OpenRouter'ın referans fiyatını bizimkinin yanına koyar:

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

Toplamda 240.000 giriş ve 16.000 çıkış token'ı. 1M token başına fiyatlar günceldir ve tarifelerimizle birlikte değişir; OpenRouter sütunu aynı iş yükü için referans fiyatları gösterir.

Toplamda, girdi ve çıktı birlikte sayıldığında, bu görev için DeepSeek-V4-Flash OpenRouter'dan daha ucuz çıkıyor. Token'ların nerede olduğuna da dikkat edin: 256.000'in 240.000'i girdi. Ajanınızın peşinden sürüklediği bağlam faturadır, bu yüzden günlüğünüzdeki adım başına in= sayısı izlenecek sayıdır. Yukarıdaki örnekte görev başına 0,50 $ bütçe bir hedef değil, kontrolden çıkmaya karşı bir sınırdır.

Model değiştirmek yalnızca MODEL değiştirmek anlamına gelir. Kimliği CheapTokens belgelerinden seçin: adlar sağlayıcılar arasında farklılık gösterir ve bir fiyat etiketinden alınan kısa bir kimlik API'de çalışmaz. Uzun ajan döngüleri için DeepSeek-V4-Flash günün her saatinde tek bir fiyata sahiptir, bu nedenle bir görev öğlen de sabah 3'te de aynı maliyettedir. Sınırları için DeepSeek sayfasına bakın.

Model düşünürken#

Bir yanıt token olarak gördüğünüz metinden çok daha uzunsa, reasoning_tokens değerine bakın. Düşünme token'ları çıktı olarak sayılır, bu nedenle akıl yürütme ağırlıklı bir adım görünen metnin ima ettiğinden çok daha fazla çıktı token'ı üretebilir ve çıktı olarak faturalandırılır. Yukarıdaki sayaç, API alanı döndürdüğünde onları meter.reasoning içinde toplar ve döndürmediğinde 0'da bırakır, böylece eksik bir anahtarda asla çökmez. Çıktının ne kadarının düşünme olduğunu görmek istiyorsanız out= yanına yazdırın. Akıl yürütme çabası ve düşünme token'ları nedenini açıklar.

Akış (streaming): usage en sonda gelir#

Ajanınız akış yapıyorsa, normal parçalarda usage yoktur. OpenAI formatında bunu stream_options={'include_usage': True} ile istersiniz. DeepSeek'in referansı (26 Ekim 2026'da kontrol edildi), seçeneğin yalnızca stream=True ile birlikte çalıştığını (aksi halde API 400 yanıtı verir), usage değerinin biri hariç her parçada null olduğunu ve data: [DONE] öncesindeki son parçanın tüm istek için toplamları taşıdığını söyler. Yani bir akış döngüsünde, usage boş olmayan parçada meter.add bir kez çağırın. Yukarıdaki akışsız döngü başlamak için en basit yerdir; Python'da akış döngünün kendisini içerir.

Sayılar yanlış görünüyorsa#

  • usage None. include_usage olmadan akış yapıyorsunuz. Ekleyin veya akışsız bir çağrıya geçin.
  • Toplam, bakiye düşüşünden düşük. Her çağrının sayaçtan geçtiğini kontrol edin: yeniden denemeler, bir özetleme çağrısı veya run_task dışında yapılan bir araç seçme çağrısı kolayca gözden kaçar. client.chat.completions.create tek bir fonksiyona sarın ve her şeyi onun üzerinden yönlendirin.
  • Adım başına maliyet tırmanmaya devam ediyor. Her şeyi messages içine ekleyen bir döngü için bu normaldir. Eski araç çıktısını kırpın veya geçmişi özetleyin; araç çıktısını bağlam dışında tutmak fikri gösterir.
  • BudgetExceeded 2. adımda tetikleniyor. Bütçeniz bir adımdan küçük. PRICE_IN değerinin 1K başına değil 1M token başına olduğunu kontrol edin.

Sayıları saklamak için, görev başına bir JSON satırı olarak meter.steps, meter.tokens_in, meter.tokens_out ve meter.cost yazın. Bu satırlardan bir haftası, ajanınız için adım başına gerçek token'ları söyler; bu da sonraki her tahmine konulacak sayıdır. Modeller, fiyatlar ve ilk istek belgelerde; araç çağrıları Python'da fonksiyon çağırma içinde ele alınmıştır.