Как работает учёт стоимости
Проблема: юнит-экономика LLM-платформы живёт или умирает на одном числе — сколько на самом деле стоит одна опубликованная статья? — и это число на удивление трудно получить. Плоские оценки за вызов расходятся с реальностью (здесь плоская константа однажды недосчитывала доминирующий драйвер расходов примерно в 6 раз); дашборды провайдеров агрегируют по аккаунту, а не по статье.
Слой 1 — неизменяемое usage-событие
Заголовок раздела «Слой 1 — неизменяемое usage-событие»Прогон эмитит неизменяемое usage-событие с вектором атрибуции: тенант, контракт, запись, пайплайн, модель, счётчики токенов, время. Не строка лога — строка запрашиваемого леджера. Стоимость в момент вызова не вычисляется: события хранят факты (токены, модель), деньги считаются позже — прайсбук меняется, и сохранённая цена заморозила бы устаревшую.
Гранулярность: одна запись на прогон, а не на вызов, разложенная по модели; ось шага хранится рядом с прогоном — рантайм снимает её той же дельтой до/после, которой считает вызовы по шагам. Без оси шага вопрос «какой шаг здесь дорогой» не имеет числового ответа; первый же замер по ней показал, что около 60% стоимости Generate даёт один шаг.
Платные не-LLM вызовы (внешний поиск) считаются там же и по всем шагам отдельным ключом: узкая метрика маховика отвечает «сколько поисков понадобилось исследованию», а метеринг обязан видеть каждый платный вызов целиком — иначе расход доминирующего шага остаётся невидимым.
Слой 2 — версионированный прайсбук
Заголовок раздела «Слой 2 — версионированный прайсбук»Цены меняются; история меняться не должна. Стоимость считается джойном событий с версионированным прайсбуком — ценой, действовавшей в момент события, — поэтому числа прошлого месяца остаются правдой после переоценки у провайдера. Тот же джойн сверяет расчётный итог с реальным счётом провайдера: если леджер и счёт расходятся — что-то не метрится, и это дефект, а не примечание об округлении.
Слой 3 — стоимость одной статьи, амортизированная
Заголовок раздела «Слой 3 — стоимость одной статьи, амортизированная»«Стоимость статьи» — это больше, чем её Generate-прогон: ресёрч Collect, который её кормил, амортизируется по статьям, которые он сделал возможными. Именно этим числом платформа рулит на самом деле — оно, например, показало, что период пост-гейтовых отказов умножал эффективную стоимость опубликованной статьи в разы при неизменных ценах за вызов. Без пер-статейной атрибуции такая регрессия невидима внутри месячного итога.
Слой 4 — бюджеты (спроектированы, ещё не заряжены)
Заголовок раздела «Слой 4 — бюджеты (спроектированы, ещё не заряжены)»Метеринг задуман кормить принуждение: бюджеты на прогон со сторожем через канал управления прогонами. Стадия принуждения пока не включена: бюджеты не сконфигурированы, а канал управления, которым пользовался бы сторож, — тот, о котором движок прогонов пишет, что бегущий прогон он на середине не прерывает.
Что работает сегодня: дневной сигнал аномалии расхода в ночном отчёте. Автоматического killswitch на уровне провайдера нет и по замыслу — автоотключение биллинга роняет прод вместе с тем перерасходом, который должно было остановить: сигнал уведомляет владельца, решение принимает человек. Страница изменится, когда бюджеты будут сконфигурированы, а сторож — измерен.
Компромиссы
Заголовок раздела «Компромиссы»Метеринг каждого вызова стоит записи на вызов и дисциплины: любой новый путь LLM-вызова обязан эмитить событие, и сверка со счётом существует ровно для того, чтобы ловить забывшие пути. Правила амортизации — выбор модели; платформа хранит сырые векторы, поэтому модель можно поменять ретроактивно без потери данных. Абсолютные цифры — на статью, за ночь, за месяц — на этом портале намеренно не публикуются: механизм публичен, бухгалтерия — нет.
Пощупать за две минуты
Заголовок раздела «Пощупать за две минуты»Домен metering в list_domains открывает read-поверхность; стоимость по
прогонам видна в отчётах прогонов.