API та SDKПосібник
Відстеження вартості токенів AI-агента в Python: usage, бюджет, зупинка
Реєструйте поле usage кожного запиту, підсумовуйте його за задачею та зупиняйте агента при бюджеті в доларах. Робочий приклад Python для сумісного з OpenAI API.

На цій сторінці
Ваш агент працював десять хвилин, а рахунок більший за саму задачу. Щоб зрозуміти чому, читайте об'єкт usage у кожній відповіді API, підсумовуйте його за задачею та множте на ціну моделі за 1M токенів. Щоб обмежити витрати, порівнюйте цю поточну суму з бюджетом після кожного кроку та зупиняйте цикл, коли її перевищено. Нижче наведено невеликий клас Python, який робить саме це.
У прикладі використовується сумісна з OpenAI кінцева точка https:/ та ідентифікатор моделі deepseek- (контекст 380K, до 32 768 вихідних токенів на відповідь). Якщо ви хочете оцінити запуск перед його початком, це інше завдання, і Як оцінити вартість AI-агента розповідає про це. Ця стаття про вимірювання та обмеження під час виконання.
Де знаходяться числа: об'єкт usage#
Кожне нестрімінгове завершення чату повертається з об'єктом usage. Довідка API DeepSeek (перевірено 26 жовтня 2026) перелічує ці поля:
prompt_tokens— усе, що ви надіслали цього разу: системний запит, історія, результати інструментів.completion_— те, що модель написала у відповідь.tokens total_tokens— ці два додані разом.
DeepSeek також документує необов'язкові додатки: prompt_ та prompt_ (вони додаються до prompt_tokens), і completion_ для моделей мислення. На сторінці не вказано дату публікації, і ці додатки є розширеннями формату OpenAI, тому код нижче вважає їх необов'язковими та покладається лише на перші два поля.
Чому реєструвати кожен крок, а не лише останній? Тому що агент повторно надсилає свій зростаючий контекст щоразу. Крок 1 може надіслати 2 000 вхідних токенів, крок 30 може надіслати 9 000, і рахунок — це сума всіх їх. Причину пояснено в чому довгий чат коштує більше, а розподіл вхідних/вихідних даних — у вхідні проти вихідних токенів.
Лічильник, який зупиняє агента#
Ось усе: лічильник, який підсумовує токени, виводить один рядок на крок і викликає помилку, коли бюджет перевищено, плюс голий цикл агента навколо нього. Встановіть SDK за допомогою pip install openai і помістіть свій ключ у CHEAPTOKENS_.
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 — це числа-заповнювачі. Скопіюйте поточні значення для вашої моделі з сторінки цін; наразі DeepSeek-V4-Flash коштує $0.015 за 1M вхідних токенів і $0.10 за 1M вихідних токенів.
Що дає запуск на 40 кроків#
Припустімо, ваш агент робить 40 кроків, і через зростання контексту середній крок надсилає 6 000 вхідних токенів і отримує 400 токенів у відповідь. Це 40 × 6 000 = 240 000 вхідних токенів і 40 × 400 = 16 000 вихідних токенів для задачі.

На DeepSeek-V4-Flash це коштує $0.0052. Таблиця виконує те саме навантаження на інших моделях і ставить довідкову ціну OpenRouter поруч із нашою:
| Модель | Вхід $/1М | Вихід $/1М | Вартість | OpenRouter |
|---|---|---|---|---|
| GLM-5.3-Flash | $0.02 | $0.04 | $0.0054 | $0.0111 |
| DeepSeek-V4-Flash | $0.015 | $0.10 | $0.0052 | $0.0139 |
| MiniMax-M2.7 | $0.05 | $0.15 | $0.0144 | $0.0912 |
240 000 вхідних і 16 000 вихідних токенів загалом. Ціни за 1 млн токенів актуальні та змінюються разом із нашими тарифами; стовпець OpenRouter показує довідкові ціни для того самого навантаження.
Загалом, з урахуванням вхідних і вихідних даних разом, DeepSeek-V4-Flash виходить дешевшим за OpenRouter для цієї задачі. Зверніть увагу також, де знаходяться токени: 240 000 з 256 000 — це вхідні. Контекст, який тягне за собою ваш агент, і є рахунком, тому число in= на крок у вашому журналі — це те, за чим слід стежити. Бюджет $0.50 за задачу в наведеному прикладі — це обмеження на розбіг, а не ціль.
Зміна моделі означає лише зміну MODEL. Виберіть ідентифікатор з документації CheapTokens: назви відрізняються між постачальниками, і короткий ідентифікатор з цінника не працюватиме в API. Для довгих циклів агента DeepSeek-V4-Flash має одну ціну в будь-яку годину дня, тому задача коштує однаково опівдні та о 3 ночі. Дивіться сторінку DeepSeek щодо її обмежень.
Коли модель думає#
Якщо відповідь набагато довша в токенах, ніж текст, який ви бачите, подивіться на reasoning_tokens. Токени мислення враховуються як вихідні, тому крок з інтенсивним міркуванням може створити набагато більше вихідних токенів, ніж припускає видимий текст, і вони оплачуються як вихідні. Лічильник вище збирає їх у meter.reasoning, коли API повертає поле, і залишає його на 0, коли ні, тому він ніколи не падає через відсутній ключ. Виведіть його поруч із out=, якщо хочете побачити, скільки з вихідних даних було мисленням. Зусилля міркування та токени мислення пояснює чому.
Стрімінг: usage надходить останнім#
Якщо ваш агент використовує стрімінг, у звичайних фрагментах немає usage. У форматі OpenAI ви запитуєте його за допомогою stream_. Довідка DeepSeek (перевірено 26 жовтня 2026) каже, що опція працює лише разом із stream=True (інакше API відповідає 400), що usage дорівнює null у кожному фрагменті, крім одного, і що останній фрагмент перед data: [DONE] несе підсумки для всього запиту. Тому в циклі стрімінгу викликайте meter.add один раз, на фрагменті, де usage не порожній. Нестрімінговий цикл вище — найпростіше місце для початку; стрімінг у Python містить сам цикл.
Якщо числа виглядають неправильно#
usageмає значення None. Ви використовуєте стрімінг безinclude_usage. Додайте його або перейдіть на нестрімінговий виклик.- Сума нижча за падіння балансу. Перевірте, що кожен виклик проходить через лічильник: повторні спроби, виклик підсумовування або виклик вибору інструменту, зроблений поза
run_task, легко пропустити. Обгорнітьclient.в одну функцію та спрямуйте все через неї.chat. completions. create - Вартість за крок продовжує зростати. Це нормально для циклу, який додає все до
messages. Обрізайте старі виводи інструментів або підсумовуйте історію; вивід інструменту поза контекстом показує ідею. BudgetExceededспрацьовує на кроці 2. Ваш бюджет менший за один крок. Перевірте, щоPRICE_INвказано за 1M токенів, а не за 1K.
Щоб зберігати числа, записуйте meter.steps, meter.tokens_in, meter.tokens_out та meter.cost як один рядок JSON на задачу. Тиждень таких рядків розповість вам реальні токени на крок для вашого агента, і саме це число слід вставляти в кожну подальшу оцінку. Моделі, ціни та перший запит — у документації; виклики інструментів розглянуто в виклику функцій у Python.



