Коротко
На формальной задаче - «вытащи из документа поля и верни JSON» - модели дают одинаковый результат, а счета отличаются в разы. Четыре модели вернули по моему тестовому счёту побайтово те же значения. Списание за один документ: 0,069 ₽ у самой дешёвой и 0,82 ₽ у самой дорогой - разница почти в двенадцать раз, и в тексте ответа она никак не видна.
Ниже - что я собрал, сколько это стоило, и три грабли, на которые я налетел в день замера:
- невидимые токены рассуждения, за которые платят как за обычные;
max_tokens, который выставлен, но не соблюдён;- половина каталога, которая в тот день просто не отвечала.
Все числа сняты 23.08.2026, курс ЦБ 82,9211 ₽/$ на 22.08.2026.
Задача: счета, которые никто не хочет вбивать руками
У меня в проекте копятся входящие счета: номер, дата, поставщик, ИНН, сумма, срок оплаты, позиции. Всё это надо превратить в строки в базе. Раньше это делал человек, и делал ровно так, как делают люди: быстро, пока их десять в месяц, и с ошибками, когда их сорок.
Требований было три:
- на выходе строгий JSON, который парсер съедает без регулярок;
- цена предсказуемая, потому что счетов будет не сорок, а тысячи;
- никаких плейсхолдеров вроде
<СУММА>- модель обязана либо дать число, либоnull.
Задача формальная: рассуждать тут не о чем, нужно аккуратно переписать поля. Значит, дорогая модель не должна давать выигрыша - это я и пошёл проверять.
Как это собрано
Код целиком - двадцать строк. Один OpenAI-совместимый клиент, у которого меняется только имя модели.
import json, os
from openai import OpenAI
client = OpenAI(base_url="https://api.altrouter.ai/v1", api_key=os.environ["AR_KEY"])
PROMPT = """Извлеки из счёта поля и верни СТРОГО JSON без пояснений:
{"number": str, "date": "YYYY-MM-DD", "supplier": str, "inn": str,
"total": float, "due_date": "YYYY-MM-DD", "items": [{"name": str, "sum": float}]}
Если поля нет - null. Никаких плейсхолдеров вида <ЗНАЧЕНИЕ>.
СЧЁТ:
"""
def parse(doc: str, model: str) -> dict:
r = client.chat.completions.create(
model=model, messages=[{"role": "user", "content": PROMPT + doc}])
return json.loads(r.choices[0].message.content)
Дальше - три прогона на каждую модель одним и тем же счётом на 100 500 ₽ с двумя позициями. JSON распарсился с первого раза у всех четырёх моделей, и значения совпали до последнего поля: номер, дата, ИНН, обе позиции, сумма. Ни одного плейсхолдера, ни одного «вот ваш JSON:» перед скобкой.
Что списалось за один документ
| Модель | Время, с | Токенов выхода | Один счёт, ₽ | 1000 счетов, ₽ |
|---|---|---|---|---|
| gpt-5.6-mini | 4,8–5,2 | 122–126 | 0,069–0,071 | ~70 |
| gemini-3-pro | 11,3–13,1 | 147 | 0,080 | ~80 |
| gpt-5.2 | 14,4–29,1 | 102 | 0,142 | ~142 |
| grok-4.3 | 16,2–39,0 | 2327–4408 | 0,45–0,82 | ~450–820 |
Токен - кусочек текста, которым модель меряет вход и выход; платят именно за них. Цены - то, что реально списалось с баланса на 23.08.2026, по три прогона на модель.
Вывод для моей задачи простой: самая дешёвая модель закрывает её полностью, и переплата ничего не покупает.

Грабля 1: токены, которых нет в ответе
Самое интересное - четвёртая строка. grok-4.3 вернул тот же самый JSON на 331 символ, что и gemini-3-pro. Но в usage у него от 2327 до 4408 токенов выхода против 147 у Gemini - при одинаковом видимом тексте.
Это токены рассуждения: модель думает «про себя», в ответ эти рассуждения не попадают, а в счёт попадают.

Практический вывод: сравнивая модели, смотрите не на текст ответа, а на usage - поле, которое API возвращает вместе с ответом. Оно одно объясняет, почему два одинаковых JSON стоят по-разному.
Грабля 2: max_tokens выставлен, но не соблюдён
Логичная защита от такого - поставить потолок на длину ответа. Я поставил max_tokens=40 и повторил все четыре запроса.
Результат на 23.08.2026: лимит проигнорирован 4 раза из 4 - 124, 147, 1281 и 102 токена выхода, причём finish_reason во всех случаях stop, то есть ответ считается нормально завершённым, а не обрезанным.
Так что относитесь к max_tokens как к предохранителю от бесконечной генерации, а не как к гарантии суммы в счёте. Соблюдает лимит модель на стороне провайдера, а шлюз может только передать его дальше. Сумму проверяйте по логам списаний, а не по тому, что вы попросили.
Грабля 3: в день замера четыре модели просто не ответили
Честная часть. Изначально в замере были Claude Haiku и Sonnet, но в тот день ни одна модель Claude мне не ответила: 503, All providers failed (last: kie 500), три попытки из трёх. Две Gemini-Flash отвалились по таймауту через 60 секунд с тем же All providers failed.
Это ровно тот случай, где автоматическое переключение между провайдерами не спасает: когда лежат все провайдеры модели, переключаться некуда.

С чего начать
- Возьмите свой документ, а не пример из статьи, и один промпт.
- Прогоните его на самой дешёвой подходящей модели три раза подряд.
- Посмотрите не на ответ, а на
usage:completion_tokensи есть ваш будущий счёт. - Умножьте на реальный поток документов в месяц - и только потом решайте, нужна ли модель дороже.
- Заложите запасную модель другого семейства: провайдеры падают, и падают целиком.
Если у вас есть зарубежная карта и свой прокси - берите официальные ключи вендоров напрямую, в коде выше не изменится ни строчки: base_url подставляется любой.
Дальше по теме: как заставить модель отдавать JSON надёжно - в разборе структурированного ответа; как раздавать задачи разным моделям по цене - в статье о маршрутизации; текущие цены и скидки по каждой модели - на странице моделей.
FAQ
Какая модель дешевле всего разбирает документы в JSON?
На замере 23.08.2026 - gpt-5.6-mini: 0,069–0,071 ₽ за счёт из семи полей и двух позиций. Результат при этом совпал с моделями в 2–12 раз дороже. Для формальных задач извлечения полей дорогая модель выигрыша не даёт.
Почему одинаковые ответы стоят по-разному?
Из-за токенов рассуждения: модель может «думать» сотнями и тысячами токенов, которые не попадают в текст ответа, но попадают в счёт. Видно это только в поле usage ответа API.
Помогает ли max_tokens ограничить расходы?
Не гарантированно. В моём замере лимит в 40 токенов был проигнорирован во всех четырёх случаях, ответы вышли на 102–1281 токен. Это защита от бесконечной генерации, а не потолок счёта.
Что делать, если модель отвечает 503?
Проверить, лежит ли она у всех провайдеров сразу: если в ошибке All providers failed, повторять тот же запрос бессмысленно. Рабочая стратегия - заранее выбранная запасная модель другого семейства.
Сколько стоит разобрать тысячу счетов?
По ценам на 23.08.2026 - от ~70 ₽ на самой дешёвой модели до ~820 ₽ на самой дорогой из проверенных, при одинаковом результате. Точную цифру считайте на своём документе: длина счёта прямо влияет на число токенов входа.