О проекте
Команда: StikerAI
Кейс HackAlem.ai: Спецтрек — Astana Innovations
Стадия: Доведённый продукт
Задача кейса: «Аким на 5 часов»: городской симулятор, распределяющий бюджет по 5 направлениям и 5 районам
Суть
Городской симулятор «Аким на 5 часов»: план из 5 инициатив (из 14) в бюджете 100, детерминированный расчёт показателей 5 районов и Astana QoL Score. Дополнительно есть карта Астаны по OSM, демо-пространство для жителей и AI-объяснение результата.
Как устроено
Данные astana-v1.json. FastAPI проверяет план: ровно 5 разных мер, не больше двух на направление, соблюдение бюджета. Расчёт на Python: эффект × (8 − лаг)/8, оценка района — взвешенная сумма показателей, Score = 0,7·D_avg + 0,3·min(районы) − N_crit. Результаты сохраняются в PostgreSQL (SQLAlchemy/Alembic) с проверкой ревизии. OpenAI Responses API по желанию объясняет уже рассчитанный результат и не меняет числа. Фронтенд на React 19 с картой MapLibre/Leaflet: OSM-границы районов и школы из Overpass.
Ключевые решения
- deterministic scoring model
- lags/synergies/conflicts
- OSM Overpass
- MapLibre GL
- Alembic migrations
- Playwright E2E
Метрики
Контрольный план стоимостью 95: базовый Score 52,55768 → 56,54307, критические показатели 2 → 0
Особенности
Реальные геоданные OSM (границы районов, 171 школа) используются как контекст и сознательно не связываются с синтетической моделью по совпадению названий. Есть citizen workspace с петициями и голосами. Источники данных и их ограничения подробно задокументированы. Сборка фронтенда блокируется, если текущий checkout отстаёт от удалённых веток.
Стек
React 19 · TypeScript · Vite 7 · MapLibre GL · Leaflet · Python 3.12 · FastAPI · Pydantic · PostgreSQL 16 · SQLAlchemy 2 · Alembic · Docker Compose · GitHub Actions · pytest · Playwright
Модели
OpenAI
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-3f85346f-stikerai.
README
README.mdStikerAI — «Аким на 5 часов»
StikerAI — учебный симулятор городских решений и демонстрация взаимодействия администрации с жителями. Пользователь собирает план из пяти инициатив в рамках общего виртуального бюджета; backend проверяет план, детерминированно считает показатели районов и итоговый Astana Quality of Life Score. AI может объяснить уже рассчитанный результат, но не принимает решение и не меняет числа.
Это прототип, а не цифровой двойник и не система прогноза реальных городских эффектов. Входные показатели, бюджетные эффекты и общественные сигналы симулятора синтетические. Реальные геоданные карты показаны отдельно и не участвуют в оценке.
Что реализовано
- Akim workspace: портфель инициатив, общий бюджет 100 виртуальных единиц, выбор районов, проверка ограничений, предварительный расчёт и сохранённый результат.
- Детерминированная модель: пять синтетических районов, десять показателей, 14 инициатив, лаги, синергии и конфликты. При отправке требуется ровно пять разных инициатив; допускается не более двух инициатив одного направления.
- Citizen workspace: демонстрационные петиции, голоса, сообщения и проекты. Это вымышленные данные, хранящиеся локально в браузере; они не меняют государственный бюджет или Score.
- Карта: шесть community-mapped границ районов и отдельный слой объектов OpenStreetMap с тегом
amenity=school. Улицы загружаются отдельным слоем карты. География является контекстом, а не официальным кадастром и не связана с синтетическими показателями по неподтверждённому совпадению названий. - AI-объяснение: необязательный вызов OpenAI Responses API получает сохранённые результаты и отдельный явно вымышленный civic-снимок. AI не пересчитывает Score и не должен представлять вымышленные сигналы как мнение жителей.
- Сохранение сценариев: PostgreSQL, анонимная браузерная сессия, проверка ревизии при записи, отправка и копирование сценариев.
Симулятор встроен в Akim workspace: откройте пункт Simulator или адрес /simulator. Общая оболочка объединяет выбор пяти мер, бюджет, карту, предварительный расчёт, сравнение показателей и AI-анализ. Сессия и каталог общие с обзором города.
Технологии и архитектура
| Слой | Технологии | Ответственность |
|---|---|---|
| Frontend | React 19, TypeScript, Vite 7, CSS, Lucide React | Рабочие пространства, локальная civic-демонстрация и отображение результатов |
| Карта | MapLibre GL, Leaflet, GeoJSON | OSM-границы районов, контекстные school POI и необязательная подложка улиц |
| API | Python 3.12, FastAPI, Pydantic, Uvicorn | Каталог, сессии, проверка и сохранение решений, расчёт, карта и объяснения |
| Хранение | PostgreSQL 16, SQLAlchemy 2, psycopg 3, Alembic | Версии набора, сценарии, расчёты, AI-объяснения и миграции |
| Запуск / CI | Docker Compose v2, GitHub Actions, pytest, Playwright | Повторяемый локальный запуск, проверки backend/frontend и сборка |
| AI | OpenAI Responses API; необязательный MiroFish gateway | Качественное объяснение рассчитанного backend результата |
Поток расчёта:
React UI → FastAPI → проверка бюджета/правил → Python scoring → сохранённый результат
└→ AI explanation (optional)
Основные файлы: frontend/src/App.tsx и frontend/src/SimulatorWorkspace.tsx — интерфейс; backend/app/api/simulator.py — сценарии и API; backend/app/services/scenarios.py — правила плана; backend/app/services/scoring.py и backend/app/services/results.py — численный расчёт; backend/app/services/llm.py — AI; backend/app/models.py и backend/migrations/ — хранение и схема БД.
Формула модели astana-qol-v1 описана в datadoc.md:
применённый эффект = полный эффект × (8 − лаг кварталов) / 8
оценка района = Σ(вес показателя × значение показателя)
D_avg = Σ(доля населения района × оценка района)
Score = 0.7 × D_avg + 0.3 × min(оценки районов) − N_crit
N_crit — количество значений «район × показатель» ниже 40. Показатели ограничиваются диапазоном 0–100; итоговый Score формулой снизу не ограничивается и теоретически может быть отрицательным. AI получает рассчитанные числа, компромиссы и решения; вычисления остаются в Python.
Установка и запуск
Нужны Git, Docker Engine/Desktop и Docker Compose v2.
git clone https://github.com/BAITC-Hacks/hack-3f85346f-stikerai.git
cd hack-3f85346f-stikerai
cp .env.example .env
docker compose up --build -d --wait
На Windows PowerShell вместо cp используйте Copy-Item .env.example .env. Compose запускает PostgreSQL, миграции и seed синтетического датасета, затем API и Vite frontend.
- Приложение: http://localhost:5173
- Симулятор в Akim workspace: http://localhost:5173/simulator
- FastAPI / Swagger: http://localhost:8000/docs
- Health: http://localhost:8000/api/health
Для детерминированного расчёта ключи не нужны. Для AI-объяснения задайте OPENAI_API_KEY и OPENAI_MODEL в .env, затем пересоздайте backend:
docker compose up -d --force-recreate backend
OPENAI_BASE_URL и OPENAI_TIMEOUT_SECONDS настраивают API endpoint и timeout. VITE_MAP_STYLE_URL задаёт публичный стиль слоя улиц, VITE_MAP_TILE_URL — тайлы школьного контекста. Эти map-переменные видны браузеру; не размещайте в них секреты. MIROFISH_ENABLED по умолчанию false; для адаптера требуется отдельный защищённый gateway. Все параметры и локальные значения находятся в .env.example.
Логи и остановка:
docker compose logs backend frontend db migrate seed
docker compose down
PostgreSQL хранится в volume postgres_data; docker compose down сохраняет его. Для чистой локальной демонстрационной БД можно выполнить docker compose down -v — эта команда удаляет volume с данными.
Пример проверки
Проверьте доступность API:
curl -fsS http://localhost:8000/api/health
Ожидаемый ответ:
{"status":"ok","service":"stikerai-backend"}
В интерфейсе нажмите Enter Command Center и соберите контрольный план из набора astana-synthetic-v1:
| Инициатива | Цель | Стоимость |
|---|---|---|
| M7 — школа и детсад | Нура | 24 |
| M8 — семейный медцентр | Нура | 20 |
| M10 — освещение и камеры | Нура | 12 |
| M12 — платформа обращений | Весь город | 14 |
| M5 — чистое топливо | Сарыарка | 25 |
Backend должен принять план стоимостью 95 из 100 и показать контрольный расчёт: базовый Score 52.55768, итоговый 56.54307, критические показатели — с 2 до 0. Это тестовый результат синтетической формулы, не оценка реального воздействия.
Backend-проверки на запущенном Compose:
docker compose exec backend python -m pytest -q
Для browser E2E на хосте нужны Python 3.12, Node.js 22.12+ и Chromium. Команда запускает изолированный тестовый API и frontend; AI-запросы не требуются.
cd backend
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements-dev.txt
cd ../frontend
npm ci
npx playwright install chromium
PATH="../backend/.venv/bin:$PATH" npm run test:e2e
Сборка frontend:
cd frontend
npm ci
npm run build
npm run build сначала запускает prebuild: скрипт получает историю веток с Git remotes и блокирует сборку, если текущий checkout отстаёт от какой-либо удалённой ветки. Для этого шага требуется Git remote и сеть. CI дополнительно проверяет генерацию типов, backend-тесты на SQLite/PostgreSQL, frontend build и Docker Compose.
Данные и внешние сервисы
| Источник | Где используется | Статус и границы |
|---|---|---|
backend/data/astana-v1.json, datadoc.md | Бюджет, районы, индикаторы, меры, эффекты и Score | Синтетический учебный набор; не официальная статистика и не прогноз |
| OpenStreetMap relations | Геометрия шести районов на карте | Снимок от 2026-09-23; community mapping, не кадастровая или официально подтверждённая граница. Лицензия ODbL и attribution показаны в UI |
| OpenStreetMap через Overpass | 171 точка в снимке объектов, помеченных amenity=school | На 2026-09-22; могут быть неполные, устаревшие или неверно размеченные записи, включая колледжи/дошкольные объекты. Только поиск кандидатов; не официальный реестр |
| OpenFreeMap и OSM tile service | Необязательные веб-подложки улиц | Загружаются браузером; требуют сети и зависят от условий/доступности поставщика. Границы и интерактивные списки остаются полезны без подложки |
| OpenAI Responses API | Необязательное текстовое объяснение | Реальный внешний запрос только с серверными OPENAI_API_KEY и OPENAI_MODEL; численная модель остаётся в backend |
| MiroFish gateway | Необязательный адаптер | Выключен по умолчанию; не собирает посты или сообщения из соцсетей |
Citizen fixtures / localStorage | Петиции, сигналы, community activity | Вымышленные локальные данные, не реальные голоса или финансирование |
Open-Meteo fixture в backend/data/enrichment/ | Исследовательская фикстура | Снимок прогноза хранится с provenance; текущий интерфейс не использует его для показателей или Score |
| YouTube livestream | Видеоконтекст | Загружается только по нажатию; видео не анализируется |
Геоданные, происхождение карты и crosswalk описаны в docs/interactive-map.md, исследование источников — в sources.md и плане обогащения. Официальные источники по транспорту, школам, безопасности, воздуху и городским активам пока не подключены как проверенные слои показателей.
Известные ограничения
- Реальные городские результаты нельзя выводить из синтетических метрик, условных цен и модельных эффектов.
- Пять синтетических профилей не имеют подтверждённого crosswalk к шести картографическим районам; совпадение названий не используется для окрашивания районов по Score.
- OSM не заменяет официальный перечень школ, полевую проверку или инженерный аудит. В текущем продукте нет дорожных замеров, аварийных точек, вместимости школ, локальных показателей воздуха или реальных данных обращений.
- Civic workspace демонстрационный: действия жителей хранятся в браузере, не синхронизируются между людьми, петиции не имеют юридического эффекта, платежи не проводятся.
- AI может быть не настроен; без ключа недоступно только внешнее текстовое объяснение. AI не подтверждает факты и не доказывает причинность.
- Стандартные OSM/OpenFreeMap подложки зависят от внешней сети и политики поставщика; для production требуется выбранный провайдер или собственный tile-сервис. Публичный deployment в репозитории не указан.
- Compose настроен для разработки: используются Vite dev server и auto-reload. Production-конфигурация, HTTPS, аутентификация пользователей и эксплуатационная поддержка не входят в этот прототип.
Развёрнутая версия и документация
Публичная развёрнутая версия в репозитории не указана. Чтобы воспроизвести проект, используйте Docker Compose выше.
Авторы коммитов
История коммитов
- 2026-09-23 18:00Integrate city simulator into the Akim workspacevasileyyy
- 2026-09-23 17:49Rewrite README for current projectieeelon
- 2026-09-23 17:30Merge latest Madi school context into both city workspacesvasileyyy
- 2026-09-23 17:19Merge latest Aigerim documentation into mainvasileyyy
- 2026-09-23 17:18Merge Vasya map and localization with main command centervasileyyy
- 2026-09-23 17:17Add real OSM school context mapieeelon
- 2026-09-23 17:15docs: update command center READMEAigerim Nurgaliyeva
- 2026-09-23 17:01Merge remote-tracking branch 'origin/Madi'vasileyyy
Все коммиты (31)
- 2026-09-23 17:00Add Astana pilot data source leadsieeelon
- 2026-09-23 16:53feat: add interactive Astana map and Kazakh localizationvasileyyy
- 2026-09-23 16:41docs: map data requirements for Astana pilotieeelon
- 2026-09-23 16:18feat: connect civic AI context and verify merged command centerAigerim Nurgaliyeva
- 2026-09-23 16:09merge: preserve local command center while integrating latest mainAigerim Nurgaliyeva
- 2026-09-23 16:08feat: add Astana command center and connected citizen workspaceAigerim Nurgaliyeva
- 2026-09-23 16:03Merge origin/Madi into main with unified scenario workflowvasileyyy
- 2026-09-23 15:43feat: wire deterministic civic scenario workflowieeelon
- 2026-09-23 15:36fix: mount current migrations and dataset in development containersAigerim Nurgaliyeva
- 2026-09-23 15:31feat: add public signals demo and civic contextieeelon
- 2026-09-23 15:27merge: pull latest main into AigerimAigerim Nurgaliyeva
- 2026-09-23 15:22Merge remote-tracking branch 'origin/Madi' into Vasyavasileyyy
- 2026-09-23 15:20merge: incorporate latest branch updates into AigerimAigerim Nurgaliyeva
- 2026-09-23 15:19build: check all remote branches before every frontend buildAigerim Nurgaliyeva
- 2026-09-23 15:18docs: plan localized public opinion analysisieeelon
- 2026-09-23 15:15merge: integrate latest branches into Aigerim with Astana designAigerim Nurgaliyeva
- 2026-09-23 15:11docs: research Astana data enrichment sourcesieeelon
- 2026-09-23 15:09feat: style mayor simulator with Astana blue and gold identityAigerim Nurgaliyeva
- 2026-09-23 15:03feat: connect simulator UI to persistent scenarios and AI analysisvasileyyy
- 2026-09-23 14:29Merge remote-tracking branch 'origin/Madi'vasileyyy
- 2026-09-23 14:26docs: add QGIS district grid planieeelon
- 2026-09-23 14:24feat: add mayor city simulator dashboardAigerim Nurgaliyeva
- 2026-09-23 14:18wip: scaffold application and simulator data modelvasileyyy
Структура репозитория (130 файлов)
.env.example .gitattributes .github/workflows/ci.yml .gitignore Data_Enrichment_Research_Plan.md MiroFish_Local_Opinion_Plan.md PRD.md QGIS_Plan.md README.md backend/.dockerignore backend/Dockerfile backend/alembic.ini backend/app/__init__.py backend/app/api/__init__.py backend/app/api/context.py backend/app/api/health.py backend/app/api/map.py backend/app/api/mirofish.py backend/app/api/public_signals.py backend/app/api/scenarios.py backend/app/api/simulator.py backend/app/db.py backend/app/domain.py backend/app/main.py backend/app/models.py backend/app/schemas.py backend/app/seed.py backend/app/services/__init__.py backend/app/services/llm.py backend/app/services/mirofish.py backend/app/services/openai_analysis.py backend/app/services/results.py backend/app/services/scenarios.py backend/app/services/scoring.py backend/data/astana-v1.json backend/data/enrichment/astana-context-v1/manifest.json backend/data/enrichment/astana-context-v1/osm/overpass-query.txt backend/data/enrichment/astana-context-v1/osm/schools.geojson backend/data/enrichment/astana-context-v1/urban-quality/README.md backend/data/enrichment/astana-context-v1/weather/forecast-raw-response.json backend/data/enrichment/astana-context-v1/weather/forecast-sample.json backend/data/geography/astana-districts.geojson backend/data/geography/crosswalk.json backend/data/geography/sources.json backend/migrations/env.py backend/migrations/script.py.mako backend/migrations/versions/0001_initial_simulator_schema.py backend/migrations/versions/0002_scenario_sessions_and_durable_analysis.py backend/pytest.ini backend/requirements-dev.txt backend/requirements.txt backend/scripts/export_types.py backend/scripts/import_osm_boundaries.py backend/tests/conftest.py backend/tests/serve_e2e.py backend/tests/test_api.py backend/tests/test_data_model.py backend/tests/test_health.py compose.yaml datadoc.md docs/data-model.md docs/enrichment/BASELINE_LOCK.md docs/enrichment/README.md docs/enrichment/boundaries/README.md docs/enrichment/boundaries/sources.csv docs/enrichment/civic-evidence-map.md docs/enrichment/population-terrain/research.md docs/enrichment/public-signals/README.md docs/enrichment/public-signals/language-evaluation-template.csv docs/enrichment/public-signals/source-card-template.md docs/enrichment/urban-quality/README.md docs/enrichment/weather/README.md docs/enrichment/weather/source-card.md docs/i18n.md docs/integration.md docs/interactive-map.md docs/mirofish-adapter.md docs/openai-evaluation.md frontend/.dockerignore frontend/Dockerfile frontend/e2e/civic-accounting.spec.ts frontend/e2e/civic.spec.ts frontend/e2e/i18n.spec.ts frontend/e2e/map.spec.ts frontend/e2e/simulator.spec.ts frontend/e2e/workspaces.spec.ts frontend/index.html frontend/package-lock.json frontend/package.json frontend/playwright.config.ts frontend/public/astana-emblem.svg frontend/public/astana-flag.svg frontend/scripts/check-branch-sync.sh frontend/src/App.tsx frontend/src/AstanaMap.tsx frontend/src/AstanaMapCanvas.tsx frontend/src/CityContextMap.tsx frontend/src/CityLiveView.tsx frontend/src/PublicSignalsPanel.tsx frontend/src/SimulatorWorkspace.tsx frontend/src/api.ts frontend/src/astana-map.css frontend/src/city-context-map.css frontend/src/city-orbit.css frontend/src/civic-context.css frontend/src/command-center.css frontend/src/components/CitizenPulse.tsx frontend/src/components/CityMap.tsx frontend/src/components/CivicForms.tsx frontend/src/components/CivicPages.tsx frontend/src/components/Government.tsx frontend/src/components/UI.tsx frontend/src/data/citizens.ts frontend/src/data/crowdfunding.ts frontend/src/data/issues.ts frontend/src/data/petitions.ts frontend/src/data/votes.ts frontend/src/futuristic-light.css frontend/src/futuristic.css frontend/src/hooks/useCivic.ts frontend/src/hooks/useSimulator.ts frontend/src/i18n.tsx frontend/src/locales/kk.ts frontend/src/main.tsx frontend/src/mapData.ts frontend/src/styles.css frontend/src/types/domain.ts frontend/tsconfig.json frontend/vite.config.ts sources.md
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.