AAYMA
RU
Войти

Career Quest

Веб-приложение, показывающее сотруднику разрыв навыков до следующего грейда и 1–3 доступных шага развития с объяснением, с пересчётом прогресса…

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

О проекте

Команда: Participants
Кейс HackAlem.ai: Менеджмент — Halyk Bank · кейс 1
Стадия: Рабочий MVP

Задача кейса: «Career Quest»: AI-навигатор, связывающий навыки сотрудника с шагами развития

Суть

Веб-приложение, показывающее сотруднику разрыв навыков до следующего грейда и 1–3 доступных шага развития с объяснением, с пересчётом прогресса после выполнения, HR-дашбордом и импортом профилей жюри.

Как устроено

FastAPI загружает профили, историю и каталог из PostgreSQL; доменный модуль считает coverage = Σmin(уровень, требуемый)/Σтребуемых и разрывы. Каталог фильтруется по роли, грейду, prerequisites, датам сессий и полезности для цели, затем кандидаты получают многофакторный локальный score (разрыв, критичность, история пропусков и отказов, длительность). Опционально LLM переупорядочивает только допустимых кандидатов; ответ принимается, если в нём известные event_id, ≥3 фактора, а первый выбор входит в локальный Top-3. Иначе используется детерминированный fallback.

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

  • coverage-based trajectory
  • eligibility filtering
  • multi-factor scoring
  • LLM rerank with validation
  • deterministic fallback
  • 5-min cache invalidation

Особенности

LLM разрешено только переранжировать заранее проверенных кандидатов с жёсткими серверными проверками (топ-1 LLM обязан входить в локальный Top-3). Если курса нет, система генерирует конкретный запрос к HR вместо выдуманного шага.

Стек

Python 3.12 · FastAPI · Pydantic · PostgreSQL 16 · psycopg · React 19 · TypeScript · Vite · Docker Compose

Модели

OpenAI Responses API · NVIDIA NIM


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

README

README.md

Career Quest

AI-навигатор развития сотрудника для HackAlem AI × Halyk Bank

Career Quest превращает разрозненные HR-активности в понятную карьерную траекторию. Сотрудник видит, какие навыки отделяют его от следующего грейда, получает 1–3 доступных шага с проверяемым объяснением и сразу видит модельный эффект выполнения. HR получает агрегированный срез по дефицитам компетенций и участию — без публичных рейтингов сотрудников.

Решение работает на синтетическом стартовом наборе и поддерживает загрузку дополнительных профилей жюри. Внешняя LLM опциональна: без API-ключей приложение использует прозрачный локальный ранжировщик.

Краткое описание

Обычный каталог обучения отвечает на вопрос «что доступно?», но не объясняет сотруднику, зачем ему конкретная активность. Career Quest связывает четыре контекста:

  • текущий грейд и требования следующего уровня;
  • фактические разрывы по навыкам;
  • историю завершений, пропусков и отказов;
  • доступность, prerequisites и ожидаемый прирост от активности.

Результат — не рекомендация по минимальному навыку, а следующий реалистичный шаг к карьерной цели с доказательствами, на которых он выбран.

Что реализовано

Требование ТЗРеализация в Career Quest
Профиль и карьерная траекторияРоль, грейд, следующая веха, долгосрочная цель, подтверждённые и модельные уровни навыков, история и обязательные активности.
1–3 рекомендацииСервер отбирает только доступные добровольные активности, сокращающие разрыв до ближайшей или долгосрочной цели.
Объяснимость минимум по трём факторамКарточка показывает цель, текущий/требуемый/ожидаемый уровень навыка, историю похожих активностей, доступность и место в локальном рейтинге.
Обновление прогресса«Отметить пройденным» применяет gain с учётом max_level, пересчитывает траекторию и рекомендации. Демо-отметку можно отменить.
HR-viewКарта дефицитов, сотрудники с разрывом без доступного шага, сотрудники без цели и статистика участия по активностям.
Загрузка проверочных профилейHR может предварительно проверить и атомарно импортировать JSON профилей и CSV истории в схеме стартового набора.
Разграничение ролейВ демо сотрудник видит только выбранный профиль; импорт и агрегаты доступны роли HR. Границы демо-авторизации явно обозначены ниже.
Запуск одной командойПриложение и PostgreSQL поднимаются через Docker Compose; схема и стартовые данные загружаются автоматически.

Установка и запуск

Потребуется Docker Desktop с запущенным Linux engine.

Copy-Item .env.example .env
docker compose up --build -d

После запуска:

Первый старт создаёт таблицы PostgreSQL и загружает data/: 200 профилей, 40 событий, 60 навыков и 2 743 записи истории. Повторный запуск не дублирует данные.

Проверить состояние контейнеров:

docker compose ps
docker compose logs app --tail 100

Остановить приложение без удаления данных:

docker compose down

PostgreSQL хранится в Docker volume postgres_data. Команда docker compose down -v удалит volume вместе с импортами и смоделированными завершениями — используйте её только для полного сброса демо.

Приложение по умолчанию привязано к 127.0.0.1. При конфликте порта измените APP_PORT в .env.

Как проверить решение

  1. Откройте «Моя траектория» и выберите E0028 либо произвольный профиль. Покажите текущий грейд, следующую веху, покрытие требований и историю.
  2. Перейдите к рекомендациям. В каждой карточке видны разрыв, прогнозируемый прирост, влияние истории и доступность. Если подходящего курса нет, система честно объяснит ограничение и сформирует конкретный запрос HR по главному разрыву или карьерной цели. Копирование запроса не изменяет навыки.
  3. Для самостоятельной активности нажмите «Отметить пройденным». Демо-отметка сохраняется датой среза, а прогресс и рекомендации пересчитываются. Очную или онлайн-активность можно отметить только после состоявшейся сессии; созданную в приложении отметку можно отменить в истории.
  4. Переключитесь на роль HR и покажите карту дефицитов, разрывы без шага, профили без цели и участие по активностям.
  5. В разделе «Импорт данных» загрузите проверочный JSON/CSV: сначала «Проверить файлы», затем «Загрузить набор». Импорт не изменяет исходные файлы и выполняется атомарно.

«Отметить пройденным» создаёт обратимую демо-запись. Исходная история датасета при этом не изменяется и не удаляется.

Как работает решение

Основной пользовательский сценарий:

  1. Платформа получает профиль сотрудника, текущий грейд, уровни навыков и историю участия из PostgreSQL.
  2. Доменный модуль определяет следующую карьерную веху и рассчитывает разрывы между текущими и требуемыми уровнями.
  3. Каталог фильтруется по роли, грейду, prerequisites, датам сессий и уже выполненным активностям; оставшиеся варианты получают многофакторную оценку.
  4. Если настроен AI-провайдер, он переупорядочивает только допустимых кандидатов. Сервер проверяет ответ модели и при любой ошибке использует локальный рейтинг.
  5. Сотрудник получает 1–3 шага с объяснением цели, разрыва, ожидаемого прироста, истории и доступности. Если курса нет, система показывает причину и готовит запрос для HR без обращения к OpenAI.
  6. После демо-отметки выполнения модельный прогресс и рекомендации пересчитываются. HR видит агрегированные дефициты и статистику участия.
flowchart LR
    A[Профиль и история] --> B[Цель и разрывы навыков]
    C[Каталог активностей] --> D[Фильтр доступности]
    B --> D
    D --> E[Прозрачный локальный score]
    E --> F{LLM настроена?}
    F -- нет или timeout --> G[Детерминированный Top 1–3]
    F -- да --> H[LLM rerank допустимых кандидатов]
    H --> I[Проверка ID, фактов и локального Top 3]
    I -- ответ валиден --> J[Объяснимые рекомендации]
    I -- ответ невалиден --> G
    G --> J
    J --> K[Модельное выполнение]
    K --> B

1. Расчёт траектории

Ближайшая веха — следующий грейд в текущей роли. Если следующего грейда нет, используется только явно заданная и валидная карьерная цель; система не придумывает направление развития. Прогресс считается по требованиям целевого профиля:

coverage = Σ min(модельный уровень, требуемый уровень) / Σ требуемых уровней

Исходные employees.skills остаются подтверждённой оценкой. Завершения после last_review_date образуют отдельный модельный уровень. Прирост ограничивается диапазоном 0–5 и значением max_level активности.

2. Фильтр допустимости

До обращения к LLM сервер исключает:

  • обязательные мероприятия — они показываются отдельно;
  • активности не для текущей роли или грейда;
  • шаги с невыполненными prerequisites;
  • уже завершённые неповторяемые активности;
  • активности в процессе или без будущей сессии;
  • шаги, которые не сокращают ни одного разрыва до цели.

Поэтому внешняя модель не может предложить несуществующую или недоступную активность.

3. Многофакторный рейтинг

Для каждого допустимого кандидата локальный слой учитывает:

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

Шаг по критичному разрыву включается в контекст LLM, но критичность сама по себе не отменяет штрафы за пропуски и отказы. Первый выбор LLM обязан входить в локальный Top 3; если локальный лидер закрывает критичный разрыв, этот приоритет сохраняется. Правила повторно проверяются сервером.

4. Роль LLM и fail-safe

LLM не генерирует каталог и не рассчитывает уровни. Она только выбирает и переупорядочивает заранее проверенных кандидатов. Ответ принимается, если:

  • содержит только известные event_id;
  • ссылается минимум на три разрешённых фактора и факты из серверного контекста;
  • ставит первым один из локальных Top 3 и сохраняет критичный приоритет локального лидера.

При отсутствии ключа, таймауте, сетевой ошибке или невалидном ответе автоматически используется детерминированный Top 1–3. Результат кэшируется на пять минут и инвалидируется после импорта или выполнения активности.

Что означает источник рекомендации в интерфейсе

  • «AI · OpenAI» — OpenAI ответил, после чего сервер проверил выбранные event_id, подтверждающие факты и соблюдение правил ранжирования и только затем принял результат. Список допустимых курсов и расчёт их пользы до обращения к модели формирует код платформы: OpenAI не создаёт активности и не изменяет уровни навыков.
  • «Анализ данных» — для сотрудника не нашлось подходящих курсов. Система локально объясняет причину и показывает запасной шаг — готовый запрос к HR по главному разрыву или карьерной цели. В этом сценарии запрос к OpenAI не отправляется, а копирование текста не влияет на прогресс.

Технологии

СлойТехнологииОтветственность
FrontendReact 19, TypeScript, ViteТраектория, рекомендации, демо-отметка выполнения, HR-dashboard, импорт.
APIPython 3.12, FastAPI, PydanticHTTP API, проверка доступа, оркестрация доменной логики.
Recommendation coreЧистый PythonПрогресс, фильтрация, scoring, объяснения и fallback без зависимости от БД/LLM.
AI adaptersOpenAI Responses API / NVIDIA NIM, httpxОпциональный rerank со структурированным и валидируемым ответом.
DataPostgreSQL 16, psycopgПрофили, история, импорты и модельные завершения.
DeliveryDocker, Docker ComposeСборка frontend и единый локальный endpoint приложения.

Архитектура проекта

Frontend собран в статические файлы и раздаётся тем же FastAPI-приложением, что обслуживает API. FastAPI получает профиль и историю из PostgreSQL, передаёт их в независимый доменный модуль, а при наличии допустимых кандидатов может вызвать настроенный AI-провайдер для rerank. Любой ответ модели проходит серверную проверку; при ошибке используется локальный результат.

Основной поток запроса:

Browser → FastAPI → domain rules → PostgreSQL
                    └→ optional LLM rerank → validator → fallback

Ключевые модули:

backend/
├── main.py          # API, роли, импорт и раздача собранного frontend
├── domain.py        # траектория, фильтр, scoring и объяснения
├── ai_provider.py   # OpenAI/NVIDIA, schema validation и fallback
├── analytics.py     # HR-агрегаты
├── ingestion.py     # парсинг и валидация JSON/CSV
├── database.py      # доступ к PostgreSQL и первичная загрузка
└── schema.sql       # схема БД
frontend/src/        # React/TypeScript интерфейс
data/                # синтетический стартовый набор
tests/               # предметные и acceptance-тесты

Данные и интеграции

Стартовый синтетический набор хранится локально в каталоге data/ и содержит:

  • employees.json — 200 профилей сотрудников;
  • events.json — 40 HR-активностей и правила прироста навыков;
  • skills.json — 60 навыков, шкалу уровней и требования профилей;
  • activity_history.csv — 2 743 записи истории за 24 месяца.

После первого запуска данные загружаются в PostgreSQL. Дополнительные профили и историю можно импортировать через HR-интерфейс. Из внешних интеграций реализованы опциональные OpenAI Responses API и NVIDIA NIM Chat Completions; при отсутствии ключей решение полностью работает на локальном детерминированном алгоритме.

Конфигурация

ПеременнаяПо умолчаниюНазначение
APP_PORT8000Локальный порт веб-приложения.
POSTGRES_DBcareerquestИмя БД PostgreSQL.
POSTGRES_USERcareerquestПользователь PostgreSQL.
POSTGRES_PASSWORDcareerquestПароль локальной демо-БД.
DEMO_MODEtrueВключает локальный переключатель ролей и профилей.
AI_PROVIDERautoauto, openai, nvidia или off.
OPENAI_API_KEY—Ключ OpenAI; для запуска не обязателен.
OPENAI_MODELgpt-4.1-miniДоступная аккаунту модель Responses API.
NVIDIA_API_KEY—Ключ NVIDIA NIM; для запуска не обязателен.
NVIDIA_MODELmeta/llama-3.3-70b-instructДоступная модель NVIDIA NIM.
AI_TIMEOUT_SECONDS7.5Общий бюджет внешнего AI; остаётся внутри лимита ТЗ в 10 секунд.

Режимы AI_PROVIDER:

  • auto — OpenAI → NVIDIA → локальный fallback;
  • openai или nvidia — выбранный провайдер → локальный fallback;
  • off — только детерминированное ранжирование.

Ключи не нужны для локального демо. Не коммитьте .env: файл исключён через .gitignore. Во внешний AI передаются целевая роль, агрегированные разрывы и обезличенные кандидаты — без имени сотрудника и сырой истории.

Импорт проверочных данных

Импорт доступен в HR-режиме и принимает файлы до 3 МБ:

  • employees.json: один профиль, массив профилей, объект { "employees": [...] } или полный формат стартового файла;
  • activity_history.csv: CSV с теми же колонками, что в data/activity_history.csv.

Минимальный пример профиля:

{
  "employee_id": "JURY_001",
  "full_name": "Test Employee",
  "department": "Backend Development",
  "role": "Backend Engineer",
  "grade": "Middle",
  "manager_id": null,
  "hire_date": "2023-01-01",
  "tenure_months": 44,
  "work_format": "hybrid",
  "preferred_language": "ru",
  "career_goal": {
    "target_role": "Backend Engineer",
    "target_grade": "Senior"
  },
  "skills": {
    "SK_PYTHON": 3,
    "SK_SYSTEM_DESIGN": 2,
    "SK_PUBLIC_SPEAKING": 2
  },
  "last_review_date": "2026-09-01"
}

CSV-заголовок:

record_id,employee_id,event_id,date,due_date,status,completion_pct,score,feedback_rating,assigned_by

Preview проверяет уникальность ID, существование ролей, грейдов, навыков и событий, диапазоны значений и ссылки истории на сотрудников. Commit выполняется одной транзакцией. Повторная загрузка тех же файлов определяется по хэшу и не создаёт дубликаты; исходный batch удалить нельзя.

API

МетодEndpointНазначение
GET/api/healthГотовность приложения и БД.
GET/api/metaВерсия/дата набора и импортированные batches.
GET/api/employeesДоступные текущей роли профили.
GET/api/employees/{id}Профиль, история и обязательные активности.
GET/api/employees/{id}/progressТраектория, покрытие и разрывы.
GET/api/employees/{id}/recommendations1–3 объяснимых шага и причины исключений.
POST/api/employees/{id}/activities/{event_id}/completeМодельное выполнение и пересчёт прогресса.
DELETE/api/employees/{id}/activities/{event_id}/completeОтмена созданной в приложении демо-отметки.
GET/api/hr/overviewАгрегированный HR-срез с фильтрами.
POST/api/import/previewВалидация файлов без записи.
POST/api/import/commitАтомарная загрузка проверочного набора.
DELETE/api/import/{batch_id}Удаление дополнительного batch.

В демо доступ задают заголовки X-Demo-Role: employee|hr и X-Demo-Employee: <id>; интерфейс устанавливает их автоматически. Полные схемы запросов доступны в /docs.

Проверка проекта

Предметные тесты не требуют запущенной БД:

python -m unittest discover -s tests -v

Они проверяют, в частности, многофакторный выбор вместо правила «минимальный навык», однократное применение прироста, ограничения каталога, влияние истории, валидацию AI-ответа и HR-агрегацию.

Сборка frontend:

Set-Location frontend
npm ci
npm run build

End-to-end smoke test после запуска Compose:

Invoke-RestMethod http://localhost:8000/api/health
Invoke-RestMethod http://localhost:8000/api/meta

Ограничения текущей версии

  • Данные стартового набора синтетические; приложение не отправляет репозиторий или данные куда-либо автоматически.
  • HR-view содержит агрегаты и рабочие списки, но не публичный рейтинг результативности сотрудников.
  • Обязательные процессы отделены от добровольных рекомендаций и не используются как игровая механика.
  • DEMO_MODE и заголовки — только имитация ролей для защиты, не корпоративная авторизация.
  • Перед работой с реальными данными необходимы SSO/RBAC, аудит доступа, управление согласиями, секрет-хранилище и согласованная политика передачи данных внешнему AI.
  • Дата расчёта фиксирована метаданными набора (2026-10-01), поэтому демо воспроизводимо и не зависит от часов компьютера.
  • Для self-paced активности историческая дата может означать назначение, а не завершение. Неоднозначные записи до последней оценки не повышают уровень автоматически.
  • Процент покрытия показывает соответствие требованиям профиля, а не вероятность повышения сотрудника.
  • Контент каталога в стартовом наборе на английском; интерфейс текущей версии — на русском.

Deployed-версия

Публичная deployed-версия в репозитории не указана. После локального запуска приложение доступно по адресу http://localhost:8000.

Возможности развития

  • SSO и корпоративная матрица ролей;
  • согласованный каталог на русском и казахском языках;
  • обратная связь сотрудника для learning-to-rank;
  • календарь, мессенджер и напоминания по добровольному opt-in;
  • конструктор активностей и симуляция карьерных сценариев для HR;
  • мониторинг качества рекомендаций, fairness и drift;
  • командные и менторские механики без публичного соревнования сотрудников.

Career Quest показывает сотруднику не просто список курсов, а следующий объяснимый шаг: куда он ведёт, какой разрыв закрывает и как изменит траекторию.

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

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

Almas456732 11alanselivanov 8Almas 2

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

  • 2026-09-23 17:23fixAlmas456732
  • 2026-09-23 17:23отредактировал read meAlmas456732
  • 2026-09-23 17:17Merge main and update project documentationAlmas456732
  • 2026-09-23 17:14added read me fileAlmas456732
  • 2026-09-23 17:12Add honest fallback steps and reversible dated completionsalanselivanov
  • 2026-09-23 17:03Merge branch 'main' of https://github.com/BAITC-Hacks/hack-ea50d4e9-participantsAlmas456732
  • 2026-09-23 17:03сделал анализ недостатковAlmas456732
  • 2026-09-23 16:44Account for demo history and prioritize critical developmentalanselivanov
Все коммиты (21)
  • 2026-09-23 16:20Merge recommendation explanations into mainalanselivanov
  • 2026-09-23 16:16Explain recommendation choices and blocked critical skillsalanselivanov
  • 2026-09-23 16:16Merge pull request #3 from BAITC-Hacks/codex/fix-requirements-bugsAlmas
  • 2026-09-23 16:12changed the frontendAlmas456732
  • 2026-09-23 15:56Merge pull request #2 from BAITC-Hacks/codex/fix-goal-recommendationsalanselivanov
  • 2026-09-23 15:54Fix goal-relevant recommendations and activity history scoringalanselivanov
  • 2026-09-23 15:36Merge pull request #1 from BAITC-Hacks/codex/fix-requirements-bugsAlmas
  • 2026-09-23 15:32Merge origin/main and resolve application conflictsAlmas456732
  • 2026-09-23 15:29Fix requirements bugs and restore application UIAlmas456732
  • 2026-09-23 15:20fixed some bugsAlmas456732
  • 2026-09-23 15:07Created MVP for starting point of the project, added deployalanselivanov
  • 2026-09-23 14:31added project planAlmas456732
  • 2026-09-23 14:29initial architecture of the appalanselivanov
Структура репозитория (29 файлов)
.dockerignore
.env.example
.gitignore
Dockerfile
README.md
backend/ai_provider.py
backend/analytics.py
backend/config.py
backend/database.py
backend/domain.py
backend/ingestion.py
backend/main.py
backend/requirements.txt
backend/schema.sql
compose.yaml
data/activity_history.csv
data/employees.json
data/events.json
data/skills.json
frontend/index.html
frontend/package-lock.json
frontend/package.json
frontend/src/App.tsx
frontend/src/main.tsx
frontend/src/styles.css
frontend/tsconfig.json
frontend/vite.config.ts
tests/test_domain.py
tests/test_requirements.py
Ветки (3)

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

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

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