WindPilot
Сервис, который превращает прогноз погоды в почасовой прогноз нормализованной мощности двух ветротурбин на 24–48 часов.
О проекте
Команда: Entropy
Кейс HackAlem.ai: Энергетика — Самрук-Казына
Стадия: Доведённый продукт
Задача кейса: AI-агент, прогнозирующий выработку ветровой электростанции по погодным данным
Суть
Сервис, который превращает прогноз погоды в почасовой прогноз нормализованной мощности двух ветротурбин на 24–48 часов. В дашборде есть сравнение с фактом, история, погода на площадке, подбор периода по порогу мощности, журнал шагов агента и карта ветра Windy.
Как устроено
Исходные CSV по турбинам (10-минутный шаг) агрегируются в часы с учётом часового пояса Asia/Almaty. Для каждой турбины своя модель HistGradientBoostingRegressor из двух компонент: базовая зависимость мощности от ветра и температуры плюс поправка по архивной прогнозной погоде (горизонт, циклические признаки часа). Погода берётся из Open-Meteo ECMWF IFS (ветер 100 м, температура 2 м), архив из Single Runs API. Детерминированный агент без LLM проходит шесть шагов (погода → проверка → признаки → модели → проверки → сохранение версии) и автообновляется каждые 900 с.
Ключевые решения
- HistGradientBoostingRegressor
- двухступенчатая модель (база + поправка по прогнозной погоде)
- бэктест с временной границей обучения
- baseline по последнему измерению
- планировщик автообновления
- версионирование расчётов
Метрики
Январь 2026, горизонт 1–48 ч: MAE 0,2093/0,2083, RMSE 0,2663/0,2657 (турбины 1/2) против бейзлайна MAE 0,3413/0,3440, RMSE 0,4486/0,4544; смещение +0,089
Особенности
Аккуратная валидация: модели обучены строго до момента прогноза, отдельная августовская ретроспектива, проверка перехода часовых поясов. В README честно названы систематическое завышение мощности (+0,09) и допущение о доступности выпуска IFS через 12 ч. Runtime-артефакты упакованы в zip с проверкой SHA-256, есть офлайн-дашборд и демо на Render.
Стек
Python · FastAPI · Uvicorn · scikit-learn · Open-Meteo · Windy · JavaScript · HTML · CSS · Render
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-16b87636-entropy.
README
README.mdWindPilot — прогноз выработки ВЭС
Команда Entropy · HackAlem AI
https://windpilot-demo.onrender.com/
WindPilot превращает прогноз погоды в почасовой прогноз относительной мощности двух ветротурбин на 24–48 часов. Пользователь видит ожидаемую выработку, сравнивает расчёт с историческими измерениями и просматривает реальные шаги агента.
Агент самостоятельно получает погоду по координатам установок, проверяет входы, запускает модель, анализирует результат и создаёт новую версию при изменении данных. Готовые модели и архив включены в репозиторий: для запуска сайта обучение не требуется.
Мощность модели — число от 0 до 1; интерфейс показывает его как 0–100%. Это нормализованная мощность по шкале датасета, не МВт, не вероятность и не процент точности. Обзор двух установок — среднее их нормализованных мощностей, а не суммарная мощность ВЭС.
Быстрый запуск
Нужны Python 3.11, Git и доступ к репозиторию. Интернет нужен для установки зависимостей, текущей погоды и карты. Сохранённые исторические расчёты работают из комплекта данных.
Windows / PowerShell
git clone https://github.com/BAITC-Hacks/hack-16b87636-entropy.git
cd hack-16b87636-entropy
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe scripts/restore_runtime.py
.\.venv\Scripts\python.exe -m uvicorn windpilot.api:app --host 127.0.0.1 --port 8000 --workers 1
Linux / macOS
git clone https://github.com/BAITC-Hacks/hack-16b87636-entropy.git
cd hack-16b87636-entropy
python3.11 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python scripts/restore_runtime.py
.venv/bin/python -m uvicorn windpilot.api:app --host 127.0.0.1 --port 8000 --workers 1
Откройте http://127.0.0.1:8000/. Документация API: http://127.0.0.1:8000/docs. Проверка сервера: /health.
Один worker нужен для согласованной работы встроенного планировщика и сохранения версий расчёта. Не запускайте несколько процессов на одну папку результатов.
restore_runtime.py проверяет SHA-256 файлов из deployment/runtime.zip по манифесту. Повторное восстановление не перезаписывает изменённые локальные артефакты. Исходные CSV и пути к компьютеру разработчика для просмотра не нужны.
Просмотр без сервера: откройте dashboard.html как файл. В нём есть 58 сохранённых расчётов, график, таблица и подбор периода. Полная история с фактом, текущая погода, живой прогноз и карта требуют FastAPI. Автономный режим явно обозначен.
Возможности
| Раздел | Что можно сделать |
|---|---|
| Сегодня и завтра | Получить прогноз мощности на текущих погодных входах, с отметкой демо-режима. |
| Обзор и «По часам» | Посмотреть график, пик и минимум, значения по установкам, погодные входы; скачать CSV. |
| Прогноз и факт | Сравнить январскую проверку и августовскую ретроспективу с измерениями; один прогноз на час, горизонт 1–24 часа. |
| История | Выбрать до 31 дня, посмотреть последние измерения, пропуски и происхождение расчётов. |
| Погода на площадке | Посмотреть температуру, ветер, порывы, влажность; прогноз по дням с выбором параметров. |
| Подобрать период | Найти часы с мощностью не ниже порога или с минимальным средним уровнем. Это не разрешение на ремонт и не гарантия производства. |
| Работа агента | Проследить шесть шагов, реальные отметки времени, версию модели, проверки и автообновление. |
| Карта ветра | Открыть независимый слой Windy, приблизить установки, выбрать прогнозный день и час. |
Среднее двух установок выводится только при наличии обоих значений за час. Пропуски остаются пустыми ячейками и разрывами линий. MAE/RMSE доступны в отчётах и API, без перегрузки бизнес-интерфейса.
Данные и доступные периоды
Исходные данные — два CSV, по одному на турбину: время, скорость ветра, нормализованная активная мощность и температура. Интервал — 10 минут. Подготовка проверяет даты, дубликаты, пропуски и диапазоны; час считается средним только при наличии всех шести корректных записей.
Часовой пояс CSV подтверждён как Asia/Almaty. При переводе в UTC учитывается историческое изменение смещения; неоднозначные локальные отметки исключаются, а не угадываются. Координаты и погодная конфигурация находятся в config.json.
| Период | Фактическая мощность | Прогноз мощности |
|---|---|---|
| 11.03.2023 — 31.01.2026 | Есть, с пропусками | Сохранён только для подготовленных проверочных периодов. |
| Август 2025 | 737 полных часов на каждую турбину | Отдельный бэктест: 648 часов прогноза, 641 час с парой «прогноз — факт» на турбину. |
| Январь 2026 | 744 часа на каждую турбину | Отложенная проверка; обучение строго до первого момента прогноза. |
| Февраль 2026 | Нет в предоставленных файлах | Воспроизведение на архивной погоде. |
| Август 2026 | Нет | Сохранённых расчётов нет. |
| Текущая дата | Нет подключения к измерениям мощности | Живой прогноз; качество на текущей дате не проверено. |
Несмотря на название исходных файлов с упоминанием февраля, фактические записи заканчиваются 31 января 2026. Погодный API не предоставляет фактическую выработку наших турбин.
В августе 2025 прогноз отсутствует 7–10 августа: в архиве не нашлось полных погодных входов. Для 6 августа использован выпуск на 24 часа старше исходно выбранного. Замена отражена в метаданных и CSV; более свежие выпуски из будущего не использовались. Августовский отчёт.
Как работает агент
flowchart LR
A[Запрос пользователя или таймер] --> B[Получить погоду Open-Meteo]
B --> C[Проверить входы и их версию]
C --> D{Входы изменились?}
D -->|Да| E[Подготовить признаки]
E --> F[Запустить модели турбин]
F --> G[Сформировать почасовой прогноз]
G --> H[Проверить диапазон, пропуски и изменения]
H --> I[Сохранить CSV, JSON и журнал]
D -->|Нет| J[Вернуть сохранённый расчёт]
Это агент с явной цепочкой действий и проверок, без LLM-чата и управления оборудованием. Обучение — отдельная операция; обычный прогноз веса не меняет.
Исторический агент проверяет границу обучения и соответствие погодной конфигурации. Живой агент сравнивает новые входы с последним запуском, а результаты — по совпадающим целевым часам. Невалидная или неполная погода приводит к понятной ошибке. Число ограничений предсказаний до диапазона [0, 1] записывается в анализ.
По умолчанию FastAPI запускает живую проверку при старте и затем через 900 секунд после завершения предыдущего цикла. Настройка: WINDPILOT_AUTO_REFRESH_SECONDS; 0 отключает таймер, положительное значение должно быть не меньше 30. Статус — /agent/status. Переменную задавайте в окружении процесса; .env автоматически используется только для ключа карты.
Версии и журнал хранятся в artifacts/api_runs/ для исторического API и artifacts/live_runs/ для живых расчётов. Фоновое обновление не заменяет выбранную историческую дату текущими данными.
ML-модель и качество
Используется scikit-learn HistGradientBoostingRegressor, отдельно для каждой установки. У каждой модели два компонента:
- Базовая зависимость мощности от наблюдённых ветра и температуры.
- Поправка по архивной прогнозной погоде: ветер, температура, горизонт, циклические признаки часа UTC и выход базовой модели.
Фиксирован random_seed=42. LightGBM, LSTM, лаги фактической мощности и прогнозные интервалы в текущую архитектуру не входят.
Основная модель обучена до 31.01.2026, 23:00 местного времени; январская проверочная — до 31.12.2025, 23:00. Для августа используется третья независимая модель, обученная до 31.07.2025, 23:00. Обучающие часы должны завершиться к соответствующей границе.
Январь 2026, горизонт 1–48 часов: метрики по 1464 парам «момент прогноза / целевой час» на турбину. Пересекающиеся прогнозы оцениваются отдельно; это 744 уникальных часа, а не 1464 независимых наблюдения.
| Установка | MAE модели | RMSE модели | MAE бейзлайна | RMSE бейзлайна |
|---|---|---|---|---|
| 1 | 0,2093 | 0,2663 | 0,3413 | 0,4486 |
| 2 | 0,2083 | 0,2657 | 0,3440 | 0,4544 |
Бейзлайн — последнее завершённое известное измерение, если его возраст не больше трёх часов. Ошибки выражены на шкале мощности 0–1: MAE 0,20 означает отклонение в среднем на 20 процентных пунктов, а не «точность 80%».
Экран «Прогноз и факт» использует только горизонт 1–24 часа, поэтому его выборка отличается от таблицы выше. Разрезы сохранены в artifacts/metrics.json после восстановления пакета. Январское среднее смещение составляет +0,0892/+0,0902: модель систематически завышает мощность. Физическая отсечка при экстремальном ветре не моделируется надёжно.
- Январская диагностика: bias, режимы мощности, погода, переобучение и тесты
- Август 2025: отдельная ретроспектива, покрытие и метрики
- Общий аудит проекта
Погода, карта и ограничения
Для мощности используется Open-Meteo / ECMWF IFS: ветер на 100 м и температура на 2 м. Архив запрашивается через Single Runs API, текущая погода — через Forecast API.
В историческом расчёте выпуск выбирается с допущением доступности через 12 часов после инициализации. Инициализация не равна публикации. Первоначальное оперативное происхождение архива независимо не подтверждено; для части истории IFS поставщик упоминает hindcast. Результаты представлены как ретроспективное воспроизведение, а не журнал прогнозов, действительно выданных нашей системой в те даты.
Живой API не сообщает используемое здесь время выпуска: weather_issued_at=null. Возраст выпуска не выдумывается. В живом прогнозе нет бейзлайна, поскольку нет свежих измерений мощности. «Онлайн» означает доступ к погодному источнику, а не соединение с энергосистемой.
Карта Windy / GFS у поверхности — отдельная визуализация. Её время не меняет входы модели мощности. Доступны ближайшие прогнозные дни, подтверждённые Windy; архива прошлых месяцев на карте нет. Погода за прошлые периоды в разделе истории относится к точкам установок.
Карта необязательна. Для неё задайте WINDY_MAP_API_KEY в окружении или локальном .env; без ключа остальные разделы работают. Ключ браузерный, поэтому ограничьте его разрешёнными доменами. .env и ключ не входят в Git. Бесплатный Windy Testing предназначен для разработки; условия публичного использования проверьте отдельно. Настройка карты, документация Windy.
У системы нет доверительных интервалов P10/P90, подтверждённой диагностики остановок, модели обледенения, подключения к энергосистеме и автоматического управления турбинами. Визуальные элементы не имитируют эти возможности.
HTTP API
| Метод и маршрут | Назначение |
|---|---|
GET / | Дашборд. |
GET /health | Состояние процесса и наличие основной модели. |
GET /forecast?date=2026-02-15&horizon=48&offline=true | Исторический прогноз; date — первый целевой день, origin — 23:00 предыдущего дня. |
GET /forecast/live?horizon=48 | Живой демонстрационный прогноз на 24 или 48 часов. |
GET /history?start=2026-01-01&end=2026-01-31 | Факт и прогноз, обе даты включены, максимум 31 день. |
GET /history/availability | Границы наблюдений и подготовленные прогнозные периоды. |
GET /weather/overview?turbine_id=1 | Текущая погодная оценка и семь дней прогноза; refresh=true обновляет кэш. |
GET /weather/status | Проверка доступности Open-Meteo. |
GET /agent/status | Состояние фонового цикла, последняя и следующая проверки. |
GET /quality | Январские метрики и допущения проверки. |
GET /map/windy | Страница карты внутри iframe. |
/forecast: offline=true запрещает сеть; refresh=true проверяет архив через сеть, если offline выключен. Январские запросы выбирают проверочную модель. Августовская ретроспектива читается через /history, а не основной /forecast.
Основные поля прогноза: run_id, turbine_id, forecast_origin, valid_at, power_pred, weather_source, weather_issued_at, model_version. Ответ также содержит status (created/reused), analysis, trace и baseline. История возвращает power_actual, погодные поля, вид расчёта и уведомления; недоступные значения — null.
Шкала исторического обзора выбирает дату origin, API принимает дату первого целевого часа. Например, 31 января в 23:00 соответствует /forecast?date=2026-02-01.
Воспроизведение и разработка
Команды ниже выполняются с Python из созданного окружения: в PowerShell замените python на .\.venv\Scripts\python.exe, в Linux/macOS — на .venv/bin/python.
Расчёты из готового пакета
python -m windpilot forecast --origin 2026-01-31T23:00:00+05:00 --horizon 48 --offline
python -m windpilot replay --start 2026-02-01 --end 2026-02-28 --horizon 48 --offline --out artifacts/february_replay
python scripts/backtest_august_2025.py
replay выполняет 28 запусков перед целевыми днями 1–28 февраля. В дашборде 58 расчётов: 29 origins с 31 января по 28 февраля, каждый на 24 и 48 часов; последний origin прогнозирует уже март. Полные горизонты сохраняются даже за границей месяца.
Августовский скрипт повторно обучает только отдельную августовскую модель. С готовым кэшем он работает без сети; --fetch-weather разрешает получение архива. Основные веса и январские результаты защищены проверками контрольных сумм.
Обучение из исходных CSV
Этот шаг необязателен для демонстрации. Положите два исходных файла в data/raw/ под указанными именами либо передайте свои пути. Папка data/ исключена из Git. Ожидаются исходные русские заголовки столбцов; их сопоставление — в data.py.
python -m windpilot prepare --turbine-1 "data/raw/turbine1.csv" --turbine-2 "data/raw/turbine2.csv" --out data/retrained
python -m windpilot fetch-weather --start 2025-10-01 --end 2026-03-01
python -m windpilot train --history data/retrained/hourly.csv --weather-start 2025-10-01 --validation-start 2026-01-01 --validation-end 2026-01-31 --final-cutoff 2026-01-31T23:00:00+05:00 --out artifacts/retrained
Результат записывается отдельно от поставляемых моделей. Диапазон наблюдений читается из CSV; границы эксперимента задаются параметрами CLI и не расширяются автоматически при поступлении новых данных. Для прогноза с новыми весами укажите --model artifacts/retrained/model.joblib. Недостающие погодные выпуски нужно получить до обучения.
Сборка интерфейса и комплекта
python scripts/build_dashboard.py
python scripts/package_runtime.py
Первая команда собирает HTML из web/, сохраняя существующие 58 расчётов. Вторая упаковывает текущие подготовленные артефакты и контрольные суммы; запускайте её после осознанного обновления данных. Для пересчёта встроенных 58 запусков служит python -m windpilot.export_dashboard: ему нужны диагностические зависимости и погодный кэш до первого целевого дня 01.03.2026.
Проверки
API-тестам и проверке комплекта нужен httpx, поэтому установите диагностические зависимости:
python -m pip install -r requirements-diagnostics.txt
python -m unittest discover -s tests -v
python scripts/check_deployment_bundle.py
DOM-тесты интерфейса — отдельно, нужен Node.js (проверено на версии 24):
npm install --prefix artifacts/ui_checks [email protected] --no-audit --no-fund
node tests/dashboard.test.cjs
node tests/weather_ui.test.cjs
node tests/history_ui.test.cjs
node tests/map_time.test.cjs
Перед текущим релизом прошли 36 Python-тестов, четыре набора DOM-тестов и воспроизведение 58 расчётов в изолированной папке без исходных CSV. В браузере проверены январь/август, отсутствие факта, CSV, обе темы, мобильный вид, живой прогноз и выбор часа Windy. Локальная проверка не подтверждает доступность публичного сервиса.
Расширенная диагностика: python -m windpilot.predict_checks. Для python -m windpilot.diagnostics нужны исходные CSV; пути передаются через --turbine-1 и --turbine-2. Диагностика не изменяет основные веса.
Публикация
Подготовлен render.yaml: один FastAPI-сервис, отдающий HTML и API с одного домена. Раздельный фронтенд и CORS не требуются. Сборка восстанавливает комплект моделей; обучение при деплое не выполняется.
Публичный HTTPS-деплой пока не подтверждён. Для публикации Render должен получить доступ к закрытому репозиторию организации; подключение только личного GitHub-аккаунта его не заменяет. Порядок публикации и проверки.
На Render Free сервис засыпает после простоя; первое обращение запускает его заново. Во время сна фоновая проверка погоды не выполняется. Новые живые расчёты на непостоянном диске могут теряться после перезапуска; исходный комплект восстанавливается из репозитория. Это ограничение хостинга, не непрерывная работа 24/7. Условия Render Free.
После получения фактической ссылки проверьте её с другого устройства и запустите python scripts/check_public_service.py https://ВАШ-СЕРВИС.onrender.com — замените пример реальным адресом.
Структура проекта
| Путь | Содержимое |
|---|---|
windpilot/ | Подготовка данных, модель, погода, агенты, планировщик, FastAPI, история. |
web/ | Исходники HTML/CSS/JS, история, погода и отдельная страница Windy. |
dashboard.html | Собранный интерфейс и встроенные исторические расчёты. |
config.json | Координаты, часовой пояс, источник погоды и задержка доступности. |
scripts/ | Сборка, упаковка, восстановление, проверка деплоя и августовский бэктест. |
tests/ | Python- и JavaScript-проверки. |
reports/ | Диагностика и описание ограничений. |
deployment/ | Комплект моделей/данных, манифест, инструкции хостинга и карты. |
data/, artifacts/ | Рабочие данные и результаты после восстановления; исключены из Git. |
Комплект содержит основную, январскую проверочную и августовскую модели, подготовленную историю, архив погоды и результаты. Исходные CSV, .env, ключи, виртуальное окружение и новые живые пользовательские запуски в него не включаются.
Авторы коммитов
История коммитов
- 2026-09-23 17:54Add demo URL to READMEAssem Abdikarim
- 2026-09-23 17:53Remove jury scenario section from READMEAssem Abdikarim
- 2026-09-23 17:46Fix formatting by removing an empty lineSarsenbayeva Aidana
- 2026-09-23 17:45Fix formatting in deployment section of READMEAssem Abdikarim
- 2026-09-23 17:36docs: rewrite WindPilot README for judges and reproducible setupMevinss
- 2026-09-23 17:19Fix actual-series legend contrast in history chartsMevinss
- 2026-09-23 17:16feat: add live site weather and historical forecast comparisonMevinss
- 2026-09-23 16:22Publish business dashboard with live agent and optional wind mapMevinss
Все коммиты (15)
- 2026-09-23 15:45Document web interface and agent architectureMevinss
- 2026-09-23 15:10Package WindPilot for single-service Render deploymentMevinss
- 2026-09-23 15:03Refine dashboard interface and update documentationMevinss
- 2026-09-23 14:44Add dashboard testsMevinss
- 2026-09-23 14:43Add portable dashboard exportMevinss
- 2026-09-23 14:40Add WindPilot dashboardMevinss
- 2026-09-23 14:39Add WindPilot forecasting pipeline, API, tests and diagnosticsMevinss
Структура репозитория (56 файлов)
.env.example .gitignore README.md config.json dashboard.html deployment/README.md deployment/WINDY.md deployment/manifest.json deployment/runtime.zip render.yaml reports/august_2025.md reports/january_2026_diagnostics.md reports/power_curve_january.png reports/windpilot_project_audit_2026-09-23.md requirements-diagnostics.txt requirements.txt scripts/backtest_august_2025.py scripts/build_dashboard.py scripts/check_deployment_bundle.py scripts/check_public_service.py scripts/package_runtime.py scripts/restore_runtime.py tests/dashboard.test.cjs tests/history_ui.test.cjs tests/map_time.test.cjs tests/test_api.py tests/test_dashboard.py tests/test_history_view.py tests/test_live_agent.py tests/test_map_view.py tests/test_pipeline.py tests/test_weather_overview.py tests/weather_ui.test.cjs web/dashboard.css web/dashboard.js web/dashboard.template.html web/history.js web/weather.js web/windy.html windpilot/__init__.py windpilot/__main__.py windpilot/agent.py windpilot/api.py windpilot/common.py windpilot/dashboard_data.py windpilot/data.py windpilot/diagnostics.py windpilot/export_dashboard.py windpilot/history_view.py windpilot/live.py windpilot/map_view.py windpilot/model.py windpilot/predict_checks.py windpilot/scheduler.py windpilot/weather.py windpilot/weather_overview.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.