О проекте
Команда: BOM КазАЙ
Кейс HackAlem.ai: Спецтрек — Astana Innovations
Стадия: Доведённый продукт
Задача кейса: «Аким на 5 часов»: городской симулятор, распределяющий бюджет по 5 направлениям и 5 районам
Суть
AI-симулятор управления Астаной с интерактивной SVG-картой 5 районов и 14 мер. Считает Astana Quality of Life Score на горизонте 8 кварталов, по запросу выдаёт AI-рекомендации на трёх языках (ru/kk/en).
Как устроено
Данные лежат в versioned JSON (tech2-v1: районы, меры, правила). Python-ядро на FastAPI проверяет бюджет, конфликты и лимит «не более двух мер на направление» и считает результат по формуле: эффект × (8 − задержка)/8, баллы районов с весами индикаторов, взвешивание по населению, Score = 0,7·среднее + 0,3·минимум − N критических показателей. Браузерная JS-модель показывает предпросмотр, её совпадение с API проверяет parity-тест. По кнопке OpenAI Responses API пишет объяснение по фактам отчёта; ответ кешируется, при ошибке включается fallback.
Ключевые решения
- deterministic scoring formula
- synergies/conflicts rules
- delayed effects
- browser/API parity test
- OpenAI Responses structured output
- fallback explanations
- i18n ru/kk/en
Особенности
Расчёт продублирован в браузере и на сервере, их совпадение проверяет отдельный parity-тест. Формула скоринга опубликована и отдельно учитывает самый слабый район. Автотестов 70 (41 JS и 29 Python); AI вызывается только по кнопке и кешируется по сценарию, языку и району.
Стек
Python 3.12 · FastAPI · Uvicorn · Pydantic v2 · Node.js 22 · vanilla JS/SVG · Docker Compose
Модели
gpt-6-luna (OpenAI Responses API)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-518b6a53-bom.
README
README.mdАким на 5 часов
AI-симулятор управления Астаной: распределите бюджет 100 условных единиц между пятью инициативами и получите Astana Quality of Life Score с объяснением последствий.
Проект предназначен для городских управленцев, аналитиков и участников симуляции. Он позволяет сравнить, как решения в транспорте, экологии, социальной инфраструктуре, безопасности и городских сервисах влияют на качество жизни. Все начинают с одинаковых синтетических данных.
Возможности
- Интерактивная карта пяти районов и 14 мероприятий с заданными стоимостью и эффектами.
- Контроль бюджета, количества решений и совместимости мер.
- Предварительный просмотр изменений и итоговый отчёт по городу и районам на горизонте восьми кварталов.
- Краткие AI-рекомендации по запросу для города или выбранного района.
- Интерфейс и объяснения на русском, казахском и английском.
Запуск
Нужны Git и Docker с Compose. Команды для Bash:
git clone https://github.com/BAITC-Hacks/hack-518b6a53-bom.git
cd hack-518b6a53-bom
test -f .env.local || cp .env.example .env.local
docker compose --env-file .env.local up -d --build
Откройте http://localhost:4173. Публичной демоверсии пока нет.
Для AI-разбора заполните в .env.local оба поля: OPENAI_API_KEY и OPENAI_MODEL — ключ и доступный API ID модели с поддержкой структурированных ответов Responses API. Модель по умолчанию не задана; текущая интеграция проверена с gpt-6-luna. После изменения настроек повторите команду запуска. Обычный расчётный отчёт доступен сразу, AI вызывается только кнопкой «Получить рекомендации ИИ». Без конфигурации AI или при ошибке OpenAI приложение сохраняет обычный отчёт и показывает сообщение о недоступности рекомендаций. Ключ не добавляйте в Git.
Остановка:
docker compose --env-file .env.local down
Если приложение не отвечает, проверьте логи:
docker compose --env-file .env.local logs --tail=100 ui api
Остальные параметры окружения описаны в .env.example.
Пример использования
Выберите карточку мероприятия и нажмите на нужный район либо перетащите её на карту. Городская мера применяется ко всему городу. Соберите такой план:
| ID | Мероприятие | Где | Стоимость |
|---|---|---|---|
| M7 | Школа + детсад | Нура | 24 |
| M8 | Центр семейного здоровья | Нура | 20 |
| M10 | Освещение и камеры Safe City | Нура | 12 |
| M12 | Платформа обращений жителей | Весь город | 14 |
| M5 | Чистое топливо для частного сектора | Сарыарка | 25 |
Нажмите «Рассчитать». Стоимость — 95 из 100, Score меняется с 52,56 до 56,54. В отчёте доступны показатели и выводы по городу и районам. Нажмите «К карте», чтобы изменить план, или «Новый сценарий», чтобы начать заново.
По умолчанию показывается обычный отчёт с числовыми результатами и шаблонными выводами. Для AI выберите вкладку города или любого района и нажмите «Получить рекомендации ИИ»: появится короткий абзац на текущем языке интерфейса. Открытие отчёта, смена района и языка не запускают AI автоматически. Полученный ответ кешируется для текущего сценария, языка и района; к обычному отчёту можно вернуться отдельной кнопкой. Изменение плана сбрасывает эти ответы.
Для проверки поведения:
- Замените M10 на M11 в Нуре: стоимость станет 93, Score — 56,33.
- Вместо M10 попробуйте добавить M3: стоимость превысила бы бюджет до 113, поэтому добавление будет отклонено.
- Удалите одну меру: расчёт недоступен, пока в плане не будет пяти допустимых решений.
Правила и расчёт
Нужно выбрать ровно пять разных мероприятий, не более двух одного направления, на сумму до 100. Выбор по одному мероприятию из каждого направления не требуется. M1 и M3 несовместимы; M4 и M7, а также M5 и M13 нельзя сочетать в одном районе.
У каждого района десять индикаторов от 0 до 100 — больше означает лучше. Эффекты мер учитывают задержку реализации и совместное действие некоторых инициатив. После их применения значения индикаторов ограничиваются диапазоном 0–100.
Эффект меры = эффект из каталога × (8 − задержка в кварталах) / 8
Балл района = сумма значений индикаторов с их весами
Средний балл = сумма баллов районов с весами по доле населения
Score = 0,7 × средний балл + 0,3 × минимальный балл района − N
N — количество пар «район — индикатор» со значением ниже 40. Формула учитывает средний уровень города, слабейший район и критические показатели. Веса, конфликты и синергии заданы в rules.json.
Технологии и архитектура
flowchart LR
Browser["Браузер: HTML, CSS, JavaScript, SVG"] <-->|":4173"| UI["Node.js: статика и прокси"]
UI <-->|":8000"| API["Python / FastAPI: проверка и расчёт"]
Data["JSON-датасет"] --> API
API <-->|"Факты / объяснение"| AI["OpenAI Responses API"]
Интерфейс работает без UI-фреймворка и npm-зависимостей. Браузерная модель показывает предварительные изменения; итоговый результат проверяет и рассчитывает Python. OpenAI получает факты отчёта и формирует объяснение. Числа в отчёте определяет расчётная модель.
В Docker используются Node.js 22 и Python 3.12. Backend — FastAPI, Uvicorn, Pydantic v2 и OpenAI SDK; версии закреплены в requirements/api.lock. Compose публикует только интерфейс на 127.0.0.1:4173, API доступен внутри сети контейнеров. Ключ OpenAI хранится на стороне API.
API предоставляет каталог, проверку сценария, расчёт и объяснение. Маршруты и форматы запросов описаны в контракте backend. Ответ объяснения содержит mode: "llm" или mode: "fallback".
Структура проекта:
frontend/ HTML, CSS, JavaScript, SVG, package.json, Node-сервер и JS-тесты
backend/ FastAPI, расчётное ядро, валидация и AI-адаптер
shared/ Схемы HTTP-запросов и ответов
data/tech2-v1/ Версионированные исходные данные и правила
docker/ Dockerfile интерфейса и API
docs/ Контракты и документация
tests/ Python-тесты и сверка браузерного расчёта с API
requirements/ Зафиксированные зависимости Python
compose.yaml Запуск интерфейса и API
Данные и ограничения
Датасет data/tech2-v1 содержит пять районов — Есиль, Алматы, Сарыарка, Байконур и Нура, — их показатели, доли населения, мероприятия и правила. Данные синтетические; персональные данные не нужны.
- Результат показывает поведение условной модели и не является проверенным прогнозом развития города.
- Живых городских данных и подключений к городским системам нет. Единственная внешняя интеграция — OpenAI для объяснений.
- Карта схематична и основана на расположении районов 2023 года; текущие юридические границы не воспроизводятся.
- Нет авторизации и сохранения сценариев: перезагрузка страницы сбрасывает план. Сохраняется только язык интерфейса.
- Сравнение команд, случайные события и генерация презентаций не реализованы.
Разработка и тесты
Запуск с подключёнными исходниками и автоматической перезагрузкой серверов:
docker compose --env-file .env.local -f compose.yaml -f compose.dev.yaml up -d --build
Интерфейс остаётся на порту 4173, API — на порту 8000. Документация Swagger UI доступна на http://localhost:8000/docs. Для остановки используйте те же Compose-файлы с командой down.
Все тесты можно запустить в Docker без Node.js и Python на хосте. Команды из корня проекта используют актуальные исходники; ответы OpenAI подменяются, платных API-вызовов нет:
docker compose --env-file .env.local build ui api
docker compose --env-file .env.local run --rm --no-deps -v .:/workspace:ro -w /workspace/frontend ui npm test
docker compose --env-file .env.local -f compose.yaml -f compose.dev.yaml run --rm --no-deps -v ./tests:/app/tests:ro api python -m unittest discover -s tests -p test_backend.py -v
Проходят 41 JavaScript-тест и 29 Python-тестов: расчёты и ограничения, переводы, API-контракты, полнота рассчитанных вкладов и дельт в AI-контексте, область AI-объяснения, fallback и отмена запроса при отключении клиента.
Для сверки браузерной модели с работающим API сначала выполните обычную команду запуска из раздела «Запуск», затем:
docker compose --env-file .env.local run --rm --no-deps -v .:/workspace:ro -w /workspace ui node tests/parity.mjs http://ui:4173
При установленном Node.js ≥ 22 те же JavaScript-проверки доступны локально через npm --prefix frontend test, а сверка с запущенным приложением — через node tests/parity.mjs или npm --prefix frontend run test:parity. Установка npm-пакетов не требуется.
Материалы
ТЗ и критерии оценки — Данные и правила кейса — Требования к README.
Исходные материалы: ТЗ в Google Docs и датасет в Google Docs.
Геометрия в frontend/map-geometry.js адаптирована по Astana districts coloured 2023.png, автор Bogomolov.PL, лицензия CC BY-SA 4.0. Уведомление относится только к геометрии карты.
Авторы коммитов
История коммитов
- 2026-09-23 17:56Remove obsolete architecture draft and dbarin test fileIlya Molokovich
- 2026-09-23 17:53Complete AI calculation context and correct architecture documentationIlya Molokovich
- 2026-09-23 17:42Merge main documentation and organize frontend with verified Docker startupIlya Molokovich
- 2026-09-23 17:37Merge latest dbarin frontend and add on-demand scoped AI recommendationsIlya Molokovich
- 2026-09-23 17:35readme mostly completed'David Dolya
- 2026-09-23 17:24Добавил адаптивный интерфейс, объяснения результатов и карточки объектовДмитрий
- 2026-09-23 17:18Verify MVP integration and improve responsive map and report behaviorIlya Molokovich
- 2026-09-23 17:03Connect MVP widget to FastAPI and localized OpenAI reportsIlya Molokovich
Все коммиты (34)
- 2026-09-23 16:55Merge david backend with latest dbarin frontend for MVPIlya Molokovich
- 2026-09-23 16:54Обновил дизайн и расположение переключателя языковДмитрий
- 2026-09-23 16:33Добавить интерактивный симулятор развития АстаныДмитрий
- 2026-09-23 16:19added technical file 1 in a proper .md formatDavid Dolya
- 2026-09-23 16:12README clean upDavid Dolya
- 2026-09-23 16:11Fix backend validation, HTTP errors and loggingDavid Dolya
- 2026-09-23 15:44backend stage 8: doneDavid Dolya
- 2026-09-23 15:38Handle malformed OpenAI explanation responsesDavid Dolya
- 2026-09-23 15:35backend stage 7: ver 1David Dolya
- 2026-09-23 15:31backend stage 6: ver 1David Dolya
- 2026-09-23 15:28Fix nested selection serialization in API responsesDavid Dolya
- 2026-09-23 15:25backend stage 5: ver 1David Dolya
- 2026-09-23 15:21backend stage 4: ver 1David Dolya
- 2026-09-23 15:18Fix budget totals for unknown district IDsDavid Dolya
- 2026-09-23 15:17Reshape simulator as a viewport-sized map widgetIlya Molokovich
- 2026-09-23 15:13backend stage 3: version 1David Dolya
- 2026-09-23 15:09backend stage 2: doneDavid Dolya
- 2026-09-23 15:05Add Astana city planning frontend demoIlya Molokovich
- 2026-09-23 15:01Fix city selection serializationDavid Dolya
- 2026-09-23 15:00backend stage 1: version 1 of project structure, primaraly backend partDavid Dolya
- 2026-09-23 14:53Добавил иллюстрации страниц и PNG-логотип в казахском стилеДмитрий
- 2026-09-23 14:50a sequence of prompts for backend agents is doneDavid Dolya
- 2026-09-23 14:30second version of architecture addedDavid Dolya
- 2026-09-23 14:17first neuroslop for project architectureDavid Dolya
- 2026-09-23 14:17added technical requirements to data.mdDavid Dolya
- 2026-09-22 12:16Тест dbarinДмитрий
Структура репозитория (76 файлов)
.dockerignore .env.example .gitignore ARCHITECTURE_PYTHON_DOCKER.md README.md assets/images/astana-kazakh-hero.png assets/images/initiatives-kazakh.png assets/images/logo-akim.png assets/images/method-kazakh.png assets/images/plan-kazakh.png assets/images/results-kazakh.png backend/__init__.py backend/adapters/__init__.py backend/adapters/dataset.py backend/adapters/fallback.py backend/adapters/llm.py backend/domain/__init__.py backend/domain/models.py backend/domain/report.py backend/domain/simulation.py backend/domain/validation.py backend/main.py backend/prompts/.gitkeep backend/prompts/explanation.txt backend/routes.py backend/services/__init__.py backend/services/explanation_context.py backend/services/explanations.py backend/services/scenarios.py backend/settings.py compose.dev.yaml compose.yaml data.md data/tech2-v1/districts.json data/tech2-v1/measures.json data/tech2-v1/presets.json data/tech2-v1/rules.json data_2_1.md docker/api.Dockerfile docker/ui.Dockerfile docs/BACKEND_AGENT_PROMPTS.md docs/BACKEND_CONTRACT.md docs/IMPLEMENTATION_LOG.md docs/INTEGRATION_CHECKS.md docs/README_PROMPT_EXAMPLE.md frontend/api.js frontend/api.test.js frontend/app.js frontend/i18n.js frontend/i18n.test.js frontend/index.html frontend/locales.js frontend/map-geometry.js frontend/map-object-art.js frontend/map-objects.js frontend/map-objects.test.js frontend/model.js frontend/model.test.js frontend/package.json frontend/server.js frontend/server.test.js frontend/styles.css frontend/svg/all.svg frontend/svg/city.svg frontend/svg/district.svg frontend/svg/ecology.svg frontend/svg/security.svg frontend/svg/services.svg frontend/svg/social.svg frontend/svg/transport.svg requirements/api.in requirements/api.lock shared/__init__.py shared/schemas.py tests/parity.mjs tests/test_backend.py
Ветки (5)
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.