AAYMA
RU
Войти

Vento

Агентная система почасового прогноза нормализованной мощности двух турбин ВЭС на 24–48 ч по архивным прогнозам NOAA GFS с анализом через OpenAI и…

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

О проекте

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

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

Суть

Агентная система почасового прогноза нормализованной мощности двух турбин ВЭС на 24–48 ч по архивным прогнозам NOAA GFS с анализом через OpenAI и пересчётом при обновлении погоды.

Как устроено

История двух турбин (291 859 строк, март 2023 – январь 2026) и 30 пакетов NOAA GFS (GRIB через ecCodes) с проверкой доступности на момент запуска → эмпирическая кривая «ветер–мощность» → OpenAI Responses API (gpt-4o-mini) анализирует результат → обновление погоды и пересчёт. Бэкенд на stdlib HTTP, UI на Node ES-модулях; пакетный режим воспроизводит февраль (28 запусков × 48 ч). Температурная поправка опциональна и по умолчанию выключена.

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

  • эмпирическая кривая мощности
  • NOAA GFS GRIB (ecCodes)
  • проверка доступности погоды по S3 Last-Modified
  • пакетный бэктест февраля
  • опциональная температурная поправка

Метрики

MAE 0.267–0.388 (нормализованная шкала) на январских проверках; 80 backend + 41 data + 30 UI тестов

Особенности

Строгий контроль утечки будущего: доступность погодного выпуска проверяется по Last-Modified объектов S3, provenance и контрольные суммы для каждого пакета, побайтово воспроизводимый CSV февраля; честно перечислены допущения (роль временной метки, высота анемометра).

Стек

Python · Node.js · JavaScript · Docker Compose · ecCodes · NOAA GFS S3

Модели

GPT-4o-mini (OpenAI Responses API)


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

README

README.md

Vento — Agentic AI для двух турбин ВЭС

Почасовой прогноз нормализованной мощности на 24–48 часов: архив NOAA GFS → проверка доступности на момент запуска → подготовка реальной истории → эмпирическая кривая мощности → анализ OpenAI → обновление погоды и повторный расчёт при изменении входов.

В общей версии объединены Data Ильи, интерфейс Богдана (22Malish22) и backend с интеграцией Codex (сессия smmaff). Полный текст ТЗ и критерии оценки сохранены в docs/task-board.md. Архитектура: docs/architecture.md, интерфейсы: docs/api-contract.md.

Что работает

Температурная поправка доступна как опциональная надстройка через apply_temperature_correction: true в запросе /api/forecasts или /api/agent/forecasts, выключена по умолчанию и не меняет базовый расчёт по кривой ветер–мощность.

  • История двух турбин за март 2023 — январь 2026: 291 859 исходных строк с контрольными суммами.
  • 30 проверяемых погодных пакетов NOAA, включая 28 ежедневных запусков для покрытия февраля.
  • API расчёта и агентного цикла; реальный OpenAI Responses API, без подстановки фиктивных ответов.
  • UI: выбор даты/часа UTC, турбин, 24/48 часов; график, таблица, CSV, анализ и выполненные этапы.
  • Февральский результат: 28 запусков по 48 часов, 2 688 точек; CSV первых суток каждого запуска содержит 1 344 строки, по 672 уникальных часа на турбину.

Запуск из чистого клона

Нужны Git, Python 3.11+ (проверено на 3.13), Node.js 22+. UI не требует npm install.

git clone https://github.com/BAITC-Hacks/hack-8df1dc64-inc.git
cd hack-8df1dc64-inc
python -m venv .venv

Активировать окружение:

# Linux/macOS
source .venv/bin/activate
# Windows PowerShell вместо строки выше
.\.venv\Scripts\Activate.ps1
python -m pip install -r data/requirements.txt

Куда проверяющему вставить ключ OpenAI

В корне репозитория (рядом с этим README.md) создайте локальный файл .env из шаблона .env.example, если файла ещё нет:

# Linux/macOS
cp .env.example .env
# Windows PowerShell: вместо команды выше
Copy-Item .env.example .env

Откройте .env и вставьте свой ключ в строку OPENAI_API_KEY после знака =:

OPENAI_API_KEY=ваш_ключ_OpenAI
OPENAI_MODEL=gpt-4o-mini

Не перезаписывайте существующий .env. OPENAI_MODEL можно изменить, если у ключа есть доступ к другой модели OpenAI. Сохраните файл и запустите backend по инструкции ниже; если сервер уже работает, перезапустите его. Для Docker Compose используется тот же .env. Ключ остаётся на backend: не вставляйте его в UI, код или Git.

Проверяющий использует свой ключ: ключ не входит в поставку проекта.

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

python -m backend.server

Второй терминал, из того же корня:

node ui/server.mjs

Открыть http://127.0.0.1:3000. Backend: http://127.0.0.1:8000/api/health. Остановить процессы: Ctrl+C. Серверы предназначены для локального демо.

Сценарий проверки

  1. Оставить 31 января 2026, 19:00 UTC, 24 часа, две турбины и явное допущение end.
  2. Нажать «Сформировать прогноз». Ожидаются 48 точек, график, таблица, реальный анализ OpenAI и длительности этапов. Первый расчёт истории может занять 10–20 секунд.
  3. Выбрать 14 февраля, 19:00 UTC, 48 часов и турбину 2: ожидаются 48 точек другого запуска.
  4. «Обновить погоду и пересчитать» повторно загружает NOAA. Это может занять несколько минут. Неизменившийся архив может дать тот же прогноз: это нормальный результат проверки обновлений.
  5. Скачать CSV и проверить поля времени, нормализованной мощности, ветра и температуры.

Без ключа остаются доступны численный /api/forecasts, пакетный расчёт и автоматические тесты. Агентный endpoint честно возвращает ошибку настройки, а не имитацию анализа.

Проверки

Финальная объединённая версия проверена из чистого клона с новым Python-окружением: 80 backend + 41 data + 30 UI тестов, два реальных HTTP-запроса с OpenAI (второй с новой загрузкой NOAA) и полный повтор февраля с побайтово одинаковым CSV; подробности — отчёт интеграции.

python -m unittest discover -s backend/tests -t . -v
python -m unittest discover -s data/tests -v
node --test ui/tests/*.test.mjs

Эквивалентные Linux/Git Bash команды: ./backend/test.sh, ./data/test.sh, ./ui/test.sh. Реальная проверка UI-клиента через HTTP при работающем backend (выполняет платные вызовы OpenAI):

node ui/smoke-api.mjs http://127.0.0.1:8000

Для проверки повторной загрузки NOAA установить LIVE_REFRESH=1 перед этой командой. Внешние API изолируются только в unit-тестах; этот smoke-сценарий использует настоящие сервисы.

Повторить февраль без OpenAI

python -m backend.batch_forecast --output-dir backend/runtime/february-recheck --timestamp-role end

Каталог результата должен быть новым. Сохраняются 28 JSON, february.csv и summary.json. Используются реальные архивы; февральских фактических мощностей нет, поэтому результат не содержит метрик точности февраля. Это численный пакетный режим, агентный анализ доступен отдельно через UI/API.

Docker Compose

Подготовлены два контейнера и общий запуск:

docker compose up --build

Предварительно заполнить локальный .env. UI: http://127.0.0.1:3000. Остановка: docker compose down. Погодный кэш хранится в именованном томе; .env исключён из контекста сборки и ключ передаётся только backend. Сборка и запуск контейнеров ещё не проверены: на рабочей машине отсутствует Docker Engine. Нативный запуск описан выше.

Настройки

ПеременнаяЗначение по умолчанию / назначение
OPENAI_API_KEYТребуется для реального анализа OpenAI
OPENAI_MODELgpt-4o-mini
WEATHER_ARCHIVE_DIRdata/weather
WEATHER_CACHE_DIRbackend/runtime/weather
UI_ORIGINShttp://127.0.0.1:3000,http://localhost:3000
PORT, HOSTUI: 3000, 127.0.0.1; задаются в окружении Node

Стек: Python stdlib HTTP/JSON, ecCodes 2.48.0 для GRIB, JavaScript ES modules/Node static server, OpenAI Responses API, NOAA GFS public S3. Постоянное хранение — исходные gzip, JSON с provenance и CSV; отдельный сервер БД не нужен.

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

  • Смысл временной метки в исходных данных выбран как допущение, не подтверждён организатором.

  • Высота исторического измерения ветра неизвестна, поправка высоты не применена.

  • Время публикации телеметрии неизвестно, используется допущение "конец интервала".

  • Часть скоростей ветра в прогнозе выходит за диапазон исторической кривой обучения, используется ближайшее крайнее значение (экстраполяция).

  • Прогнозируется нормализованная мощность 0–1; без номинальной мощности нет честного перевода в кВт/кВт·ч.

  • Роль метки 10-минутного интервала пока не подтверждена организатором. end — рабочее допущение; ответ всегда содержит timestamp_role_confirmed=false.

  • Архив GFS имеет сетку 0.5°, поэтому близкие турбины получают одинаковую погоду. Историческая высота анемометра неизвестна, поправка высоты не применяется.

  • Историческая доступность погоды проверяется по выпуску и Last-Modified конкретных объектов S3. Это доказательство времени текущей версии объекта, не журнал фактических запросов в прошлом.

  • Baseline — эмпирическая кривая ветер–мощность, без обучения сложной ML-модели. Январские проверки Data показывают MAE около 0.267–0.388 в нормализованной шкале; это ограниченная проверка, не оценка февраля. Подробнее: Data handoff.

  • Февральская фактическая мощность отсутствует. Тесты совместимости не доказывают точность прогнозирования.

  • Автоматические проверки DOM/HTTP не заменяют визуальную приёмку в браузере; она ещё требуется.

Проверка малых скоростей: распределение истории и отклик модели. Около 13,4% обучающих часов имеют ветер ≤2 м/с; низкие значения мощности согласуются с историей.

Доступ для экспертов и вклад

История, погодные пакеты, provenance и февральский расчёт доступны без аккаунта. Для live-анализа команда должна передать экспертам тестовый ключ отдельным закрытым каналом либо показать запущенный локальный стенд с настроенным ключом. Общедоступный стенд пока не опубликован; секретов в репозитории нет.

Шаблоны инструкций и .claude/ подготовлены заранее. Код Data, backend и UI создан во время работы над кейсом при помощи Codex; история и объяснение изменений — docs/progress.md. Исходный шаблон README и план сохранены в docs/archive. Все изменения ведутся в репозитории организатора.

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

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

smmaff 2022Malish22 9McPon4ik 4

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

  • 2026-09-23 17:54Подтвердить финальную интеграцию из чистого клона и реальные NOAA/OpenAI проверкиsmmaff
  • 2026-09-23 17:44Объединить все модули: backend B7, Data D2 и UI Ventosmmaff
  • 2026-09-23 17:39Добавить опциональную температурную поправку без изменения базовой кривойsmmaff
  • 2026-09-23 17:35Уточнить NOAA, единицы времени и проверить модель при слабом ветреsmmaff
  • 2026-09-23 17:32feat(ui): brand Vento and improve forecast chart readability22Malish22
  • 2026-09-23 17:28docs: explain where reviewers set OpenAI API keysmmaff
  • 2026-09-23 16:49Зафиксировать локальный запуск и проверку двух прогнозовsmmaff
  • 2026-09-23 16:35Подтвердить чистый запуск и воспроизводимость февральского расчётаsmmaff
Все коммиты (33)
  • 2026-09-23 16:30Подключить UI к агентному циклу и рассчитать февраль по NOAAsmmaff
  • 2026-09-23 16:06Объединить опубликованный UI и сохранить актуальные инструкции модулейsmmaff
  • 2026-09-23 16:05Объединить Data D2 с backend и сохранить контракты обоих модулейsmmaff
  • 2026-09-23 15:55feat(data): deliver audited NOAA forecast archive and backend integration checksMcPon4ik
  • 2026-09-23 15:55feat(ui): animate wind turbines and breeze lines22Malish22
  • 2026-09-23 15:46Подключить реальный анализ OpenAI и формат погоды Open-Meteosmmaff
  • 2026-09-23 15:38fix(ui): redraw turbine silhouettes and credit 22Malish2222Malish22
  • 2026-09-23 15:23Реализовать расчёт мощности B2 и HTTP API B3 с проверкой историиsmmaff
  • 2026-09-23 15:21feat(ui): revise visual design and add loading and site information22Malish22
  • 2026-09-23 15:12Зафиксировать контракты расчёта B2 и HTTP API B3smmaff
  • 2026-09-23 15:05feat(ui): add turbine and UTC hour selection with saved settings22Malish22
  • 2026-09-23 15:03Merge remote-tracking branch 'origin/data' into backendsmmaff
  • 2026-09-23 15:03Синхронизировать общие документы backend с опубликованным контрактом Data D1smmaff
  • 2026-09-23 14:53feat(data): import organizer turbine history and prepare cutoff-safe hourly dataMcPon4ik
  • 2026-09-23 14:49merge: update markdown content from main b804db322Malish22
  • 2026-09-23 14:46docs: import module markdown and audit documentation gaps22Malish22
  • 2026-09-23 14:46Закрепить регулярную синхронизацию агентов и обновить отчёт UIsmmaff
  • 2026-09-23 14:43merge: sync shared main files into ui22Malish22
  • 2026-09-23 14:29Синхронизировать общие документы и локальные файлы командыsmmaff
  • 2026-09-23 14:16feat(ui): add wind forecast setup screen and real tests22Malish22
  • 2026-09-23 14:12Реализовать B1: проверку погодных данных и почасового горизонтаsmmaff
  • 2026-09-23 14:09feat(data): audit source CSV quality with real tests and usage guideMcPon4ik
  • 2026-09-23 14:08docs(data): record CSV audit ownership and pending source datasetMcPon4ik
  • 2026-09-23 14:02Согласовать контракт B1 и зафиксировать начало работы backendsmmaff
  • 2026-09-23 13:40Заполнить контрактные файлы под кейс: Agentic AI-систему для прогнозирования почасовой выработки ветроэлектростанции (ВЭС) на горизонте 24–48 часов.smmaff
Структура репозитория (201 файлов)
.claude/.gitattributes
.claude/agents/supervisor.md
.claude/hooks/check-progress-and-tests.sh
.claude/settings.json
.dockerignore
.env.example
.gitignore
AGENTS.md
CLAUDE.md
README.md
backend/.gitattributes
backend/.gitignore
backend/Dockerfile
backend/README.md
backend/__init__.py
backend/agent.py
backend/analyze_weather.py
backend/audit_low_wind.py
backend/b4-verification.md
backend/batch_forecast.py
backend/config.py
backend/contract-proposal.md
backend/examples/README.md
backend/examples/open_meteo_user_sample.json
backend/manual_check.py
backend/manual_history.py
backend/model.py
backend/openai_analysis.py
backend/reports/clean-clone.md
backend/reports/february/february.csv
backend/reports/february/runs/20260131T190000Z.json
backend/reports/february/runs/20260201T190000Z.json
backend/reports/february/runs/20260202T190000Z.json
backend/reports/february/runs/20260203T190000Z.json
backend/reports/february/runs/20260204T190000Z.json
backend/reports/february/runs/20260205T190000Z.json
backend/reports/february/runs/20260206T190000Z.json
backend/reports/february/runs/20260207T190000Z.json
backend/reports/february/runs/20260208T190000Z.json
backend/reports/february/runs/20260209T190000Z.json
backend/reports/february/runs/20260210T190000Z.json
backend/reports/february/runs/20260211T190000Z.json
backend/reports/february/runs/20260212T190000Z.json
backend/reports/february/runs/20260213T190000Z.json
backend/reports/february/runs/20260214T190000Z.json
backend/reports/february/runs/20260215T190000Z.json
backend/reports/february/runs/20260216T190000Z.json
backend/reports/february/runs/20260217T190000Z.json
backend/reports/february/runs/20260218T190000Z.json
backend/reports/february/runs/20260219T190000Z.json
backend/reports/february/runs/20260220T190000Z.json
backend/reports/february/runs/20260221T190000Z.json
backend/reports/february/runs/20260222T190000Z.json
backend/reports/february/runs/20260223T190000Z.json
backend/reports/february/runs/20260224T190000Z.json
backend/reports/february/runs/20260225T190000Z.json
backend/reports/february/runs/20260226T190000Z.json
backend/reports/february/runs/20260227T190000Z.json
backend/reports/february/summary.json
backend/reports/final-integration.json
backend/reports/live-cycle.json
backend/reports/low-wind/README.md
backend/reports/low-wind/distribution.png
backend/reports/low-wind/live-checks.json
backend/reports/low-wind/summary.json
backend/requirements-audit.txt
backend/server.py
backend/service.py
backend/temperature_correction.py
backend/test.sh
backend/tests/__init__.py
backend/tests/test_analysis.py
backend/tests/test_model.py
backend/tests/test_server.py
backend/tests/test_service.py
backend/tests/test_temperature_correction.py
backend/tests/test_validation.py
backend/tests/test_workflow.py
backend/validation.py
backend/weather_analysis.py
backend/weather_provider.py
compose.yaml
data/.gitignore
data/README.md
data/__init__.py
data/audit_csv.py
data/check_backend.py
data/history.py
data/prepare_history.py
data/prepare_weather.py
data/raw/manifest.json
data/raw/turbine_1.csv.gz
data/raw/turbine_2.csv.gz
data/reports/D2-handoff.md
data/reports/backend_current_integration.json
data/reports/source_audit.json
data/reports/weather_coverage.json
data/requirements.txt
data/test.sh
data/tests/test_audit_csv.py
data/tests/test_history.py
data/tests/test_weather.py
data/weather/20260115T190000Z.json
data/weather/20260115T190000Z.provenance.json
data/weather/20260123T190000Z.json
data/weather/20260123T190000Z.provenance.json
data/weather/20260131T190000Z.json
data/weather/20260131T190000Z.provenance.json
data/weather/20260201T190000Z.json
data/weather/20260201T190000Z.provenance.json
data/weather/20260202T190000Z.json
data/weather/20260202T190000Z.provenance.json
data/weather/20260203T190000Z.json
data/weather/20260203T190000Z.provenance.json
data/weather/20260204T190000Z.json
data/weather/20260204T190000Z.provenance.json
data/weather/20260205T190000Z.json
data/weather/20260205T190000Z.provenance.json
data/weather/20260206T190000Z.json
data/weather/20260206T190000Z.provenance.json
data/weather/20260207T190000Z.json
data/weather/20260207T190000Z.provenance.json
data/weather/20260208T190000Z.json
data/weather/20260208T190000Z.provenance.json
data/weather/20260209T190000Z.json
data/weather/20260209T190000Z.provenance.json
data/weather/20260210T190000Z.json
data/weather/20260210T190000Z.provenance.json
data/weather/20260211T190000Z.json
data/weather/20260211T190000Z.provenance.json
data/weather/20260212T190000Z.json
data/weather/20260212T190000Z.provenance.json
data/weather/20260213T190000Z.json
data/weather/20260213T190000Z.provenance.json
data/weather/20260214T190000Z.json
data/weather/20260214T190000Z.provenance.json
data/weather/20260215T190000Z.json
data/weather/20260215T190000Z.provenance.json
data/weather/20260216T190000Z.json
data/weather/20260216T190000Z.provenance.json
data/weather/20260217T190000Z.json
data/weather/20260217T190000Z.provenance.json
data/weather/20260218T190000Z.json
data/weather/20260218T190000Z.provenance.json
data/weather/20260219T190000Z.json
data/weather/20260219T190000Z.provenance.json
data/weather/20260220T190000Z.json
data/weather/20260220T190000Z.provenance.json
data/weather/20260221T190000Z.json
data/weather/20260221T190000Z.provenance.json
data/weather/20260222T190000Z.json
data/weather/20260222T190000Z.provenance.json
data/weather/20260223T190000Z.json
data/weather/20260223T190000Z.provenance.json
data/weather/20260224T190000Z.json
data/weather/20260224T190000Z.provenance.json
data/weather/20260225T190000Z.json
data/weather/20260225T190000Z.provenance.json
data/weather/20260226T190000Z.json
data/weather/20260226T190000Z.provenance.json
data/weather/20260227T190000Z.json
data/weather/20260227T190000Z.provenance.json
data/weather_gfs.py
docs/api-contract.md
docs/architecture.md
docs/archive/README-before-integration.md
docs/archive/architecture-before-integration.md
docs/archive/plan-before-integration.md
docs/db-schema.md
docs/generator-prompt.md
docs/handover-protocol.md
docs/kickoff-prompt-template.md
docs/md-audit.md
docs/plan.md
docs/progress.md
docs/repository-sync.md
docs/resources-needed.md
docs/task-board.md
ui/.gitattributes
ui/Dockerfile
ui/README.md
ui/api.mjs
ui/app.mjs
ui/boot.mjs
ui/design-review.md
ui/draft.mjs
ui/index.html
ui/initialization.mjs
ui/parameters.mjs
ui/privacy.html
ui/results.mjs
ui/server.mjs
ui/smoke-api.mjs
ui/styles.css
ui/terms.html
ui/test.sh
ui/tests/api.test.mjs
ui/tests/design.test.mjs
ui/tests/draft.test.mjs
ui/tests/results.test.mjs
ui/tests/ui.test.mjs
Ветки (4)

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

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

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