$ sudo teach IT

Каждый запрос к модели стоит денег и имеет предел по объёму. Если не понимать, из чего складывается цена и сколько текста помещается в один запрос, легко получить неприятные сюрпризы: агент, который в тестах стоил копейки, в работе съедает бюджет за неделю, а длинный документ просто не помещается в модель и запрос падает с ошибкой.

После урока вы сможете заранее прикинуть, сколько токенов займёт текст, поместится ли он в контекстное окно и во сколько обойдётся один запрос и тысяча запросов. Это базовый навык проектирования агента: решения «какую модель взять», «сколько шагов разрешить» и «сколько истории хранить» принимаются именно по этим цифрам.

Что уже умеем

В прошлом уроке вы узнали, что агент — это модель, инструкции, инструменты и цикл, в котором каждый шаг означает новое обращение к модели. Теперь посмотрим на модель с практической стороны: в каких единицах она измеряет текст и как эти единицы превращаются в деньги.

Что вы узнаете в рамках статьи

  • что такое токен и почему он не равен слову или символу;
  • как посчитать токены в Python с помощью библиотеки tiktoken;
  • что такое контекстное окно и что в него входит;
  • как рассчитать стоимость запроса по входным и выходным токенам;
  • почему расход токенов у агента растёт с каждым шагом.

Ключевые термины

  • Токен — кусочек текста, с которым работает модель: часть слова, целое слово, знак препинания или пробел.
  • Токенизатор — программа, которая разбивает текст на токены и превращает их в числа.
  • Входные токены (input tokens) — всё, что вы отправили модели: инструкции, вопрос, историю, описания инструментов.
  • Выходные токены (output tokens) — всё, что сгенерировала модель в ответ.
  • Контекстное окно — максимальное число токенов, которое модель обрабатывает за один запрос: вход и выход вместе.
  • Тариф — цена за миллион входных и миллион выходных токенов, у каждой модели своя.

Токены: как модель видит текст

Модель не читает буквы и слова так, как человек. Перед обработкой текст разбивается на токены — часто встречающиеся фрагменты. Короткое частое английское слово обычно занимает один токен, длинное или редкое слово распадается на несколько. Русский текст в среднем «дороже» английского: на то же содержание уходит больше токенов, потому что кириллических фрагментов в словаре токенизатора меньше.

Посчитать токены можно локально, без обращения к API, с помощью библиотеки tiktoken (pip install tiktoken):

import tiktoken

enc = tiktoken.get_encoding("o200k_base")  # кодировка современных моделей OpenAI

for text in ["Hello, world!", "Привет, мир!", "Контекстное окно модели"]:
    tokens = enc.encode(text)
    print(f"{text!r}: {len(text)} символов, {len(tokens)} токенов")

Что увидим в консоли: для каждой строки — число символов и число токенов. Английская фраза займёт около 4 токенов, русские — заметно больше на тот же смысл. Точные числа зависят от версии токенизатора, поэтому относитесь к локальному подсчёту как к хорошей оценке, а не к счёту из бухгалтерии: точное число токенов API сообщает в каждом ответе, это вы увидите в следующем уроке.

Для быстрых прикидок без кода пригодится грубое правило: в английском тексте токен в среднем около 4 символов, в русском — около 2–3. В задачах курса такое соотношение всегда будет указано в условии.

Контекстное окно: сколько помещается в один запрос

Модель не помнит ничего между запросами. Всё, что она должна учесть, — инструкции, вопрос пользователя, историю диалога, документы, описания инструментов — передаётся в каждом запросе заново. Предел этого объёма называется контекстным окном. Важная деталь: ответ модели тоже занимает место в окне. Если окно 128 000 токенов, а вход занял 127 000, на ответ останется всего 1 000.

CONTEXT_WINDOW = 128_000   # условный размер окна для примера

def fits(input_text: str, reserve_for_answer: int = 2_000) -> bool:
    used = len(enc.encode(input_text))
    free = CONTEXT_WINDOW - used
    print(f"Вход: {used} токенов, свободно: {free}")
    return free >= reserve_for_answer

report = "Квартальный отчёт... " * 5_000
print(fits(report))

Что увидим: число токенов во входе, сколько осталось свободно и True или False. Функция резервирует место под ответ: проверять нужно не «влезает ли вход», а «влезает ли вход вместе с ответом». Если текст не помещается, его нужно сократить или разбить на части — как это делать правильно, вы узнаете в модуле про RAG.

Даже когда текст влезает, не стоит заполнять окно до предела. Чем длиннее контекст, тем дороже запрос, тем дольше ждать ответа и тем выше риск, что модель упустит важную деталь из середины.

Стоимость: входные и выходные токены

Провайдер берёт плату отдельно за входные и выходные токены, причём выходные обычно дороже в несколько раз: генерировать текст сложнее, чем читать. Тариф указывают за миллион токенов. В примерах курса используем учебную модель gpt-6-luna с ценами $0.10 за 1M входных и $0.50 за 1M выходных токенов.

Формула стоимости одного запроса:

PRICE_IN = 0.10    # долларов за 1M входных токенов
PRICE_OUT = 0.50   # долларов за 1M выходных токенов

def request_cost(input_tokens: int, output_tokens: int) -> float:
    return (input_tokens * PRICE_IN + output_tokens * PRICE_OUT) / 1_000_000

one = request_cost(3_000, 500)
print(f"Один запрос: ${one:.6f}")
print(f"10 000 запросов: ${one * 10_000:.2f}")

Что увидим в консоли:

Один запрос: $0.000550
10 000 запросов: $5.50

Один запрос стоит доли цента, но умножение на реальный поток обращений быстро даёт ощутимые суммы. Обратите внимание на соотношение: 3 000 входных токенов обошлись в $0.0003, а 500 выходных — в $0.00025. Длинный ответ стоит почти столько же, сколько вшестеро более длинный вход.

Почему агент расходует больше токенов, чем кажется

Вспомните цикл агента: модель решает, программа вызывает инструмент, результат добавляется в историю, и модель вызывается снова — со всей историей. Значит, каждый следующий запрос длиннее предыдущего, а входные токены оплачиваются заново на каждом шаге.

base = 1_000          # инструкции + вопрос пользователя
step_growth = 500     # решение модели + результат инструмента
total_input = 0

for step in range(1, 5):
    tokens = base + step_growth * (step - 1)
    total_input += tokens
    print(f"Шаг {step}: на вход {tokens} токенов")

print(f"Всего входных токенов: {total_input}")

Что увидим: 1 000, 1 500, 2 000 и 2 500 токенов на шагах, а в сумме 7 000 — в семь раз больше, чем исходный вопрос. Поэтому лимит шагов в агенте защищает не только от зацикливания, но и от лишних расходов, а длинные результаты инструментов лучше сокращать до того, как отдавать их модели.

Частые ошибки

  • Считать токены словами. Токен — не слово и не символ. Русский текст из 100 слов может занять 200 токенов и больше, поэтому оценивайте объём токенизатором или соотношением символов к токенам.
  • Забывать про место под ответ. Контекстное окно делят вход и выход. Если вход занял почти всё окно, ответ оборвётся или запрос не выполнится.
  • Считать только входные токены. Выходные токены дороже. Просьба «ответь подробно» может удвоить стоимость запроса.
  • Оценивать агента по одному запросу. Агент делает несколько запросов, и каждый следующий длиннее предыдущего. Считайте суммарные токены по всем шагам.

Наиболее частые вопросы

  • Почему на русском запросы дороже? — Токенизатор обучен в основном на английских текстах, поэтому русские слова разбиваются на большее число фрагментов, а платите вы за токены.
  • Насколько точен подсчёт через tiktoken? — Это хорошая оценка для планирования. Точные числа по факту запроса API возвращает в поле usage ответа.
  • Если модель «помнит» диалог в чате, зачем передавать историю? — Модель ничего не хранит между запросами. Ощущение памяти создаёт программа, которая каждый раз отправляет историю заново, и эта история оплачивается.
  • Где узнать размер окна и цены конкретной модели? — На странице модели в документации провайдера. Цены меняются, поэтому в расчётах всегда опирайтесь на актуальный тариф.

Итоги

Отличная работа! Теперь вы смотрите на запрос к модели глазами инженера: знаете, что текст измеряется токенами, что контекстное окно общее для вопроса и ответа, и умеете по тарифу посчитать стоимость одного запроса и целого потока обращений. Вы также понимаете, почему агент с каждым шагом расходует всё больше токенов и зачем ему лимит.

В следующем уроке вы наконец отправите первый настоящий запрос к модели через Responses API: подключите ключ, выберете модель, зададите инструкции и увидите, как API сообщает точное число потраченных токенов.

На следующий урок