AAYMA
RU
Войти

Career Quest

Веб-приложение и Telegram-бот с 1–3 обоснованными карьерными рекомендациями для сотрудника, HR-дашбордом с тепловой картой разрывов и AI-ассистентом…

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

О проекте

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

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

Суть

Веб-приложение и Telegram-бот с 1–3 обоснованными карьерными рекомендациями для сотрудника, HR-дашбордом с тепловой картой разрывов и AI-ассистентом с function calling (поиск ментора, симуляция по отделу).

Как устроено

Детерминированный recommender.py считает эффективные навыки, разрыв до грейда или цели и скор активности: закрытие разрыва, вес ×2 за критичность навыка и штраф за историю пропусков в данном формате. Он же оценивает срок до повышения по личному темпу. GPT-4o-mini (или NVIDIA NIM) только переводит готовые факты в текст на preferred_language, для него есть шаблонный fallback. Агент через OpenAI function calling вызывает find_mentor и simulate_department_impact, а каталог ID передаётся в системный промпт против выдуманных идентификаторов. Бэкенд на FastAPI, данные в памяти с догрузкой jury-файлов.

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

  • многофакторный скоринг рекомендаций
  • штраф за историю пропусков
  • OpenAI function calling
  • LLM-объяснитель с fallback
  • Telegram-бот и Mini App
  • ролевой доступ через заголовки

Особенности

Явно разобрана «ловушка жюри»: некритичный навык с максимальным разрывом не вытесняет критичный. Переключатель «Показать логику AI» показывает сырые веса скоринга. Есть HR-симуляция «что если назначить курс всему отделу».

Стек

Python · FastAPI · Pydantic · vanilla HTML/CSS/JS · Telegram Bot API · ngrok

Модели

OpenAI gpt-4o-mini · NVIDIA NIM


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

README

README.md

Career Quest — AI-навигатор развития

HackAlem AI 2026 · Halyk Bank case

Веб-приложение, которое отвечает сотруднику на вопрос «что мне делать дальше в карьере и почему именно это» — не списком случайных курсов, а 1-3 рекомендациями с прозрачным, проверяемым обоснованием. Плюс HR-дашборд, показывающий проседающие компетенции и людей, выпавших из развития.

Почему это не «LLM угадывает»

Ключевое архитектурное решение: расчёт и объяснение — разные слои.

  1. Детерминированный движок (engine/recommender.py) — обычный Python, без единого обращения к нейросети. Считает:

    • эффективный уровень навыков сотрудника (базовый профиль + прирост от активностей, завершённых после последней аттестации);
    • разрыв до следующего грейда и/или личной карьерной цели;
    • скоринг каждой доступной активности по нескольким факторам: сколько разрыва закрывает, критичен ли навык для повышения (вес ×2), как сотрудник вёл себя на активностях такого формата раньше (штраф за историю пропусков/отказов);
    • честную оценку «сколько ещё месяцев» — по фактическому темпу самого сотрудника из истории, а не наугад.
  2. LLM (engine/llm_explainer.py, GPT-4o-mini) подключается только на последнем шаге — превращает уже посчитанные факты в связный текст на предпочитаемом языке сотрудника. Ей запрещено что-либо решать или выдумывать цифры. Если LLM недоступна или не отвечает вовремя — есть детерминированный текстовый fallback, который склеивает те же факты без единого обращения к сети. Демо никогда не падает из-за таймаута API.

Это защищает от главного риска подобных кейсов: наивное правило «рекомендуй то, что просело сильнее всего» ошибается, если самый слабый навык — некритичный, а сотрудник уже трижды проигнорировал мероприятия в этом формате. Наш скоринг учитывает это явно (см. «Проверка на ловушке» ниже).

AI-агент (диалог поверх той же математики)

Третий слой — карьерный ассистент с настоящим OpenAI function-calling (engine/agent.py, engine/agent_tools.py), а не имитацией диалога через промпт. Модель сама решает, вызывать ли инструмент, но инструменты — обычный Python по реальным данным:

  • find_mentor — ищет реальных коллег с сильным уровнем нужного навыка (для наставничества), а не только «пройди курс»;
  • simulate_department_impact — HR-версия «что если»: массово применяет тот же скоринг ко всему отделу и честно считает, сколько разрыва закроется.

Модели никогда не даётся возможность угадывать ID — в системный промпт передаётся точный каталог skill_id/event_id, иначе она рано или поздно придумает несуществующий (например, SK_APPLICATION_SECURITY вместо настоящего SK_APP_SECURITY) и молча получит пустой результат. Ответ агента также подстраивается под preferred_language сотрудника (ru/kk/en). Каждый вызов инструмента виден в интерфейсе — раскрывающаяся плашка показывает точные аргументы и результат, чтобы это нельзя было принять на веру.

Что внутри

ЭкранЧто показывает
Профиль сотрудникаТраектория до следующего грейда и до личной карьерной цели, разрывы по навыкам (с отметкой критичных), 1-3 рекомендации с факторами и объяснением, оценка «сколько до повышения», кнопка «Выполнено» с мгновенным пересчётом, история активностей
Показать логику AI (тумблер на карточке рекомендации)Заменяет текст объяснения на сырые веса скоринга (gap_score, critical_weight_applied, history_risk_ratio, risk_multiplier, final_score) — доказательство, что под текстом реальная математика, а не история, придуманная моделью
HR-обзорТоп проседающих навыков по компании, тепловая карта разрывов по отделам, сотрудники без доступных рекомендаций, сотрудники без прогресса 6+ месяцев, явка по активностям
Спросить AI-ассистента (чат на вкладках профиля и HR)Диалог поверх движка: сотрудник может спросить «кто может быть моим ментором», HR — «что если назначить курс X всему отделу Y». Каждый ответ можно раскрыть и увидеть, какой инструмент был вызван и с какими данными
Загрузка профилей жюриDrag-and-drop для employees.json / activity_history.csv в формате датасета — данные домешиваются в память без перезапуска сервера, сразу доступны в поиске и в HR-обзоре

Интерфейс поддерживает светлую и тёмную тему (переключатель в шапке). Бонус: параллельно с веб-сервером поднимается Telegram-бот на том же движке, с привязкой к личности и интерактивной кнопкой «Выполнено» прямо в чате — подробности в разделе «Как проверить» ниже.

Проверка на ловушке жюри

Мы сознательно тестировали кейс: сотрудник, у которого сильнее всего просел некритичный навык (Public Speaking), но при этом он трижды подряд пропускал офлайн-мероприятия — а критичный для повышения System Design просел меньше, но именно он нужен для грейда. Наивное правило «бери максимальный разрыв» рекомендует Public Speaking. Наш движок — нет: критичность даёт вес ×2, а штраф за историю снижает приоритет активностей в формате, который сотрудник систематически игнорирует. System Design остаётся в топе.

Это воспроизводимо через сам интерфейс: загрузите в разделе «Загрузка профилей жюри» файл с похожим профилем и откройте его карточку.

Загрузка принимает JSON в любом разумном виде — {"employees": [...]}, один объект без обёртки (как в примере из ТЗ), или голый массив объектов — на случай, если проверочный файл или скрипт пришлёт формат чуть иначе, чем в датасете.

Запуск

pip install -r requirements.txt
cp .env.example .env   # заполнить OPENAI_API_KEY (или NVIDIA_*), опционально BOT_TOKEN
python app.py

Откройте http://localhost:8791.

Без ключа LLM приложение тоже работает — просто объяснения будут собираться из детерминированного шаблона вместо GPT (тот же принцип, что и в основном движке: сначала факты, LLM только для формулировки).

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

Веб — http://localhost:8791 после python app.py. Если открываете не на том же компьютере, где запущен сервер, замените localhost на реальный адрес/домен.

Telegram-бот (@nexon_agent_bot) — бонусный канал на том же движке:

  1. Напишите /start.
  2. Введите свой employee_id (например E0028) — бот привяжет этот чат к профилю. С этого момента бот показывает только привязанный профиль (это осознанное разграничение прав, а не баг) — чтобы проверить другого сотрудника, отправьте /reset и введите новый ID.
  3. Под каждой рекомендацией есть кнопка «✅ Выполнено» — работает через тот же код, что и кнопка на сайте, прогресс пересчитывается сразу.
  4. Кнопка «📊 HR-обзор» видна только если привязанный ID имеет роль HR Business Partner в датасете (например E0014) — это тоже намеренно, не отсутствующая функциональность.
  5. Если задан TELEGRAM_WEBAPP_URL, появляется кнопка «🖥 Открыть в мини-приложении» — тот же веб-интерфейс, но внутри Telegram. Она указывает на туннель (ngrok), поднятый на момент демонстрации; если ссылка успела истечь — просто пользуйтесь ботом напрямую или веб-версией, функциональность идентична.

Переменные окружения (.env)

ПеременнаяНазначение
LLM_PROVIDERopenai или nvidia — какой провайдер использовать для объяснений
OPENAI_API_KEY, OPENAI_MODELКлюч и модель OpenAI (по умолчанию gpt-4o-mini)
NVIDIA_API_KEY, NVIDIA_MODEL, NVIDIA_URLТо же для NVIDIA NIM
BOT_TOKENТокен Telegram-бота (опционально — без него бот просто не запускается)
TELEGRAM_WEBAPP_URLПубличный HTTPS-адрес (ngrok-туннель) для кнопки Mini App в боте (опционально)
API_PORTПорт веб-сервера (по умолчанию 8791 — 8000 зарезервирован Windows)
LLM_TIMEOUT_SECONDSТаймаут на объяснение от LLM, после которого используется fallback

API

МетодПутьНазначение
GET/api/employeesСписок сотрудников (для поиска в сайдбаре)
GET/api/employees/{id}Полный профиль: траектории, рекомендации, история
POST/api/employees/{id}/completeОтметить активность выполненной → пересчёт профиля
GET/api/hr/overviewАгрегаты для HR-дашборда
POST/api/data/employeesЗагрузить/домешать employees.json (jury-файлы)
POST/api/data/activityЗагрузить/домешать activity_history.csv
POST/api/agent/chatДиалог с AI-агентом (employee_id задан → контекст сотрудника, null → HR-режим)
GET/healthСтатус сервиса, кол-во загруженных записей, конфигурация LLM

Разделение прав сотрудник/HR

Без дополнительных заголовков API ведёт себя так же, как раньше — полный доступ ко всем эндпоинтам (это осознанно, чтобы жюри/скрипт проверки могли тестировать любой профиль без лишних танцев с авторизацией). Веб-интерфейс и бот, когда действуют от лица конкретного сотрудника, добавляют заголовки X-Viewer-Role: employee и X-Viewer-Employee-Id: <id> — в этом режиме сервер отдаёт 403 на любой запрос к чужому профилю, общему списку сотрудников, HR-агрегатам или загрузке данных. Это настоящая проверка на бэкенде (app.py, функции require_hr/require_self_or_hr), не косметика в интерфейсе.

Структура проекта

app.py                    FastAPI-сервер: роуты, сборка профиля и HR-обзора, Telegram-бот
engine/
  models.py                Pydantic-модели домена (Employee, Event, Skill, ...)
  data_store.py             In-memory хранилище датасета + merge jury-загрузок
  recommender.py             Детерминированный скоринг: разрывы, рекомендации, оценка темпа
  llm_explainer.py           LLM только для текста объяснения, с fallback-шаблоном
  agent.py                    Диалоговый слой: system-промпт, каталог id, вызов инструментов
  agent_tools.py               find_mentor / simulate_department_impact — чистая математика по данным
  schemas.py                  API-контракт (request/response модели)
static/                    Веб-интерфейс: index.html, app.js, styles.css (без сборки)
data/                      Датасет хакатона (employees.json, events.json, skills.json, activity_history.csv)

Технологии

FastAPI · Pydantic v2 · aiogram (Telegram-бот) · OpenAI (GPT-4o-mini + function calling) / NVIDIA NIM API · ванильный JS/CSS на фронте (без сборки, без фреймворков)


Разработано в рамках HackAlem AI 2026 (команда Nexon). Синтетический датасет, реальные люди не использовались.

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

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

SlyNursamatYT 6

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

  • 2026-09-23 17:40feat: Telegram-бот с привязкой identity и мини-приложением, разделение прав employee/HR, устойчивость загрузки к разным форматам входных данныхSlyNursamatYT
  • 2026-09-23 17:21feat: init project scaffoldSlyNursamatYT
  • 2026-09-23 15:52feat: init project scaffoldSlyNursamatYT
  • 2026-09-23 15:06feat: init project scaffoldSlyNursamatYT
  • 2026-09-23 14:02feat: init project scaffoldSlyNursamatYT
  • 2026-09-23 13:19feat: init project scaffoldSlyNursamatYT
Структура репозитория (24 файлов)
.claude/launch.json
.env.example
.gitignore
README.md
app.py
data/README.kz.md
data/README.md
data/README.ru.md
data/activity_history.csv
data/employees.json
data/events.json
data/skills.json
engine/__init__.py
engine/agent.py
engine/agent_tools.py
engine/data_store.py
engine/llm_explainer.py
engine/models.py
engine/recommender.py
engine/schemas.py
requirements.txt
static/app.js
static/index.html
static/styles.css

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

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

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