О проекте
Команда: Commit and Pray
Кейс HackAlem.ai: Спецтрек — Astana Innovations
Стадия: Рабочий MVP
Задача кейса: «Аким на 5 часов»: городской симулятор, распределяющий бюджет по 5 направлениям и 5 районам
Суть
Игровой симулятор: игрок выбирает 5 мер из 14 по районам Астаны в пределах бюджета 100 и получает Astana Quality of Life Score, объяснение от «Аким-AI» и 2–3 альтернативных сценария «что если».
Как устроено
Детерминированная модель на FastAPI (10 индикаторов × 5 районов, лаг внедрения, каскадные эффекты, синергии, штраф за критические показатели) с валидатором правил. /api/preview мгновенно пересчитывает неполный набор при наведении на меру, /api/simulate делает финальный расчёт, /api/recommend генерирует альтернативы, каждая из которых пересчитывается через compute_score(). LLM (OpenAI-совместимый API) только пишет текстовое объяснение готового результата, без ключа используется детерминированный fallback-текст.
Ключевые решения
- детерминированный scoring-движок
- валидация правил набора мер
- what-if генерация альтернатив
- hover-preview пересчёт
- LLM-нарратив поверх расчёта
Метрики
Тесты сверяются с ТЗ: базовый Score 52.56; пример M7+M8+M10+M12+M5, бюджет 95, Score ≈ 56.5
Особенности
Предпросмотр эффекта меры при наведении (дельты и пунктирный контур на радаре) и блокировка недопустимых мер в UI с указанием причины. Альтернативные сценарии гарантированно отличаются по составу и честно пересчитаны. Почасовые снапшоты сохранены в отдельных ветках.
Стек
Python 3.12 · FastAPI · Pydantic · Uvicorn · pytest · React 19 · TypeScript · Vite · Tailwind CSS v4 · Recharts · Framer Motion · Docker Compose · nginx
Модели
OpenAI-совместимый LLM
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-ed2dd7b0-commit-and-pray.
README
README.md«Аким на 5 часов» — AI-симулятор управления городом
Спец-трек Astana Innovations, HackAlem AI 2026. Команда: Commit and Pray.
Основной код и финальная версия — в ветке main. Промежуточные почасовые
снапшоты доступны в ветках codex/frontend-and-features (~14:55) и
codex/design-mobile (~16:43) — параллельная работа над UI/AI-фичами,
позже слитая в main.
1. Описание
Городской бюджет (100 условных единиц) нужно разложить по 5 направлениям — транспорт, экология, соцсфера, безопасность, сервисы — с учётом того, что ресурсы ограничены и эффект от мер проявляется не сразу. Игрок выбирает ровно 5 мероприятий из каталога (14 шт.), распределяя их по 5 условным районам Астаны, и получает итоговый Astana Quality of Life Score с объяснением от «Аким-AI»: что получилось хорошо, какие риски и компромиссы остались.
Данные и формула — из официального ТЗ и датасета районов, предоставленных организаторами (владелец задачи: Astana Innovations).
Методология
Ядро — детерминированная численная модель городских показателей (10 индикаторов × 5 районов), построенная по логике городских цифровых двойников (в духе UrbanSim, в упрощённом виде): каждое управленческое решение имеет заданный лаг внедрения, каскадно затрагивает несколько показателей одновременно (например, перевод района на чистое топливо снижает не только загрязнение воздуха, но и нагрузку на теплосети) и может усиливаться синергией с другими мерами или штрафоваться за критически низкие показатели в отстающих районах. LLM в этой модели — слой интерпретации и рекомендаций поверх честного расчёта, а не источник чисел: это осознанный баланс между «игровым» интерактивным опытом и воспроизводимой аналитикой.
2. Архитектура
Подробная схема, формула Score и роль LLM — в docs/architecture.md.
Frontend (React + Vite + Tailwind) ⇄ Backend (FastAPI) ⇄ LLM (опционально)
/api/districts, /api/measures, /api/preview, /api/simulate, /api/recommend
-
/api/preview— мгновенный пересчёт тем же движком для неполного набора мер (без LLM): при наведении на меру карточка её района показывает «до/после» — дельты показателей, изменение балла района, пунктирный контур на радаре. -
/api/simulate— финальный расчёт набора из 5 мер с полной валидацией правил и объяснением «Аким-AI». -
/api/recommend— альтернативные сценарии (что-если анализ). -
backend/app/simulation/data.py — официальный датасет районов и каталог мероприятий.
-
backend/app/simulation/validator.py — проверка правил набора решений.
-
backend/app/simulation/scoring.py — детерминированный расчёт Score (каскад эффектов по показателям/районам).
-
backend/app/simulation/recommendations.py — генерация альтернативных сценариев (что-если анализ), каждый честно пересчитан через
compute_score(). -
backend/app/simulation/narrative.py — LLM-объяснение готового результата.
3. Технологии
| Слой | Технологии |
|---|---|
| Backend | Python 3.12+, FastAPI, Pydantic, Uvicorn, pytest |
| Frontend | React 19, TypeScript, Vite, TailwindCSS v4, Recharts, Framer Motion |
| AI | OpenAI API — LLM-объяснение уже посчитанного результата (не сам расчёт) |
| Хранилище | Не используется — расчёт полностью детерминирован (см. раздел «Методология») и не требует базы данных или персистентного состояния между запросами |
| Деплой | Docker Compose (backend + nginx-frontend), либо локальный запуск |
4. Установка и запуск
Вариант A — Docker Compose (рекомендуется для проверки)
cp .env.example .env
docker compose up --build
- Frontend: http://localhost:8080
- Backend API: http://localhost:8000/api
Вариант B — локально, без Docker
Backend:
cd backend
python -m venv .venv
.venv/Scripts/activate # Windows; на Linux/Mac: source .venv/bin/activate
pip install -r requirements.txt
cp ../.env.example ../.env
uvicorn app.main:app --reload --port 8000
Frontend (в отдельном терминале):
cd frontend
npm install
npm run dev
Frontend откроется на http://localhost:5173 и проксирует /api на
http://localhost:8000 (настроено в vite.config.ts).
5. Переменные окружения
См. .env.example. Ключевые:
| Переменная | Назначение | Обязательна? |
|---|---|---|
LLM_API_KEY | Ключ LLM для генерации объяснений | Нет — без ключа работает детерминированный fallback-текст, демо не ломается |
LLM_BASE_URL | Эндпоинт LLM (любой OpenAI-совместимый провайдер) | Нет, есть значение по умолчанию |
LLM_MODEL | Название модели | Нет |
CORS_ORIGINS | Разрешённые origin для backend | Нет, по умолчанию http://localhost:5173 |
6. Автономность запуска и тестовые доступы
Проект не требует никаких персональных аккаунтов участников или платных ключей для полной проверки экспертами:
- Расчёт Score, превью эффекта мер, валидация набора решений и генерация
альтернативных сценариев (
/api/preview,/api/simulate,/api/recommend) — полностью детерминированный код, работает без единого внешнего API и без ключей. - Единственная опциональная интеграция —
LLM_API_KEYдля текстового объяснения от «Аким-AI». Без ключа (пустое значение в.env, как в.env.exampleпо умолчанию) приложение автоматически переключается на детерминированный fallback-текст, собранный из тех же чисел — демо и проверка работают end-to-end без единого ключа. - Если эксперты захотят увидеть именно LLM-версию объяснений — достаточно
любого личного ключа OpenAI (или другого OpenAI-совместимого провайдера)
в
.env, специальных прав/доступов от команды не требуется. - База данных не используется, персистентных внешних сервисов нет —
единственная зависимость на этапе запуска:
pip install/npm install.
7. Проверка (Verification Steps)
- Убедиться, что формула Score реализована корректно:
Все тесты сверяются с контрольными числами из официального ТЗ, включая базовый Score = 52.56 и пример из документа (набор M7+M8+M10+M12+M5 в Нуре/Сарыарке, бюджет 95, Score ≈ 56.5).cd backend pytest -q - Запустить backend и frontend (см. раздел 4).
- В интерфейсе выбрать меру (например, M1 → район Алматы) и навести на неё курсор: карточка Алматы покажет эффект меры (T1/T2 и балл района с дельтами). Недоступные меры (превышение бюджета, лимит 2 на направление, несовместимость M1/M3, 5 мер уже выбрано) блокируются с указанием причины — превысить бюджет из интерфейса нельзя.
- Выбрать ровно 5 мероприятий (для мер типа «Район» — указать район), нажать «Утвердить бюджет города».
- Убедиться, что:
- при превышении бюджета/нарушении правил (повтор меры, несовместимость M1+M3, >2 мер на направление и т.д.) выводится понятная ошибка вместо Score;
- при валидном наборе Score и показатели районов обновляются, а «Аким-AI» даёт текстовое объяснение результата;
- в блоке «Сценарии от Аким-AI» появляются 2-3 альтернативных набора мер с разным составом и разным, честно пересчитанным Score (не дубликаты друг друга и не дубликат текущего результата) — это и есть что-если анализ поверх основного сценария.
8. Open Source & AI Declarations
- AI-модель: LLM (OpenAI-совместимый API) используется исключительно
для генерации текстового объяснения уже посчитанного результата —
числа Score считаются детерминированным кодом (
scoring.py), LLM их не вычисляет и не придумывает. - Данные: синтетический датасет районов и каталог мероприятий, предоставлены организаторами трека (Astana Innovations), не содержат персональных данных.
- Открытый код: FastAPI, Pydantic, Uvicorn, React, Vite, TailwindCSS, Recharts, Framer Motion, OpenAI Python SDK — все используемые библиотеки распространяются под открытыми лицензиями (MIT/Apache-2.0/BSD).
Авторы коммитов
История коммитов
- 2026-09-23 17:55docs: note hourly-snapshot branches in READMEKItsunexdd
- 2026-09-23 17:48Smoother hover animations, final README polishKItsunexdd
- 2026-09-23 17:46Smoother district card hover and collapse animationsKItsunexdd
- 2026-09-23 17:37Fix hover preview after district selection, animate district score from before to afterKItsunexdd
- 2026-09-23 17:22Final: per-district hover preview via /api/preview, UI budget/rule enforcement, radar legend, README compliance, code cleanupKItsunexdd
- 2026-09-23 16:43Real AI recommendations via /api/recommend, animations, mobile tabs, design polishKItsunexdd
- 2026-09-23 16:00Hour 4: radar charts, delta indicators, direction icons, recommendation cards, responsive header/mobile fixesKItsunexdd
- 2026-09-23 14:55feat: integrate UI features and improvementsKItsunexdd
Все коммиты (12)
- 2026-09-23 13:54docs: add architecture documentation and editor launch configsKItsunexdd
- 2026-09-23 13:54feat(frontend): add interactive dashboard UI with QoL gauge and district cardsKItsunexdd
- 2026-09-23 13:53feat(backend): implement FastAPI scoring engine and REST API endpointsKItsunexdd
- 2026-09-23 13:52chore: initial repository configuration and project metadataKItsunexdd
Структура репозитория (46 файлов)
.agent.md .claude/launch.json .env.example .gitignore README.md backend/Dockerfile backend/app/__init__.py backend/app/api/__init__.py backend/app/api/routes.py backend/app/config.py backend/app/main.py backend/app/models/__init__.py backend/app/models/schemas.py backend/app/simulation/__init__.py backend/app/simulation/data.py backend/app/simulation/narrative.py backend/app/simulation/recommendations.py backend/app/simulation/scoring.py backend/app/simulation/validator.py backend/requirements.txt backend/tests/test_scoring.py docker-compose.yml docs/architecture.md frontend/.gitignore frontend/.oxlintrc.json frontend/Dockerfile frontend/README.md frontend/index.html frontend/nginx.conf frontend/package-lock.json frontend/package.json frontend/public/favicon.svg frontend/public/icons.svg frontend/src/App.tsx frontend/src/api/client.ts frontend/src/components/DistrictCard.tsx frontend/src/components/MeasureSelector.tsx frontend/src/components/QoLGauge.tsx frontend/src/components/VerdictPanel.tsx frontend/src/index.css frontend/src/main.tsx frontend/src/types.ts frontend/tsconfig.app.json frontend/tsconfig.json frontend/tsconfig.node.json frontend/vite.config.ts
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.