Пошаговые инструкции Средний уровень 18 мин

Как сделать ИИ-агента для прогноза спроса

Пошаговая инструкция от нуля до рабочего прототипа: история продаж, остатки, события, baseline-прогноз, LLM-объяснение, approval и backtest.

AI-агенты n8n Google Sheets закупки остатки прогноз спроса demand forecasting backtest

Что получится в результате

Соберем ИИ-агента, который раз в неделю прогнозирует спрос по товарам или услугам и готовит понятные рекомендации для закупки, производства или маркетинга.

Первая рабочая версия будет делать так:

  1. история продаж лежит в таблице `sales_history`;
  2. остатки лежат в `stock`;
  3. промо, праздники и события лежат в `events`;
  4. n8n запускает расчет по расписанию;
  5. workflow строит простой базовый прогноз на 4 недели вперед;
  6. агент проверяет выбросы, остатки и дни без товара;
  7. LLM объясняет, почему прогноз вырос или снизился;
  8. результат попадает в `forecast_output` со статусом `draft`;
  9. менеджер проверяет прогноз и ставит `approved`, `needs_review` или `rejected`;
  10. approved-рекомендации превращаются во внутренние задачи, но не создают заказ поставщику автоматически.

В первой версии агент не закупает товар сам, не меняет цены, не запускает рекламу и не обещает точность. Он считает прогноз, показывает основания и помогает принять решение.

Что понадобится

  • n8n Cloud или self-hosted n8n.
  • Google Sheets для первого прототипа.
  • История продаж минимум за 8-12 недель, лучше за 6-12 месяцев.
  • Список товаров или услуг.
  • Остатки и дни отсутствия товара.
  • Данные о промо, праздниках и крупных событиях.
  • API-ключ LLM-провайдера.
  • Ответственный менеджер, который подтверждает рекомендации.

Шаг 1. Выберите объект прогноза

Не начинайте с “прогнозировать весь бизнес”.

Для первого прототипа выберите один уровень:

  1. SKU;
  2. категория;
  3. услуга;
  4. филиал;
  5. канал продаж.

Самый простой старт:

text
прогноз спроса по SKU на 4 недели вперед

Проверка: у каждого SKU есть история продаж и текущий остаток.

Шаг 2. Создайте таблицу проекта

Создайте Google Sheet:

text
Demand forecast AI agent

Добавьте листы:

text
products
sales_history
stock
events
forecast_output
action_queue
forecast_log
settings
backtest
test_cases

Проверка: у n8n есть доступ на чтение и запись ко всем листам.

Шаг 3. Создайте справочник товаров

В листе `products` сделайте колонки:

text
sku
product_name
category
unit
min_stock
lead_time_days
is_active
manager

Пример:

text
SKU-1001
AI-консультация базовая
services
шт
5
7
yes
Иван

Проверка: у каждого активного товара есть `sku`, `min_stock`, `lead_time_days` и ответственный.

Шаг 4. Создайте историю продаж

В листе `sales_history` сделайте колонки:

text
date
sku
quantity
revenue
channel
region
order_id
is_return

Пример:

text
2026-05-01
SKU-1001
3
45000
site
moscow
O-9001
no

Правило:

text
возвраты храните отдельно через is_return = yes

Проверка: за выбранный период по каждому SKU есть продажи по датам.

Шаг 5. Создайте лист остатков

В листе `stock` сделайте колонки:

text
date
sku
stock_on_hand
reserved
available_stock
stockout

Пример:

text
2026-05-20
SKU-1001
18
3
15
no

Если товара не было в наличии:

text
stockout: yes

Проверка: агент сможет отличить падение спроса от ситуации “товара не было на складе”.

Шаг 6. Создайте календарь событий

В листе `events` сделайте колонки:

text
date_start
date_end
event_type
sku
category
impact
comment

Типы:

  • `promo`;
  • `holiday`;
  • `price_change`;
  • `stockout`;
  • `launch`;
  • `external_event`.

Пример:

text
2026-05-10
2026-05-17
promo
SKU-1001
services
high
скидка 20% на базовую консультацию

Проверка: крупные промо и события не теряются в “шуме” продаж.

Шаг 7. Создайте настройки прогноза

В листе `settings` добавьте:

text
key
value
comment

Заполните:

text
forecast_horizon_weeks | 4 | на сколько недель вперед прогнозировать
history_weeks | 12 | сколько недель брать для базового прогноза
moving_average_weeks | 4 | окно скользящего среднего
min_history_points | 8 | минимум недель для прогноза
stockout_adjustment | yes | учитывать дни без товара
high_risk_wape | 0.35 | порог плохой точности

Проверка: параметры прогноза можно менять без переписывания workflow.

Шаг 8. Создайте лист результата

В листе `forecast_output` сделайте колонки:

text
forecast_id
sku
product_name
category
period_start
period_end
forecast_quantity
baseline_quantity
last_4_weeks_avg
trend
current_stock
recommended_order_qty
risk_level
confidence
explanation
review_status
review_comment
approved_by
created_at
approved_at

Статусы:

  • `draft`;
  • `approved`;
  • `needs_review`;
  • `rejected`;
  • `done`;
  • `error`.

Проверка: прогноз и рекомендация не смешиваются с сырыми продажами.

Шаг 9. Создайте очередь действий

В листе `action_queue` сделайте колонки:

text
action_id
forecast_id
sku
manager
action_type
message_draft
reason
risk_level
review_status
task_id
created_at
processed_at
error

Типы действий:

  • `order_more`;
  • `reduce_order`;
  • `check_stockout`;
  • `review_promo`;
  • `no_action`.

Проверка: даже approved-прогноз сначала превращается во внутреннюю задачу, а не в автоматический заказ.

Шаг 10. Создайте workflow расчета

Назовите workflow:

text
Demand forecast weekly

Добавьте узлы:

  1. `Schedule Trigger`;
  2. `Google Sheets` - чтение `settings`;
  3. `Google Sheets` - чтение `products`;
  4. `Google Sheets` - чтение `sales_history`;
  5. `Google Sheets` - чтение `stock`;
  6. `Google Sheets` - чтение `events`;
  7. `Code` - нормализация данных;
  8. `Code` - агрегация продаж по неделям;
  9. `Code` - расчет базового прогноза;
  10. `Code` - расчет потребности и рисков;
  11. `LLM` - объяснение прогноза;
  12. `Code` - проверка JSON;
  13. `Google Sheets` - запись `forecast_output`;
  14. `Google Sheets` - запись `action_queue`;
  15. `Google Sheets` - запись `forecast_log`.

Проверка: workflow создан и запускается вручную.

Шаг 11. Настройте расписание

В `Schedule Trigger` поставьте:

text
Mode: Every Week
Weekday: Monday
Hour: 07
Minute: 30
Timezone: Europe/Moscow

Проверка: прогноз готов до планирования закупок или производства.

Шаг 12. Нормализуйте продажи

В узле `Code` приведите данные к одному виду.

javascript
function qty(value) {
  return Math.max(0, Number(String(value || '0').replace(',', '.')));
}

function money(value) {
  return Math.round(Number(String(value || '0').replace(',', '.')) * 100) / 100;
}

function dateOnly(value) {
  return String(value || '').slice(0, 10);
}

Возвраты учитывайте отдельно:

text
если is_return = yes, quantity вычитается из продаж

Проверка: продажи, возвраты и пустые значения не ломают расчет.

Шаг 13. Сгруппируйте продажи по неделям

Для каждого SKU посчитайте:

text
week_start
sku
quantity_sum
revenue_sum
orders_count

Неделя начинается с понедельника.

Пример:

text
2026-05-04 | SKU-1001 | 18 | 270000 | 12
2026-05-11 | SKU-1001 | 25 | 375000 | 16

Проверка: по каждому SKU есть недельный ряд, а не разрозненные продажи по дням.

Шаг 14. Уберите недели без наличия

Если в неделе был `stockout = yes`, не считайте ее обычным падением спроса.

Правило первой версии:

text
если stockout_days >= 2, неделя помечается как distorted
distorted-недели не входят в moving average

Проверка: отсутствие товара не занижает прогноз.

Шаг 15. Посчитайте базовый прогноз

Используйте простую и проверяемую формулу:

text
baseline = среднее quantity_sum за последние 4 нормальные недели

Если доступно меньше 4 недель, но больше `min_history_points`, берите среднее по доступным неделям.

Если истории меньше минимума:

text
review_status = needs_review
risk_level = high
reason = мало истории

Проверка: прогноз можно пересчитать вручную по таблице.

Шаг 16. Посчитайте тренд

Сравните средние:

text
last_4_weeks_avg
previous_4_weeks_avg
trend = (last_4_weeks_avg - previous_4_weeks_avg) / previous_4_weeks_avg

Интерпретация:

  • `trend > 0.20` - спрос растет;
  • `trend < -0.20` - спрос падает;
  • иначе спрос стабилен.

Проверка: резкий рост или спад виден отдельно от базового среднего.

Шаг 17. Учтите промо и события

Если на будущий период запланировано промо:

text
impact = high -> baseline * 1.25
impact = medium -> baseline * 1.10
impact = low -> baseline * 1.05

Если промо было в прошлых 4 неделях, но в будущем его нет:

text
снизить влияние промо-недели или отправить прогноз в needs_review

Проверка: скидочная неделя не превращается в завышенный обычный спрос.

Шаг 18. Рассчитайте прогноз на 4 недели

Для каждой будущей недели:

text
forecast_quantity = baseline с учетом trend и events

Округление:

text
товары в штуках -> округлить вверх
услуги -> округлить до целого или до допустимой единицы

Проверка: в `forecast_output` будет отдельная строка на SKU и неделю.

Шаг 19. Рассчитайте рекомендуемый заказ

Формула первой версии:

text
recommended_order_qty = forecast_quantity + min_stock - available_stock

Если результат меньше 0:

text
recommended_order_qty = 0

Если `lead_time_days > 7`, учитывайте две недели прогноза:

text
recommended_order_qty = forecast_next_2_weeks + min_stock - available_stock

Проверка: агент не предлагает заказать товар, которого и так достаточно на складе.

Шаг 20. Посчитайте уровень риска

Правила:

text
critical: available_stock = 0 и forecast_quantity > 0
high: recommended_order_qty > 0 и lead_time_days >= 14
medium: trend > 20% или trend < -20%
low: обычный прогноз без отклонений

Отдельно ставьте `needs_review`, если:

  • мало истории;
  • были stockout-недели;
  • есть промо с high impact;
  • прогноз отличается от прошлого больше чем на 50%.

Проверка: самые рискованные SKU поднимаются наверх.

Шаг 21. Добавьте LLM-объяснение

LLM не должен считать прогноз. Он объясняет уже посчитанные цифры.

System prompt:

text
Ты аналитик спроса.
Пиши только по переданным данным.
Не придумывай причины роста или падения.
Не обещай точность прогноза.
Верни только JSON.

User prompt:

text
Данные прогноза:
{{ JSON.stringify($json.forecast_item) }}

Верни JSON:
{
  "explanation": "2-3 предложения: почему такой прогноз",
  "recommended_action": "что сделать менеджеру",
  "risk_level": "low|medium|high|critical",
  "needs_review_reason": "string|null"
}

Проверка: ответ модели не содержит новых цифр, которых не было во входных данных.

Шаг 22. Проверьте JSON и факты

После LLM добавьте `Code`.

Правила:

  • JSON парсится;
  • `risk_level` входит в разрешенный список;
  • `explanation` не длиннее 500 символов;
  • модель не добавила новые факты: “конкуренты”, “погода”, “новый рынок”, если их нет в events;
  • нет автоматического решения “срочно заказать”.

Если проверка не прошла:

text
review_status = needs_review
validation_error = invalid_llm_explanation

Проверка: объяснение помогает, но не управляет расчетом.

Шаг 23. Запишите результат в forecast_output

Для каждой строки прогноза запишите:

text
forecast_id
sku
product_name
category
period_start
period_end
forecast_quantity
baseline_quantity
last_4_weeks_avg
trend
current_stock
recommended_order_qty
risk_level
confidence
explanation
review_status
created_at

Статус:

text
draft - если данных достаточно
needs_review - если мало истории, stockout или сильное отклонение

Проверка: менеджер видит прогноз, основание и статус.

Шаг 24. Проверьте прогноз человеком

Менеджер открывает `forecast_output`.

Проверяет:

  • не было ли разовой крупной сделки;
  • не было ли stockout;
  • не было ли промо;
  • не менялась ли цена;
  • не планируется ли запуск или остановка канала продаж;
  • адекватен ли recommended_order_qty.

После проверки ставит:

text
review_status: approved
approved_by: имя
approved_at: дата

Или:

text
review_status: rejected
review_comment: причина

Проверка: без `approved` агент не создает задачу на закупку.

Шаг 25. Создайте workflow для approved-действий

Назовите workflow:

text
Demand forecast actions approved

Он делает:

  1. читает `forecast_output`;
  2. берет только `review_status = approved`;
  3. создает строку в `action_queue`;
  4. отправляет задачу ответственному менеджеру;
  5. меняет статус на `done`.

Пример задачи:

text
SKU-1001: прогноз 28 шт. на неделю 25-31 мая.
Остаток 15 шт., min_stock 5, рекомендуемый заказ 18 шт.
Причина: спрос выше среднего на 22%, промо не запланировано.

Проверка: задача внутренняя, поставщику заказ не отправляется автоматически.

Шаг 26. Сделайте backtest

В листе `backtest` храните проверку качества.

Колонки:

text
run_id
sku
period_start
period_end
forecast_quantity
actual_quantity
absolute_error
ape
wape_group
created_at

Формулы:

text
absolute_error = abs(actual_quantity - forecast_quantity)
ape = absolute_error / actual_quantity

Для группы SKU считайте WAPE:

text
WAPE = сумма absolute_error / сумма actual_quantity

Если WAPE выше `high_risk_wape`, прогнозы по этой категории отправляйте в `needs_review`.

Проверка: вы видите не только прогноз, но и насколько он был точным после факта.

Минимальная проверка результата

Прототип работает, если выполняются все пункты:

  • товары читаются из `products`;
  • продажи читаются из `sales_history`;
  • остатки читаются из `stock`;
  • события читаются из `events`;
  • продажи агрегируются по неделям;
  • stockout-недели не занижают прогноз;
  • прогноз считается кодом, а не LLM;
  • объяснение формируется LLM по готовым цифрам;
  • результат пишется в `forecast_output`;
  • без `approved` задача не создается;
  • backtest считает ошибку прогноза.

Что нельзя автоматизировать в первой версии

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

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

Можно ли сразу использовать сложную ML-модель?

Можно, но для первой версии лучше начать с простого baseline. Если простой прогноз уже дает пользу и понятные ошибки, потом можно подключать более сложные модели.

Почему LLM не должен сам считать прогноз?

Потому что прогноз должен быть воспроизводимым. Арифметику считает код, а LLM объясняет результат понятным языком и помогает сформулировать действие.

Что делать с товарами без истории?

Ставить `needs_review`. Для новых товаров используйте аналоги, план запуска, промо и экспертную оценку, но не выдавайте прогноз как автоматический расчет.

Как учитывать дни без товара?

Если товара не было на складе, продажи ниже не потому, что спрос упал. Такие недели нужно исключать из среднего или помечать прогноз как рискованный.

Какой минимум нужен для запуска?

Листы `products`, `sales_history`, `stock`, `events`, `forecast_output`, n8n workflow, простой baseline-прогноз, LLM-объяснение, approval менеджера и backtest качества.

Дальше по теме

Похожие материалы