AAYMA
RU
Войти

Анемо

Агентная система почасового прогноза выработки ВЭС на 48 часов с интервалами p10/p50/p90.

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

О проекте

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

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

Суть

Агентная система почасового прогноза выработки ВЭС на 48 часов с интервалами p10/p50/p90. Прогноз строится по архивным прогнозам погоды семи моделей Open-Meteo. Есть журнал агента в реальном времени, паспорт выпуска и сравнение с предыдущим выпуском.

Как устроено

На истории двух турбин при старте обучается HistGradientBoostingRegressor с квантильной функцией потерь и конформной калибровкой интервалов. Агент с 7 инструментами выбирает источники погоды через Open-Meteo Previous Runs и берёт только выпуски NWP, опубликованные до момента решения (задержка 7 ч). Затем он готовит признаки, запускает модель, проверяет результат (validate_forecast с откатом на кривую мощности) и пишет объяснение. В LIVE инструменты выбирает LLM, в DEMO — детерминированный планировщик. Автономный прогон по февралю пересчитывает прогноз, когда выходит свежий выпуск погоды.

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

  • HistGradientBoostingRegressor quantile
  • конформная калибровка p10/p50/p90
  • Open-Meteo Previous Runs (7 NWP)
  • защита от утечки погоды
  • паспорт выпуска с хешами
  • бэктест 28 выпусков
  • эмпирическая кривая мощности

Метрики

Метрики nMAE (% номинала) и сравнение с базовыми методами B0/B1 есть в разделе 8 README, но сами числа в карточку не попали

Особенности

Проверяемость прогноза: берётся только погода, опубликованная до момента решения, у каждого выпуска есть паспорт с хешами и неизменяемые версии. Команда документирует и неудачные эксперименты (признаки не улучшили MAE в 3 из 4 месяцев). Прогноз привязан к нормативам РК по заявкам ВИЭ. Интерфейс на трёх языках, есть роли и масштабирование на парк станций.

Стек

Python · FastAPI · scikit-learn · pandas · NumPy · HTTPX · React · TypeScript · Vite · ECharts · Leaflet · SQLite · Docker Compose · pytest

Модели

gpt-5.4-mini · OpenAI-совместимый API


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

README

README.md

Анемо

Развёрнутая версия: https://hack.aican.cloud — живой режим с LLM; подробности в разделе 11. Проверка по этому README от неё не зависит: запуск из репозитория работает без ключа.

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

Анемо — агентная система прогнозирования почасовой выработки ветроэлектростанции на 24–48 часов.

Трек HackAlem AI — «Энергетика», задача — Agentic AI для прогнозирования выработки ВЭС. Формулировка задачи, исходные условия и допущения команды сохранены в CASE.md.

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

Проект помогает диспетчеру или аналитику ВЭС оценить выработку станции на следующие двое суток, увидеть часы низкой генерации и неопределённость прогноза, а также сравнить новый выпуск с предыдущим.

На вход подаётся дата исторического выпуска. Агент сам запрашивает по координатам станции прогнозы погоды семи моделей Open-Meteo, выпущенные до момента решения (без сети — берёт архив из репозитория), рассчитывает 48 почасовых значений и показывает график, таблицу, пояснение и журнал своих действий в реальном времени.

Загружать ничего не нужно. История двух турбин от организатора и архив погоды уже лежат в репозитории; модель обучается на них сама при старте контейнера.

Текущая версия решает ретроспективную задачу февраля 2026 года: даты выпуска — с 31 января по 27 февраля, момент решения — 23:59 местного времени станции (UTC+5). Мощность дана в долях номинала от 0 до 1; установленная мощность в МВт организатором не предоставлена.

Практическая ценность для Казахстана

  • Производитель ВИЭ подаёт заявку с почасовыми объёмами поставки до 08:00 по времени Астаны в сутки, предшествующие операционным суткам: пункт 9 правил, утверждённых приказом Министра энергетики РК от 2 марта 2015 года № 164. Выпуск делается в конце дня D, поэтому заявку на операционные сутки D+2 (срок — 08:00 дня D+1) можно подать уже по нему, а D+1 — самый свежий прогноз на ближайшие сутки для внутрисуточного планирования и оценки дисбаланса (backend/app/forecast/pipeline.py).
  • Дисбаланс определяется как разница планового и фактического сальдо за каждый час операционных суток: пункт 78 Правил функционирования балансирующего рынка электрической энергии. Поэтому продукт показывает именно почасовой прогноз и выделяет часы существенного пересмотра (backend/app/forecast/passport.py, frontend/src/features/forecast/).
  • По данным годового отчёта KEGOC за 2024 год, в Казахстане действовали 57 ВЭС суммарной мощностью 1 525,7 МВт. Задача точного планирования относится уже к значимому для энергосистемы классу генерации.
  • Прогноз выработки ВИЭ развивают и крупные игроки (KEGOC, «Самрук-Энерго»), поэтому мы не заявляем первенство. Отличие решения — проверяемость: только погода, опубликованная до момента решения, паспорт и хеши каждого выпуска, измеренная польза против простых методов на одинаковых исторических условиях.

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

Требование или возможностьСостояниеГде реализованоКак проверить
R1. Обучение модели на истории двух турбинРеализовано; обучение при старте процессаdata.py, model.pyДождаться model: ready в /health; расчёт метрик — раздел 8
R2. Получение архивных прогнозов погоды по координатамРеализовано; доступность в прошлом проверяется по правилу с задержкой 7 чweather.py, model.run_leadКоманда weather, тест временного правила, поле time_integrity
R3. Почасовой прогноз на 24–48 часовРеализован горизонт 48 ч: станция и две турбиныpipeline.pyВыпуск 09.02 → 48 часов за 10–11.02
R4. Агентный цикл и повторный расчётСемь инструментов, LIVE и планировщик без LLM; автономный прогон по дням: агент сам находит часы, для которых вышел более свежий выпуск погоды, и пересчитывает прогнозagent.py (run, autonomous_run)Пересчитать выпуск и смотреть живой журнал; «Прогноз на период» → автономный прогон
R5. Последовательные выпуски за тестовый периодРеализован прогон 28 датcli.py1 344 строки полного CSV и 672 строки итогового февраля
Диапазон неопределённости и проверка результатаКвантили p10/p50/p90, калибровка, проверка границ и порядкаcalibrate.py, agent.validateГрафик, поле validation, тесты ядра
Паспорт и сохранённые версии выпускаРеализованы хеши входов/результата, режим исполнения и сравнение выпусковpassport.pypassport в ответе API и JSON в outputs/forecasts
Интерфейс, графики и выгрузкиВкладки «Прогноз», «Прогноз на период», «Качество модели», «Станции», «О проекте»; русский, казахский, английскийfrontend/src/featuresРучной сценарий в разделе 8
Живой журнал агентаХоды LLM и вызовы инструментов появляются по мере выполнения, этапы отмечаются по ходуagent.py (progress), GET /api/forecast/progress/{date}, AgentLog.tsxНажать «Пересчитать» и смотреть журнал
Вход и ролиДиспетчер — прогноз; аналитик — ещё полный прогон и автономный прогон; администратор — ещё станции. Чтение открытоauth.py, stations.py, LoginBox.tsxКнопка «Демонстратор» в шапке; тест test_auth_stations.py
Станции и турбины (задел на масштабирование)Раздел для масштабирования на парк станций владельца. Добавить станцию и турбины, загрузить историю CSV по месяцам (месяцы дописываются, повторы по времени заменяются; проверка столбцов, шага и диапазона мощности). Модель новой станции пересчитывается автоматически после каждой загрузки — эмпирическая кривая мощности p10/p50/p90 по всей истории; прогноз на 48 ч — по текущему ветру Open-Meteo для координат станции. Это упрощённая модель: бустинг, архивная погода и калибровка — только для станции из ТЗstations.py, station_model.py, stationsВкладка «Станции» под «Демонстратором»; тест test_station_model.py

Наличие реализации в таблице не означает, что все её режимы проверены на каждой машине. Сохранённые метрики и команды воспроизведения приведены в разделе 8; ограничения — в разделе 10.

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

  1. Пользователь нажимает «Демонстратор» в шапке (вход одной кнопкой, учётка demo / demo со всеми правами), открывает вкладку «Прогноз», выбирает дату выпуска 09.02.2026 и объект «Станция».
  2. Нажимает «Сделать прогноз» или «Пересчитать». При открытии даты интерфейс также может показать уже сохранённый выпуск.
  3. Агент оценивает погодные источники, получает прогнозы погоды, готовит признаки, запускает модель и проверяет результат. Каждый ход LLM и каждый вызов инструмента появляется в журнале в момент выполнения; строка внизу показывает, что происходит сейчас.
  4. На экране появляются 48 почасовых прогнозов на 10–11 февраля: медиана p50, диапазон p10–p90, прогнозы турбин, ветер, пояснение и карточки внимания.
  5. Пользователь смотрит таблицу по часам, сравнение с предыдущим выпуском, карточки внимания и журнал инструментов.
  6. На вкладке «Прогноз на период» доступны календарь 28 выпусков, итоговый график и два CSV, а также автономный прогон: агент проходит февраль по дням, на каждом дне проверяет, вышел ли более свежий выпуск погоды для уже спрогнозированных часов, и пересчитывает прогноз с записью пересмотра.
  7. На вкладке «Качество модели» показаны сохранённые метрики и сравнение прогноза с фактом января 2026 года.

Показатель дневной выработки — сумма нормированных почасовых значений, то есть эквивалентные часы работы на полной мощности, а не МВт·ч.

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

КомпонентТехнологии и назначение
Сервер и APIPython 3.12, FastAPI, Uvicorn, Pydantic и pydantic-settings
Численная модельpandas, NumPy, scikit-learn; HistGradientBoostingRegressor с квантильной функцией потерь
AI-агентСобственный цикл вызова инструментов; OpenAI Python SDK и OpenAI-совместимый API в LIVE
Модель LLM по умолчаниюgpt-5.4-mini из конфигурации; меняется через LLM_MODEL
ПогодаHTTPX и Open-Meteo Previous Runs API
ИнтерфейсReact, TypeScript, Vite, Apache ECharts, Lucide, Leaflet
ХранениеCSV и JSON для данных/результатов; SQLite и SQLAlchemy в инфраструктурном каркасе
Запуск и проверкиDocker Compose, pytest, Ruff, oxlint

Зависимости Python зафиксированы в requirements.txt и requirements-dev.txt, frontend — в package-lock.json. SQLite не хранит прогнозы: они сохраняются в outputs/.

Роль AI и режимы

  • DEMO, без LLM (в интерфейсе — «Режим проверки (без ключа)»): детерминированный планировщик выполняет те же инструменты и реальные численные расчёты. Для основного прогноза не нужны ключ и сохранённые ответы LLM.
  • LIVE: при APP_MODE=live и заданном LLM_API_KEY модель выбирает вызовы инструментов и формирует объяснение по их результатам. При недоступности LLM расчёт выполняет планировщик с mode: demo. При незавершённом LIVE-цикле дополнительно выставляется fallback и добавляется запись в журнал.
  • Полный февральский прогон всегда выполняется планировщиком. Отдельные LIVE-выпуски хранятся как другой режим версии и не подменяют календарь этого прогона.

LLM не вычисляет мощность: прогноз, метрики, интервалы и сравнения рассчитывает Python-код. Общий LLM-клиент умеет сохранять ответы в data/ai-cache/; это отдельный механизм, а не основа DEMO-прогноза ВЭС.

Раскрытие сохранённых ответов LLM. В data/ai-cache лежат 12 JSON-файлов — ответы gpt-4o-mini-2024-07-18, записанные клиентом во время LIVE-прогонов при разработке 23.09.2026 (в каждом файле — модель, дата и хеш входа). Прогноз в режиме без ключа их не использует: планировщик не обращается к LLM. Проверка: удалить каталог и выполнить smoke — результат тот же.

При разработке использовались Claude Code (Максим и Оксана) и OpenAI Codex (Владимир). Вызовы LLM в продукте и использование ассистентов при разработке — разные роли.

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

Браузер: React → HTTP API FastAPI
                         │
                         ▼
              агент / планировщик
              1. rank_weather_sources
              2. fetch_weather
              3. build_features
              4. run_forecast
              5. validate_forecast
              6. analyze_forecast
              7. compare_with_previous
                         │
              ┌──────────┴──────────┐
              ▼                     ▼
        прогноз и журнал      паспорт и версия
        → график/таблица       → outputs/forecasts/
  • main.py подключает API, запускает обучение модели в фоне и отдаёт собранный frontend.
  • api/forecast.py принимает запросы прогноза, истории, метрик и полного прогона.
  • forecast/data.py агрегирует историю турбин; weather.py читает или скачивает погодные архивы.
  • model.py обучает квантильные модели станции и медианные модели турбин; calibrate.py корректирует ширину интервала.
  • agent.py управляет инструментами; passport.py сохраняет происхождение входов и версии.
  • Dockerfile собирает frontend и backend в один контейнер с одним портом.

Паспорт содержит момент решения, период прогноза, границу обучения, погодные источники, идентификаторы модели и калибровки, input_hash, result_hash и режим исполнения. Режим исполнения входит в хеш входов, поэтому LIVE и DEMO получают разные версии даже при одинаковых численных входах. Существующий файл версии не перезаписывается. Сравнение использует сохранённый предыдущий выпуск; если его нет, применяется явно отмеченная реконструкция.

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

Основной способ: Docker

Нужны Git, Docker Engine или Docker Desktop с работающим движком и Docker Compose v2, поддерживающий параметр env_file.required из docker-compose.yml. Порт 8000 должен быть свободен.

Для первой сборки нужен интернет: скачиваются образы и зависимости. После сборки основной DEMO-сценарий использует данные из репозитория и работает без ключа и интернета. Подложка карты загружается из сети отдельно.

Команды выполняются из терминала Bash либо PowerShell:

git clone https://github.com/BAITC-Hacks/hack-be10e779-ku-group.git
cd hack-be10e779-ku-group
docker compose config --quiet
docker compose up --build

Если репозиторий закрыт, для клонирования нужен предоставленный организатором доступ к нему. Личный аккаунт участника или его API-ключ для DEMO-прогноза не требуется.

Файл .env для первого запуска не обязателен. Если нужна настройка порта или LIVE-режима, перед запуском создайте его из .env.example, только если своего файла ещё нет:

# Bash, из корня репозитория
test -f .env || cp .env.example .env
# PowerShell, из корня репозитория
if (-not (Test-Path .env)) { Copy-Item .env.example .env }

Откройте http://localhost:8000 и нажмите «Демонстратор» в шапке. Чтение (графики, метрики, сохранённые выпуски) открыто без входа; запуск прогноза и прогонов требует роли, форма входа откроется сама. Тестовые учётки — только для проверки, заданы в .env.example и config.py:

Логин / парольРольЧто разрешено
demo / demoадминистраторвсё — кнопка «Демонстратор»
dispatcher / dispatcher123диспетчерпрогноз
analyst / analyst123аналитик+ полный прогон февраля и автономный прогон
admin / admin123администратор+ станции, турбины, загрузка истории

Во втором терминале проверьте http://localhost:8000/health: для готовности прогноза нужны status: "ok" и model: "ready". Пока идёт обучение, состояние — warming; один status: "ok" не доказывает готовность модели.

Если model: "error", посмотрите docker compose logs app и наличие обоих файлов в data/raw/. Ошибка при разборе env_file.required означает, что Compose нужно обновить. Если занят порт, задайте в .env APP_PORT=8080 и открывайте порт 8080.

Остановить приложение можно через Ctrl+C, затем docker compose down. В Compose не настроен постоянный том: новые результаты внутри контейнера нужно скачать или скопировать до его удаления.

Параметры окружения

ИмяНазначениеПо умолчаниюКогда нужно менять
APP_MODEdemo — планировщик, live — LLMdemoДля LIVE
LLM_API_KEYКлюч провайдера LLMПустоТолько для LIVE
LLM_MODELМодель LLMgpt-5.4-miniПри выборе другой модели
LLM_BASE_URLOpenAI-совместимый адрес; пусто — OpenAIПустоДля другого провайдера
APP_PORTВнешний порт Docker8000Если порт занят
BUILD_COMMITМетка сборки в /healthdevДля идентификации развёрнутой версии
LLM_TIMEOUT_SТаймаут запроса LLM, секунд60При необходимости
DATABASE_URLSQLite инфраструктурного каркасаsqlite:///<корень>/data/app.dbДля другого хранилища каркаса
AI_CACHE_DIRКаталог сохранённых ответов LLM<корень>/data/ai-cacheДля другого каталога
STATIC_DIRКаталог собранного frontend<корень>/frontend/distПри другом размещении
WEATHER_ONLINE1 — агент сам запрашивает Open-Meteo на окно выпуска, без сети откатывается на data/weather/; 0 — только архив1Для полностью офлайн-проверки
AUTH_REQUIRED1 — действия требуют входа; 0 — проверка ролей отключена1Отключать только локально
AUTH_SECRETСекрет подписи токеновchange-me-in-productionОбязательно на своём сервере
AUTH_USERSУчётки логин:пароль:роль через запятуючетыре тестовые учёткиНа своём сервере

Источник значений — config.py и docker-compose.yml. BUILD_COMMIT, LLM_TIMEOUT_S, DATABASE_URL, AI_CACHE_DIR и STATIC_DIR отсутствуют в шаблоне .env.example, но поддерживаются кодом или сборкой. Без ключа приложение остаётся в DEMO. Ключи нельзя коммитить.

Запуск для разработки без Docker

Нужны Python 3.12, Node.js 20.19+ в ветке 20 либо Node.js 22.12+ и npm. В контейнере используется Node.js 24. Далее команды для Bash, из корня репозитория:

python3.12 -m venv backend/.venv
backend/.venv/bin/python -m pip install -r backend/requirements-dev.txt
cd backend
.venv/bin/python -m uvicorn app.main:app --reload --port 8000

Во втором терминале, из корня репозитория:

cd frontend
npm ci
npm run dev

Откройте http://localhost:5173: Vite проксирует /api и /health на backend. В PowerShell используйте python версии 3.12 и пути backend/.venv/Scripts/python.exe / .venv/Scripts/python.exe вместо путей bin/python.

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

Повторяемый сценарий для жюри

После готовности модели:

ШагДействиеОжидаемый результат
0Нажать «Демонстратор» в шапкеВ шапке «демонстратор · администратор»
1«Прогноз» → дата 09.02.2026 → «Станция» → «Пересчитать» / «Сделать прогноз»48 часов: с 10.02 00:00 по 11.02 23:00, UTC+5
2Во время расчёта смотреть журнал агента, затем открыть почасовую таблицуШаги появляются по ходу, этапы отмечаются по одному; значения в пределах 0–100%, прогноз внутри показанного диапазона; видны семь инструментов
3Переключиться на турбину 1 или 2График показывает выбранную турбину
4Изменить дату на 10.02 и пересчитатьНовый выпуск на 11–12.02; сравнение с предыдущим выпуском
5«Прогноз на период» → скачать оба CSVВсе выпуски: 1 344 строки; итог: 672 часа 01–28.02
5а«Прогноз на период» → запустить автономный прогонЛента по дням: решение агента, свежесть погоды, пересмотр; около 3 с на день
6«Качество модели» → дата январского выпуска 20.01График прогноза и фактической выработки за 21–22.01; модель может быть хуже базового метода на отдельном выпуске
7«Станции» → добавить станцию и турбину → загрузить файл data/raw/turbine1.csv из репозитория (перетащить или «Загрузить файлы») → шаг 3, прогнозОтчёт проверки файла и покрытие по месяцам; «модель пересчитана: кривая мощности по 23 763 ч истории»; прогноз на 48 ч по текущему ветру Open-Meteo (нужна сеть). Это упрощённая модель для масштабирования, не модель из ТЗ

Сохранённые файлы — результаты вычислений, а не факт февраля и не доказательство нового расчёта. Для проверки вычисления используйте кнопку пересчёта или POST, а не только открытие сохранённого выпуска.

Автоматический smoke и API

В Bash (Linux/macOS, Git Bash или WSL), при запущенном приложении, из корня:

bash scripts/smoke.sh

Скрипт ждёт готовности модели до 300 секунд, проверяет, что без входа прогноз отклоняется (401), входит тестовым диспетчером (SMOKE_USER / SMOKE_PASS), рассчитывает прогноз на 09.02, проверяет 48 часов, временное правило, наличие основных шагов агента, ошибку для даты вне диапазона, метрики, историю и главную страницу. Успешный итог — Smoke пройден. Для другого порта: bash scripts/smoke.sh http://localhost:8080.

Прямой запрос в Bash: сначала вход, затем прогноз с токеном.

TOKEN=$(curl -s http://localhost:8000/api/auth/login -H 'Content-Type: application/json' \
  -d '{"username":"demo","password":"demo"}' | sed -E 's/.*"token":"([^"]+)".*/\1/')
curl --fail --max-time 300 http://localhost:8000/api/forecast \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"issue_date":"2026-02-09"}'

В PowerShell:

$login = Invoke-RestMethod -Method Post -Uri http://localhost:8000/api/auth/login -ContentType 'application/json' -Body '{"username":"demo","password":"demo"}'
$headers = @{ Authorization = "Bearer $($login.token)" }
$result = Invoke-RestMethod -Method Post -Uri http://localhost:8000/api/forecast -Headers $headers -ContentType 'application/json' -Body '{"issue_date":"2026-02-09"}'
$result.hours.Count
$result.time_integrity.ok
$result.validation.ok

Ожидается 48, True, True. Ответ также содержит steps, mode, passport, cards и weather_retrieval (откуда агент взял погоду: сеть или архив, снимок с хешем, семь источников). Без токена прогноз возвращает HTTP 401. Выпуск 2026-03-15 должен вернуть HTTP 400; отсутствие обязательной даты — HTTP 422. Полный API доступен в Swagger, маршруты — в api/forecast.py.

Пересчёт февраля и метрик

Из корня репозитория при работающем контейнере:

docker compose exec app python -m app.forecast.cli backtest
docker compose cp app:/app/outputs/forecast_feb2026.csv ./forecast_feb2026.csv
docker compose cp app:/app/outputs/forecast_feb2026_final.csv ./forecast_feb2026_final.csv
docker compose exec app python -m app.forecast.cli metrics

При локальном запуске те же команды python -m app.forecast.cli backtest и python -m app.forecast.cli metrics выполняются из backend/ в установленном окружении.

Полный CSV содержит 28 × 48 = 1 344 строки, включая D+2 последнего выпуска — 1 марта, помеченное outside_test_period. Итоговый CSV содержит только D+1 каждого выпуска — 672 часа февраля. Повторный прогон пересоздаёт CSV; версии JSON сохраняются отдельно.

Сохранённые показатели качества

Источник — outputs/metrics.json. Проверка: скользящие месяцы октябрь 2025 — январь 2026, обучение до каждого проверяемого периода с временным отступом для D+2. Методика реализована в model.holdout_metrics; команда metrics воспроизводит расчёт. GET /api/metrics возвращает метрики и поле calibration из outputs/calibration.json.

Мощность нормирована к номиналу: значения MAE и RMSE ниже умножены на 100 и выражены в процентах номинальной мощности.

ГоризонтМетодЧасовnMAE, %nRMSE, %
D+1Бустинг, ансамбль погоды2 88514,9022,25
D+1Кривая мощности2 88518,1726,95
D+1Персистентность («завтра как сегодня»)2 84635,5547,50
D+2Бустинг, ансамбль погоды2 88516,0923,75
D+2Кривая мощности2 88519,3028,34
D+2Персистентность («завтра как сегодня»)2 82637,3448,95

Для персистентности доступно меньше часов, поэтому сравнение с ней выполнено не на строго одинаковом наборе наблюдений. Проверка исключения gfs_ws100 не улучшила MAE (D+1: 0,1495 против 0,1490); агент исключает источники при пропусках в прогнозном окне.

По outputs/calibration.json, калибровка на октябре–декабре увеличила покрытие p10–p90 на отложенном январе с 66,5% до 77,5% при цели 80%; средняя ширина интервала выросла с 0,445 до 0,477. Это измерение на прошлом периоде, а не гарантия покрытия будущих наблюдений.

Для контекста, обзор Giebel et al. со ссылкой на опыт Германии (Rohrig) приводит для day-ahead прогноза отдельной ВЭС диапазон 10–20% RMSE от номинальной мощности (стр. 59 отчёта). Наши 22,25% для D+1 и 23,75% для D+2 находятся выше этого ориентира; сравнение ориентировочное, поскольку площадки, периоды и доступные входы различаются.

Что проверили и не взяли. Дополнительные эксперименты с признаками, смесью модели и кривой мощности, средним прогнозом турбин и старыми погодными выпусками не вошли в рабочую модель.

Гипотеза (оценка: окт 2025 — янв 2026, критерий — выигрыш ≥ 0,002 в 3 из 4 месяцев)Среднее MAE, база 0,1546Решение
Ансамбль 6 моделей погоды (ECMWF, ICON, GFS, JMA, CMA, GEM: значения, среднее, разброс)−11 % к одному best_matchпринято
Исключение худшего источника (gfs_ws100) по ошибке ветра (B0/B1)0,1495 против 0,1490 (D+1)не брать
Плотность воздуха, ρ·v³, ветер 80/120 м, вес свежих данныхбез устойчивого выигрышане брать
Смесь модели с кривой мощности (вес по прошлому месяцу)0,1548не брать
Прогноз станции как среднее турбинных моделей0,1542 (2 из 4)не брать
Медленный бустинг (500 деревьев, шаг 0,04)0,1526 (2 из 4), обучение ×2,5не брать
Lagged ensemble — выпуски за N+1, N+2 суток того же часа0,1545 (1 из 4)не брать
Траектория прогнозного ветра ±3 ч того же выпуска0,1526 (2 из 4)не брать
Соседние точки сетки ±0,25–0,5°: градиенты давления, «гора − станция», кольцо ветра0,1529–0,1564не брать

Вывод: при доступных архивных прогнозах погоды модель близка к пределу; дальнейший выигрыш требует новой информации (например, оперативной телеметрии SCADA), которой в кейсе нет. Критерий принятия — среднее по D+1 и D+2 снижение MAE минимум на 0,002 хотя бы в трёх из четырёх месяцев проверки. Код находится в backend/experiments, результаты — в журнале backend.

Тесты и сборка

После установки зависимостей, в Bash из корня:

cd backend
.venv/bin/python -m pytest -q
.venv/bin/python -m ruff check .

Отдельно из frontend/:

npm run build
npm run lint

Тесты ядра проверяют горизонт, границы, порядок квантилей и правило доступности погоды. Тесты API включают как подменённые ответы для проверки контрактов, так и test_forecast_real_agent с настоящим расчётом без LLM. В тестах ключ отключён через conftest.py; их успешность не подтверждает доступность LIVE-провайдера.

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

История турбин и погодные данные

  • data/raw/turbine1.csv и turbine2.csv — предоставленная организатором история с 11.03.2023 по 31.01.2026: время, ветер, температура и нормированная активная мощность, шаг 10 минут. Это исходные данные кейса, не синтетический набор.
  • Часовая точка — среднее шести 10-минутных измерений; неполные часы исключаются. Мощность станции — среднее нормированных мощностей обеих турбин при наличии обеих.
  • Координаты Т1: 43.645150, 78.535604; Т2: 43.643198, 78.538828. Для погодного запроса используется общая точка станции: 43.6442, 78.5372.
  • data/weather содержит ответы Open-Meteo Previous Runs API: best_match, ECMWF IFS, ICON, GFS, JMA, CMA и GEM. Данные распространяются по CC BY 4.0; источник — Open-Meteo, лицензия.
  • Свои данные. Модель читает ровно два файла data/raw/turbine1.csv и turbine2.csv в формате организатора. Чтобы проверить на других данных тех же столбцов, замените файлы и перезапустите контейнер: модель переобучится при старте. На данных, отличных от кейса, это не проверялось. Загрузка CSV во вкладке «Станции» (демо масштабирования) строит для новой станции упрощённую модель — кривую мощности по её истории — и прогноз по текущему ветру Open-Meteo; полная модель с агентным циклом и архивной погодой — только для станции из ТЗ.
  • outputs содержит вычисленные прогнозы, метрики и калибровку. Они не являются измеренной выработкой февраля. Синтетические ответы встречаются в тестовых фикстурах и не используются как исходная история для модели.

Погодный архив можно обновить командой docker compose exec app python -m app.forecast.cli weather; для неё нужен интернет. В штатной проверке обновление не требуется. После обновления перезапустите приложение для повторного обучения и выполните пересчёт.

Проверка доступности погоды в прошлом

Для целевого часа h выбирается минимальное N из 1, 2, 3, удовлетворяющее правилу:

h − N суток + 7 часов ≤ момент решения D, 23:59 UTC+5

Для выпуска 09.02 это 17 часов с previous_day1, 24 — с previous_day2 и 7 — с previous_day3. В прогнозных признаках используются архивные прогнозы, а не фактическая погода будущих часов.

Задержка 7 часов — допущение реализации. Статус verified_by_rule подтверждает выполнение этого правила; код не получает индивидуальные подтверждённые отметки публикации каждого NWP-выпуска.

Внешние сервисы

Open-Meteo получает координаты, период и перечень погодных переменных. В LIVE внешнему LLM API передаются инструкция, запрос и результаты вызванных инструментов. При просмотре карты браузер обращается к тайлам OpenStreetMap. Для DEMO-прогноза внешние аккаунты не нужны; LIVE требует настроенного ключа провайдера. Адрес другого OpenAI-совместимого сервиса задаётся через LLM_BASE_URL, но совместимость каждого такого сервиса отдельно не гарантируется.

Раскрытие заготовок и сторонних материалов

До старта были подготовлены организационные инструкции AGENTS.md, CLAUDE.md, предварительные документы в docs/, команды и настройки Claude Code, preflight.sh, общий каркас FastAPI/React/Vite, конфигурация SQLite, LLM-клиент и общий цикл инструментов, загрузка файлов, Docker Compose, базовый smoke и шаблон README. Эти заготовки не содержали предметного решения задачи ВЭС. Также заранее была подготовлена серверная инфраструктура, описанная в docs/deploy.md.

До старта команда провела с AI-ассистентами обзор отраслей и треков; обзор не включён в репозиторий. Предметная реализация отражена в истории коммитов и docs/progress.md.

КомпонентНазначениеЛицензия / условияИсточник
Данные двух турбинОбучение и проверкаПредоставлены организатором для кейса; отдельная открытая лицензия не указанаCASE.md, data/raw
Open-Meteo и перечисленные NWP-источникиАрхивные погодные прогнозыCC BY 4.0Open-Meteo
FastAPI, Pydantic, pydantic-settingsAPI, валидация, настройкиMITFastAPI, Pydantic, pydantic-settings
StarletteОснова HTTP-приложения FastAPIBSD-3-ClauseЛицензия Starlette
UvicornСервер ASGIBSD-3-ClauseUvicorn
SQLAlchemyИнфраструктура SQLiteMITSQLAlchemy
python-multipartИнфраструктура загрузки файловApache-2.0python-multipart
pandas, NumPy, scikit-learnРяды и прогнозная модельBSD-3-Clausepandas, NumPy, scikit-learn
HTTPXHTTP-клиентBSD-3-ClauseHTTPX
OpenAI Python SDKВызовы LIVE-агентаApache-2.0openai-python
Модель LLM провайдераВыбор инструментов и объяснениеУсловия выбранного API; веса в репозитории не распространяютсяКонфигурация, клиент
React, React DOMИнтерфейсMITReact
Apache EChartsГрафикиApache-2.0ECharts
LeafletКарта станцииBSD-2-ClauseLeaflet
OpenStreetMapПодложка картыODbLOpenStreetMap
Логотипы HackAlem AI, организаторов и партнёровУказание события и его организаторов в подвале интерфейсаОтдельная открытая лицензия в репозитории не указанаhackalem.ai, файлы, источник и назначение в коде
LucideИконкиISCLucide
Manrope, JetBrains Mono через FontsourceЛокальные шрифтыOFL-1.1Manrope, JetBrains Mono
Vite, create-vite, plugin-reactСборка и шаблон frontendMITVite
TypeScriptТипизацияApache-2.0TypeScript
pytest, Ruff, oxlintТесты и линтерыMITpytest, Ruff, oxc

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

  • Это ретроспективная система для двух заданных турбин. Произвольные даты вне 31.01–27.02.2026 не принимаются; постоянного мониторинга новых погодных выпусков нет.
  • Факта февраля 2026 года нет, поэтому точность на тестовом месяце локально не оценена. Метрики прошлых месяцев не гарантируют такой же результат в феврале.
  • Номинальная мощность неизвестна: вывод в МВт и МВт·ч не реализован. Среднее нормированных мощностей двух турбин — принятое в кейсе допущение.
  • У турбины 1 есть крупные пропуски истории в мае–июле 2024 года. Неполные часы отбрасываются; источники сравниваются с учётом доступных наблюдений.
  • Проверка доступности погоды основана на описанном правиле с задержкой 7 часов, а не на журнале реальных публикаций провайдера.
  • Целевое покрытие диапазона 80% не достигнуто: на январской проверке после калибровки — 77,5%.
  • LIVE зависит от внешнего API и ключа. Без него сохраняется численный прогноз планировщика, но нет живого выбора инструментов моделью.
  • Учётки в .env.example — тестовые, для проверки. На своём сервере нужно задать AUTH_SECRET и AUTH_USERS. Пользователи хранятся в переменной окружения, регистрации нет.
  • Карта требует сети. Отсутствие тайлов не мешает численному прогнозу.
  • Для добавленных станций используется упрощённая модель — эмпирическая кривая мощности по загруженной истории и текущий прогноз ветра Open-Meteo (нужна сеть). Бустинг, ансамбль архивной погоды и калибровка интервала для них не обучаются; интервал p10–p90 — разброс мощности в бине ветра из истории.
  • Пороги карточек пересмотра на 10 процентных пунктов и ширины диапазона 30 процентных пунктов заданы командой для демонстрации; это не нормативы диспетчерского управления.
  • Результаты записываются в локальные файлы; постоянный том Docker и многопользовательская эксплуатация не настроены. Торговля электроэнергией и управление оборудованием не реализованы.

11. Ссылка на развёрнутую версию

https://hack.aican.cloud — развёрнута конкурсная версия; работает в живом режиме (LIVE): шаги агента выбирает LLM (gpt-5.4-mini, ключ команды), числа считает тот же код, что в репозитории. Какой коммит развёрнут, видно в GET https://hack.aican.cloud/health (поле commit); как развёрнуто — docs/deploy.md, раздел «Развёрнуто 23.09».

Проверено 23.09.2026: /health → mode: live, model: ready; главная страница, /api/meta, /api/backtest, /api/metrics, /api/holdout и сохранённый выпуск GET /api/forecast/2026-02-09 отвечают 200. LIVE-прогноз POST /api/forecast на 2026-02-09 по публичному адресу — HTTP 200 за 16 с: LLM сама прошла все семь инструментов (fallback: false), 48 часов, проверка времени пройдена, выпуск сохранён отдельной версией с execution_mode: llm.

Ссылка — дополнение, а не замена: запуск из репозитория (раздел 7) от неё не зависит и работает без ключа в режиме DEMO. Сервер общий, поэтому после перезапуска контейнера модель прогревается ~20–25 минут: интерфейс открывается сразу, а новый прогноз ждёт окончания прогрева (model: ready в /health).

Звёзды
⭐ 0
Форки
0
Язык
TypeScript
Последний push
в прошлом месяце
Коммиты
63
Авторы
3
Файлы
262
Ветки
1

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

MaximushkaBed 37Оксана 21Vladimir 5

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

  • 2026-09-23 17:44chore: .gitattributes — *.sh всегда с LF, иначе smoke.sh падает на клоне с CRLF (Windows/WSL)Оксана
  • 2026-09-23 17:37docs: шаг «Станции» в сценарии жюри на файле турбины из репозитория; актуальный статус при загрузке истории одним файломMaximushkaBed
  • 2026-09-23 17:32docs: вкладка «Станции» — демо масштабирования (значок, пояснение, «О проекте»), README без противоречия про прогноз новых станцийОксана
  • 2026-09-23 17:25feat: понятная вкладка «Станции» по шагам — турбины → загрузка истории (перетаскивание, отчёт проверки файлов, покрытие по месяцам) → модель и прогноз; линтер в экспериментеОксана
  • 2026-09-23 17:10docs: ссылка на развёрнутую версию в начале READMEMaximushkaBed
  • 2026-09-23 17:09docs: README и stations.py — новая станция получает упрощённую модель автоматически (убрано устаревшее «не обучается»)Оксана
  • 2026-09-23 17:09feat: новые станции — загрузка истории турбин по месяцам, автоматический пересчёт кривой мощности, прогноз на 48 ч; вкладка «Станции»; README и тест; понятный текст при входеОксана
  • 2026-09-23 17:08docs: README — вход и тестовые учётки, запросы API с токеном, переменные авторизации и погоды, живой журнал, автономный прогон, раскрытие сохранённых ответов LLM; раздел 11 — развёрнутая версияMaximushkaBed
Все коммиты (63)
  • 2026-09-23 17:03feat: живой журнал агента — ходы LLM и инструменты появляются по мере выполнения, строка «что происходит сейчас» вместо крутилкиMaximushkaBed
  • 2026-09-23 16:58fix: этапы агента отмечаются по ходу работы, а не все сразу после ответа — прогресс шагов с бэкендаMaximushkaBed
  • 2026-09-23 16:48fix: validation и калибровка в ответах API по ревью; кнопка «Демонстратор» (demo/demo, все права); .env.example честно описывает режим без ключаMaximushkaBed
  • 2026-09-23 16:34merge: main в i18n — вход в шапке на трёх языкахОксана
  • 2026-09-23 16:33merge: main в i18n — перевод новых экранов (прогноз на период, автономный прогон, получение погоды), режим проверки на трёх языкахОксана
  • 2026-09-23 16:30feat: вход в шапке интерфейса — токен в запросах, форма открывается сама на 401/403, тестовые учётки в подсказкеMaximushkaBed
  • 2026-09-23 16:25feat: интерфейс на трёх языках (қазақша, русский, English) и тема «как в системе» без мигания при загрузкеОксана
  • 2026-09-23 16:23refactor: вкладка «Прогноз на период» без дублей — главное, агент (5 последних дней), календарь и почасовой график, CSVОксана
  • 2026-09-23 16:19feat: авторизация по ролям, станции и турбины с загрузкой истории; поле weather_retrieval в ответе прогнозаMaximushkaBed
  • 2026-09-23 16:16feat: лента «Агент проходит февраль сам» (автономный прогон), бейдж получения погоды агентом, «Режим проверки (без ключа)» вместо DEMOОксана
  • 2026-09-23 16:11feat: вкладка «Прогноз на период» вместо «Февраль 2026» — период из API, февраль как тестовый период ТЗОксана
  • 2026-09-23 16:08feat: агент сам получает погоду по координатам (7 источников, снимок с хешем, откат на архив) и автономный прогон по дням с обнаружением обновления входных данных и пересчётомMaximushkaBed
  • 2026-09-23 16:01feat: вкладка «О проекте» — презентация продукта; карта «откуда погода» с номерами узлов и обеими турбинами; «7 источников погоды»; без выгрузки журнала в JSONОксана
  • 2026-09-23 15:53docs: README — вернуть ценность для Казахстана, сравнение с отраслевой нормой и таблицу 10 проверенных гипотезMaximushkaBed
  • 2026-09-23 15:53exp: траектория ветра (Codex) и соседние точки сетки — не прошли критерий 3 из 4 месяцевMaximushkaBed
  • 2026-09-23 15:49docs: привести README к инструкции хакатона и проверяемому сценариюVladimir
  • 2026-09-23 15:49docs: синхронизировать название Анемо и раскрыть логотипыVladimir
  • 2026-09-23 15:47docs: README сверен с кодом — роли горизонтов для заявки ВИЭ, раскрытие всех зависимостей, калибровка, паспорт; название «Анемо»MaximushkaBed
  • 2026-09-23 15:47checkpoint(час 3): API под фронт, валидатор агента, честная оценка, smoke в Docker, READMEMaximushkaBed
  • 2026-09-23 15:44exp: смесь с кривой мощности, среднее турбин, медленный бустинг, lagged ensemble — ни один не прошёл критерий 3 из 4 месяцевMaximushkaBed
  • 2026-09-23 15:40feat: название «Анемо» и знак-ветротурбина — шапка, favicon, заголовок вкладки, «О системе», футерОксана
  • 2026-09-23 15:35feat: футер — проект в рамках HackAlem AI, лента организаторов и партнёров хакатона (логотипы с hackalem.ai)Оксана
  • 2026-09-23 15:28feat: понятные вкладки «Февраль» и «Качество» — главное одной фразой, язык без жаргона, подписи методовОксана
  • 2026-09-23 15:27fix: LIVE-выпуск — отдельная версия со своим паспортом; в DEMO /health без имени LLMMaximushkaBed
  • 2026-09-23 15:25fix: календарь = официальный прогон планировщика, holdout с хешем калибровки и автопересчётом; smoke в Docker пройденMaximushkaBed
  • 2026-09-23 15:24docs: README — архитектура агента, честность по времени, паспорт и версии, метрики и проверка B0/B1, Казахстан, раскрытиеMaximushkaBed
  • 2026-09-23 15:23docs: уточнить инструкцию по READMEVladimir
  • 2026-09-23 15:23fix: фронт под новые правила агента — шаг проверки результата, порог неуверенности 0.60, источники исключаются только при пропускахОксана
  • 2026-09-23 15:21feat: понятный первый экран — главный вывод, что сделать диспетчеру, как это работает, карта станции и откуда погода, язык без жаргонаОксана
  • 2026-09-23 15:19feat: инструмент агента validate_forecast — проверка результата перед выдачей с откатом на кривую мощности; порог флага неопределённости по распределению февраляMaximushkaBed
  • 2026-09-23 15:15fix: честная оценка — граница обучения S−1 сут−1 ч, точная конформная статистика; источник исключается только при пропусках (B0/B1 показал, что исключение по ошибке не помогает)MaximushkaBed
  • 2026-09-23 15:09docs: журнал по часам (часы 1–2 по истории коммитов)MaximushkaBed
  • 2026-09-23 15:07chore: метрики — nMAE в % номиналаMaximushkaBed
  • 2026-09-23 15:05fix: время в time_integrity в ISO, флаг fallback, имя LLM в /health; бриф сверен с кодомMaximushkaBed
  • 2026-09-23 15:03feat: эндпоинты под фронт — meta, сохранённый выпуск, бэктест из версий, CSV, holdout; паспорт и карточки в схемахMaximushkaBed
  • 2026-09-23 14:52feat: паспорт прогноза и неизменяемые версии выпусков, сравнение с сохранённым прошлым выпуском, карточки для диспетчера; прогон февраля через агентаMaximushkaBed
  • 2026-09-23 14:52feat: веб-интерфейс по контракту API — прогноз с журналом агента, февраль, качество модели, о системеОксана
  • 2026-09-23 14:47exp: проверка признаков (плотность воздуха, ветер 80/120 м, вес свежих данных) — ни один не улучшил MAE в 3 из 4 месяцевMaximushkaBed
  • 2026-09-23 14:46docs: бриф — поправки после реализации (дата выпуска, правило погоды, 6 инструментов, метрики, кэш)Оксана
  • 2026-09-23 14:45fix: погода без утечки — для каждого часа самый свежий выпуск NWP, опубликованный до момента прогноза (задержка 7 ч, выпуски за 1–3 суток); пересчёт калибровки, метрик и февраляMaximushkaBed
  • 2026-09-23 14:45feat: API на агенте, прогрев модели при старте, outputs в образе, smoke под сценарий прогнозаMaximushkaBed
  • 2026-09-23 14:15docs: контракт API v2 по коду агента, момент прогноза — конец дня DОксана
  • 2026-09-23 14:11feat: API прогноза — forecast, backtest, metrics, history по контрактуMaximushkaBed
  • 2026-09-23 14:11docs: README по ТЗ и тесты ядра (нет утечки погоды, горизонты, диапазоны); игнор своп-файловMaximushkaBed
  • 2026-09-23 14:08docs: удалить файл хакатона и добавить инструкцию READMEVladimir
  • 2026-09-23 14:06docs: правило — коммиты без строк соавторства AIMaximushkaBed
  • 2026-09-23 14:06feat: агент прогноза — 6 инструментов цикла ТЗ, проверка честности по времени, выбор источников погоды, конформная калибровка интервалаMaximushkaBed
  • 2026-09-23 14:01docs: добавить документ по хакатонуVladimir
  • 2026-09-23 13:56feat: ядро прогноза ВЭС — архивная погода 6 моделей, бустинг с квантилями, цикл ТЗ, бэктест февраля; память командыMaximushkaBed
  • 2026-09-23 13:48docs: дизайн-бриф интерфейса и ответы организаторов в CASE.mdОксана
  • 2026-09-23 13:42docs: контракт API для веба (прогноз, бэктест, метрики, история)MaximushkaBed
  • 2026-09-23 13:41docs: план P0 и решения по кейсу ВЭСMaximushkaBed
  • 2026-09-23 13:36docs: разбор кейса — CASE.md и исторические данные турбин от организаторовMaximushkaBed
  • 2026-09-23 13:27chore: типовой каркас (FastAPI, React+Vite, Docker), подготовленный до стартаMaximushkaBed
  • 2026-09-23 13:26chore: импорт раскрытых заготовок, подготовленных до стартаMaximushkaBed
Структура репозитория (262 файлов)
.claude/commands/api-contract.md
.claude/commands/case-intake.md
.claude/commands/freeze.md
.claude/commands/hourly.md
.claude/commands/judge.md
.claude/commands/p0-plan.md
.claude/commands/smoke.md
.claude/settings.json
.dockerignore
.env.example
.gitattributes
.gitignore
AGENTS.md
CASE.md
CLAUDE.md
DECISIONS.md
Dockerfile
README.md
TASKS.md
backend/app/__init__.py
backend/app/ai/__init__.py
backend/app/ai/agent.py
backend/app/ai/llm.py
backend/app/api/__init__.py
backend/app/api/forecast.py
backend/app/api/station_model.py
backend/app/api/stations.py
backend/app/auth.py
backend/app/config.py
backend/app/db.py
backend/app/forecast/__init__.py
backend/app/forecast/agent.py
backend/app/forecast/calibrate.py
backend/app/forecast/cli.py
backend/app/forecast/data.py
backend/app/forecast/model.py
backend/app/forecast/passport.py
backend/app/forecast/pipeline.py
backend/app/forecast/weather.py
backend/app/main.py
backend/app/models.py
backend/app/schemas.py
backend/app/services/__init__.py
backend/app/services/uploads.py
backend/experiments/curve_feature_exp.py
backend/experiments/features_exp.py
backend/experiments/lagged_exp.py
backend/experiments/model_exp.py
backend/experiments/nwp_weight_exp.py
backend/experiments/spatial_exp.py
backend/experiments/trajectory_exp.py
backend/pyproject.toml
backend/requirements-dev.txt
backend/requirements.txt
backend/tests/conftest.py
backend/tests/test_ai.py
backend/tests/test_api_forecast.py
backend/tests/test_auth_stations.py
backend/tests/test_forecast_core.py
backend/tests/test_health.py
backend/tests/test_llm_live.py
backend/tests/test_routes.py
backend/tests/test_station_model.py
data/ai-cache/.gitkeep
data/ai-cache/1ec42728c1f154bc944169851e5586e043655289086e97eb29be7d9e39189a98.json
data/ai-cache/221cd3714d1063e4b9f329d73da6d9d013f789ec80b8b9bc11af0fa6636a008e.json
data/ai-cache/23e090f2577ad5523c01e071df65963b4655b5eac5350baa71d46abfdafd0a3b.json
data/ai-cache/4a7817a039f02b40a4cbf12912df663dc53c22784bb3203d365bbdd01aaee932.json
data/ai-cache/6acfc42a076baeb76eab09477189594542f5921e809929fcf067f25163a37cd2.json
data/ai-cache/943f92e9db624b8444504c9708ba172898239cffaa767ecb374f98ea4b2f3a05.json
data/ai-cache/9be1190b15aa52708967d98fc44a3db2a9f28cbab39815b94c841ec3334a7933.json
data/ai-cache/a236935991c394552b248abd085ddf09d8884d9e0f78364d0136d2d6966491c9.json
data/ai-cache/a877b4003e559991469b1dbd3ac02308c5839c2a398881592dd7069c70581a92.json
data/ai-cache/c2e057bd69604939a384acb7f7981b0ffca6c4ce86f493faf2fdc2690c846710.json
data/ai-cache/c8194df58e7770d581a09a162b2f1ca9431577a41371f4fd327d2a1ee4188517.json
data/ai-cache/d2a4a0f1be8a5302eb87834b63385bbeee7ab949a18508186dc37a1b3ad233d0.json
data/demo/.gitkeep
data/raw/turbine1.csv
data/raw/turbine2.csv
data/weather/exp_best_match.json
data/weather/exp_ecmwf_ifs025.json
data/weather/exp_icon_global.json
data/weather/prev_cma_grapes_global.json
data/weather/prev_ecmwf_ifs025.json
data/weather/prev_gem_seamless.json
data/weather/prev_gfs_seamless.json
data/weather/prev_icon_global.json
data/weather/prev_jma_seamless.json
data/weather/previous_runs.json
data/weather/spatial/e25.json
data/weather/spatial/e50.json
data/weather/spatial/n25.json
data/weather/spatial/n50.json
data/weather/spatial/s25.json
data/weather/spatial/s50.json
data/weather/spatial/w25.json
data/weather/spatial/w50.json
docker-compose.yml
docs/api-contract.md
docs/architecture.md
docs/deploy.md
docs/design-brief.md
docs/hackathon-regulations-full.md
docs/hackathon-rules.md
docs/memory/README.md
docs/memory/backend.md
docs/playbook.md
docs/progress.md
docs/readme-instructions.md
docs/toolbox.md
frontend/.gitignore
frontend/.oxlintrc.json
frontend/index.html
frontend/package-lock.json
frontend/package.json
frontend/public/favicon.svg
frontend/public/partners/ai-digital-ministry.svg
frontend/public/partners/astana-hub.svg
frontend/public/partners/asu.svg
frontend/public/partners/baitc.svg
frontend/public/partners/digital-bridge.svg
frontend/public/partners/hackalem.svg
frontend/public/partners/mnvo.svg
frontend/public/partners/nvidia.png
frontend/public/partners/openai.svg
frontend/public/partners/paloalto.svg
frontend/public/partners/silkroad.svg
frontend/src/App.css
frontend/src/App.tsx
frontend/src/api/client.ts
frontend/src/api/endpoints.ts
frontend/src/api/types.ts
frontend/src/app/shared.ts
frontend/src/components/BrandMark.tsx
frontend/src/components/EChart.tsx
frontend/src/components/ErrorBoundary.tsx
frontend/src/components/LanguageSelector.tsx
frontend/src/components/LoginBox.css
frontend/src/components/LoginBox.tsx
frontend/src/components/SiteFooter.css
frontend/src/components/SiteFooter.tsx
frontend/src/components/ThemeToggle.tsx
frontend/src/components/ui.tsx
frontend/src/features/about/AboutModal.tsx
frontend/src/features/about/about.css
frontend/src/features/february/AutonomousRun.tsx
frontend/src/features/february/FebCalendar.tsx
frontend/src/features/february/FebChart.tsx
frontend/src/features/february/FebDownloads.tsx
frontend/src/features/february/FebruaryTab.tsx
frontend/src/features/february/febData.ts
frontend/src/features/february/february.css
frontend/src/features/forecast/AgentLog.tsx
frontend/src/features/forecast/ControlPanel.tsx
frontend/src/features/forecast/ForecastChart.tsx
frontend/src/features/forecast/ForecastTab.tsx
frontend/src/features/forecast/HourlyTable.tsx
frontend/src/features/forecast/HowItWorks.tsx
frontend/src/features/forecast/Insights.tsx
frontend/src/features/forecast/KpiRow.tsx
frontend/src/features/forecast/Provenance.tsx
frontend/src/features/forecast/StationMap.tsx
frontend/src/features/forecast/Verdict.tsx
frontend/src/features/forecast/chartOption.ts
frontend/src/features/forecast/forecast.css
frontend/src/features/forecast/hooks.ts
frontend/src/features/forecast/model.ts
frontend/src/features/forecast/plain.ts
frontend/src/features/forecast/rich.tsx
frontend/src/features/project/ProjectTab.tsx
frontend/src/features/project/project.css
frontend/src/features/quality/Contrast.tsx
frontend/src/features/quality/CoverageBlock.tsx
frontend/src/features/quality/HoldoutCard.tsx
frontend/src/features/quality/MetricsTable.tsx
frontend/src/features/quality/QualityTab.tsx
frontend/src/features/quality/charts.ts
frontend/src/features/quality/model.ts
frontend/src/features/quality/quality.css
frontend/src/features/stations/StationsTab.tsx
frontend/src/features/stations/UploadBox.tsx
frontend/src/features/stations/stations.css
frontend/src/i18n/GLOSSARY.md
frontend/src/i18n/core.ts
frontend/src/i18n/index.tsx
frontend/src/i18n/locales/en/about.ts
frontend/src/i18n/locales/en/app.ts
frontend/src/i18n/locales/en/common.ts
frontend/src/i18n/locales/en/february.ts
frontend/src/i18n/locales/en/footer.ts
frontend/src/i18n/locales/en/forecast.ts
frontend/src/i18n/locales/en/index.ts
frontend/src/i18n/locales/en/project.ts
frontend/src/i18n/locales/en/quality.ts
frontend/src/i18n/locales/en/steps.ts
frontend/src/i18n/locales/kk/about.ts
frontend/src/i18n/locales/kk/app.ts
frontend/src/i18n/locales/kk/common.ts
frontend/src/i18n/locales/kk/february.ts
frontend/src/i18n/locales/kk/footer.ts
frontend/src/i18n/locales/kk/forecast.ts
frontend/src/i18n/locales/kk/index.ts
frontend/src/i18n/locales/kk/project.ts
frontend/src/i18n/locales/kk/quality.ts
frontend/src/i18n/locales/kk/steps.ts
frontend/src/i18n/locales/ru/about.ts
frontend/src/i18n/locales/ru/app.ts
frontend/src/i18n/locales/ru/common.ts
frontend/src/i18n/locales/ru/february.ts
frontend/src/i18n/locales/ru/footer.ts
frontend/src/i18n/locales/ru/forecast.ts
frontend/src/i18n/locales/ru/index.ts
frontend/src/i18n/locales/ru/project.ts
frontend/src/i18n/locales/ru/quality.ts
frontend/src/i18n/locales/ru/steps.ts
frontend/src/index.css
frontend/src/lib/constants.ts
frontend/src/lib/format.ts
frontend/src/lib/steps.ts
frontend/src/lib/theme.ts
frontend/src/lib/themeManager.ts
frontend/src/main.tsx
frontend/tsconfig.app.json
frontend/tsconfig.json
frontend/tsconfig.node.json
frontend/vite.config.ts
outputs/calibration.json
outputs/forecast_feb2026.csv
outputs/forecast_feb2026_final.csv
outputs/forecasts/2026-01-31_c95c39d2.json
outputs/forecasts/2026-02-01_77f62bf0.json
outputs/forecasts/2026-02-02_9523b8ba.json
outputs/forecasts/2026-02-03_85b83973.json
outputs/forecasts/2026-02-04_013a8742.json
outputs/forecasts/2026-02-05_32639f5c.json
outputs/forecasts/2026-02-06_62e302c0.json
outputs/forecasts/2026-02-07_8e4956ed.json
outputs/forecasts/2026-02-08_4e2110b3.json
outputs/forecasts/2026-02-09_36e006e3.json
outputs/forecasts/2026-02-10_23f1b3c4.json
outputs/forecasts/2026-02-11_ab460420.json
outputs/forecasts/2026-02-12_135d75a8.json
outputs/forecasts/2026-02-13_0d660e33.json
outputs/forecasts/2026-02-14_a011fd75.json
outputs/forecasts/2026-02-15_21802606.json
outputs/forecasts/2026-02-16_a03bb0b8.json
outputs/forecasts/2026-02-17_458c4a8e.json
outputs/forecasts/2026-02-18_936fcd32.json
outputs/forecasts/2026-02-19_d8a56442.json
outputs/forecasts/2026-02-20_7aea9a81.json
outputs/forecasts/2026-02-21_1e014524.json
outputs/forecasts/2026-02-22_ba36205c.json
outputs/forecasts/2026-02-23_c8b7135d.json
outputs/forecasts/2026-02-24_1245e924.json
outputs/forecasts/2026-02-25_2d4fc5c5.json
outputs/forecasts/2026-02-26_f5bb1220.json
outputs/forecasts/2026-02-27_cc552042.json
outputs/holdout_jan2026.csv
outputs/holdout_jan2026.json
outputs/metrics.json
scripts/preflight.sh
scripts/smoke.sh

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

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

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