AAYMA
RU
Войти

WindPower Agent

CLI-система почасового прогноза нормализованной мощности двух ветротурбин на 24/48 часов по историческим данным и архивному прогнозу погоды…

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

О проекте

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

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

Суть

CLI-система почасового прогноза нормализованной мощности двух ветротурбин на 24/48 часов по историческим данным и архивному прогнозу погоды Open-Meteo, с интервалами P10/P50/P90 и расчётом энергии.

Как устроено

10-минутные CSV турбин приводятся к единой схеме, чистятся от дубликатов и агрегируются в часовую сетку, неполные часы исключаются. weather_archive.py берёт последний доступный запуск ECMWF IFS через Open-Meteo Single Runs API (ветер 10/80 м, температура) и сохраняет snapshot с SHA-256 и manifest. forecast_agent.py обучает power curve (биннинг скорости ветра), Ridge с лаговыми, rolling и календарными признаками и LightGBM с квантилями. Модели объединяются ансамблем с весами 0.35/0.20/0.45, прогноз рекурсивный. Бенчмарк считает MAE, RMSE и WMAPE.

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

  • power curve binning
  • Ridge regression
  • LightGBM
  • LightGBM quantile P10/P50/P90
  • weighted ensemble
  • recursive forecasting
  • rolling-origin backtest
  • Open-Meteo ECMWF IFS

Особенности

Используется архивный прогноз погоды (Single Runs API) с задержкой доступности 6 ч, что честнее для проверки на истории. Provenance каждого snapshot (URL, model run, SHA-256) сохраняется. В backend/wind_agent есть заготовки LLM-чата и оркестратора, но README говорит, что LLM в сценарии не вызывается.

Стек

Python · pandas · NumPy · LightGBM · Open-Meteo API · React · Vite


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

README

README.md

WindPower Agent

Система краткосрочного прогнозирования почасовой выработки двух ветряных турбин.

1. Название проекта

WindPower Agent — ML-решение для прогноза нормализованной активной мощности турбин на горизонте 24 или 48 часов.

2. Краткое описание

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

Результат выдаётся в нормализованном диапазоне 0–1. Если указать установленную мощность турбины, система дополнительно рассчитывает ожидаемую энергию в кВт·ч и МВт·ч.

Решение запускается локально из командной строки и ориентировано на воспроизводимую проверку жюри хакатона.

3. Что реализовано

  • чтение CSV-файлов двух турбин;
  • приведение исходных колонок к единой схеме и обработка некорректных дат/чисел;
  • удаление дубликатов временных меток;
  • агрегация 10-минутных измерений в почасовую сетку;
  • исключение неполных часов из обучения и валидации;
  • baseline-модель PowerCurveRegressor с биннингом скорости ветра;
  • RidgePowerRegressor с погодными, календарными, лаговыми и rolling-признаками;
  • point-модель LightGBM при наличии библиотеки;
  • модели квантилей P10/P50/P90 на LightGBM;
  • fallback на Ridge и эмпирический residual band, если LightGBM не установлен;
  • взвешенный ансамбль моделей;
  • рекурсивный прогноз на 24 или 48 часов;
  • расчёт MAE, RMSE и WMAPE при benchmark-проверке;
  • получение архивного погодного прогноза через Open-Meteo Single Runs API;
  • сохранение исходного ответа API, нормализованного CSV и manifest с параметрами запуска и SHA-256;
  • расчёт энергии при переданной установленной мощности;
  • сохранение прогнозов в CSV и метаданных запусков в JSONL.

4. Как работает решение

Основной сценарий:

  1. Пользователь задаёт дату и время запуска прогноза, горизонт и, при необходимости, мощность турбин.
  2. weather_archive.py выбирает последний доступный модельный запуск погоды и получает для координат каждой турбины почасовые значения температуры и скорости ветра.
  3. Исторические CSV читаются и агрегируются до часовой сетки.
  4. На данных до момента прогноза обучаются power curve, Ridge и LightGBM (если доступен).
  5. Для каждого будущего часа формируются признаки и рассчитываются прогнозы отдельных моделей.
  6. Прогнозы объединяются фиксированными весами: power curve — 0.35, Ridge — 0.20, LightGBM — 0.45. При отсутствии LightGBM его компонент заменяется Ridge fallback.
  7. Одновременно формируется интервал P10/P50/P90.
  8. Нормализованная мощность сохраняется в outputs/forecast/*.csv; при заданной мощности добавляются оценки энергии.

Для отдельного benchmark-сценария ml_baseline.py использует исторические измеренные ветер и температуру на validation-горизонте. Это benchmark для проверки моделей, а не полноценная оценка качества будущего прогноза погоды.

5. Технологии

  • Python 3.10+;
  • pandas — чтение и обработка временных рядов;
  • NumPy — признаки, расчёты и Ridge-регрессия;
  • LightGBM — point- и quantile-регрессия;
  • стандартная библиотека Python (urllib, json, csv, hashlib, zoneinfo) — запросы, нормализация и versioning погодных данных;
  • argparse — CLI-интерфейс;
  • Open-Meteo Single Runs API — архивные погодные прогнозы;
  • JSON/JSONL/CSV — форматы результатов и метаданных.

Полный набор объявленных зависимостей находится в requirements.txt. В нём также указаны scikit-learn, requests, pyarrow, fastapi, uvicorn, anthropic, openai, python-dotenv, joblib и pytest; текущий CLI-пайплайн напрямую использует прежде всего pandas, NumPy и опционально LightGBM. LLM API в текущем сценарии не вызываются.

6. Архитектура проекта

datasets/*.csv
      │
      ▼
ml_baseline.py
  ├─ read_turbine_csv()
  ├─ to_hourly()
  ├─ make_features()
  ├─ PowerCurveRegressor
  ├─ RidgePowerRegressor
  └─ evaluate_origins()
      │
      └──────────────► outputs/ml_benchmark.json

weather_archive.py ──► Open-Meteo API
      │
      └──────────────► outputs/weather_archive/
                       ├─ runs/*/response.json
                       ├─ runs/*/forecast.csv
                       └─ manifest.jsonl

forecast_agent.py
  ├─ получает/читает weather snapshot
  ├─ обучает набор моделей
  ├─ строит ensemble и P10/P50/P90
  └─ рассчитывает энергию
      │
      └──────────────► outputs/forecast/
                       ├─ forecast_*.csv
                       └─ forecast_manifest.jsonl

Основные файлы:

  • ml_baseline.py — подготовка исторических данных, модели baseline/Ridge и валидация;
  • weather_archive.py — выбор доступного запуска погоды, запрос Open-Meteo и сохранение snapshot;
  • forecast_agent.py — интегрированный сценарий «погода → модели → интервалы → энергия»;
  • requirements.txt — зависимости проекта;
  • datasets/ — исторические CSV турбин.

7. Установка и запуск

7.1. Установка

git clone https://github.com/BAITC-Hacks/hack-54f1ae1b-astana-hackers.git
cd hack-54f1ae1b-astana-hackers

python -m venv .venv
# Linux/macOS
source .venv/bin/activate
# Windows PowerShell:
# .\.venv\Scripts\Activate.ps1

python -m pip install --upgrade pip
python -m pip install -r requirements.txt

Для минимального benchmark достаточно установить pandas и NumPy:

python -m pip install "pandas>=2.2,<3" "numpy>=2,<3"

7.2. Benchmark исторических данных

В репозитории должны присутствовать два файла из раздела «Данные и интеграции». Запуск из корня проекта:

python ml_baseline.py \
  --turbine1 "datasets/Dataset HackAlemAI для участников 11.03.2023-28.02.2026 - turbine 1.csv" \
  --turbine2 "datasets/Dataset HackAlemAI для участников 11.03.2023-28.02.2026 - turbine 2.csv" \
  --output outputs/ml_benchmark.json

В Windows PowerShell используйте обратный апостроф ` вместо \ для переноса строк либо выполните команду в одну строку.

7.3. Проверка выбора погодного запуска без сетевого запроса

python weather_archive.py \
  --as-of "2026-01-31T00:00" \
  --horizon-hours 48 \
  --dry-run

7.4. Полный прогноз

Команда ниже получает погодные данные, строит ансамблевый прогноз и сохраняет результаты:

python forecast_agent.py \
  --as-of "2026-01-31T00:00" \
  --horizon-hours 48 \
  --capacity-kw-turbine1 3000 \
  --capacity-kw-turbine2 3000

Значения --capacity-kw-turbine1 и --capacity-kw-turbine2 нужно заменить на фактическую установленную мощность. Если параметры не указаны, прогноз мощности всё равно строится, но абсолютная энергия не рассчитывается.

8. Как проверить решение

Жюри может повторить следующий сценарий:

  1. Клонировать репозиторий и установить зависимости.
  2. Убедиться, что CSV-файлы находятся в datasets/.
  3. Запустить benchmark из раздела 7.2.
  4. Проверить напечатанные в консоли MAE, RMSE, WMAPE и число использованных validation origins.
  5. Открыть JSON-результат:
cat outputs/ml_benchmark.json

В Windows PowerShell:

Get-Content -Raw .\outputs\ml_benchmark.json

Для проверки полного пользовательского сценария запустите команду из раздела 7.4 с доступом к интернету и проверьте:

  • outputs/weather_archive/manifest.jsonl и сохранённые погодные snapshot;
  • outputs/forecast/forecast_turbine_*.csv;
  • outputs/forecast/forecast_manifest.jsonl;
  • колонки power_p10_norm, power_p50_norm, power_p90_norm и, при заданной мощности, energy_p50_kwh/energy_p50_mwh.

9. Данные и интеграции

Исторические данные

Используются два CSV-файла:

  • datasets/Dataset HackAlemAI для участников 11.03.2023-28.02.2026 - turbine 1.csv;
  • datasets/Dataset HackAlemAI для участников 11.03.2023-28.02.2026 - turbine 2.csv.

Первые пять колонок интерпретируются как идентификатор, время, средняя скорость ветра, нормализованная активная мощность и средняя температура окружающей среды. Исходная периодичность — 10 минут.

Погодный API

weather_archive.py использует Open-Meteo Single Runs API:

https://open-meteo.com/en/docs/single-runs-api

Для турбин заданы координаты:

  • turbine 1: 43.645150, 78.535604;
  • turbine 2: 43.643194, 78.538833.

Запрашиваются temperature_2m, wind_speed_10m и wind_speed_80m. Используется модель ecmwf_ifs, часовой пояс Asia/Almaty, выбор наземной grid cell и консервативная задержка доступности запуска 6 часов.

Каждый snapshot содержит исходный JSON, нормализованный CSV и запись provenance в manifest.jsonl, включая URL, выбранный model run, координаты, горизонт, время получения и SHA-256 ответа.

10. Ограничения текущей версии

  • нет веб-интерфейса, публичного API, планировщика и production-мониторинга;
  • deployed-версия отсутствует, запуск выполняется локально через CLI;
  • validation в ml_baseline.py использует фактические исторические погодные значения, а не архивный forecast, доступный на момент исторического запуска;
  • LightGBM является опциональным для работы forecast_agent.py: без него используется Ridge fallback, а интервалы строятся по residual band;
  • веса ансамбля заданы конфигурационно и автоматически не подбираются по out-of-fold-прогнозам;
  • абсолютная энергия зависит от корректно переданной установленной мощности;
  • рекурсивный прогноз может накапливать ошибку на длинном горизонте;
  • архивные погодные snapshot сохраняются локально, но автоматическое управление сроком их хранения не реализовано;
  • текущая версия работает с двумя заранее заданными турбинами и не предоставляет универсальный интерфейс конфигурации станции.

11. Deployed-версия

В текущем репозитории deployed-версия не обнаружена. Решение запускается локально командами из раздела 7.

Исходный репозиторий: https://github.com/BAITC-Hacks/hack-54f1ae1b-astana-hackers

Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
9
Авторы
4
Файлы
60
Ветки
4

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

janymau 3Arkazhan 2ErsultanN 2janymau 2

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

  • 2026-09-23 17:44Create comprehensive Russian README for WindPower Agentjanymau
  • 2026-09-23 17:42BackendArkazhan
  • 2026-09-23 17:40other filesjanymau
  • 2026-09-23 17:35Merge pull request #1 from BAITC-Hacks/new-mljanymau
  • 2026-09-23 17:27more-powerfull-ml-modelsArkazhan
  • 2026-09-23 16:28ML-baseline-readmejanymau
  • 2026-09-23 16:18ML-baselinejanymau
  • 2026-09-23 17:42test-frontendErsultanN
Все коммиты (9)
  • 2026-09-23 16:52open-meteo api featureErsultanN
Структура репозитория (60 файлов)
README.md
artifacts/agent_log_production.jsonl
artifacts/agent_log_validation.jsonl
artifacts/metrics_validation.json
artifacts/missing_turbine_1.json
artifacts/missing_turbine_2.json
artifacts/model_selection.json
artifacts/model_selection_basis.json
artifacts/predictions_production.csv
artifacts/predictions_validation.csv
artifacts/previous_runs_check.json
artifacts/revisions_production.csv
artifacts/revisions_validation.csv
artifacts/run_summary.json
artifacts/selected_production.csv
artifacts/selected_validation.csv
backend/wind_agent/__init__.py
backend/wind_agent/analysis.py
backend/wind_agent/api.py
backend/wind_agent/backtest.py
backend/wind_agent/chat.py
backend/wind_agent/config.py
backend/wind_agent/data.py
backend/wind_agent/llm.py
backend/wind_agent/model.py
backend/wind_agent/orchestrator.py
backend/wind_agent/tools.py
backend/wind_agent/weather_agent.py
data/case.pdf
data/raw/turbine_1.csv
data/raw/turbine_2.csv
datasets/Dataset HackAlemAI для участников 11.03.2023-28.02.2026 - turbine 1.csv
datasets/Dataset HackAlemAI для участников 11.03.2023-28.02.2026 - turbine 2.csv
forecast_agent.py
frontend/index.html
frontend/package-lock.json
frontend/package.json
frontend/src/main.jsx
frontend/src/style.css
frontend/vite.config.js
install_advanced_ml.ps1
integration_forecast_local/forecast_manifest.jsonl
integration_forecast_local/forecast_turbine_1_20260131T0000.csv
integration_forecast_local/forecast_turbine_2_20260131T0000.csv
ml_baseline.py
outputs/ml_benchmark.json
requirements.txt
tests/test_chat.py
tests/test_core.py
weather_archive.py
weather_archive_test/manifest.jsonl
weather_archive_test/runs/turbine_1__asof-20260130T1900Z__run-20260130T1200Z__retrieved-20260923T113345Z__11a60b0f/forecast.csv
weather_archive_test/runs/turbine_1__asof-20260130T1900Z__run-20260130T1200Z__retrieved-20260923T113345Z__11a60b0f/response.json
weather_archive_test/runs/turbine_2__asof-20260130T1900Z__run-20260130T1200Z__retrieved-20260923T113346Z__7a6a903e/forecast.csv
weather_archive_test/runs/turbine_2__asof-20260130T1900Z__run-20260130T1200Z__retrieved-20260923T113346Z__7a6a903e/response.json
weather_archive_test2/manifest.jsonl
weather_archive_test2/runs/turbine_1__asof-20260130T1900Z__run-20260130T1200Z__retrieved-20260923T113509Z__658a0902/forecast.csv
weather_archive_test2/runs/turbine_1__asof-20260130T1900Z__run-20260130T1200Z__retrieved-20260923T113509Z__658a0902/response.json
weather_archive_test2/runs/turbine_2__asof-20260130T1900Z__run-20260130T1200Z__retrieved-20260923T113509Z__6abb764c/forecast.csv
weather_archive_test2/runs/turbine_2__asof-20260130T1900Z__run-20260130T1200Z__retrieved-20260923T113509Z__6abb764c/response.json
Ветки (4)

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

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

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