ब्लॉग पर वापस जाएं

API और SDKगाइड

Python में AI एजेंट टोकन लागत ट्रैक करें: usage, बजट, स्टॉप

हर अनुरोध के usage फ़ील्ड को लॉग करें, इसे प्रति कार्य जोड़ें और डॉलर बजट पर एजेंट रोकें। OpenAI-संगत API के लिए कार्यशील Python उदाहरण।

CheapTokens Team द्वाराप्रकाशित 10 मिनट का पाठ

टर्मिनल-शैली कोड कार्ड: प्रति-चरण usage लॉग और एक बजट जाँच जो AI एजेंट को रोकती है
इस पृष्ठ पर
  1. संख्याएँ कहाँ हैं: usage ऑब्जेक्ट
  2. एक मीटर जो एजेंट को रोकता है
  3. 40-चरणीय रन का योग क्या होता है
  4. जब मॉडल सोच रहा हो
  5. स्ट्रीमिंग: usage अंत में आता है
  6. यदि संख्याएँ गलत लगें

आपका एजेंट दस मिनट तक चला और बिल काम से बड़ा है। इसका कारण देखने के लिए, हर API प्रतिक्रिया में usage ऑब्जेक्ट पढ़ें, इसे प्रति कार्य जोड़ें और मॉडल की प्रति 1M टोकन कीमत से गुणा करें। इसे सीमित करने के लिए, प्रत्येक चरण के बाद उस चल रहे कुल की तुलना बजट से करें और सीमा पार होने पर लूप रोक दें। नीचे एक छोटा Python क्लास है जो ठीक यही करता है।

उदाहरण OpenAI-संगत एंडपॉइंट https://api.cheaptokens.dev/v1 और मॉडल आईडी deepseek-ai/DeepSeek-V4-Flash-0731 का उपयोग करता है (380K संदर्भ, प्रति उत्तर अधिकतम 32,768 आउटपुट टोकन)। यदि आप रन शुरू करने से पहले अनुमान लगाना चाहते हैं, तो वह अलग काम है, और How to estimate the cost of an AI agent इसे कवर करता है। यह लेख रन के दौरान मापने और सीमित करने के बारे में है।

संख्याएँ कहाँ हैं: usage ऑब्जेक्ट#

हर नॉन-स्ट्रीमिंग चैट पूर्णता usage ऑब्जेक्ट के साथ वापस आती है। DeepSeek का API संदर्भ (26 अक्टूबर 2026 को जाँचा गया) इन फ़ील्ड्स को सूचीबद्ध करता है:

  • prompt_tokens — इस बार आपने जो कुछ भी भेजा: सिस्टम प्रॉम्प्ट, इतिहास, टूल परिणाम।
  • completion_tokens — मॉडल ने जो वापस लिखा।
  • total_tokens — दोनों को जोड़कर।

DeepSeek वैकल्पिक अतिरिक्त भी दस्तावेज़ित करता है: prompt_cache_hit_tokens और prompt_cache_miss_tokens (वे prompt_tokens तक जोड़ते हैं), और थिंकिंग मॉडल के लिए completion_tokens_details.reasoning_tokens। पृष्ठ कोई प्रकाशन तिथि नहीं दिखाता, और ये अतिरिक्त OpenAI प्रारूप के विस्तार हैं, इसलिए नीचे दिया गया कोड उन्हें वैकल्पिक मानता है और केवल पहले दो फ़ील्ड्स पर निर्भर करता है।

प्रत्येक चरण को लॉग क्यों करें और केवल अंतिम को नहीं? क्योंकि एक एजेंट हर बार अपना बढ़ता संदर्भ फिर से भेजता है। चरण 1 शायद 2,000 इनपुट टोकन भेजे, चरण 30 शायद 9,000 भेजे, और बिल उन सभी का योग है। कारण why a long chat costs more में समझाया गया है, और इनपुट/आउटपुट विभाजन input vs output tokens में।

एक मीटर जो एजेंट को रोकता है#

यहाँ पूरी बात है: एक मीटर जो टोकन जोड़ता है, प्रति चरण एक पंक्ति प्रिंट करता है और बजट पार होने पर त्रुटि उठाता है, साथ ही उसके चारों ओर एक बेयर एजेंट लूप। SDK को pip install openai से इंस्टॉल करें और अपनी कुंजी 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)

वहाँ तीन विकल्प कॉपी करने योग्य हैं।

निर्णय लेने से पहले लॉग करें। meter.add पहले चरण को रिकॉर्ड करता है और उसके बाद ही बजट की जाँच करता है, इसलिए रुका हुआ रन भी पूरा ट्रेस छोड़ता है। जाँच उस कॉल के बाद होती है जिसने रेखा पार की, इसलिए आप अधिकतम एक चरण तक ओवरशूट कर सकते हैं। max_tokens=1024 उस अंतिम चरण के आउटपुट को सीमित करता है।

दो हार्ड स्टॉप, एक नहीं। max_steps उस एजेंट को पकड़ता है जो बहुत खर्च किए बिना लूप करता है; डॉलर बजट उसे पकड़ता है जो प्रति चरण बहुत खर्च करता है। आपको दोनों चाहिए।

कीमतें एक ही जगह रहती हैं। PRICE_IN और PRICE_OUT प्लेसहोल्डर संख्याएँ हैं। अपने मॉडल के लिए वर्तमान मान pricing page से कॉपी करें; अभी DeepSeek-V4-Flash प्रति 1M इनपुट टोकन $0.015 और प्रति 1M आउटपुट टोकन $0.10 है।

40-चरणीय रन का योग क्या होता है#

मान लें कि आपका एजेंट 40 चरण लेता है, और संदर्भ बढ़ने के कारण, औसत चरण 6,000 इनपुट टोकन भेजता है और 400 टोकन वापस पाता है। यह कार्य के लिए 40 × 6,000 = 240,000 इनपुट टोकन और 40 × 400 = 16,000 आउटपुट टोकन है।

Step 1 sends 2,000 input tokens, step 30 sends 9,000; the task total is the sum of all steps
Illustration with the article's assumptions, not a run result

DeepSeek-V4-Flash पर इसकी लागत $0.0052 है। तालिका वही कार्यभार अन्य मॉडलों पर चलाती है और OpenRouter की संदर्भ कीमत को हमारी कीमत के बगल में रखती है:

मॉडल लागत OpenRouter
GLM-5.3-Flash $0.0054 $0.0111
DeepSeek-V4-Flash $0.0052 $0.0139
MiniMax-M2.7 $0.0144 $0.0912

कुल 2,40,000 इनपुट और 16,000 आउटपुट टोकन। प्रति 1M टोकन की कीमतें वर्तमान हैं और हमारे टैरिफ के साथ बदलती रहती हैं; OpenRouter कॉलम समान कार्यभार के लिए संदर्भ कीमतें दिखाता है।

कुल मिलाकर, इनपुट और आउटपुट को एक साथ गिनते हुए, इस कार्य के लिए DeepSeek-V4-Flash OpenRouter से सस्ता निकलता है। यह भी ध्यान दें कि टोकन कहाँ हैं: 256,000 में से 240,000 इनपुट हैं। आपका एजेंट जो संदर्भ साथ ले जाता है वही बिल है, इसलिए आपके लॉग में प्रति-चरण in= संख्या देखने वाली है। ऊपर के उदाहरण में प्रति कार्य $0.50 का बजट एक भागते हुए को सीमित करना है, लक्ष्य नहीं।

मॉडल बदलने का मतलब केवल MODEL बदलना है। आईडी CheapTokens docs से चुनें: नाम प्रदाताओं के बीच भिन्न होते हैं, और मूल्य लेबल से एक छोटा आईडी API में काम नहीं करेगा। लंबे एजेंट लूप के लिए, DeepSeek-V4-Flash की दिन के किसी भी घंटे एक ही कीमत है, इसलिए एक कार्य की लागत दोपहर और सुबह 3 बजे समान होती है। इसकी सीमाओं के लिए DeepSeek page देखें।

जब मॉडल सोच रहा हो#

यदि कोई उत्तर टोकन में आपके देखे गए टेक्स्ट से बहुत लंबा है, तो reasoning_tokens देखें। थिंकिंग टोकन आउटपुट के रूप में गिने जाते हैं, इसलिए तर्क-भारी चरण दृश्यमान टेक्स्ट की तुलना में बहुत अधिक आउटपुट टोकन उत्पन्न कर सकता है, और उन्हें आउटपुट के रूप में बिल किया जाता है। ऊपर का मीटर उन्हें meter.reasoning में एकत्र करता है जब API फ़ील्ड लौटाता है और जब नहीं लौटाता तो इसे 0 पर छोड़ देता है, इसलिए यह कभी भी गुम कुंजी पर क्रैश नहीं होता। यदि आप देखना चाहते हैं कि आउटपुट का कितना हिस्सा सोच था, तो इसे out= के बगल में प्रिंट करें। Reasoning effort and thinking tokens कारण बताता है।

स्ट्रीमिंग: usage अंत में आता है#

यदि आपका एजेंट स्ट्रीम करता है, तो सामान्य चंक्स में usage नहीं होता। OpenAI प्रारूप में आप इसे stream_options={'include_usage': True} के साथ माँगते हैं। DeepSeek का संदर्भ (26 अक्टूबर 2026 को जाँचा गया) कहता है कि विकल्प केवल stream=True के साथ काम करता है (अन्यथा API 400 उत्तर देता है), कि usage हर चंक में null है सिवाय एक के, और कि data: [DONE] से पहले का अंतिम चंक पूरे अनुरोध के कुल योग रखता है। इसलिए स्ट्रीमिंग लूप में, meter.add को एक बार कॉल करें, उस चंक पर जहाँ usage खाली नहीं है। ऊपर का नॉन-स्ट्रीमिंग लूप शुरू करने के लिए सबसे सरल जगह है; streaming in Python में लूप स्वयं है।

यदि संख्याएँ गलत लगें#

  • usage None है। आप include_usage के बिना स्ट्रीम कर रहे हैं। इसे जोड़ें, या नॉन-स्ट्रीमिंग कॉल पर स्विच करें।
  • कुल शेष राशि की गिरावट से कम है। जाँचें कि हर कॉल मीटर से गुज़रती है: पुनः प्रयास, एक सारांश कॉल या run_task के बाहर किया गया टूल-चयन कॉल छूट सकते हैं। client.chat.completions.create को एक फ़ंक्शन में लपेटें और सब कुछ उसी से रूट करें।
  • प्रति चरण लागत बढ़ती जा रही है। यह उस लूप के लिए सामान्य है जो सब कुछ messages में जोड़ता है। पुराने टूल आउटपुट को ट्रिम करें या इतिहास का सारांश बनाएँ; tool output out of context विचार दिखाता है।
  • BudgetExceeded चरण 2 पर सक्रिय होता है। आपका बजट एक चरण से छोटा है। जाँचें कि PRICE_IN प्रति 1M टोकन है, प्रति 1K नहीं।

संख्याओं को संग्रहीत करने के लिए, meter.steps, meter.tokens_in, meter.tokens_out और meter.cost को प्रति कार्य एक JSON पंक्ति के रूप में लिखें। उन पंक्तियों का एक सप्ताह आपको आपके एजेंट के लिए प्रति चरण वास्तविक टोकन बताता है, जो बाद में हर अनुमान में डालने वाली संख्या है। मॉडल, कीमतें और पहला अनुरोध docs में हैं; टूल कॉल function calling in Python में कवर किए गए हैं।