AAYMA
RU
Войти

ALT Energy

Веб-приложение, которое прогнозирует нормализованную мощность двух ветровых турбин на 24 или 48 часов по архивным прогнозам погоды ECMWF IFS.

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

О проекте

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

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

Суть

Веб-приложение, которое прогнозирует нормализованную мощность двух ветровых турбин на 24 или 48 часов по архивным прогнозам погоды ECMWF IFS. Параметры можно ввести вручную или текстом через ИИ.

Как устроено

Десятиминутные наблюдения агрегируются в часовые ряды. Для каждой турбины строится сглаженная кривая мощности по прогнозной скорости ветра на 100 м (бины 0,5 м/с). Погода берётся из архивных выпусков ECMWF IFS через Open-Meteo Single Runs: выпуск должен быть инициализирован не позже чем за 12 ч до запуска, чтобы исключить утечку будущего. FastAPI валидирует запрос и сохраняет запуски в SQLite, React рисует SVG-график и таблицу. gpt-4o-mini через Responses API со строгой JSON-схемой только разбирает текстовый ввод в параметры и сам мощность не генерирует. Бустинг с расширенными признаками ведётся отдельным экспериментом и в API не подключён.

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

  • кривая мощности (binned power curve)
  • gradient boosting
  • последовательный backtest
  • point-in-time weather selection
  • Open-Meteo Single Runs API
  • structured outputs JSON schema

Метрики

MAE нормализованной мощности: кривая мощности 0,328 (дек 2025) / 0,289 (янв 2026); бустинг с расширенной погодой 0,270 / 0,244; бустинг только по ветру 0,278 / 0,221

Особенности

Честная валидация без утечки: учитывается расчётная доступность погодного выпуска к моменту запуска, backtest строго последовательный, и команда прямо оговаривает, что январь не является нетронутым тестом, а MAE не равен «точности». LLM только разбирает ввод и не выдумывает прогноз. Есть replay на 116 февральских сценариев и интерфейс на трёх языках.

Стек

Python · FastAPI · Pydantic · Uvicorn · SQLite · React 19 · TypeScript · Vite · Docker Compose · scikit-learn

Модели

gpt-4o-mini


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

README

README.md

ALT Energy — почасовой прогноз мощности ветровых турбин

ALT Energy — веб-приложение, созданное для HackAlem AI на выданных организаторами датасетах. Оно строит прогноз нормализованной активной мощности двух ветровых турбин на 24 или 48 часов с шагом один час. Пользователь задаёт турбину, момент исторического запуска и горизонт вручную или текстом через ИИ. Система применяет обученную модель к архивному прогнозу ветра и показывает результат вместе с происхождением погоды и версией модели.

Быстрый пример: турбина 1, запуск 2026-02-01T12:00:00Z, горизонт 48 часов. Обученные модели и необходимый погодный кэш уже включены в репозиторий; для первого ручного расчёта переобучение и ключ OpenAI не нужны. Февральский replay содержит 116 сценариев: 29 ежедневных запусков в 12:00 UTC с 31 января по 28 февраля, две турбины и два горизонта.

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

  • Два режима ввода: «Вручную» и «Спросить ИИ», с выбором турбины и горизонта в обоих режимах. ИИ разбирает текстовую дату и параметры, после чего интерфейс запускает обычное прогнозное ядро; неоднозначный ввод требует уточнения.
  • Интерфейс на русском, казахском и английском с сохранением выбранного языка.
  • Интерактивный график с выбором часа, почасовая таблица, минимум, среднее и максимум прогнозной мощности; отдельное окно со сведениями об исходных CSV и пропусках.
  • Подготовка десятиминутных наблюдений в часовые ряды, обучение отдельной кривой мощности для каждой турбины и выбор версии модели без использования будущих наблюдений.
  • Получение архивного погодного выпуска ECMWF IFS, проверка его расчётной доступности к моменту запуска и вывод происхождения погоды вместе с прогнозом.
  • HTTP API с валидацией запроса и результата, сохранением успешных запусков в SQLite, февральский replay на 116 запусков и последовательная проверка на декабре–январе.
  • Воспроизводимый эксперимент с расширенными погодными признаками. Экспериментальная модель пока не подключена к API.

Технологии и архитектура

Frontend: React 19, TypeScript 5.8, Vite 8 и Lucide; график реализован на SVG. Backend: Python, FastAPI, Pydantic и Uvicorn; прогнозное ядро также написано на Python. Для хранения запусков используется SQLite — локальный файл, которому не нужен отдельный сервер БД. Совместный локальный запуск выполняется через Docker Compose. Текстовый ввод использует OpenAI Responses API со строгой JSON-схемой. scikit-learn нужен только для отдельного эксперимента. Зависимости указаны в backend/requirements.txt, backend/requirements-test.txt, frontend/package.json и forecasting/requirements-experiment.txt.

Ручной ввод ────────────────────────────→ параметры прогноза
Текст → FastAPI → OpenAI Responses ────→ параметры прогноза
                                                 │
                                         FastAPI /forecast-runs
                                                 │
                                         forecasting.runner
                                          │             │
                                     модель JSON    архив ECMWF IFS
                                                 │
                                       проверка → SQLite
                                                 │
                                         график и таблица
ПапкаОтветственность
backend/HTTP API, валидация, проверка временных границ, сохранение успешных запусков
frontend/Выбор параметров, график и таблица почасового прогноза, ошибки
forecasting/Подготовка часовых рядов, погодный архив, обучение и расчёт модели
data/raw/Два исходных CSV, выданных организаторами
data/processed/Часовые ряды, манифест исторических запусков и отчёт проверки
data/weather/Сохранённые ответы архива погоды
shared/API.mdФормат запросов и ответов между участниками

При текстовом вводе frontend сначала получает проверенные параметры, затем вызывает тот же endpoint прогноза, что и ручная форма. ИИ не генерирует значения мощности. В OpenAI передаются текст пользователя и выбранные параметры; CSV и прогнозные ряды не передаются. Ключ используется только на backend.

Данные и модель

Исходные CSV организаторов сохранены без изменений и содержат десятиминутные наблюдения двух турбин с 11 марта 2023 года по 31 января 2026 года: время, скорость ветра, температуру и нормализованную активную мощность. Февраль 2026 года — период исторического воспроизведения прогнозов; фактических значений мощности за февраль в репозитории нет. Целевая величина находится в диапазоне 0–1 и не является кВт·ч.

ФайлНаблюденийПропущенных десятиминутных интервалов
data/raw/turbine_1.csv142 3609 992
data/raw/turbine_2.csv149 4992 853

Шесть записей HH:00–HH:50 образуют среднее за час, обозначенный концом HH+1:00. Для действующей модели используются сопоставленные примеры ноября 2025 — января 2026, а не весь многолетний CSV. Кривая строится отдельно для каждой турбины по интервалам скорости 0,5 м/с; редкие интервалы сглаживаются к среднему обучающего ряда.

Подготовка данных формирует часовую сетку и сохраняет пропуски. Для обучения используются только полные часы с известной мощностью. Текущая базовая модель — сглаженная зависимость мощности от прогнозной скорости ветра на высоте 100 м. Прогнозы ветра взяты из отдельных архивных запусков ECMWF IFS через Open-Meteo Single Runs; код выбирает выпуск, инициализированный не позже чем за 12 часов до расчёта. Время инициализации модели погоды и расчётный порог доступности отдельно показаны в API, интерфейсе и манифесте. Фактическое время публикации в архиве неизвестно; подробности — в forecasting/README.md.

Исходные метки времени используются как в датасете, без прибавления или вычитания часового пояса. Для соединения с погодой одинаковые календарные даты и часы сопоставляются напрямую с осью API. В моделях и отчётах записано time_alignment.policy = as_provided_no_shift. Это принятое правило обработки предоставленных данных. API принимает явное смещение или Z и возвращает UTC. Первая точка прогноза соответствует часу, заканчивающемуся через час после запуска.

Качество модели

Проверка последовательная: ноябрь → декабрь, ноябрь–декабрь → январь. Целевые часы обучения строго предшествуют проверяемому периоду. MAE — средняя абсолютная ошибка нормализованной мощности; меньше лучше. Значение 0,328 означает отклонение в среднем на 32,8 процентного пункта шкалы 0–1, а не «точность 67,2%».

МодельДекабрь 2025, MAEЯнварь 2026, MAEИспользование
Сглаженная кривая мощности0,327760,28852Действующая модель API
Бустинг: расширенная погода и производные признаки0,269980,24369Эксперимент, выбран по декабрю
Бустинг: ветер и временные производные0,278440,22097Контрольное сравнение

Метрики объединяют обе турбины и горизонты 1–24 и 1–48 часов; часть целевых часов учитывается повторно. Январь уже использовался для анализа проекта и не является новым нетронутым тестом. Расширенный вариант улучшает ошибку относительно действующей модели, но польза именно новых погодных величин нестабильна: в январе контрольный вариант лучше. Эксперимент не заменяет модель приложения.

Подробности: backtest_report.json, аудит прогнозов, эксперимент с архивными признаками. Ошибку за февраль по предоставленным файлам вычислить нельзя.

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

Для локального запуска нужны Python 3.11+ и Node.js версии ^20.19.0 или >=22.12.0. Для контейнерного запуска достаточно Docker с Compose. Интернет нужен для установки зависимостей, режима ИИ и погодных выпусков, которых нет в локальном кэше. Ключ API для реализованного погодного запроса не требуется. Начните с клонирования:

git clone https://github.com/BAITC-Hacks/hack-1f9ed603-alt.git
cd hack-1f9ed603-alt

Локально

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

python -m venv .venv
.\.venv\Scripts\python -m pip install -r backend\requirements.txt
# Выполните один раз, если .env ещё не создан:
Copy-Item .env.example .env
# Заполните OPENAI_API_KEY в .env для режима ИИ (ручной режим работает без ключа).
.\.venv\Scripts\python -m uvicorn backend.app.main:app --reload --port 8000 --env-file .env

На macOS/Linux команды первого терминала:

python3 -m venv .venv
.venv/bin/python -m pip install -r backend/requirements.txt
# Выполните один раз, если .env ещё не создан:
cp .env.example .env
.venv/bin/python -m uvicorn backend.app.main:app --reload --port 8000 --env-file .env

Если .env уже существует, сохраните его настройки вместо повторного копирования. Ключ хранится только на backend и не включается в frontend. Во втором терминале, из корня репозитория:

cd frontend
npm ci
npm run dev

Откройте http://localhost:5173. Документация API: http://localhost:8000/docs. Vite проксирует /api к http://localhost:8000.

Настройки окружения

ПеременнаяНазначение
OPENAI_API_KEYСерверный ключ для «Спросить ИИ»; ручной режим работает без него
OPENAI_MODELПо умолчанию gpt-4o-mini; нужен Responses API и поддержка строгой JSON-схемы
DATA_DIRCSV для сведений о турбинах в API; по умолчанию data/raw
RUNS_DB_PATHSQLite успешных расчётов; локально backend/runs.sqlite3
VITE_API_PROXY_TARGETАдрес backend для Vite; локально http://localhost:8000

Backend читает .env через --env-file; Compose передаёт ключ и модель из корневого .env или окружения. Для изменения локального прокси задайте VITE_API_PROXY_TARGET в окружении терминала frontend перед npm run dev: например, $env:VITE_API_PROXY_TARGET="http://localhost:8001" в PowerShell. Корневой .env автоматически процессом Vite не загружается. DATA_DIR не меняет пути обучения и артефактов прогнозного ядра; сохраняйте стандартную структуру проекта. .env исключён из Git и Docker-образов; не используйте префикс VITE_ для секретов.

Docker

Если установлен Docker с Compose, вместо двух локальных серверов выполните из корня репозитория. Для ручного режима .env не обязателен; для ИИ предварительно создайте его из .env.example и заполните ключ:

docker compose up --build

Интерфейс откроется на http://localhost:5173, документация API — на http://localhost:8000/docs. Исходные CSV монтируются в контейнер backend без записи. Сохранённые погодные выпуски монтируются из data/weather/ecmwf_ifs/; новые выпуски backend может добавить в эту папку через внешний API, поэтому для дат вне кэша нужна сеть. Успешные расчёты хранятся в именованном томе runs_data и сохраняются при пересоздании контейнера и обычном docker compose down. Команда docker compose down -v удаляет этот том.

Проверки и воспроизводимость

Команды Python выполняются из корня в созданном окружении. Если оно не активировано, вместо python используйте .\.venv\Scripts\python.exe на Windows или .venv/bin/python на macOS/Linux.

python -m pip install -r backend/requirements-test.txt
python -m unittest discover -s forecasting/tests -v
python -m unittest discover -s backend/tests -v

Frontend:

cd frontend
npm ci
npm test
npm run build

Для пересоздания моделей и отчётов, из корня:

python -m forecasting.train_baseline
python -m forecasting.replay_february
python -m forecasting.audit

Эти команды перезаписывают генерируемые артефакты и отчёты. Используется локальный погодный кэш; отсутствующие выпуски запрашиваются у Open-Meteo. Для обычного запуска приложения повторное обучение не требуется. Подробности — в forecasting/README.md.

Отдельный эксперимент с расширенной погодой:

python -m pip install -r forecasting/requirements-experiment.txt
python -m forecasting.experiment_features

Эксперимент работает офлайн на выданных CSV и 92 сохранённых погодных запусках, записывает data/processed/feature_experiment.json и не заменяет действующую модель.

Проверить основной сценарий

  1. Откройте интерфейс и убедитесь, что отображаются обе турбины и количество наблюдений.
  2. Выберите турбину 1, горизонт 48 часов и введите 2026-02-01T12:00:00Z.
  3. Нажмите «Построить прогноз». Ожидаемый результат — график и таблица из 48 значений: от 2026-02-01T13:00:00Z до 2026-02-03T12:00:00Z.
  4. В блоке «Источник и параметры запуска» проверьте время инициализации погодной модели, расчётный порог её доступности, идентификатор погодного запуска и версию модели.

Для текстового ввода при настроенном ключе откройте «Спросить ИИ», выберите турбину и горизонт и введите «22 февраля 17:00 2026 года». Форма получит 2026-02-22T17:00:00Z, а график и таблица будут построены обычной моделью. Первая точка — 18:00. Если турбина или горизонт указаны в тексте, они заменяют выбранные значения; иначе используются параметры формы. Время без явно указанного пояса не сдвигается. Неполная дата, отсутствующий год или неподдерживаемый горизонт требуют уточнения.

Ручной запрос через API на macOS/Linux:

curl -X POST http://localhost:8000/api/forecast-runs \
  -H "Content-Type: application/json" \
  -d '{"turbine_id":"turbine_1","issued_at":"2026-02-01T12:00:00Z","horizon_hours":48}'

PowerShell:

Invoke-RestMethod http://localhost:8000/api/health
$body = '{"turbine_id":"turbine_1","issued_at":"2026-02-01T12:00:00Z","horizon_hours":48}'
$result = Invoke-RestMethod -Method Post -Uri http://localhost:8000/api/forecast-runs -ContentType 'application/json' -Body $body
$result.points.Count  # 48
$result.points[0]
$result.points[-1]

Успех — HTTP 201, status: completed, уникальный run_id, 48 почасовых точек в диапазоне 0–1 и сохранённый расчёт в SQLite. Полная структура — в shared/API.md.

EndpointНазначение
GET /api/healthПроверка доступности процесса API; не полная диагностика зависимостей
GET /api/turbinesКоординаты и сводка исходных CSV
POST /api/forecast-runsРасчёт и сохранение прогноза
POST /api/assistant/forecast-parametersРазбор текста: ready с параметрами либо clarification с уточнением

Ошибки имеют формат {"error":"сообщение"}. Неверный запрос возвращает 422; отсутствие модуля прогнозного ядра — 501; некорректный ответ ядра/ИИ — 502; недоступные данные, погода, хранилище или сервис ИИ — 503; внутренняя ошибка — 500. Ручной режим не зависит от OpenAI. При ошибке прогноз не подменяется вымышленными значениями.

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

  • Прогнозируемая величина — доля нормализованной активной мощности от 0 до 1. Без номинальной мощности турбин её нельзя корректно перевести в кВт или кВт·ч.
  • Основной проверенный сценарий — исторические запуски. Для 2026-01-31T12:00:00Z используется отдельная модель, обученная до запуска; с 1 февраля доступна финальная модель. Более ранние даты требуют отдельно обученного артефакта. Постоянного переобучения на текущих наблюдениях нет.
  • Февральский replay сохраняет результаты и происхождение погоды в data/processed/february_replay.json. Фактической мощности за февраль в предоставленных файлах нет, поэтому ошибку этих прогнозов здесь оценить нельзя.
  • Фактическое историческое время публикации погодного выпуска архив не предоставляет; используется консервативное правило доступности через 12 часов после инициализации.
  • Исходные метки CSV используются без сдвига; группировка десятиминутных записей по часам — принятое правило обработки, сохранённое в артефактах.
  • Прогноз погоды использует ветер на высоте 100 м. Обе турбины попадают в одну погодную ячейку архива, поэтому локальные различия ветра моделью погоды не разрешаются.
  • Модель основана на статистической кривой «скорость ветра → мощность»; редкие экстремальные скорости, остановки и ограничения работы турбины она не воспроизводит надёжно. Результаты аудита — в data/processed/validation_report.json.
  • На Windows обнаружен отказ доступа при конкурентном чтении/обновлении погодного кэша: соответствующий тест завершается PermissionError. Ошибка воспроизведена и вне песочницы; общий набор тестов прогнозирования сейчас не полностью проходит.
  • Режиму ИИ нужны сеть, действующий серверный ключ и доступный лимит OpenAI. Распознанные параметры показываются пользователю; неполные и неоднозначные запросы требуют уточнения. Это помощник для ввода параметров, а не универсальный чат или управление турбинами.
  • В SQLite сохраняются успешные расчёты, но интерфейс истории не реализован. Нет авторизации и ограничения частоты запросов. Compose предназначен для локального запуска и использует Vite dev server.

Развёрнутая версия

Публичный URL приложения в репозитории не указан. Проект запускается локально по инструкции выше.

Отчёт проверки — 23 сентября 2026

При подготовке этой редакции README проверена текущая реализация на Windows с Python 3.13 и Node.js 24.12:

ПроверкаРезультат
Backend unittest29 тестов пройдено, включая все 116 сценариев replay через API
Forecasting unittest27 из 28 пройдено; конкурентный доступ к погодному кэшу завершился PermissionError
npm ciЗависимости установлены по lock-файлу
npm test8 тестов пройдено
npm run buildПроверка TypeScript и сборка Vite успешны

Backend-тесты используют настоящее прогнозное ядро, архивную погоду и временную SQLite. Ответ OpenAI подменяется только в автоматических тестах. Docker, браузер и реальный сетевой вызов OpenAI в этой проверке повторно не запускались. Предыдущие проверки команды с реальным OpenAI и браузером описаны в backend/AI_QA.md; более ранняя проверка интеграции — в backend/QA.md.

Использованные материалы

  • Условие задачи и исходные CSV предоставлены организаторами HackAlem AI.
  • Погодные данные: ECMWF IFS через Open-Meteo Single Runs, условия использования и атрибуции — Open-Meteo Terms.
  • OpenAI Responses API используется только для текстового ввода; настройка и поведение описаны в backend/README.md. Реализация задаёт store: false, таймаут 30 секунд и повторно проверяет структурированный ответ.
  • Библиотеки перечислены в backend/requirements.txt и frontend/package.json.
  • При разработке использовался OpenAI Codex.
Звёзды
⭐ 0
Форки
0
Язык
Python
Последний push
в прошлом месяце
Коммиты
24
Авторы
3
Файлы
297
Ветки
1

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

korolbbichey 11Temirlan Abugali 7Азиз 6

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

  • 2026-09-23 17:40docs: finalize ALT Energy product READMEkorolbbichey
  • 2026-09-23 17:23feat(frontend): add forecast selectors to AI setup and simplify contextTemirlan Abugali
  • 2026-09-23 17:09feat: connect AI date input to the forecasting workflowАзиз
  • 2026-09-23 16:52chore(frontend): rename product to ALT EnergyTemirlan Abugali
  • 2026-09-23 16:49feat(frontend): add manual and AI demo setup modesTemirlan Abugali
  • 2026-09-23 16:46Evaluate extended archived weather on supplied turbine datasetskorolbbichey
  • 2026-09-23 16:36feat(frontend): build multilingual forecast workspaceTemirlan Abugali
  • 2026-09-23 16:21docs: complete project README for handoffkorolbbichey
Все коммиты (24)
  • 2026-09-23 16:13Use dataset clock labels without timezone conversionАзиз
  • 2026-09-23 15:51Harden forecasting integration and audit prediction realismАзиз
  • 2026-09-23 15:49feat(frontend): refine forecast dashboard designTemirlan Abugali
  • 2026-09-23 15:29docs: complete final integration QA and task statuskorolbbichey
  • 2026-09-23 15:16docs: verify and complete forecasting tasks F1 and F2Азиз
  • 2026-09-23 15:08feat: expose weather run availability provenancekorolbbichey
  • 2026-09-23 14:59docs: mark backend and Docker tasks completekorolbbichey
  • 2026-09-23 14:54Complete point-in-time forecasting and February replayАзиз
  • 2026-09-23 14:54fix: validate forecast hours and persist Docker runskorolbbichey
  • 2026-09-23 14:53feat(frontend): validate demo forecast launch timeTemirlan Abugali
  • 2026-09-23 14:43docs: update project status and assign QA taskskorolbbichey
  • 2026-09-23 14:31feat(forecasting): add archived-weather baseline and backtestsАзиз
  • 2026-09-23 14:20feat(frontend): display hourly forecast and weather provenanceTemirlan Abugali
  • 2026-09-23 14:15feat: validate and store forecast runs in backendkorolbbichey
  • 2026-09-23 14:03docs: finalize turbine coordinates and forecast API contractkorolbbichey
  • 2026-09-23 13:51chore: scaffold wind forecasting projectkorolbbichey
Структура репозитория (297 файлов)
.dockerignore
.env.example
.gitignore
AGENTS.md
README.md
TASKS.md
backend/.gitignore
backend/AGENTS.md
backend/AI_QA.md
backend/Dockerfile
backend/QA.md
backend/README.md
backend/__init__.py
backend/app/__init__.py
backend/app/assistant_service.py
backend/app/db.py
backend/app/forecast_service.py
backend/app/main.py
backend/app/schemas.py
backend/requirements-test.txt
backend/requirements.txt
backend/tests/__init__.py
backend/tests/test_api_integration.py
backend/tests/test_assistant.py
backend/tests/test_forecast_service.py
compose.yaml
data/processed/backtest_report.json
data/processed/feature_experiment.json
data/processed/february_replay.json
data/processed/historical_launches.json
data/processed/hourly_turbine_1.csv
data/processed/hourly_turbine_2.csv
data/processed/validation_report.json
data/raw/turbine_1.csv
data/raw/turbine_2.csv
data/weather/ecmwf_ifs/ecmwf_ifs_20251101T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251102T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251103T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251104T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251105T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251106T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251107T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251108T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251109T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251110T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251111T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251112T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251113T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251114T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251115T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251116T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251117T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251118T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251119T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251120T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251121T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251122T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251123T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251124T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251125T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251126T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251127T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251128T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251129T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251130T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251201T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251202T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251203T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251204T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251205T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251206T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251207T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251208T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251209T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251210T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251211T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251212T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251213T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251214T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251215T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251216T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251217T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251218T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251219T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251220T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251221T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251222T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251223T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251224T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251225T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251226T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251227T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251228T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251229T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251230T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20251231T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260101T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260102T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260103T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260104T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260105T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260106T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260107T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260108T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260109T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260110T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260111T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260112T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260113T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260114T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260115T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260116T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260117T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260118T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260119T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260120T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260121T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260122T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260123T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260124T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260125T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260126T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260127T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260128T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260129T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260130T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260131T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260201T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260202T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260203T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260204T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260205T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260206T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260207T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260208T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260209T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260210T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260211T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260212T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260213T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260214T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260215T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260216T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260217T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260218T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260219T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260220T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260221T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260222T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260223T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260224T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260225T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260226T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260227T0000Z.json
data/weather/ecmwf_ifs/ecmwf_ifs_20260228T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251101T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251102T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251103T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251104T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251105T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251106T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251107T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251108T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251109T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251110T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251111T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251112T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251113T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251114T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251115T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251116T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251117T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251118T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251119T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251120T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251121T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251122T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251123T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251124T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251125T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251126T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251127T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251128T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251129T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251130T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251201T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251202T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251203T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251204T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251205T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251206T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251207T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251208T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251209T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251210T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251211T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251212T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251213T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251214T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251215T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251216T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251217T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251218T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251219T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251220T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251221T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251222T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251223T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251224T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251225T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251226T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251227T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251228T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251229T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251230T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20251231T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260101T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260102T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260103T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260104T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260105T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260106T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260107T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260108T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260109T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260110T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260111T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260112T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260113T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260114T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260115T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260116T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260117T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260118T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260119T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260120T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260121T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260122T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260123T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260124T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260125T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260126T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260127T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260128T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260129T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260130T0000Z.json
data/weather/ecmwf_ifs_features/ecmwf_ifs_20260131T0000Z.json
forecasting/AGENTS.md
forecasting/FEATURE_EXPERIMENT.md
forecasting/README.md
forecasting/__init__.py
forecasting/artifacts/baseline_model.json
forecasting/artifacts/baseline_pre_20260131T1200Z.json
forecasting/audit.py
forecasting/baseline.py
forecasting/dataset.py
forecasting/experiment_features.py
forecasting/feature_weather.py
forecasting/forecast.py
forecasting/hourly.py
forecasting/inspect_data.py
forecasting/replay_february.py
forecasting/requirements-experiment.txt
forecasting/runner.py
forecasting/sites.py
forecasting/storage.py
forecasting/tests/test_feature_experiment.py
forecasting/tests/test_forecasting.py
forecasting/tests/test_validation.py
forecasting/time_alignment.py
forecasting/train_baseline.py
forecasting/weather.py
frontend/AGENTS.md
frontend/Dockerfile
frontend/index.html
frontend/package-lock.json
frontend/package.json
frontend/public/favicon.svg
frontend/public/images/wind-dusk.jpg
frontend/public/images/wind-sunset.jpg
frontend/src/App.tsx
frontend/src/AssistantPanel.css
frontend/src/AssistantPanel.tsx
frontend/src/ForecastResult.css
frontend/src/ForecastResult.tsx
frontend/src/ForecastSelectors.tsx
frontend/src/api.ts
frontend/src/assistantMessages.ts
frontend/src/forecastMessages.ts
frontend/src/i18n.tsx
frontend/src/main.tsx
frontend/src/messages.ts
frontend/src/style.css
frontend/tests/api.test.mjs
frontend/tsconfig.json
frontend/vite.config.ts
shared/API.md

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

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

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