AAYMA
RU
Войти

Wind48

AI-агент ежедневно выпускает почасовой вероятностный прогноз P10/P50/P90 выработки ВЭС из двух турбин на 48 часов по архивным прогнозам погоды…

Доведённый продукт
Команда «Gjigi» 5💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: Gjigi
Кейс HackAlem.ai: Энергетика — Самрук-Казына
Стадия: Доведённый продукт

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

Суть

AI-агент ежедневно выпускает почасовой вероятностный прогноз P10/P50/P90 выработки ВЭС из двух турбин на 48 часов по архивным прогнозам погоды, опубликованным к моменту выпуска. Сделана ретро-симуляция февраля 2026 и Streamlit-дашборд.

Как устроено

SCADA двух турбин (10 мин) служит только целевой переменной. Признаки строятся из архивных NWP-прогонов Open-Meteo (ECMWF IFS 9 км, GFS, ICON, ECMWF 0.25°) с правилом as_of против утечки: ансамбль, соседние часы, плотность воздуха, сдвиг ветра. Модель: квантильный LightGBM, изотоническая кривая мощности и конформная калибровка интервала. Агент на OpenAI function calling (gpt-4.1, 10 инструментов с обязательным полем reason) сам скачивает погоду, отбраковывает источники-выбросы, пересчитывает прогноз при выходе нового прогона, валидирует результат, рассчитывает заявку на балансирующий рынок и пишет сводку диспетчеру. Есть fallback RuleAgent.

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

  • LightGBM quantile regression
  • изотоническая кривая мощности
  • конформная калибровка
  • NWP-ансамбль ECMWF/GFS/ICON
  • защита от утечки as_of
  • function calling
  • rule-based fallback agent
  • оптимальный квантиль для заявки на БРЭ
  • стресс-тест агента

Метрики

MAE 0.150 (D+1) / 0.176 (D+2) доли номинала на январе 2026; −9% MAE к NWP+кривая мощности; агент −7% MAE D+1 (0.162→0.150); при испорченном источнике 0.160 против 0.307; покрытие P10–P90 81%/77%; −58% стоимости небалансов к климатологии

Особенности

Среди лучших по инженерной честности. make verify побитово воспроизводит все 28 выпусков февраля. Отсутствие утечки проверяется тестом (удаление будущих прогонов не меняет прогноз). Вклад агента измерен отдельно. Добавлена экономика небалансов и ограничение в коде: агент не может исключить исправный ECMWF, потому что в стресс-тесте LLM пыталась это сделать.

Стек

Python · pandas · NumPy · PyArrow · LightGBM · scikit-learn · Streamlit · Plotly · Matplotlib · pytest · Open-Meteo API · Make

Модели

gpt-4.1


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

README

README.md

HackAlem AI — Agentic AI для прогноза выработки ВЭС на 24–48 ч

Что решает продукт

Выработка ветровой электростанции зависит от ветра, а ВЭС должна заранее сообщать, сколько энергии выдаст в каждый час следующих суток: по этому плану работают энергосистема и балансирующий рынок. Ошибка стоит денег: за недовыработку против плана станция платит штраф, перевыработка продаётся дешевле. Продукт — AI-агент, который каждый день сам делает почасовой прогноз выработки ВЭС на следующие 24–48 часов по открытым прогнозам погоды и сам следит за качеством этого прогноза.

Задача хакатона: воспроизвести работу так, как если бы прогноз выпускался в прошлом, — 31.01.2026, затем 01.02 и так далее до конца февраля, используя только те прогнозы погоды, которые были опубликованы на каждый момент.

Как это работает — подробнее: Агент каждый день в 10:00 (время станции) выпускает почасовой вероятностный прогноз (P10/P50/P90) выработки ВЭС из двух турбин на следующие двое суток. Для прогноза он использует только архивные погодные прогнозы, опубликованные к моменту выпуска. Агент сам проверяет входные данные, запускает ML-модель, проверяет результат, отбрасывает неисправные источники, пересчитывает прогноз при выходе нового прогона погодной модели и пишет сводку для диспетчера. Каждое решение с объяснением попадает в журнал.

ИтогЗначение
Результат (файл сдачи)outputs/forecast_feb2026.csv: 28 выпусков (31.01–27.02.2026) × 48 ч, почасовой прогноз выработки ВЭС
Точность, репетиция на январе 2026 (модели не видели дек–янв)MAE 0.150 на D+1, 0.176 на D+2 (доля номинала), LLM-агент
Выигрыш к классическому «NWP + кривая мощности»−9% MAE (holdout дек–янв), +6% в среднем за 12 месяцев CV
Вклад агента (пересчёт на свежем прогоне, отбраковка источников)−7% MAE на D+1 (0.162 → 0.150); при испорченном источнике погоды ошибка конвейера ×2 (0.307), агента — 0.160
Экономический эффект (план подачи на БРЭ)−58% стоимости небалансов к климатологии, −28% за счёт оптимального квантиля вместо медианы
Интервал P10–P90покрытие 81% / 77% на D+1 / D+2 (цель 80%)
Защита от утечкиправило публикации + тесты + аудит каждого выпуска

Ключевые результаты

Быстрый старт для жюри (3 команды, ~2 мин, интернет не обязателен)

python3 -m pip install -r requirements.txt && python3 -m pip install -e .
make verify    # агент заново делает все 28 выпусков февраля и сверяет с эталоном → REPRODUCED
make demo      # дашборд http://localhost:8501: прогноз, журнал решений агента, репетиция против факта, живой запуск

Итоговый прогноз — outputs/forecast_feb2026.csv. LLM-режим агента включается ключом в .env (раздел 8). Без ключа тот же агент работает на правилах: это детерминированный режим, его и проверяет make verify. Нужен Python ≥ 3.11 и make (есть на macOS/Linux; без make — команды из Makefile, например python3 scripts/verify.py).

Технологии

ЧтоЧем
ЯзыкPython 3.11+
Погодные данныеOpen-Meteo: архив точных прогонов ECMWF IFS 9 км (Single Runs API) и прогнозы GFS, ICON, ECMWF 0.25° (Previous Runs API)
Данные и признакиpandas, NumPy, PyArrow (parquet)
ML-модельLightGBM (квантильная регрессия P10/P50/P90), scikit-learn (изотоническая кривая мощности, baselines), конформная калибровка интервала
AI-агентOpenAI API (gpt-4.1), function calling (10 инструментов + обязательное объяснение каждого шага); запасной режим — агент на правилах
ДемоStreamlit + Plotly (дашборд), Matplotlib (графики отчётов)
Проверкаpytest (18 тестов), make verify (побитовое воспроизведение февраля)

Как проверить решение (≈5 минут)

  1. Установить и воспроизвести результат: make verify — агент заново делает все 28 выпусков (сам получает погоду → прогноз → проверки → пересчёт) и сверяет с эталоном docs/reference/ → REPRODUCED.
  2. Прогнать тесты: make test — 18 тестов: очистка данных, отсутствие утечки (удаление всех будущих прогонов погоды не меняет прогноз), признаки без данных SCADA, модель, полный цикл агента, работа без интернета и при пропаже любого источника.
  3. Посмотреть, какие прогнозы погоды использовал каждый выпуск: docs/forecast/issue_log.csv — все прогоны опубликованы до момента выпуска.
  4. Посмотреть решения агента: docs/agent/AGENT_REPORT.md и журналы docs/agent/logs/<дата>.json — каждый шаг с объяснением.
  5. Проверить качество на реальном факте: в данных нет факта за февраль, поэтому та же процедура прогнана на январе 2026 с моделями, не видевшими декабрь–январь: make rehearsal → docs/agent_rehearsal/AGENT_REPORT.md.
  6. Увидеть всё вживую: make demo → http://localhost:8501; make stress — агент против испорченных данных; make live — реальный прогноз на ближайшие двое суток (нужен интернет).

1. Архитектура

flowchart LR
    subgraph Data["Данные"]
        S[SCADA 2 турбины<br/>10 мин, 2023-03 … 2026-01]
        W[Open-Meteo архив прогнозов<br/>ECMWF 9 км точные прогоны<br/>GFS · ICON · ECMWF 0.25°]
    end
    W -->|fetch_weather:<br/>агент скачивает сам| ST[(Прогнозы в сессии<br/>init_time · valid_time · available_at)]
    ST -->|get_forecast as_of<br/>только опубликованное| F[Признаки<br/>ансамбль, соседние часы,<br/>плотность, сдвиг ветра, календарь]
    S -->|только как целевая переменная| M
    F --> M[LightGBM квантили<br/>P10/P50/P90 + mean<br/>+ кривая мощности<br/>+ конформная калибровка]
    M --> A
    subgraph A["Агент: OpenAI function calling / правила"]
        direction TB
        a0[fetch_weather] --> a1[check_weather_inputs] --> a2[run_forecast] --> a3[validate_forecast]
        a3 --> a4[compare_with_previous] --> a5[check_for_new_runs]
        a5 -->|новый прогон опубликован| a6[rerun_with_update]
        a3 -->|проблема: выброс источника| a2
        a6 --> ab[recommend_bid]
        a5 --> ab
        ab --> a7[finalize + сводка диспетчеру]
    end
    A --> O[Прогноз 48 ч · журнал решений · отчёт]

Полный цикл из ТЗ: получить внешние погодные данные → подготовить данные → запустить модель → сформировать почасовой прогноз → проанализировать результат → пересчитать при обновлении входных данных. Каждый шаг — отдельный инструмент агента (src/hackalem/agent/tools.py).

2. Агент

  • Мозг — LLM (OpenAI, function calling) (agent.py). Модель получает не сырые массивы, а факты от инструментов: покрытие и свежесть каждого источника, расхождение моделей, итоги валидации, правку к вчерашнему прогнозу, появление новых прогонов. Сама решает, что делать дальше. Каждый вызов обязан содержать поле reason — объяснение решения.
  • Запасной мозг — правила (RuleAgent) с теми же инструментами. Включается автоматически, если нет OPENAI_API_KEY или LLM недоступна, поэтому проект всегда воспроизводим.
  • Сам получает погоду (fetch_weather): сессия выпуска начинается пустой. Агент по координатам ВЭС запрашивает у Open-Meteo прогоны ECMWF, GFS и ICON, опубликованные к моменту выпуска (ответы кэшируются). Если сети нет, берёт те же данные из архива в репозитории и пишет об этом в журнал. Тест проверяет, что оба пути дают одинаковые входные данные.
  • Какие решения принимает агент:
    • исключает NWP-источник, который сильно отклоняется от медианы ансамбля или имеет пропуски (ECMWF 9 км не трогает, только если он сломан);
    • при сильном расхождении моделей расширяет интервал (ограниченно: он уже откалиброван);
    • пересчитывает прогноз, когда публикуется более свежий прогон (обычно ECMWF 00z в 14:00 по времени станции, тот же день D, до начала целевых суток) и сообщает, насколько изменился прогноз;
    • проверяет итог: пропуски, границы [0, 1], порядок квантилей, нереальные скачки, согласованность станции и турбин;
    • рассчитывает план подачи на балансирующий рынок (recommend_bid, раздел 6);
    • пишет сводку для диспетчера на русском.
  • Живой режим (make live): тот же агент выпускает реальный прогноз на ближайшие двое суток по самым свежим прогонам.
  • Страховка: агент не может завершиться без прогноза. Если LLM не вызвала finalize, срабатывает резервный путь.
  • Ограничения в коде, а не только в инструкции LLM: исправный ECMWF 9 км (главный и самый точный источник) исключить нельзя, инструмент откажет и объяснит почему. Это ограничение появилось после стресс-теста: LLM в запутанных ситуациях иногда пыталась его исключить.
  • Журнал решений: docs/agent/logs/<дата>.json (каждый шаг: инструмент, аргументы, объяснение, результат), общий отчёт — docs/agent/AGENT_REPORT.md.

Пример (выпуск 11.02.2026, LLM gpt-4.1, полный журнал) — каждое решение опирается на цифры:

 1 fetch_weather           | Начинаю сессии: требуется загрузить прогнозы погоды, опубликованные к 10:00 2026-02-11, чтобы оценить покрытие и свежесть NWP источников.
 2 check_weather_inputs    | Загружены прогнозы ECMWF (2 прогона: 18z и 12z), GFS, ICON и ECMWF 0.25°, всего 591 строк; необходимо проверить полноту и согласованность источников.
 3 run_forecast [-gfs]     | GFS отклоняется от медианы на 3.31 м/с (порог 3.0), остальные источники в пределах нормы; исключаю GFS из прогноза.
 4 validate_forecast       | Прогноз рассчитан без GFS, средняя ширина интервала D+1: 0.448, D+2: 0.328; проверяю корректность и аномалии.
 5 compare_with_previous   | Доступен прогноз предыдущего дня; необходимо сравнить текущий и предыдущий прогнозы для выявления крупных изменений.
 6 check_for_new_runs      | Среднее абсолютное изменение прогноза по сравнению с предыдущим днем 0.092, крупных пересмотров нет; проверяю наличие более свежих прогонов NWP.
 7 rerun_with_update       | Свежие прогоны ECMWF 00z и других моделей изменяют средний ветер на 0.59 м/с (порог 0.3); пересчитываю прогноз с обновленными данными.
 8 recommend_bid           | Прогноз обновлен с учетом свежих прогонов (ECMWF 00z и др.), среднее изменение ветра 0.59 м/с, средний p50 D+1: 0.19, D+2: 0.055; рассчитываю оптимальную заявку.
 9 finalize                | Прогноз и заявка обновлены с учетом свежих прогонов и исключения GFS; все проверки пройдены, крупных аномалий нет.

3. Протокол прогноза и защита от утечки

  • Выпуск в день D в 10:00 по времени станции (= время SCADA = UTC+6, установлено по данным, см. ниже), прогноз на локальные сутки D+1 и D+2 (48 часов; заблаговременность 14–61 ч). Первый выпуск — 31.01.2026, последний — 27.02.2026. Агент может выпустить обновление в тот же день D после публикации нового прогона.
  • Погода — только архивные прогнозы, а не реанализ (ERA5) и не факт:
    • ECMWF IFS 9 км — точные прогоны как были выпущены (Open-Meteo Single Runs API, 00/06/12/18z, с 03.2024);
    • GFS, ICON, ECMWF 0.25° — Open-Meteo Previous Runs API (значение, спрогнозированное за 1–3 суток). Мы проверили сравнением с точными прогонами: previous_dayN для часа t — это прогон floor_6h(t) − N суток.
  • Правило доступности: строка прогноза используется в момент as_of, только если init_time + задержка_публикации ≤ as_of (консервативно: ECMWF 8 ч, GFS и ICON 6 ч) — weather/store.py.
  • Проверки:
    • тесты: результат не меняется, если удалить все будущие прогоны; в признаках нет данных SCADA;
    • аудит каждого тестового выпуска с использованными прогонами — docs/forecast/issue_log.csv.
  • Обучение на тех же условиях, что и тест: процедура выпуска воспроизведена на истории (723 выпуска с 03.2024), модель учится на прогнозах погоды в том виде, в каком они были доступны в момент выпуска.
  • SCADA не используется как вход (например, «вчерашняя мощность»): данные организаторов заканчиваются 31.01, для февральских выпусков такого признака не было бы.

4. Данные и находки

Подробно — docs/eda/EDA.md, docs/weather/WEATHER.md.

  • Две турбины в ~350 м друг от друга ведут себя почти одинаково (корреляция 0.997). Цель — средняя станции, плюс отдельные модели T1 и T2.
  • Очистка: простои (мощность ≈0 при ветре ≥5 м/с) и ограничения мощности (видны «полки» 0.41/0.61/0.72) исключены из обучения, исходная мощность сохранена для оценки.
  • Время SCADA — фиксированное UTC+6: переход Казахстана на UTC+5 в 03.2024 в данных не отражён. Установлено кросс-корреляцией с прогнозами ECMWF. Ошибка в час напрямую испортила бы прогноз.
  • Датчик температуры — в гондоле (на 3–5 °C теплее воздуха), поэтому плотность воздуха считается по NWP.
  • Ансамбль 4 моделей лучше любой одной: MAE ветра на D+1 1.89 против 2.18 м/с у ECMWF 9 км. ECMWF занижает ветер на площадке на ~1 м/с, зимой сильнее.

5. Модель

src/hackalem/models/gbm.py, отчёт — docs/model/MODEL.md.

  • LightGBM, квантильная регрессия P10/P50/P90 и отдельная модель среднего. P50 оптимален для MAE, среднее — для RMSE.
  • 73 признака: по каждой NWP-модели (ветер 10/100 м, порывы, направление, температура, плотность воздуха, сдвиг ветра, заблаговременность), статистики ансамбля (среднее, разброс, min/max), соседние часы и значение в середине часа (SCADA — среднее за час, NWP — мгновенное значение), календарь и горизонт, физический признак — кривая мощности турбины по прогнозу ветра.
  • Конформная калибровка интервала (CQR) на данных вне выборки.
  • Число итераций — по early stopping. Финальные модели обучены на всей истории до 31.01.2026 (models/).

6. Результаты

Мощность нормализована к номиналу, поэтому MAE = nMAE.

Базовые прогнозы и модель, holdout декабрь 2025 – январь 2026 (обучение только до 01.12.2025):

МетодMAERMSE
Persistence («завтра как сегодня»)0.3770.492
Климатология (месяц × час)0.3210.361
ECMWF + кривая мощности0.2000.290
Ансамбль 4 NWP + кривая мощности + калибровка (лучший baseline)0.1920.268
LightGBM квантили0.1750.251

Rolling CV по 12 месяцам (02.2025–01.2026) и абляции:

ВариантMAERMSEПокрытие 80%
Полная модель0.1630.23179%
Без физического признака0.1620.23180%
Только ECMWF (без ансамбля)0.1720.24379%
Лучший baseline0.173——

→ Главный источник выигрыша — мультимодельный ансамбль NWP.

Сквозная репетиция на январе 2026 (весь конвейер по выпускам, модели обучены до 01.12.2025, сравнение с фактом SCADA):

MAE D+1MAE D+2RMSE D+1Покрытие 80% D+1 / D+2
Конвейер без агента (выпуск в 10:00)0.1620.1780.23873% / 75%
Агент на правилах (отчёт)0.1490.1800.21981% / 77%
Агент на LLM, OpenAI gpt-4.1 (отчёт)0.1500.1770.22181% / 77%

LLM принимает решения не строго детерминированно (в прогонах с gpt-4o-mini MAE D+1 была 0.144–0.150). В таблице — последний прогон с gpt-4.1, его журналы лежат в репозитории. Агент пересчитывает не всегда: в 23 из 31 январского выпуска свежий прогон заметно менял ветер (≥ 0.3 м/с), в остальных агент оставил выпуск 10:00 и объяснил почему.

Основной выигрыш агента — пересчёт после публикации свежего прогона (00z, в 14:00 того же дня D) и отбраковка источника-выброса (чаще всего GFS). Порог расширения интервала для агента на правилах подобран по этой же репетиции, поэтому его покрытие немного оптимистично. Остальные решения от январских данных не настраивались.

Репетиция на январе

Стресс-тест агента (docs/agent_stress/STRESS.md, make stress): намеренно портим входные данные на 10 январских выпусках и сравниваем с фактом SCADA.

СценарийКонвейер без агентаАгент (правила)Агент (LLM)Агент исключил источник
Данные исправны0.1620.1600.1600 / 10
GFS выдаёт мусор (×2.5 + 4 м/с)0.3070.1610.16010 / 10 — GFS
ICON недоступен0.1730.1690.1710–1 / 10 (пропуск модель переносит сама)
ECMWF 9 км (главный источник) недоступен0.2110.2050.2050 / 10 (прогноз продолжается на 3 моделях)

→ Обычный конвейер «проглатывает» сломанный источник, и ошибка удваивается. Агент замечает выброс и исключает его. При пропаже любого источника, даже главного, система продолжает выдавать прогноз (тесты test_forecast_survives_any_missing_source).

Экономика балансирующего рынка (docs/economics/ECONOMICS.md, make economics). Недовыработка против плана стоит дороже перевыработки (иллюстративно 40 и 18 тг/кВт·ч, параметры в config.yaml). Поэтому план, минимизирующий ожидаемые потери, — квантиль прогноза q* = c₊/(c₊+c₋) ≈ 0.31, а не медиана (инструмент агента recommend_bid). Стоимость небалансов на январе, на 1 МВт установленной мощности:

План на сутки вперёдтыс. тг / МВт·месЭкономия к климатологии
Климатология (без прогноза погоды)6 240—
Модель без агента, медиана4 00736%
Агент, медиана3 69141%
Агент, оптимальный квантиль P312 64058%

7. Результат

Прогноз на февраль

В папке outputs/ лежит только то, что требует задание, — outputs/forecast_feb2026.csv: почасовой прогноз выработки ВЭС на 24–48 ч для каждого ежедневного выпуска с 31.01 по 27.02.2026 (28 × 48 = 1344 строки).

КолонкаСмысл
issue_dateдень выпуска D (31.01 — первый, 27.02 — последний)
issue_timeмомент выпуска по времени станции: 10:00, или время пересчёта агентом после публикации свежего прогона (тот же день D)
datetimeпрогнозируемый час (время станции, начало часа), сутки D+1 и D+2
horizon_hчасов от выпуска до прогнозируемого часа
power_forecastпрогноз нормализованной активной мощности станции (среднее двух турбин, 0..1), медиана P50

Каждый час февраля покрыт двумя выпусками: за сутки (D+1) и за двое суток (D+2).

Всё остальное — материалы для проверки решения в docs/: отчёты этапов (EDA, погодный архив, baselines, модель), журнал решений агента (docs/agent/logs/*.json, AGENT_REPORT.md), аудит прогонов NWP по выпускам, стресс-тест, экономика, живой прогноз (docs/live/), прогноз без агента и репетиции на январе.

8. Запуск

git clone https://github.com/BAITC-Hacks/hack-ee3eb0d0-gjigi.git && cd hack-ee3eb0d0-gjigi
python3 -m pip install -r requirements.txt && python3 -m pip install -e .

# (необязательно) LLM-агент: положите свой ключ в .env (файл в .gitignore)
echo 'OPENAI_API_KEY=sk-...' > .env        # модель: OPENAI_MODEL, по умолчанию gpt-4.1

make agent        # агент по февралю 2026 → outputs/forecast_feb2026.csv + журнал в docs/agent/ (~1 мин на правилах, ~5 мин с LLM)
make rehearsal    # агент на январе 2026 + сравнение с фактом
make forecast     # тот же прогноз без агента (для сравнения) → docs/forecast/
make test         # 18 тестов (в т.ч. на отсутствие утечки) + make verify
make demo         # дашборд Streamlit → http://localhost:8501
make live         # реальный прогноз на ближайшие 2 суток по свежим прогонам (нужен интернет)
make stress       # стресс-тест: испорченные/пропавшие источники погоды, конвейер против агента
make economics    # стоимость небалансов на январе: медиана против оптимального квантиля

Дашборд (app.py): прогноз на февраль с интервалами (станция, T1, T2); любой выпуск с журналом решений агента и сводкой для диспетчера; репетиция на январе против факта SCADA; живой запуск агента на выбранную дату (правила или LLM).

Архив погодных прогнозов (data/weather/) и обученные модели (models/) лежат в репозитории, поэтому команды выше работают без интернета. Полное воспроизведение с нуля: make all (скачивание архива ~15 мин, обучение с CV ~20 мин).

ЭтапКомандаРезультат
0. EDA и очисткаmake edadocs/eda/
1. Архив прогнозов погодыmake weatherdata/weather/, docs/weather/
2. Признаки и baselinesmake baselinesdocs/baselines/
3. Модельmake trainmodels/, docs/model/
4. Прогноз по выпускамmake forecastdocs/forecast/
5. Агентmake agent / make rehearsaloutputs/forecast_feb2026.csv, docs/agent/, docs/agent_rehearsal/
6. Демоmake demoдашборд
Проверкаmake verifyвоспроизведение февраля и сверка с docs/reference/

Python ≥ 3.11. Зависимости: pandas, numpy, scikit-learn, LightGBM, pyarrow, requests, openai, python-dotenv, matplotlib, streamlit, plotly.

9. Структура

config.yaml                  все параметры: координаты, протокол выпуска, модели NWP, задержки, пороги агента
src/hackalem/
  data/turbines.py           SCADA: загрузка, флаги качества, часовая агрегация
  weather/openmeteo.py       HTTP-клиент (кэш, ограничение частоты, повторы)
  weather/sources.py         Single Runs / Previous Runs → единый формат
  weather/store.py           архив + get_forecast(as_of) без утечки
  weather/issued.py          воспроизведение протокола выпуска на истории
  features/build.py          признаки (только NWP + календарь)
  models/baselines.py        климатология, persistence, кривая мощности, изотоника
  models/gbm.py              квантильный LightGBM + CQR
  evaluation.py              метрики, holdout, rolling CV
  forecast.py                run_issue(): один выпуск прогноза
  agent/tools.py             инструменты агента
  agent/agent.py             LLM-агент (OpenAI) и агент на правилах
  weather/fetch.py           загрузка погоды агентом по требованию (с запасным вариантом из архива)
  economics.py               план подачи на БРЭ: оптимальный квантиль, стоимость небалансов
app.py                       дашборд Streamlit
outputs/forecast_feb2026.csv итоговый прогноз (единственный файл результата)
docs/                        отчёты, графики, журналы агента, репетиции
scripts/                     run_eda · build_weather_archive · check_weather · run_baselines ·
                             train_model · run_backtest · run_agent · forecast_live ·
                             agent_stress_test · economics_eval
tests/                       18 тестов (данные, утечка, признаки, модель, агент)

10. Ограничения

  • Факта за февраль 2026 в данных нет, поэтому качество оценено на декабре–январе (holdout, репетиция) и 12-месячной CV.
  • Задержки публикации NWP заданы консервативно, а не измерены. Реальная доступность может быть раньше, это только в пользу честности.
  • В 03–08.2024 в архиве нет части прогонов ECMWF 06/18z. Тогда используется предыдущий опубликованный прогон.
  • Простои и ограничения мощности не прогнозируются: модель прогнозирует выработку при исправной работе турбин.

11. Потенциал развития

  • Экономика БРЭ уже работает (recommend_bid, раздел 6). Дальше: реальные тарифы и цены по часам, месячные ограничения плана и автоматическая подача плана оператору рынка.
  • Масштабирование: координаты, модели NWP и пороги агента — в config.yaml. Новая станция = новый конфиг + архив её SCADA.
  • Больше источников (ансамбли ECMWF ENS/GEFS для интервалов), учёт плановых ремонтов и ограничений мощности как отдельной модели доступности.
  • Живой режим: тот же run_issue(as_of=now) по расписанию, агент реагирует на каждый новый прогон.
Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
23
Авторы
1
Файлы
206
Ветки
1

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

kelpopope 23

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

  • 2026-09-23 17:32Dashboard: 48-hour forecast table (plant, T1, T2, interval, market plan) after a live agent runkelpopope
  • 2026-09-23 17:22Dashboard redesign (Wind48 style): light green theme, sidebar, KPI cards, agent steps panel; same functionalitykelpopope
  • 2026-09-23 17:09Dashboard: remove legend block, keep clear labelskelpopope
  • 2026-09-23 17:07Dashboard: legend of all terms (T1/T2, P10-P90, D+1/D+2, MAE...), clearer labels and captionskelpopope
  • 2026-09-23 16:57Agent explains decisions with concrete numbers; skips pointless steps; gpt-4.1kelpopope
  • 2026-09-23 16:21Stress test: 4 scenarios incl. ECMWF outage, with code guardrail; figures from result fileskelpopope
  • 2026-09-23 16:14Code guardrail: agent cannot exclude a healthy ECMWF 9 km (LLM did it in stress scenarios)kelpopope
  • 2026-09-23 16:02README: what the product solves, technologies, step-by-step verification for the jurykelpopope
Все коммиты (23)
  • 2026-09-23 15:56Forecast survives any missing NWP source (incl. ECMWF); remove pitch noteskelpopope
  • 2026-09-23 15:55Quick start for the jury, make verify (bit-exact reproduction of February), README figureskelpopope
  • 2026-09-23 15:42Pin dependency versions; force numeric NWP dtypes (fix fresh-install failure)kelpopope
  • 2026-09-23 15:39Final results: LLM agent with fetch_weather + recommend_bid, stress test, economicskelpopope
  • 2026-09-23 15:13Agent fetches weather itself; live mode, stress test, balancing-market economicskelpopope
  • 2026-09-23 14:55Keep only the required deliverable in outputs/kelpopope
  • 2026-09-23 14:47Stage 6: Streamlit demo dashboard (forecast, agent decisions, rehearsal, live agent run)kelpopope
  • 2026-09-23 14:44Stage 5: forecasting agent (OpenAI function calling + rule fallback), final READMEkelpopope
  • 2026-09-23 14:30Stage 3-4: quantile LightGBM, February rolling forecast, agent tools draftkelpopope
  • 2026-09-23 14:09Stage 2: features, baselines, validation schemekelpopope
  • 2026-09-23 14:02Stage 1: leak-free archived NWP forecastskelpopope
  • 2026-09-23 14:02Merge web upload into main historykelpopope
  • 2026-09-23 14:02Remove duplicate scripts from web upload (real ones live in scripts/)kelpopope
  • 2026-09-23 13:58Add files via uploadkelpopope
  • 2026-09-23 13:53Stage 0-1: project skeleton, SCADA cleaning, EDA, NWP archive fetcherskelpopope
Структура репозитория (206 файлов)
.gitignore
.streamlit/config.toml
Makefile
README.md
app.py
config.yaml
data/raw/turbine_1.csv
data/raw/turbine_2.csv
data/weather/forecast_store.parquet
data/weather/issued_forecasts.parquet
docs/agent/AGENT_REPORT.md
docs/agent/agent_forecasts.csv
docs/agent/decisions.csv
docs/agent/logs/2026-01-31.json
docs/agent/logs/2026-02-01.json
docs/agent/logs/2026-02-02.json
docs/agent/logs/2026-02-03.json
docs/agent/logs/2026-02-04.json
docs/agent/logs/2026-02-05.json
docs/agent/logs/2026-02-06.json
docs/agent/logs/2026-02-07.json
docs/agent/logs/2026-02-08.json
docs/agent/logs/2026-02-09.json
docs/agent/logs/2026-02-10.json
docs/agent/logs/2026-02-11.json
docs/agent/logs/2026-02-12.json
docs/agent/logs/2026-02-13.json
docs/agent/logs/2026-02-14.json
docs/agent/logs/2026-02-15.json
docs/agent/logs/2026-02-16.json
docs/agent/logs/2026-02-17.json
docs/agent/logs/2026-02-18.json
docs/agent/logs/2026-02-19.json
docs/agent/logs/2026-02-20.json
docs/agent/logs/2026-02-21.json
docs/agent/logs/2026-02-22.json
docs/agent/logs/2026-02-23.json
docs/agent/logs/2026-02-24.json
docs/agent/logs/2026-02-25.json
docs/agent/logs/2026-02-26.json
docs/agent/logs/2026-02-27.json
docs/agent_rehearsal/AGENT_REPORT.md
docs/agent_rehearsal/agent_forecasts.csv
docs/agent_rehearsal/decisions.csv
docs/agent_rehearsal/logs/2025-12-31.json
docs/agent_rehearsal/logs/2026-01-01.json
docs/agent_rehearsal/logs/2026-01-02.json
docs/agent_rehearsal/logs/2026-01-03.json
docs/agent_rehearsal/logs/2026-01-04.json
docs/agent_rehearsal/logs/2026-01-05.json
docs/agent_rehearsal/logs/2026-01-06.json
docs/agent_rehearsal/logs/2026-01-07.json
docs/agent_rehearsal/logs/2026-01-08.json
docs/agent_rehearsal/logs/2026-01-09.json
docs/agent_rehearsal/logs/2026-01-10.json
docs/agent_rehearsal/logs/2026-01-11.json
docs/agent_rehearsal/logs/2026-01-12.json
docs/agent_rehearsal/logs/2026-01-13.json
docs/agent_rehearsal/logs/2026-01-14.json
docs/agent_rehearsal/logs/2026-01-15.json
docs/agent_rehearsal/logs/2026-01-16.json
docs/agent_rehearsal/logs/2026-01-17.json
docs/agent_rehearsal/logs/2026-01-18.json
docs/agent_rehearsal/logs/2026-01-19.json
docs/agent_rehearsal/logs/2026-01-20.json
docs/agent_rehearsal/logs/2026-01-21.json
docs/agent_rehearsal/logs/2026-01-22.json
docs/agent_rehearsal/logs/2026-01-23.json
docs/agent_rehearsal/logs/2026-01-24.json
docs/agent_rehearsal/logs/2026-01-25.json
docs/agent_rehearsal/logs/2026-01-26.json
docs/agent_rehearsal/logs/2026-01-27.json
docs/agent_rehearsal/logs/2026-01-28.json
docs/agent_rehearsal/logs/2026-01-29.json
docs/agent_rehearsal/logs/2026-01-30.json
docs/agent_rehearsal_rules/AGENT_REPORT.md
docs/agent_rehearsal_rules/agent_forecasts.csv
docs/agent_rehearsal_rules/decisions.csv
docs/agent_rehearsal_rules/logs/2025-12-31.json
docs/agent_rehearsal_rules/logs/2026-01-01.json
docs/agent_rehearsal_rules/logs/2026-01-02.json
docs/agent_rehearsal_rules/logs/2026-01-03.json
docs/agent_rehearsal_rules/logs/2026-01-04.json
docs/agent_rehearsal_rules/logs/2026-01-05.json
docs/agent_rehearsal_rules/logs/2026-01-06.json
docs/agent_rehearsal_rules/logs/2026-01-07.json
docs/agent_rehearsal_rules/logs/2026-01-08.json
docs/agent_rehearsal_rules/logs/2026-01-09.json
docs/agent_rehearsal_rules/logs/2026-01-10.json
docs/agent_rehearsal_rules/logs/2026-01-11.json
docs/agent_rehearsal_rules/logs/2026-01-12.json
docs/agent_rehearsal_rules/logs/2026-01-13.json
docs/agent_rehearsal_rules/logs/2026-01-14.json
docs/agent_rehearsal_rules/logs/2026-01-15.json
docs/agent_rehearsal_rules/logs/2026-01-16.json
docs/agent_rehearsal_rules/logs/2026-01-17.json
docs/agent_rehearsal_rules/logs/2026-01-18.json
docs/agent_rehearsal_rules/logs/2026-01-19.json
docs/agent_rehearsal_rules/logs/2026-01-20.json
docs/agent_rehearsal_rules/logs/2026-01-21.json
docs/agent_rehearsal_rules/logs/2026-01-22.json
docs/agent_rehearsal_rules/logs/2026-01-23.json
docs/agent_rehearsal_rules/logs/2026-01-24.json
docs/agent_rehearsal_rules/logs/2026-01-25.json
docs/agent_rehearsal_rules/logs/2026-01-26.json
docs/agent_rehearsal_rules/logs/2026-01-27.json
docs/agent_rehearsal_rules/logs/2026-01-28.json
docs/agent_rehearsal_rules/logs/2026-01-29.json
docs/agent_rehearsal_rules/logs/2026-01-30.json
docs/agent_stress/STRESS.md
docs/agent_stress/stress_results.csv
docs/baselines/01_baseline_mae.png
docs/baselines/02_cv_by_month.png
docs/baselines/03_holdout_sample.png
docs/baselines/BASELINES.md
docs/baselines/baselines_summary.json
docs/baselines/cv_monthly_metrics.csv
docs/baselines/holdout_metrics.csv
docs/economics/ECONOMICS.md
docs/economics/economics.csv
docs/eda/01_power_curve_flags.png
docs/eda/02_monthly_coverage.png
docs/eda/03_monthly_cf_by_year.png
docs/eda/04_month_hour_heatmap.png
docs/eda/05_tz_check_tmax_hour.png
docs/eda/06_turbine_agreement.png
docs/eda/07_acf.png
docs/eda/08_distributions.png
docs/eda/09_jan_2026.png
docs/eda/EDA.md
docs/eda/eda_summary.json
docs/forecast/01_feb2026_forecast.png
docs/forecast/backtest_summary.json
docs/forecast/forecast_no_agent_feb2026.csv
docs/forecast/forecasts_all_issues.csv
docs/forecast/issue_log.csv
docs/forecast/rehearsal_jan2026.csv
docs/img/feb_forecast.png
docs/img/jan_rehearsal.png
docs/img/key_results.png
docs/live/forecast_2026-09-23.csv
docs/live/log_2026-09-23.json
docs/model/01_holdout_sample.png
docs/model/02_feature_importance.png
docs/model/03_cv_by_month.png
docs/model/MODEL.md
docs/model/cv_metrics.csv
docs/model/feature_importance_p50.csv
docs/model/holdout_metrics.csv
docs/model/model_summary.json
docs/model/train.log
docs/reference/forecast_feb2026_rules.csv
docs/weather/01_tz_offset.png
docs/weather/02_nwp_vs_measured.png
docs/weather/03_ecmwf_error_by_month.png
docs/weather/WEATHER.md
docs/weather/check_weather.log
docs/weather/nwp_skill_wind.csv
docs/weather/test_issue_runs.csv
docs/weather/weather_summary.json
models/gbm_y_T1.pkl
models/gbm_y_T2.pkl
models/gbm_y_plant.pkl
models/metadata.json
outputs/forecast_feb2026.csv
pyproject.toml
requirements.txt
scripts/agent_stress_test.py
scripts/build_weather_archive.py
scripts/check_weather.py
scripts/economics_eval.py
scripts/forecast_live.py
scripts/make_figures.py
scripts/run_agent.py
scripts/run_backtest.py
scripts/run_baselines.py
scripts/run_eda.py
scripts/train_model.py
scripts/verify.py
src/hackalem/__init__.py
src/hackalem/agent/__init__.py
src/hackalem/agent/agent.py
src/hackalem/agent/tools.py
src/hackalem/config.py
src/hackalem/data/__init__.py
src/hackalem/data/turbines.py
src/hackalem/economics.py
src/hackalem/evaluation.py
src/hackalem/features/__init__.py
src/hackalem/features/build.py
src/hackalem/forecast.py
src/hackalem/models/__init__.py
src/hackalem/models/baselines.py
src/hackalem/models/gbm.py
src/hackalem/timeutils.py
src/hackalem/weather/__init__.py
src/hackalem/weather/fetch.py
src/hackalem/weather/issued.py
src/hackalem/weather/openmeteo.py
src/hackalem/weather/sources.py
src/hackalem/weather/store.py
tests/test_agent.py
tests/test_features.py
tests/test_gbm.py
tests/test_turbines.py
tests/test_weather_store.py

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

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

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