Сорок кабинетов и дедлайн 12:00

Агентство ведёт около 40 клиентских кабинетов на Ozon и Wildberries. Каждое утро по каждому проекту менеджер отчитывается клиенту, дедлайн 12:00 МСК. План, факт и прогноз по заказам, рекламе, продажам, прибыли, ДРР и марже. Отдельно за день и за месяц, отдельно по каждой площадке.

Собрать цифры это половина работы. Дальше клиент спрашивает, почему просела прибыль, что с рекламой, какой товар тянет вниз. На сорока проектах ежедневно этого никто не тянет. Отчёт вырождается в сводку чисел без выводов.

Вторая беда тише и хуже. Аналитика умеет молча врать. Реальный случай: у клиента перестал показываться P&L по Wildberries из-за пробела на конце API-токена. Заголовок авторизации уходил битым, площадка отбивала запросы, страница честно отдавала HTTP 200 и пустой список. Ошибки нет. Есть нули. Модель поверх такой картинки бодро прокомментировала бы их как провал продаж и сделала бы ложь убедительнее.

Модель не подпускают к цифрам

Нажатие уходит в один эндпоинт. Дальше работает конвейер, где на долю модели остаётся только формулировка.

  • Код собирает факты. Отдельный слой ходит в таблицу дневного P&L, суммирует факт за день и за месяц, достаёт планы проекта и ручные правки, досчитывает производные: ДРР, маржинальность, рентабельность на себестоимость.
  • Код ставит оценку. Каждая метрика получает цвет светофора по порогам, зашитым в функции. Выручка и реклама считаются по разной логике: перерасход по рекламе это плохо. Плана нет: цвет серый.
  • Схема из 57 полей разворачивается в плоский текст, 14 строк фактов на площадку в формате «метрика: план, факт, цвет». Ozon и Wildberries отдельными блоками.
  • Текст подклеивается к одному промпту: роль аналитика маркетплейсов и требование дать 3-5 коротких пунктов без воды. Один запрос, без инструментов и без доступа к данным.
!
Чего здесь нет

Это не чат с ИИ. Диалога, вопросов и переписки в интерфейсе нет: одна кнопка, один запрос, несколько пунктов текста. Читает их менеджер агентства, продавцу этот текст не уходит. Замеров точности и экономического эффекта мы не приводим, потому что их не делали: ни тестов промпта, ни A/B, ни оценки полезности. Светофор, панель действий, стоп-кран по остаткам, бенчмарк ниши и движок ставок это детерминированный код с порогами, модель там не участвует.

Почему она не может соврать про число

У модели нет ни базы, ни калькулятора, ни способа запросить что-то ещё. Числа приходят к ней округлёнными и подписанными, оценка «хорошо или плохо» проставлена кодом. Пространство для ошибки остаётся только в интерпретации.

Остальное закрыто ограничителями, которые поставили специально.

  • Одна генерация на пару проект и дата. Повтор возвращает сохранённый текст, кнопка блокируется, новых обращений к платному API нет.
  • На произвольном периоде функция выключена. Комментируется только стандартный день, для которого план разложен корректно.
  • Текст модели не попадает ни в копию отчёта для клиента, ни в картинку. Он живёт в интерфейсе агентства. Менеджер читает, решает и отправляет клиенту то, что написал сам.
  • Раздел закрыт ролью: доступ есть у команды, роль клиента отрезана на бэкенде и редиректится на фронте.
  • Вызов сделан на httpx, пакета SDK в зависимостях нет вообще. Ключ живёт только на бэкенде. Пустой ключ выключает функцию целиком.

Второй контур: аналитика без модели

Вопрос «какой товар тянет вниз» решает обычный код. LLM там нет вообще. В разделе рекламы Ozon работают панель «Что сделать сейчас» и светофор «Здоровье портфеля»: товары и кампании получают статусы «Слив без заказов», «Перерасход», «Есть запас», «Норма», «Мало данных», список отсортирован по рублям потерь. Рядом стоп-кран по остаткам: если свежего остатка нет, товар в список не попадает.

Сквозной принцип повторён в комментариях нескольких модулей. «Нет данных» и «ноль» обязаны выглядеть по-разному. Нет строки: NULL. Не набрали порог: «Мало данных». В бенчмарке ниши бакет не собрал нужное число разных продавцов: медиана не показывается. У автопилота ставок есть блок «Почему не тронуты остальные» с разбивкой причин по каждой пропущенной кампании.

Грабли

Главные грабли проекта опаснее любой галлюцинации: пустота вместо ошибки. После разбора с токеном две ветки синхронизации, раньше рапортовавшие «ок, получено 0 записей», переведены в статус «частично» с человекочитаемым сообщением по-русски. ИИ-слой имеет смысл ставить только поверх аналитики, которая умеет признаваться в поломке.

Что нашли у себя и держим в списке долгов:

  • Комментарий может разъехаться с цифрами. Текст пишется один раз и дальше отдаётся из кэша, снапшот фактов фиксируется в момент сдачи отчёта. Пересинк между этими событиями никак не подсвечен.
  • Прогноз в фактбуке считается линейной экстраполяцией, хотя в проекте уже лежит модуль прогноза по дню недели. Его собственный докстринг говорит, что выходные слабее будней и линейка врёт.
  • Сырой текст ошибки от OpenAI доходил до интерфейса. Внутреннее правило требует держать его только в логах.
  • В репозитории жил устаревший дубль модуля отчётов со своим промптом. Две версии промпта в одном репозитории это ловушка: правка легко уходит не в тот файл.

Частые вопросы

Может ли модель ошибиться в цифрах отчёта?

У неё нет ни базы, ни калькулятора, ни способа запросить что-то ещё. Код считает 57 полей по каждой площадке, округляет числа и сам ставит цвет светофора по порогам. Модель получает готовый плоский текст, 14 строк фактов на площадку в формате «метрика: план, факт, цвет», и отдаёт 3-5 коротких пунктов. Пространство для ошибки остаётся только в интерпретации.

Что будет, если аналитика отдаст нули из-за сбоя интеграции?

Это опаснее любой галлюцинации, поэтому чинили в первую очередь. Реальный случай: пробел на конце API-токена Wildberries, площадка отбивала запросы, страница честно отдавала HTTP 200 и пустой список. После разбора две ветки синхронизации, раньше рапортовавшие «ок, получено 0 записей», переведены в статус «частично» с человекочитаемым сообщением по-русски. ИИ-слой имеет смысл ставить только поверх аналитики, которая умеет признаваться в поломке.

Сколько обращений к платному API уходит на один проект?

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

Текст модели уходит клиенту в отчёт?

Нет. Он живёт в интерфейсе агентства, ни в копию отчёта для клиента, ни в картинку не попадает. Менеджер читает пункты, решает и отправляет клиенту то, что написал сам. Раздел закрыт ролью: роль клиента отрезана на бэкенде и редиректится на фронте.

Есть замеры точности и экономического эффекта?

Замеров нет, и мы их не приводим: ни тестов промпта, ни A/B, ни оценки полезности не делали. Известна исходная нагрузка: около 40 клиентских кабинетов на Ozon и Wildberries, дедлайн отчёта клиенту 12:00 МСК каждый день. Светофор, панель действий, стоп-кран по остаткам и движок ставок это детерминированный код с порогами, модель там не участвует.