AAYMA
RU
Войти

GridAgent-Wind

Почасовой прогноз нормализованной мощности двух ветротурбин на 24–48 ч по архивным прогнозам ECMWF IFS: модель LightGBM и LLM-агент в консоли…

Рабочий MVP
Команда «Nexcel solution» 10💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Nexcel solution
Кейс HackAlem.ai: Энергетика — Самрук-Казына
Стадия: Рабочий MVP

Задача кейса: AI-агент, прогнозирующий выработку ветровой электростанции по погодным данным

Суть

Почасовой прогноз нормализованной мощности двух ветротурбин на 24–48 ч по архивным прогнозам ECMWF IFS: модель LightGBM и LLM-агент в консоли диспетчера, который объясняет результат.

Как устроено

SCADA с шагом 10 минут усредняется до часа. Погода берётся из Open-Meteo Previous Runs API (ecmwf_ifs025) с учётом 7-часовой задержки публикации, чтобы не было утечки будущего. Из неё строятся 16 физических признаков: скорость ветра на высотах, u/v, v³, сдвиг ветра, sin/cos времени, turbine_id. LightGBM (Huber, 700 деревьев) предсказывает мощность, результат обрезается до [0,1] и обнуляется при ветре >25 м/с, затем прогноз проверяется правилами (flat_forecast, icing_risk, расхождение с прошлым прогнозом). Агент на gpt-4o-mini через tool calling вызывает run_forecast_cycle, check_weather_update и get_weather_tool (до 4 раундов) и пересказывает цифры в FastAPI-консоли.

Ключевые решения

  • LightGBM
  • Huber loss
  • TimeSeriesSplit
  • walk-forward backtest
  • Model Output Statistics
  • leakage-safe as-of weather
  • tool calling
  • CatBoost (эксперимент)

Метрики

Holdout январь 2026: MAE 0.2468, RMSE 0.3004 (в долях номинала); тесты 23/24

Особенности

Утечка будущего исключена: используются только прогоны ECMWF, опубликованные до момента выпуска прогноза, а не реанализ ERA5. Модель учится на связке «прогноз погоды → факт SCADA» по идее MOS. Кнопка «Проверить обновление погоды» сравнивает хэш входов и пересчитывает прогноз.

Стек

Python · pandas · NumPy · LightGBM · FastAPI · Open-Meteo API · HTML · pytest

Модели

gpt-4o-mini


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-d830a856-nexcel-solution.

README

README.md

GridAgent-Wind — почасовой прогноз выработки ВЭС на 24–48 часов

Проект для хакатона HackAlem AI, трек «Энергетика» (кейс Самрук-Казына).

Система сама берёт архивный прогноз погоды ECMWF IFS по координатам двух ветротурбин. Затем она прогоняет его через локальную ML-модель и выдаёт почасовой прогноз нормализованной мощности на 24 или 48 часов вперёд. LLM-агент в чате только вызывает эти расчёты и объясняет результат, сам он цифры не считает.


1. Проблема

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

Объект. ВЭС из двух ветроустановок, Алматинская область (Шелекский ветровой коридор).

ТурбинаШиротаДолгота
Т143.64319478.538833
Т243.64513978.535611

Т2 стоит примерно в 340 м от Т1, по азимуту ~310° (на северо-запад). При ветре северо-западного или юго-восточного направления одна турбина может оказаться в аэродинамическом следе другой. Отдельно этот эффект не моделируется: в модель подаются направление ветра и номер турбины, так что она может выучить разницу неявно. Это не проверялось.


2. Демо

TODO: добавить скриншот или GIF HTML-консоли диспетчера (чат, график и журнал шагов агента).


3. SMART-цель

  • S — прогнозировать нормализованную активную мощность (0…1 от номинала) двух турбин по часам на 24–48 ч.
  • M — на отложенной выборке (январь 2026) модель показала MAE = 0.2468 и RMSE = 0.3004 (в долях номинала).
  • A — обучение на SCADA за 11.03.2023–31.01.2026 и архивных прогнозах ECMWF IFS, модель LightGBM.
  • R — прогноз нужен оператору ВЭС, чтобы подавать график выработки на следующие сутки.
  • T — walk-forward прогноз на 1–28 февраля 2026 строится командой backtest_runner.py. Метрика за февраль будет посчитана после получения факта SCADA за этот период (TODO).

4. Архитектура: два контура

Модель и физика — детерминированный Python-код. LLM только вызывает этот код и пересказывает результат.

  SCADA (10 мин, XLSX/CSV)          Open-Meteo ECMWF IFS (1 ч)
            │                                   │
            ▼                                   ▼
┌──────────────────────────────────────────────────────────────┐
│  ДЕТЕРМИНИРОВАННЫЙ КОНТУР  (pandas / NumPy / LightGBM)       │
│  • SCADA → почасовые средние                                 │
│  • погода «на момент выпуска» — без заглядывания в будущее   │
│  • физические признаки (сдвиг ветра, u/v, v³, время суток)   │
│  • LightGBM: прогноз погоды → фактическая мощность           │
│  • ограничения: мощность в [0, 1], 0 при ветре > 25 м/с      │
│  • проверки прогноза по правилам                             │
└───────────────────────────┬──────────────────────────────────┘
                            │ ForecastResult: цифры, шаги, предупреждения
                            ▼
┌──────────────────────────────────────────────────────────────┐
│  АГЕНТНЫЙ КОНТУР  (OpenAI gpt-4o-mini, tool calling)         │
│  run_forecast_cycle · check_weather_update · get_weather_tool│
│  не более 4 раундов вызова инструментов                      │
└───────────────────────────┬──────────────────────────────────┘
                            ▼
┌──────────────────────────────────────────────────────────────┐
│  FastAPI + HTML-консоль: чат · график по турбинам · метрики  │
│  журнал шагов агента · «Проверить обновление погоды»         │
└──────────────────────────────────────────────────────────────┘

Один цикл прогноза (src/agents/pipeline.py)

Прогноз, выпущенный в день D в 12:00 UTC, покрывает часы с D+1 00:00 UTC на 24 или 48 ч.

  1. context — загрузка модели models/wind_power_lgb.pkl и её метрик.
  2. weather — прогноз погоды для каждой турбины, но только из прогонов ECMWF, опубликованных до момента выпуска. Учитывается задержка публикации 7 ч. Источник — Open-Meteo Previous Runs API, модель ecmwf_ifs025. Нет сети — берётся локальный кэш. Если хоть одного часа нет, цикл останавливается с ошибкой и не подставляет выдуманные значения.
  3. features — 16 признаков (раздел 5).
  4. model — предсказание, ограничения, сохранение в outputs/forecasts/forecast_<дата>_t12_<h>h.csv.
  5. validation — проверки по правилам (раздел 6) и сравнение с прогнозом предыдущего дня.

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


5. Данные, погода и признаки

Защита от утечки будущего

  • В прогнозе и бэктесте используются только архивные прогнозы ECMWF IFS, опубликованные до выпуска прогноза. Реанализ ERA5 не используется: он построен на фактических наблюдениях задним числом и в реальном времени недоступен.
  • Модель обучается сопоставлять «прогноз погоды → фактическая мощность SCADA», а не «анемометр → мощность». Так она сразу учитывает систематическую ошибку глобальной модели для этой местности (идея Model Output Statistics).

Шаг по времени

SCADA приходит с шагом 10 минут. Данные усредняются до 1 часа (resample("1h").mean() в src/train/build_train_set.py), потому что у ECMWF шаг 1 час.

Признаки (src/tools/feature_tool.py)

ГруппаПризнаки
Ветер по высотамwind_speed_10m, wind_speed_80m, wind_speed_100m
Направлениеwind_direction_10m, wind_direction_100m, sin/cos направления на 100 м
Сдвиг ветраdelta_v = v100 − v10
Перенос массwind_u = −v·sin(θ), wind_v = −v·cos(θ)
Энергия потокаv3 = v100³
Температураtemperature_2m (связана с плотностью воздуха)
Календарьhour_sin, hour_cos, day_of_year
Турбинаturbine_id (категориальный)

Previous Runs API не отдаёт ветер на 80 м. В прогнозе он восстанавливается из 10 м и 100 м по логарифмическому профилю.

Модель (src/train/train_model.py)

  • LightGBM, функция потерь Huber, 700 деревьев, learning rate 0.03, фиксированный seed.
  • Обучение: 11.03.2023–31.12.2025, кросс-валидация по времени (TimeSeriesSplit).
  • Отложенная выборка: январь 2026 → MAE 0.2468, RMSE 0.3004.
  • Сравнения с базовой моделью (например, «сырой» прогноз ветра через кривую мощности) пока нет — TODO.

6. Проверки прогноза и ограничения

Все проверки считаются в Python. LLM их только пересказывает.

ПроверкаПравило
Ограничение мощностипрогноз обрезается до [0, 1]
shutdown_windветер на 100 м > 25 м/с → мощность = 0 (отключение турбины)
low_wind_high_powerветер < 3 м/с при мощности > 0.2 — подозрительно
flat_forecastстандартное отклонение прогноза турбины < 0.01
icing_riskтемпература ≤ 0 °C (влажность пока не запрашивается, поэтому это только информация)
divergence_from_previous_issueсредняя разница с прогнозом прошлого дня > 0.15

Пороги подобраны вручную: паспорта турбин у команды нет.


7. Быстрый запуск (Windows PowerShell, Python 3.11+)

python -m venv .venv
.venv\Scripts\Activate.ps1
python -m pip install -r requirements.txt
python -m src.train.train_model      # обучение → models/wind_power_lgb.pkl
python -m src.app                     # UI на http://127.0.0.1:7860
  • Первое обучение скачивает погоду в data/weather_cache/. Дальше можно обучать без сети: python -m src.train.train_model --offline.
  • Прогноз из UI в первый раз тоже требует интернета (Open-Meteo Previous Runs API). После этого погода кэшируется в data/weather_cache/*_previous_runs.parquet.
  • Walk-forward бэктест на февраль 2026: python backtest_runner.py → submissions/forecast_february_2026.csv и backtest_report.json.
  • LLM-чат: скопируйте .env.example в .env, укажите OPENAI_API_KEY, поставьте MOCK_MODE=false. Без ключа или при MOCK_MODE=true чат отвечает заглушкой, а прогноз по кнопке работает как обычно.

8. Тесты

pytest -v
  • tests/test_agent_tools.py — инструменты агента, ограничения мощности, порядок «погода → модель».
  • tests/test_orchestrator_mock.py — чат в демо-режиме без LLM.
  • tests/test_agent_cycle.py — полный цикл прогноза: проверки, обновление погоды, неполная погода.

Сейчас проходят 23 из 24 тестов. test_incomplete_weather_fails_loud ждёт другой текст ошибки (TODO).


9. Почему просто

Мы сознательно не даём LLM считать мощность или погоду: языковая модель может выдумать цифру, а оператору нужны воспроизводимые числа. Поэтому весь расчёт — это обычный Python-конвейер из пяти шагов, который работает и без LLM, и его можно проверить тестами. Агент только выбирает один из трёх инструментов и объясняет результат. Модель — один LightGBM на обе турбины, без ансамблей и нейросетей: её легко переобучить за минуты и объяснить судье.


10. Известные ограничения

  • Обучение использует Open-Meteo Historical Forecast API (ecmwf_ifs), а прогноз — Previous Runs API (ecmwf_ifs025). Источники близкие, но не одинаковые, поэтому ошибка на реальных данных может отличаться от holdout.
  • Без интернета и без кэша *_previous_runs.parquet прогноз останавливается на шаге погоды.
  • Экономический эффект (сколько экономится на штрафах за небаланс) не считался.

11. Дальше (не реализовано)

  • Расчёт стоимости небаланса по тарифам балансирующего рынка РК и рекомендации диспетчеру.
  • Явный учёт аэродинамического следа между Т1 и Т2.
  • Сценарии для демонстрации (резкий спад ветра, сильный сдвиг ветра).
  • Метрика walk-forward за февраль 2026 по факту SCADA.

12. Команда

  • Alisher — оркестратор и инструменты агента (src/agents/).
  • TODO — обучение модели и обработка данных (src/train/).
  • TODO — архивная погода и проверка координат (src/tools/weather_tool.py).
Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
20
Авторы
3
Файлы
57
Ветки
3

Авторы коммитов

Tarlan 8muhambetovbektas7 7BektasMukhambetov 5

История коммитов

  • 2026-09-23 18:03Merge remote-tracking branch 'origin/main'muhambetovbektas7
  • 2026-09-23 18:01Merge remote-tracking branch 'origin/main'muhambetovbektas7
  • 2026-09-23 17:58Update README.mdBektasMukhambetov
  • 2026-09-23 17:58Add leakage-safe forecast backtestmuhambetovbektas7
  • 2026-09-23 17:55Merge remote-tracking branch 'origin/main' into feat/html-uiTarlan
  • 2026-09-23 17:55Add files via uploadBektasMukhambetov
  • 2026-09-23 17:51Редизайн: HTML-консоль диспетчера на FastAPI вместо GradioTarlan
  • 2026-09-23 17:47Delete src/core/power_curve.pyBektasMukhambetov
Все коммиты (20)
  • 2026-09-23 17:47Delete src/core/forecast_model.pyBektasMukhambetov
  • 2026-09-23 17:46Delete .claude directoryBektasMukhambetov
  • 2026-09-23 17:32Merge pull request #1 from BAITC-Hacks/feat/agent-integrationTarlan Baimyrza
  • 2026-09-23 17:24Готовый проект без дизайна: связка агента, модели и UITarlan
  • 2026-09-23 16:45Merge main and complete forecast integrationmuhambetovbektas7
  • 2026-09-23 16:35Integrate deterministic forecast toolsmuhambetovbektas7
  • 2026-09-23 16:11Add README/AGENTS.md, fix error handling+logging in orchestrator, add sanity testsTarlan
  • 2026-09-23 16:04Merge main and add deterministic wind training pipelinemuhambetovbektas7
  • 2026-09-23 15:23Add ML training core and data preprocessingmuhambetovbektas7
  • 2026-09-23 15:16Add AI chat dashboard and project skillsTarlan
  • 2026-09-23 14:20Remove unused scaffold filesTarlan
  • 2026-09-23 14:15Create project skeletonTarlan
Структура репозитория (57 файлов)
.env.example
.gitignore
AGENTS.md
README.md
README_1.md
backtest_runner.py
catboost_info/catboost_training.json
catboost_info/learn/events.out.tfevents
catboost_info/learn_error.tsv
catboost_info/time_left.tsv
data/Dataset HackAlemAI для участников 11.03.2023-28.02.2026 - turbine 2.csv
data/Dataset_HackAlemAI_для_участников_11_03_2023_28_02_2026_turbine.xlsx
data/turbine_22.csv
data/turbines.json
docs/skills/skill-agentic-loop.md
docs/skills/skill-code-quality.md
docs/skills/skill-readme.md
models/.gitkeep
models/forecast_model.pkl
models/metrics.json
outputs/forecasts/.gitkeep
pytest.ini
requirements.txt
run.sh
setup.sh
src/agents/__init__.py
src/agents/orchestrator.py
src/agents/pipeline.py
src/agents/tools.py
src/app.py
src/backtest.py
src/core/__init__.py
src/core/features.py
src/core/train.py
src/tools/__init__.py
src/tools/feature_tool.py
src/tools/inference_tool.py
src/tools/weather_tool.py
src/train/__init__.py
src/train/build_train_set.py
src/train/train_model.py
src/weather/__init__.py
src/weather/archive_client.py
src/weather/mock_weather.py
src/web/index.html
tests/test_agent_cycle.py
tests/test_agent_tools.py
tests/test_api.py
tests/test_as_of_backtest.py
tests/test_forecast_model.py
tests/test_orchestrator_mock.py
tests/test_power_curve.py
tests/test_weather_client.py
training/eda.ipynb
training/evaluate.py
training/train.py
training/training_report.md
Ветки (3)

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.