О проекте
Команда: Djem
Кейс HackAlem.ai: Спецтрек — Astana Innovations
Стадия: Доведённый продукт
Задача кейса: «Аким на 5 часов»: городской симулятор, распределяющий бюджет по 5 направлениям и 5 районам
Суть
Полноценный продукт-симулятор Астаны: карта районов, 14 инициатив, 5 решений, Score и AI-разбор. Есть миссии, городские события (паводок, смог, снегопад), личный кабинет, библиотека сценариев, HTML-презентация и админ-агент для редактирования данных.
Как устроено
Python считает Score = 0.7·взвешенный средний + 0.3·слабейший район − число показателей ниже 40 с лагом (8−lag)/8 и синергиями. Лучший план ищется полным перебором (694 395 допустимых сценариев); для каждой меры сравнивается план с ней и без неё. AI на gpt-4.1-mini через OpenAI Responses API с вызовами Python-инструментов объясняет результат, а админ-агент меняет данные через проверяемые функции с версионированием и аудитом. Данные в SQLite, аккаунты с PBKDF2.
Ключевые решения
- exhaustive search
- leave-one-out attribution
- OpenAI Responses API tool calling
- dataset versioning
- PBKDF2 auth
Метрики
Исходный Score 52.55768; лучший по полному перебору 57.236735 (694 395 сценариев, стоимость 9.8 млрд ₸)
Особенности
Кроме симулятора есть AI-агент администратора с версиями датасета и журналом действий: у агента нет доступа к SQL и .env. Городские события резервируют часть бюджета. Интерфейс показывает, доказан ли оптимум полным перебором или поиск ограничен по времени.
Стек
Python · FastAPI · SQLite · JavaScript · GeoJSON · Docker · Nginx · NVIDIA Brev
Модели
GPT-4.1-mini
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-b52316ac-djem.
README
README.mdАким на 5 часов
Открыть сайт — akim-o237lkzkv.gobrev.dev
«Аким на 5 часов» — AI-симулятор управления Астаной. Распределяйте бюджет в тенге, принимайте 5 решений и сравнивайте сценарии. Карта, прогнозы и Score показывают эффект, а AI объясняет риски и предлагает улучшения. Результаты сохраняются в кабинете.
Проект создан для хакатона на Python / FastAPI + SQLite. Стартовый бюджет — 10 млрд ₸, одна единица кейса — 100 млн ₸. Датасет, цены и эффекты инициатив синтетические. Числа рассчитывает Python по правилам модели; AI объясняет результат и предлагает улучшения.
Что умеет продукт
- Гостевая главная: карта, показатели районов, бюджет и каталог доступны для просмотра без входа. Данные обновляются из БД каждые 30 секунд, пока вкладка открыта.
- Пять направлений: транспорт, озеленение и экология, социальная инфраструктура, безопасность, городские сервисы. В каталоге 14 инициатив с ценами в тенге, эффектами, задержками и выбором района.
- Пять решений: сервер проверяет бюджет, повторы и несовместимые меры; допускается не более двух инициатив одного направления.
- Карта и прогноз: контуры районов Астаны, сравнение факта и прогноза по районам и направлениям, подробные показатели.
- Объяснение результата: цепочка «инициатива → показатели → район → изменение Score», сильные стороны, риски и компромиссы.
- Три миссии: повышение качества жизни, баланс районов и подготовка к паводку. Итоговая сводка показывает достижение цели, расходы по направлениям, остаток бюджета и ключевой эффект.
- Лучший сценарий + AI: поиск допустимого сочетания мер и автоматический подробный разбор. Интерфейс указывает, доказан ли оптимум полным перебором или поиск ограничен временем.
- Улучшение плана: сравнение одиночных замен с численным приростом Score и применением подходящего варианта.
- Городские события: снегопад, паводок и смог меняют условия и резервируют часть бюджета. Прежний план сохраняется при неудачной загрузке новых условий.
- Личный кабинет: аккаунты, автосохранение рабочего плана, библиотека сценариев, AI-разборов, рекомендаций и результатов поиска.
- Презентация: пять HTML-слайдов с бюджетом, инициативами, прогнозом и рисками; просмотр на сайте, скачивание и печать в PDF.
- Администрирование: редактор данных, AI-агент с инструментами изменения, версии датасета, восстановление версий и журнал действий.
Как попробовать
- Откройте сайт и изучите исходные показатели.
- Войдите в аккаунт сотрудника и на главной выберите миссию или «Найти лучший сценарий».
- Соберите пять допустимых решений и нажмите «Завершить и рассчитать».
- Посмотрите сводку, диаграмму расходов и подробный разбор; раскройте детали, чтобы изучить цепочки влияния.
- Сохраните сценарий или создайте презентацию. Готовые материалы доступны в «Мои результаты» на главной.
Демонстрационный сотрудник: user / 12345678. На новой установке этот аккаунт автоматически не создаётся: сотрудников добавляет администратор.
Аккаунты и сохранение
| Роль | Возможности |
|---|---|
| Гость | Просмотр главной, карты, показателей и каталога |
| Сотрудник | Собственные планы, сценарии, результаты инструментов, AI-разбор и презентации |
| Администратор | Управление пользователями, общими данными, настройками и агентом; доступ ко всем сценариям для сравнения |
При первом запуске создаётся admin; начальный пароль задаётся INITIAL_ADMIN_PASSWORD в .env, по умолчанию — admin. Изменение переменной не сбрасывает пароль уже существующего аккаунта. Пароль меняется в «Главная → Настройки аккаунта», сотрудники создаются в «Данные и агент → Аккаунты сотрудников». Для публичной установки задайте собственный пароль администратора.
План, событие, версия данных, выбранные районы, миссия, итоговая сводка, фильтры, поля форм и полученный AI-разбор сохраняются в персональном workspace. Автосохранение отправляется через 400 мс после изменения; локальная копия помогает при перезагрузке страницы. Конфликт двух вкладок не перезаписывает более свежую серверную версию.
Библиотека «Мои результаты» показывает черновик, сценарии, результаты поиска, AI-разборы, рекомендации и презентации. Открытие карточки не заменяет рабочий план: для этого есть отдельная кнопка. Результаты хранятся с владельцем и снимком прогноза; повторное получение одинакового результата обновляет карточку без дубликатов. Старые презентации, которые ранее только скачивались и не сохранялись на сервере, нужно создать заново.
SQLite хранит хеши паролей PBKDF2-SHA256 с индивидуальной солью. Сессии действуют 7 дней через HttpOnly cookie; в БД сохраняется хеш токена. Выход и смена пароля отзывают сессии. Пароли и API-ключи не записываются в рабочий черновик. Миграции при запуске сохраняют существующие аккаунты и сценарии.
Численная модель
В исходном датасете 5 районов, 5 направлений и 10 показателей на район. На карте дополнительно показан Сарайшык; его показатели пока не предоставлены. Границы взяты из опубликованного слоя геосервиса Астаны, локальная копия — от 23.09.2026. Контуры, легенда и переход к району работают с локальным GeoJSON; подложка OpenStreetMap требует интернета.
Горизонт расчёта — 8 кварталов. Эффект меры умножается на (8 - lag_quarters) / 8, учитываются синергии, показатели ограничиваются диапазоном 0–100. Веса находятся в seed/dataset.json.
Score = 0.7 × средний Score районов, взвешенный по населению
+ 0.3 × Score слабейшего района
− количество показателей ниже 40
Правила используемого датасета: ровно 5 различных мер, не больше 2 в направлении. Выбор идёт из пяти направлений, без требования ровно одной меры каждого вида. M1/M3 конфликтуют глобально; M4/M7 и M5/M13 — в одном районе.
Для исходной версии без городского события:
| Показатель | Значение |
|---|---|
| Исходный Score | 52,55768 |
| Лучший Score полного перебора | 57,236735 |
| Допустимых сценариев проверено | 694 395 |
| Стоимость лучшего плана | 9,8 млрд ₸ |
| План | M2 — весь город; M3, M8, M9 — Нура; M14 — весь город |
Поддержка слабейшего района и устранение критических показателей дают основной прирост. Эти значения относятся к исходному учебному набору; после изменения данных или события результат будет другим. Для честного сравнения команды используют одинаковую версию данных и одинаковое событие.
В блоке «Почему изменился Score» для каждой меры сравнивается полный план с планом без неё в тех же условиях. Показаны задержка, синергии, переход через порог 40 и компоненты Score. Такие эффекты отдельных мер нельзя складывать. Изменение относительно исходного факта и эффект решений относительно сценария с тем же событием показаны отдельно. Например, цель миссии с паводком проверяется относительно паводка без решений.
Это учебная модель для сравнения сценариев, а не статистически подтверждённый прогноз реального города или обоснование реальных расходов.
AI и API
Для внешнего AI заполните OPENAI_API_KEY в серверном .env и перезапустите приложение. OPENAI_MODEL задаёт модель разбора, OPENAI_AGENT_MODEL — модель агента; в текущих настройках по умолчанию обе — gpt-4.1-mini. Без ключа численный расчёт, карта и интерфейс работают, а недоступность AI обозначается явно.
После поиска плана AI получает рассчитанные данные и объясняет причины выбора мер, положительные и отрицательные последствия, риски, нерешённые проблемы, этапы внедрения и возможные улучшения. Готовый ответ сохраняется и после перезагрузки не запрашивается заново. Интеграция использует OpenAI Responses API и вызовы инструментов Python.
AI-редактор доступен администратору. Он может менять показатели, цены, эффекты, бюджет, совместимость мер, сценарии и тексты сайта через проверяемые функции. Правки создают версии и записи аудита; старые сценарии остаются связаны со своими исходными данными. Агенту не предоставляются произвольный SQL, команды сервера или чтение .env.
Документация API доступна по /docs, схема — /openapi.json. Браузер использует сессию вошедшего пользователя и его роль. Для внешних интеграций поддерживается Authorization: Bearer <ADMIN_API_TOKEN или AGENT_API_TOKEN>; оба служебных токена дают административные права на рабочие данные. Обзор и численный прогноз открыты, поиск оптимума, внешний AI, личные результаты и изменения требуют авторизации.
Инструменты внешнего агента: GET /api/agent/tools, POST /api/agent/execute. Встроенный чат: POST /api/agent/chat.
Локальный запуск
Нужен Python 3.11+. Выполните команды из каталога проекта.
Linux / macOS:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python init_env.py
# Настройте .env: ключ AI при необходимости и INITIAL_ADMIN_PASSWORD.
python run.py
Windows PowerShell (активация окружения не требуется):
python -m venv .venv
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe init_env.py
# Настройте .env: ключ AI при необходимости и INITIAL_ADMIN_PASSWORD.
.\.venv\Scripts\python.exe run.py
При стандартных настройках локальный адрес — http://127.0.0.1:8000. База создаётся в data/akim.sqlite3. init_env.py создаёт .env из шаблона с независимыми служебными токенами и не перезаписывает существующий файл. Настройте ключ AI и начальный пароль администратора до первого запуска.
Сервер NVIDIA Brev
Публичный сайт проекта: https://akim-o237lkzkv.gobrev.dev/.
Jupyter использует 8888, сайт — 8080. При прямом запуске через Brev Python слушает 8080; в варианте с Nginx/Docker внешний порт остаётся 8080, а Python слушает 8000 за прокси. В .env укажите домен сайта:
ALLOWED_HOSTS=localhost,127.0.0.1,testserver,akim-o237lkzkv.gobrev.dev
Полная установка: DEPLOY_BREV.md. Обновление и откат: docs/UPDATE_GUIDE.md. Для установленного проекта с прямым запуском:
.venv/bin/python backup_db.py
# Обновите исходники из GitHub или архива, сохранив .env и data/.
bash deploy/restart_brev.sh
curl -fsS http://127.0.0.1:8080/health
Скрипт перезапуска относится к прямому запуску на 8080. Для Docker обновление выполняется через docker compose up -d --build. Не удаляйте Docker-том с БД при обновлении. Push в GitHub сам по себе не обновляет работающий сайт.
Проверки
Из каталога проекта, в активированном Python-окружении:
python -m pip install -r requirements-dev.txt
python -m pytest -q
Проверки интерфейсной логики требуют Node.js 22+; для работы самого сайта Node.js не нужен:
node --check static/app.js
node tests/test_missions.mjs
node tests/test_api_response.mjs
Последняя локальная проверка: 20 тестов Python пройдены, проверки JavaScript пройдены. В браузере проверены миссии, выбор мер и районов, сводка, перезагрузка, сохранённая презентация, восстановление после ошибок и ширина 390 px. Интеграция OpenAI ранее проверена с локальным ключом; её доступность на другом сервере проверяется отдельно. Поправка проверки порта в restart_brev.sh проверена синтаксически; Linux-перезапуск после неё требует проверки на сервере.
Проверка установленного сайта:
python verify_install.py --url http://127.0.0.1:8080
Добавьте --live-ai для одного реального платного AI-разбора с серверным ключом. Проверьте публичную ссылку в приватном окне перед демонстрацией.
Структура и документация
| Путь | Назначение |
|---|---|
app/main.py | FastAPI, маршруты и проверка прав |
app/model.py, app/optimizer.py, app/events.py | Расчёт, поиск сценариев и городские события |
app/db.py, app/accounts.py, app/library.py | SQLite, аккаунты, личное состояние и результаты |
app/agent.py, app/presentation.py | AI-инструменты и презентации |
static/ | Интерфейс, карта, миссии, диаграммы и итоговая сводка |
seed/ | Синтетические исходные данные |
deploy/, compose.yaml | Nginx, Docker и перезапуск на Brev |
backup_db.py | Согласованная резервная копия SQLite |
tests/ | Проверки API, модели и интерфейсной логики |
- Соответствие кейсу и ограничения
- Развёртывание на Brev
- Обновление и откат
- Отчёт объединения версий
- Сценарий демонстрации для жюри
.env, реальные API-ключи, рабочие базы, логи и резервные копии не включаются в исходники и переносимые архивы.
Авторы коммитов
История коммитов
- 2026-09-23 17:57Delete outputs directorybeka68
- 2026-09-23 17:56Update backup_db.pyArturEnixx
- 2026-09-23 17:54Add files via uploadArturEnixx
- 2026-09-23 17:44Update product README, demo URL and deployment instructionsbeka68
- 2026-09-23 17:37Update README.mdbeka68
- 2026-09-23 17:33Allow immediate Brev restarts with connections in TIME_WAITbeka68
- 2026-09-23 17:28Merge mission UX while preserving accounts and saved resultsbeka68
- 2026-09-23 17:21Update README.mdbeka68
Все коммиты (20)
- 2026-09-23 17:11Polish session UX and document safe updateArturEnixx
- 2026-09-23 17:06Move tools to homepage and add visual personal results librarybeka68
- 2026-09-23 16:44Add read-only dashboard, user accounts, persistent workspaces and detailed AI advicebeka68
- 2026-09-23 16:17Add mission briefing and session summaryArturEnixx
- 2026-09-23 16:11Explain initiative impacts through indicators, districts and city scorebeka68
- 2026-09-23 15:58Add published Astana district polygons with outlines, hover details and map controlsbeka68
- 2026-09-23 15:44Add concise showcase pitchArturEnixx
- 2026-09-23 15:18Complete city case with budget stress events, actionable recommendations and five-slide exportbeka68
- 2026-09-23 14:48Ignore stale plan additions and clear outdated optimization statusbeka68
- 2026-09-23 14:47Build Python city simulator with SQLite, KZT forecasts, map, AI tools and Brev deploymentbeka68
- 2026-09-23 14:20Start Python city simulator with versioned dataset and server environmentbeka68
- 2026-09-23 12:47Add test file to verify GitHub uploadbeka68
Структура репозитория (44 файлов)
.dockerignore .env.example .gitignore ACCEPTANCE.md DEPLOY_BREV.md Dockerfile README.md app/__init__.py app/accounts.py app/agent.py app/config.py app/db.py app/events.py app/library.py app/main.py app/model.py app/optimizer.py app/presentation.py backup_db.py codex-upload-test.txt compose.yaml deploy/nginx-docker.conf deploy/nginx.conf deploy/restart_brev.sh docs/MERGE_REPORT.md docs/SHOWCASE_PITCH.md docs/UPDATE_GUIDE.md init_env.py requirements-dev.txt requirements.txt run.py seed/dataset.json static/api-response.js static/app.js static/boundaries.js static/data/astana-districts.geojson static/impact.js static/index.html static/missions.js static/style.css tests/test_api_response.mjs tests/test_app.py tests/test_missions.mjs verify_install.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.