AAYMA
RU
Войти

Astana AI — Urban Decision Intelligence

Городской симулятор на Next.js: пользователь собирает план из 5 мер по районам и видит состояние до и после, оптимизатор предлагает Top-3…

Рабочий MVP
Команда «edu_ai» 3💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: edu_ai
Кейс HackAlem.ai: Спецтрек — Astana Innovations
Стадия: Рабочий MVP

Задача кейса: «Аким на 5 часов»: городской симулятор, распределяющий бюджет по 5 направлениям и 5 районам

Суть

Городской симулятор на Next.js: пользователь собирает план из 5 мер по районам и видит состояние до и после, оптимизатор предлагает Top-3 альтернатив, AI-советник разбирает текущий план и объясняет результат.

Как устроено

Детерминированный движок simulateScenario проверяет ограничения (бюджет, совместимость, не больше двух мер одного направления) и учитывает лаг внедрения по формуле effect×(8−lag)/8, синергии и ограничение 0–100. Score = 0.7×средний районный + 0.3×слабейший район − число критических показателей. Оптимизатор перебирает допустимые наборы с отсечением и ранжирует их под цель. LLM переводит свободный текст в структурированную цель и выбирает, какие проверенные факты объяснить. Числа LLM не генерирует, без ключа работает deterministic fallback.

Ключевые решения

  • детерминированный движок симуляции
  • перебор сценариев с pruning
  • Top-3 ранжирование по целям
  • NL-цель в structured objective
  • Structured Outputs

Метрики

Контрольный сценарий: Score 52.558 → 56.543, стоимость 95, критические показатели 2 → 0

Особенности

Цепочка «цель на естественном языке → валидированная структурированная цель → детерминированный поиск → Top-3 → объяснение по фактам». Анализ текущего плана показывает минимальные изменения под цель и сравнение с каждой альтернативой.

Стек

Next.js 16 · React 19 · TypeScript 5 · Vitest 4 · CSS Modules

Модели

gpt-4o-mini (OpenAI Responses API)


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-ec7c49fc-edu-ai.

README

README.md

Astana AI — Urban Decision Intelligence

Проблема

Городской управленец распределяет ограниченный бюджет между транспортом, экологией, социальной инфраструктурой, безопасностью и сервисами. До принятия решения важно понять последствия для каждого района и города в целом.

Решение

  • Deterministic simulation engine проверяет ограничения и рассчитывает последствия сценария.
  • Scenario optimizer ищет допустимые комбинации и ранжирует альтернативы под цель пользователя.
  • AI advisor интерпретирует запрос, анализирует текущий план и объясняет результаты.
  • Frontend dashboard позволяет собрать план, увидеть before/after, сравнить альтернативы и применить предложение к конструктору.

Ключевой принцип

LLM не рассчитывает числа. Score, бюджет, значения показателей, эффекты, синергии, критические показатели и районные оценки поступают из simulateScenario(input: ScenarioInput): SimulationResult.

Optimizer сравнивает готовые результаты; стоимость из каталога используется только для отсечения заведомо недопустимых вариантов. AI выбирает акценты среди проверенных фактов, а числовой текст формируется приложением из результатов движка. Frontend отображает результаты и не воспроизводит формулы.

Архитектура

Frontend
  → Advisor API / Scenario Builder
  → Optimizer
  → Simulation Engine
  → Synthetic Track Dataset

Ручной конструктор вызывает движок напрямую. Advisor использует POST /api/advisor. Общие типы: src/types/domain.ts; контракт Advisor: docs/advisor-api.md.

Данные

Источник — синтетический датасет, предоставленный организаторами кейса Astana Innovations «Аким на 5 часов».

  • 5 районов: Есиль, Алматы, Сарыарка, Байконур, Нура.
  • 10 показателей качества жизни.
  • 14 мер в 5 направлениях.
  • Бюджет: 100 условных единиц.
  • Ровно 5 уникальных решений в сценарии.
  • Горизонт: 8 кварталов.

Формула симуляции

Эффекты мер корректируются с учётом задержки: effect × (8 − lag) / 8. Затем добавляются заданные синергии, а значения показателей ограничиваются диапазоном 0–100. Совместимость, район/город, бюджет и лимит двух мер одного направления проверяются до расчёта.

Районный Score — взвешенная сумма показателей. Средний городской результат учитывает доли населения. Итоговый QoL Score:

Score = 0.7 × средний районный Score
      + 0.3 × Score слабейшего района
      − количество показателей строго ниже 40

Контрольный сценарий: M7, M8, M10 в Нуре; M12 на весь город; M5 в Сарыарке. Движок возвращает стоимость 95, остаток 5, Score 52.55768 → 56.54307 и критические показатели 2 → 0.

AI / Agent flow

Natural language goal
  → validated structured objective
  → deterministic search
  → simulate candidates
  → Top-3
  → grounded explanation

Поддерживаются maximize_city_score, improve_district, reduce_critical_indicators, balanced_development. При reduceCritical=true первично уменьшение числа критических показателей, затем район и целевые показатели, затем общий Score, стоимость и стабильный tie-breaker. Для сбалансированного развития дополнительно приоритетен результат слабейшего района. Top-3 содержит разные наборы мер.

Одинаковая структурированная цель и версия датасета дают одинаковое ранжирование. Интерпретация свободного текста внешней моделью может варьироваться.

Анализ текущего плана

Если передан currentScenario, сервер повторно вызывает настоящий simulateScenario() и добавляет необязательное поле currentScenarioAnalysis. Анализ содержит исходный SimulationResult, сильные стороны, слабые места, оставшиеся критические показатели, минимальные изменения по цели и сравнение с каждой альтернативой. Старые поля ответа сохранены.

Стоимость сравнивается с результатом цели по готовым сценариям; система не приписывает отдельной мере неподтверждённую неэффективность. Невалидный план получает диагностику движка без выдуманного after-state. Русское объяснение и сравнение доступны также без OpenAI.

Tech stack

Next.js 16 (App Router, Turbopack), React 19, TypeScript 5, Vitest 4. OpenAI Responses API вызывается серверным fetch; дополнительный SDK не требуется. Стили — CSS Modules.

Системные требования

Node.js >= 20.9.0 и npm. Для разработки и проверки используется корень репозитория.

Установка

npm install

Для воспроизводимой установки по package-lock.json:

npm ci

Создайте .env.local по образцу .env.example:

OPENAI_API_KEY=...
OPENAI_MODEL=gpt-4o-mini

Ключ нужен только для внешней модели. Без ключа применяется deterministic fallback. Пустой OPENAI_MODEL использует gpt-4o-mini. Не используйте префикс NEXT_PUBLIC_ для ключа и не коммитьте .env.local.

npm run dev

Откройте локальный адрес, показанный Next.js в терминале.

Проверка

npm test
npm run typecheck
npm run build

typecheck сначала создаёт Next.js-типы маршрутов, поэтому работает и без существующей .next. Тесты проверяют reference scenario, ограничения, приоритеты optimizer, анализ текущего плана, API errors и fallback при недоступности OpenAI. Тесты модели используют подменённый HTTP и не тратят API-кредиты.

Demo flow

  1. Показать baseline: Score 52.56, слабейший район Нура, два критических показателя.
  2. Выбрать пять инициатив контрольного сценария.
  3. Нажать «Рассчитать сценарий».
  4. Показать before/after: около 56.54, бюджет 95, критические 2 → 0.
  5. Спросить AI: «Улучши Нуру и убери критические социальные показатели, не выходя за бюджет 100».
  6. Показать trace, анализ текущего плана и Top-3.
  7. Выбрать альтернативу и нажать «Сравнить с моим планом».
  8. Нажать «Использовать этот сценарий» и пересчитать его в конструкторе.

Дополнительные запросы: «Максимизируй общий Astana Quality of Life Score» и «Предложи более сбалансированный сценарий, чтобы не оставить слабый район».

Ограничения

  • Данные синтетические; результаты относятся только к правилам кейса.
  • Это decision-support, не реальный прогноз политики Астаны.
  • При отсутствии ключа, ошибке или таймауте OpenAI используется deterministic fallback.
  • Общегородской поиск перебирает больше вариантов, чем районный, и может занимать заметно больше времени.
  • Финальное решение принимает человек.
  • LLM не является источником числовой истины и не оценивает риски, которых нет в данных симулятора.

Проверка AI жюри

Основной simulator и полный путь Advisor работают без ключа. Для проверки реального LLM задайте собственный OPENAI_API_KEY в .env.local (не в репозиторий) и перезапустите сервер. .env.example содержит только пустые плейсхолдеры.

Запросы к Responses API выполняются только на сервере с таймаутом 8 секунд на вызов. Structured output проверяется приложением. Модель интерпретирует цель и выбирает ключи подтверждённых фактов для объяснения; произвольные числа и факты из её текста не отображаются. Успешный fallback сам по себе не доказывает, что внешний API был вызван успешно.

Чеклист перед демо:

  1. Отозвать любой ранее раскрытый ключ в OpenAI API keys и создать новый.
  2. Прописать новый ключ только в .env.local, перезапустить npm run dev.
  3. Вызвать POST /api/advisor с демо-запросом и убедиться, что ответ приходит при наличии ключа (не только fallback без ключа).
  4. Пройти UI: расчёт → советник → сравнение → применение → пересчёт.
  5. Контракт ошибок: см. docs/advisor-api.md § Errors.

Сторонние компоненты

Next.js, React, React DOM, TypeScript, Vitest, типы Node.js/React/React DOM из package.json; необязательный внешний сервис — OpenAI API. Базы данных, аутентификации и иных внешних сервисов нет.

Звёзды
⭐ 0
Форки
0
Язык
TypeScript
Последний push
в прошлом месяце
Коммиты
29
Авторы
4
Файлы
60
Ветки
3

Авторы коммитов

автор (email скрыт) 14Bolat Abdulaziz 7zekochka 5Abdulaziz 3

История коммитов

  • 2026-09-23 17:53changesBolat Abdulaziz
  • 2026-09-23 17:38changesBolat Abdulaziz
  • 2026-09-23 17:18feat: change READMEавтор (email скрыт)
  • 2026-09-23 17:16Merge pull request #4 from BAITC-Hacks/feat/simulation-engineAbdulaziz
  • 2026-09-23 17:14fix: fix readme2zekochka
  • 2026-09-23 16:49merge: integrate latest main with frontend advisorавтор (email скрыт)
  • 2026-09-23 16:48feat(ui): connect AI advisor and shared scenario stateавтор (email скрыт)
  • 2026-09-23 16:24feat(ui): connect simulation resultsавтор (email скрыт)
Все коммиты (29)
  • 2026-09-23 16:09changesBolat Abdulaziz
  • 2026-09-23 15:47Merge branch 'main' of https://github.com/BAITC-Hacks/hack-ec7c49fc-edu-ai into feat/dashboard-uiавтор (email скрыт)
  • 2026-09-23 15:46perf: speed up scenario optimizer with pruningBolat Abdulaziz
  • 2026-09-23 15:45Merge pull request #3 from BAITC-Hacks/feat/simulation-engineAbdulaziz
  • 2026-09-23 15:44Merge remote-tracking branch 'origin/feat/simulation-engine' into feat/dashboard-uiавтор (email скрыт)
  • 2026-09-23 15:33feat(ui): add scenario builderавтор (email скрыт)
  • 2026-09-23 15:16feat: 2nd employee functionalzekochka
  • 2026-09-23 15:15Merge remote-tracking branch 'origin/feat/dashboard-ui' into feat/dashboard-uiавтор (email скрыт)
  • 2026-09-23 15:12merge: integrate simulation and advisor updatesавтор (email скрыт)
  • 2026-09-23 15:04feat: added connection with data and openaiBolat Abdulaziz
  • 2026-09-23 14:42Merge branch 'main' into feat/dashboard-uiToktar
  • 2026-09-23 14:39add: commit +1автор (email скрыт)
  • 2026-09-23 14:36Merge branch 'main' of https://github.com/BAITC-Hacks/hack-ec7c49fc-edu-ai into feat/dashboard-uiавтор (email скрыт)
  • 2026-09-23 14:35Merge pull request #1 from BAITC-Hacks/feat/simulation-engineAbdulaziz
  • 2026-09-23 14:30fix: fix readmezekochka
  • 2026-09-23 14:26feat: added AI / Agent layer partBolat Abdulaziz
  • 2026-09-23 14:24feat: add +1 rowавтор (email скрыт)
  • 2026-09-23 14:21feat: new row2zekochka
  • 2026-09-23 13:48somethingBolat Abdulaziz
  • 2026-09-23 13:46feat: new rowzekochka
  • 2026-09-23 13:371st commitавтор (email скрыт)
Структура репозитория (60 файлов)
.env.example
.gitignore
AGENTS.md
CLAUDE.md
README.md
docs/advisor-api.md
docs/demo-queries.md
docs/demo-script.md
docs/frontend-integration.md
frontend/AGENTS.md
frontend/Plan.md
next-env.d.ts
package-lock.json
package.json
src/app/api/advisor/route.ts
src/app/layout.tsx
src/app/page.tsx
src/components/dashboard/AdvisorPanel.module.css
src/components/dashboard/AdvisorPanel.tsx
src/components/dashboard/Dashboard.tsx
src/components/dashboard/SimulationResults.tsx
src/components/dashboard/dashboard.module.css
src/components/dashboard/districts.ts
src/components/scenario/ScenarioBuilder.module.css
src/components/scenario/ScenarioBuilder.tsx
src/data/astana-track-data.ts
src/data/districts.ts
src/data/indicators.ts
src/data/measures.ts
src/lib/agent/advisor.ts
src/lib/agent/analysis.ts
src/lib/agent/explanation.ts
src/lib/agent/objective.ts
src/lib/agent/openai.ts
src/lib/agent/prompts.ts
src/lib/optimizer/catalog.ts
src/lib/optimizer/optimizer.ts
src/lib/optimizer/types.ts
src/lib/simulation/INTEGRATION.md
src/lib/simulation/README.md
src/lib/simulation/constants.ts
src/lib/simulation/engine.ts
src/lib/simulation/index.ts
src/lib/simulation/score.ts
src/lib/simulation/types.ts
src/lib/simulation/validator.ts
src/types/domain.ts
tests/agent/analysis.test.ts
tests/agent/api-route.test.ts
tests/agent/explanation.test.ts
tests/agent/objective.test.ts
tests/agent/openai.test.ts
tests/optimizer/optimizer.test.ts
tests/optimizer/performance.test.ts
tests/simulation/data.test.ts
tests/simulation/engine.test.ts
tests/simulation/score.test.ts
tests/simulation/validator.test.ts
tsconfig.json
vitest.config.ts
Ветки (3)

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.