ARYS
Django-портал с ML-сервисом, который прогнозирует нормализованную мощность двух ветротурбин на 48 часов по прогнозам погоды JMA GSM (Open-Meteo).
О проекте
Команда: Арыс
Кейс HackAlem.ai: Энергетика — Самрук-Казына
Стадия: Доведённый продукт
Задача кейса: AI-агент, прогнозирующий выработку ветровой электростанции по погодным данным
Суть
Django-портал с ML-сервисом, который прогнозирует нормализованную мощность двух ветротурбин на 48 часов по прогнозам погоды JMA GSM (Open-Meteo). Есть режимы live и исторического replay, история, кэш и экспорт CSV/JSON.
Как устроено
Django получает погодный прогноз JMA GSM (ветер 10 м, направление, температура 2 м) через Open-Meteo или импортированный архив и сохраняет неизменяемый снимок в SQLite. Затем отправляет 48 часов в отдельный ML-сервис POST /v1/predict по версионированному контракту windpower.input.v1 и получает 48 значений predicted_normalized_power в [0,1] с версией модели и флагом alignment_confirmed. Модель обучалась на GPU в Brev; сравнивались нейросетевые функции потерь и бустинг с хронологической валидацией. «Агент» здесь детерминированная оркестрация с журналом этапов, без LLM.
Ключевые решения
- gradient boosting
- нейросети (сравнение функций потерь)
- хронологическая валидация
- версионированный JSON-контракт ML
- Open-Meteo Previous Runs для replay
- кэш по снимку, турбине и версии модели
Особенности
Сильная защита от утечки будущего: as_of в replay трактуется как момент решения, неподтверждённое выравнивание времени честно помечается alignment_confirmed=false и требует явного --allow-provisional. Ошибки никогда не подменяются выдуманной мощностью. Строгий контракт ML-сервиса с JSON Schema и OpenAPI.
Стек
Python · Django · SQLite · Open-Meteo · Docker · GitHub Actions · Brev (GPU) · HTML · CSS · JavaScript
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-15d1fa83-team.
README
README.mdARYS — прогнозирование выработки ВЭС
Единый проект команды АРЫС для HackAlem: Django-портал с нативным HTML/CSS/JavaScript, модуль текущих и архивных прогнозов погоды и обученная ML-модель двух турбин. Основная ветка — main. Веса уже находятся в репозитории; для прогнозирования не нужны GPU, NVIDIA key, Brev или обучение.
Это готовая интегрированная хакатонная сборка, а не подтверждённая промышленная система управления ВЭС. Временная привязка исходных измерений не подтверждена: модель честно возвращает
alignment_confirmed=false. Для запуска требуется явный--allow-provisional. Февральской фактической мощности для оценки качества нет.
Что умеет проект
- Прогнозировать нормализованную мощность каждой из двух турбин на 48 последовательных часов.
- Показывать все 48 или первые 24 часа, график, погоду, журнал расчёта и историю.
- Работать в live (Django выбирает «сейчас») и историческом replay (заданный момент решения).
- Получать только погодные прогнозы JMA GSM: ветер на 10 м, температура на 2 м; не подменять их наблюдениями/реанализом.
- Сохранять погодные снимки, версию модели, статус согласования и ошибки; экспортировать CSV/JSON.
- Проверять возможности загруженных весов через metadata и кэшировать результат по снимку + турбине + версии модели.
- Обновлять прогноз при изменении погоды или модели. Ошибки никогда не заменяются выдуманной мощностью.
Быстрый запуск — Windows PowerShell
Все команды выполняйте в корне проекта. Для текущей рабочей копии:
Set-Location 'C:\Users\evgen\Desktop\Hackathon\Hackalem AI\Source'
На другом компьютере клонируйте основную ветку:
git clone --branch main https://github.com/BAITC-Hacks/hack-15d1fa83-team.git
cd hack-15d1fa83-team
Требуется Python 3.12. Создавайте среду только если её ещё нет:
py -3.12 -m venv .venv
Не пересоздавайте .venv, пока из неё запущены серверы: Windows может блокировать Scripts/python.exe. Активация и изменение ExecutionPolicy не нужны.
Установка и подготовка базы:
.venv/Scripts/python.exe -m pip install -r requirements.txt
.venv/Scripts/python.exe manage.py migrate
.venv/Scripts/python.exe manage.py seed_demo
Несмотря на историческое название, seed_demo добавляет только две турбины с координатами и не переключает ML на заглушку, не переписывает существующие координаты.
Запуск всего проекта одной командой:
.venv/Scripts/python.exe tools/run_project.py --allow-provisional
Откройте http://127.0.0.1:8000. ML-сервис работает на http://127.0.0.1:8001. Выберите турбину, источник Open-Meteo и нажмите «Построить прогноз». Интернет нужен погодному модулю, но не вычислениям ML. Ctrl+C останавливает оба дочерних процесса. Запускатель не останавливает чужие процессы при занятом порте; можно указать --web-port 8002 --ml-port 8003.
Флаг --allow-provisional разрешает использование конкретного неподтверждённого артефакта, но не делает alignment_confirmed истинным. Без флага текущая модель отказывается запускаться.
Linux / macOS
# Только при отсутствии .venv:
python3.12 -m venv .venv
. .venv/bin/activate
python -m pip install -r requirements.txt
python manage.py migrate
python manage.py seed_demo
python tools/run_project.py --allow-provisional
Запуск сервисов отдельно
Терминал 1:
.venv/Scripts/python.exe inference/serve.py --allow-provisional
Терминал 2:
$env:ML_BACKEND = 'http'
$env:ML_SERVICE_URL = 'http://127.0.0.1:8001/v1/predict'
.venv/Scripts/python.exe manage.py runserver
Для полностью офлайн-проверки UI: python tools/run_project.py --demo, затем источник «Демонстрационные данные». Это явно обозначенная синтетическая погода и аналитическая заглушка, а не обученная модель. Такой режим не используется автоматически при сбоях. HTTP-режим не отправляет синтетический источник рабочему ML.
Архитектура и ответственность
Браузер (HTML / CSS / JavaScript)
→ Django: live/replay, проверка возможностей ML
→ Weather: JMA GSM / импортированный архив
→ SQLite: неизменяемый погодный снимок
→ POST ML /v1/predict: 48 подготовленных часов
← 48 значений мощности + версия + alignment_confirmed
→ проверка ответа, кэш, история, CSV/JSON
→ график 24/48 часов
Django владеет получением погоды, выбором прогноза, проверкой исторической доступности, кэшем и хранением. ML загружает включённые веса один раз и выполняет CPU-инференс. Обучение и скачивание погоды внутри /v1/predict не выполняются. Legacy-маршрут ML /power/forecast сохранён для совместимости, но единый проект его не использует и не настраивает ему погодный URL.
Агент здесь — детерминированная оркестрация с журналом этапов, не LLM. Команда refresh_forecasts выполняет один проход обновлений; постоянный планировщик автоматически не устанавливается.
Турбины и погодные данные
| Турбина | Широта | Долгота |
|---|---|---|
| turbine_1 | 43.645150 | 78.535604 |
| turbine_2 | 43.643198 | 78.538828 |
Координаты взяты из задания: турбина 1, турбина 2. Обе поддерживаются включёнными весами. Они близко расположены: одинаковые значения погодной сетки возможны, но ID турбин и запросы не смешиваются.
Параметры Open-Meteo: models=jma_gsm, hourly=wind_speed_10m,wind_direction_10m,temperature_2m, wind_speed_unit=ms, temperature_unit=celsius, timezone=UTC. Координаты и настройки сетки соответствуют загрузчику обучения. Ветер 100 м или GFS/ICON нельзя переименовать в эти признаки.
| Режим | Выбор времени и данных |
|---|---|
| Live | Django выбирает текущий UTC-момент и следующий целый час; текущий JMA-прогноз |
| Replay / Open-Meteo | Previous Runs, переменные _previous_dayN; сведения о выпуске оценочные |
| Replay / импорт | Последний проверенный выпуск, доступный на as_of и покрывающий 48 часов |
| Demo | Только явно выбранная синтетика; не оценка точности |
Пользователь не вводит время выпуска прогноза. as_of в replay — момент принятия решения, а не issued_at. Live отклоняет присланные клиентом as_of/start_time.
Previous Runs не раскрывает точное время каждого выпуска/публикации. Запас 8 часов в Django — консервативная эвристика, не доказательство отсутствия утечки будущего. Такие результаты помечены estimated_fixed_lead. Для строгого конкурсного replay нужны оригинальные выпуски с подтверждённой доступностью. У live выдачи время выпуска неизвестно и остаётся null; время получения не выдаётся за него.
Подробности формата и импорта — погодный модуль. Старые 100-метровые снимки сохранены для просмотра, но исключены из новой инференс-цепочки.
API и ML-контракт
Дизайн интеграции · ML-контракт · общий OpenAPI · OpenAPI ML-сервиса.
Django на порту 8000:
| Метод | Путь | Назначение |
|---|---|---|
| GET | /api/v1/health/ | Состояние Django, не гарантия доступности ML |
| GET | /api/v1/ml/metadata/ | Нормализованные возможности реально загруженных весов |
| GET | /api/v1/turbines/ | Турбины и координаты |
| POST / GET | /api/v1/forecasts/ | Создать прогноз / история |
| GET | /api/v1/forecasts/{id}/ | Результат, погода, журнал и ошибки |
| POST | /api/v1/forecasts/{id}/refresh/ | Обновить с проверкой снимка и версии модели |
| GET | /api/v1/forecasts/{id}/ml-input/ | Точное тело запроса к ML |
| GET | /api/v1/forecasts/{id}/export.csv | Все 48 прогнозов, версия и alignment |
| POST | /api/v1/weather/forecast/ | Погода без вызова ML |
| GET | /api/v1/weather/snapshots/{id}/ | Снимок и происхождение |
| POST | /api/v1/weather/import/ | Импорт проверенного архивного выпуска |
Live-запрос к Django:
{"mode":"live","turbine_id":"turbine_2","provider":"open_meteo","weather_model":"jma_gsm"}
Replay-запрос:
{"mode":"replay","turbine_id":"turbine_2","provider":"archive","weather_model":"jma_gsm","as_of":"2026-01-31T18:00:00Z","start_time":"2026-02-01T00:00:00Z"}
ML на порту 8001: GET /health, GET /v1/metadata, POST /v1/predict, интерактивные /docs. В запросе predict — schema_version=windpower.input.v1, turbine_id, weather_model=jma_gsm и ровно 48 records:
| Поле каждой записи | Значение |
|---|---|
| target_time | Aware ISO 8601, целые последовательные часы, желательно UTC Z |
| wind_speed_10m_ms | Ветер 10 м, м/с, от 0 до 100 |
| wind_direction_10m_deg | Откуда дует ветер, от севера по часовой стрелке, 0–360° |
| temperature_2m_c | Температура 2 м, °C, от −100 до 70 |
Строки вместо чисел, null, boolean, NaN/Infinity, пропуски/дубли и неизвестные поля запрещены. Давление, возраст и сведения о выпуске хранятся в Django, а не в predict body.
Ответ: windpower.output.v1, turbine_id, weather_model, model_version, alignment_confirmed и 48 совпадающих часов с predicted_normalized_power в [0,1]. Это доля, не проценты/МВт. График показывает проценты, JSON/CSV сохраняют долю. Выбор 24 часов не сокращает ML-запрос.
Metadata артефакта использует supported_turbines, supported_weather_models, fields, версии схем, required_records и alignment_confirmed. Django адаптирован к этой фактической структуре; поддержка турбин не угадывается по названию модели.
Ошибки 401 (токен), 422 (контракт/турбина/источник), 502/504 (ответ/доступность/тайм-аут) видны в интерфейсе и истории. При смене артефакта между metadata и predict возвращается 409, чтобы не записать ответ под неверной версией кэша.
Настройки
.env.example — справочник. Python-приложения не читают .env автоматически: экспортируйте переменные в терминале и перезапускайте процессы. Compose использует .env только для подстановки своих переменных.
| Переменная | Назначение |
|---|---|
| ML_BACKEND | http по умолчанию; demo только явно |
| ML_SERVICE_URL | Доступный адрес POST /v1/predict |
| ML_METADATA_URL | Необязательно; по умолчанию соседний /v1/metadata |
| ML_SERVICE_TOKEN | Одинаковый Bearer-токен у Django и ML; пустой допустим локально |
| MODEL_PATH | Путь к включённому или новому проверенному артефакту |
| ALLOW_PROVISIONAL_MODEL | 1 разрешает текущую неподтверждённую модель; по умолчанию 0 |
| HTTP_TIMEOUT | Тайм-аут обращений Django, 30 секунд |
| API_TOKEN | Отдельный токен входящего Django API, не токен ML |
| DJANGO_DB_PATH | Необязательный путь SQLite; по умолчанию db.sqlite3 в корне |
| DJANGO_DEBUG / DJANGO_SECRET_KEY / DJANGO_ALLOWED_HOSTS | Настройки окружения Django |
Токены ML/API не являются NVIDIA/Brev API key. Для двух отдельных терминалов задайте одинаковый ML_SERVICE_TOKEN в обоих. При едином запускателе он наследуется обоими процессами. Секреты не коммитить.
Ссылка на ветку GitHub — исходный код, не работающий API. В разных контейнерах localhost не указывает на соседний сервис.
Веса, обучение и честные ограничения
Включена модель mlp-76540e5972a6, JMA GSM, обе турбины: веса, manifest и SHA-256, метрики. Сеть MLP 64 → 32 → 1, ReLU/sigmoid, 2 881 параметр; нормализация и веса уже экспортированы для NumPy-инференса. Обучение на CUDA: 28 эпох, выбран checkpoint 18.
Признаки: три погодные величины, производные скорости/направления, циклические UTC-час/день года и ID турбины. Датасет: 96 900 строк, 48 450 пар «турбина–час», два архивных смещения. Обучение до октября 2025; validation октябрь–декабрь; оценка январь 2026.
| Январь 2026 | Обе турбины | Турбина 1 | Турбина 2 |
|---|---|---|---|
| MAE | 0.178525 | 0.173897 | 0.183153 |
| RMSE | 0.238635 | 0.232772 | 0.244357 |
| Bias | +0.066447 | +0.059136 | +0.073758 |
Это ошибки в долях нормализованной шкалы, не MAPE и не «процент точности». Январь содержит 2 956 примеров с коррелирующими архивными вариантами и просматривался в разработке, поэтому не является полностью слепым внешним тестом. Сравнения альтернатив сохранены; выбранные веса при объединении не переобучались и не менялись.
Остаются ограничения:
- Начало/конец десятиминутного интервала измерений не подтверждены; принято начало, часовой пояс Asia/Almaty с историческим изменением смещения. Поэтому alignment_confirmed=false.
- Fixed-offset архив не доказывает доступность точного выпуска в прошлом.
- Измерения заканчиваются 31 января: точность 1–28 февраля не заявляется.
- Для перевода доли в МВт нужны подтверждённые номинальные мощности и соглашение нормализации.
- SQLite и синхронная оркестрация рассчитаны на хакатонную нагрузку; это не отказоустойчивый промышленный диспетчер.
Создание следующих моделей вынесено в training_toolkit/run.py; подробности в руководстве обучения. CPU-инференс не устанавливает PyTorch/CatBoost. Облачные задания, GPU, платежи и переобучение не запускаются автоматически.
Проверки
Установить инструменты тестирования (обучение только маленьких синтетических фикстур на CPU):
.venv/Scripts/python.exe -m pip install '.[test]'
.venv/Scripts/python.exe -m pip install torch==2.6.0 --index-url https://download.pytorch.org/whl/cpu
.venv/Scripts/python.exe manage.py check
.venv/Scripts/python.exe manage.py makemigrations --check --dry-run
.venv/Scripts/python.exe -m pytest -q
При запущенном ML:
Для локальных учебных фикстур и CI используется CPU PyTorch 2.6.0. Сборка 2.14.0+cpu не загрузила c10.dll на проверенном Windows; это не затрагивает NumPy-инференс включённых весов. Исходный обучающий GPU-релиз и его версии сохранены в отчётах.
.venv/Scripts/python.exe inference/smoke_test.py --url http://127.0.0.1:8001
Общий набор включает Django, ML, защиту от некорректных признаков, обучающие фикстуры, хеш реального артефакта, эталонные ответы двух турбин и Django → настоящий ML по локальному HTTP. Сетевые обращения к Open-Meteo в регрессионных тестах не выполняются. Фактические результаты интеграционной приёмки — VERIFICATION. GitHub Actions запускает этот набор при push/PR; локальный успех сам по себе не доказывает статус hosted CI.
Replay и обновления
python manage.py import_weather path/to/verified-run.json
python manage.py backtest --provider archive --weather-model jma_gsm --turbine turbine_2 --output output/turbine-2.csv
python manage.py refresh_forecasts --limit 20
Backtest рассчитывает отдельные 48-часовые горизонты ежедневно с моментом решения в 18:00 UTC предыдущего дня. Пересекающиеся прогнозы не усредняются. Существующий CSV не перезаписывается, ошибка останавливает прогон с сохранением выполненной части. Для другой турбины используйте другой файл. Синтетический пример импорта намеренно отклоняется, а не выдаётся за реальный архив.
Docker Compose и production
Для локальной демонстрации двух сервисов с постоянной SQLite-базой:
$env:ALLOW_PROVISIONAL_MODEL = '1'
docker compose up --build
Портал: http://127.0.0.1:8000. Внутри Compose Django обращается к http://windpower-ml:8000/v1/predict. Порты привязаны только к localhost. Остановка: docker compose down; не добавляйте -v, если нужно сохранить базу. Docker-сборку следует проверить там, где доступен Docker Engine; состояние проверки отражено в VERIFICATION.
Compose использует development runserver и не предназначен для публичного production. Для внешнего развёртывания нужны WSGI/ASGI-сервер, HTTPS/reverse proxy, static, PostgreSQL/очередь при нагрузке, секреты и ограничение доступа. При DJANGO_DEBUG=0 установите уникальный DJANGO_SECRET_KEY, API_TOKEN и точные ALLOWED_HOSTS. UI требует входа; создайте пользователя python manage.py createsuperuser. Сервисный токен обязателен на открытом ML endpoint.
Структура и документация
README.md Единая точка входа и запуска
config/, common/ Django-настройки, проверки, HTTP-доступ
forecasting/ Оркестрация, история, API, адаптер ML
weather_archive/ Источники, выбор архивов, снимки
templates/, static/ Нативный интерфейс
src/windpower/ Признаки, NumPy-модель, FastAPI, обучение
models/production/ Выбранные веса и происхождение
inference/ Запуск ML, HTTP smoke test, эталоны
tools/run_project.py Совместный локальный запуск
training_toolkit/, scripts/ Явные команды разработки моделей
tests/ Общие регрессионные тесты
docs/, reports/ Контракты, руководство обучения, отчёты
Подробные технические документы дополняют этот README, а не задают альтернативный способ сборки. Старые отчёты ML сохранены как история экспериментов; актуальный статус объединения — docs/VERIFICATION.md. Сырые данные, локальная база, PDF/изображения задания, venv, погодный кэш и секреты не включаются в Git.
Если что-то не запускается
- ML не готов / alignment: запустите с явным --allow-provisional после прочтения ограничений; не меняйте флаг внутри весов.
- ModuleNotFoundError windpower: выполните pip install -r requirements.txt именно Python из .venv.
- Порт занят: завершите свой старый сервер или выберите другие порты; не пересоздавайте работающий venv.
- 401: одинаковый ML_SERVICE_TOKEN на обоих сервисах; API_TOKEN — отдельная настройка Django.
- 422: проверьте JMA GSM, 10 м, диапазоны, 48 целых UTC-часов и ID.
- Погода недоступна: проверьте сеть и наличие JMA для периода. Автоматического fallback нет.
- Старые снимки: они остаются в истории, но для новой модели нужен новый JMA 10 м снимок.
Авторы коммитов
История коммитов
- 2026-09-23 17:52Merge weather dashboard and trained two-turbine model for pre-finaldaktotakoymesha
- 2026-09-23 17:43Publish unified release on main with consolidated READMES.Ev
- 2026-09-23 17:40Merge trained two-turbine ML with Django into unified final projectS.Ev
- 2026-09-23 17:09Merge main history for unified release documentationS.Ev
- 2026-09-23 17:08Record Source workspace and unified release workflowS.Ev
- 2026-09-23 17:06Update README.mderasyltregali-art
- 2026-09-23 17:04Ship verified two-turbine model, separate training toolkit, and English/Russian integration guidesdaktotakoymesha
- 2026-09-23 16:50Update README.mderasyltregali-art
Все коммиты (24)
- 2026-09-23 16:41Adapt Django and weather modules to windpower v1 ML contractS.Ev
- 2026-09-23 16:38Benchmark neural losses and boosted trees on both turbines with chronological validationdaktotakoymesha
- 2026-09-23 16:32Update README.mderasyltregali-art
- 2026-09-23 16:28Verify both-turbine GPU model and document completed trainingdaktotakoymesha
- 2026-09-23 16:21Fix training launcher lock recovery and bound Brev startup waitsdaktotakoymesha
- 2026-09-23 16:09Implement versioned direct weather-to-power API and team integration contractdaktotakoymesha
- 2026-09-23 15:56Prepare joint turbine training, separate evaluations and shared weather proposaldaktotakoymesha
- 2026-09-23 15:53Revise README content and formattingerasyltregali-art
- 2026-09-23 15:42Fix flat training ZIP downloads and record verified GPU model resultsdaktotakoymesha
- 2026-09-23 15:29Update README.mderasyltregali-art
- 2026-09-23 15:22Automate Brev training, result verification and GPU shutdowndaktotakoymesha
- 2026-09-23 15:16Build Django wind forecast portal and archived weather moduleS.Ev
- 2026-09-23 14:54Update README with new sections on data processingerasyltregali-art
- 2026-09-23 14:45Revise README with project and team detailserasyltregali-art
- 2026-09-23 14:44Add tested Brev training launcher, data assembly report and integration docsdaktotakoymesha
- 2026-09-23 14:34Add initial weather-to-power training and service checkpointdaktotakoymesha
Структура репозитория (112 файлов)
.dockerignore .env.example .github/workflows/tests.yml .gitignore AGENTS.md Dockerfile README.md common/__init__.py common/contracts.py common/http.py compose.yaml config/__init__.py config/settings.py config/urls.py config/wsgi.py docs/BREV.md docs/DATA.md docs/ML_INTEGRATION.md docs/ML_SERVICE_CONTRACT.md docs/MODEL_COMPARISON.md docs/STATUS.md docs/TEAM_INTEGRATION_PROPOSAL.md docs/TRAINING.md docs/VERIFICATION.md docs/WEATHER_ARCHIVE.md docs/WEATHER_CONTRACT.md docs/examples/archived-run-synthetic.json docs/examples/direct-input.json docs/examples/ml-input.json docs/examples/ml-output.json docs/ml-input.schema.json docs/ml-output.schema.json docs/ml-service.openapi.json docs/openapi.json forecasting/__init__.py forecasting/admin.py forecasting/management/__init__.py forecasting/management/commands/__init__.py forecasting/management/commands/backtest.py forecasting/management/commands/refresh_forecasts.py forecasting/management/commands/seed_demo.py forecasting/migrations/0001_initial.py forecasting/migrations/0002_forecast_alignment_confirmed_and_more.py forecasting/migrations/__init__.py forecasting/ml_client.py forecasting/models.py forecasting/services.py forecasting/views.py inference/examples/turbine_1-48h-request.json inference/examples/turbine_1-48h-response.json inference/examples/turbine_2-48h-request.json inference/examples/turbine_2-48h-response.json inference/serve.py inference/smoke_test.py manage.py models/production/independent_verification.json models/production/manifest.json models/production/metrics.json models/production/model.json pyproject.toml reports/cloud_training_both_verification.json reports/cloud_training_verification.json reports/dataset_assembly.json reports/dataset_assembly_both.json reports/direct_api_verification.json reports/model_comparison_v1.json reports/release_verification.json reports/unified_integration.json reports/verification.json requirements-runtime.txt requirements.txt scripts/auto_train.py scripts/benchmark_models.py scripts/brev_train.py scripts/export_contract.py scripts/verify_trained_model.py src/windpower/__init__.py src/windpower/api.py src/windpower/archive.py src/windpower/contracts.py src/windpower/dataset.py src/windpower/features.py src/windpower/model.py src/windpower/train.py static/app.css static/app.js templates/dashboard.html templates/registration/login.html tests/__init__.py tests/conftest.py tests/test_automation.py tests/test_dataset.py tests/test_direct_api.py tests/test_model_api.py tests/test_release.py tests/test_remote.py tests/test_two_turbines.py tests/test_unified_integration.py tests/test_workflow.py tools/mock_ml_service.py tools/run_project.py training_toolkit/run.py weather_archive/__init__.py weather_archive/admin.py weather_archive/management/__init__.py weather_archive/management/commands/__init__.py weather_archive/management/commands/import_weather.py weather_archive/migrations/0001_initial.py weather_archive/migrations/0002_archivedrun_schema_version.py weather_archive/migrations/__init__.py weather_archive/models.py weather_archive/services.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.