AAYMA
RU
Войти

Career Quest

Веб-приложение для сотрудника и HR: профиль, покрытие требований карьерной цели, до трёх рекомендаций обучения с объяснением, отметка выполнения с…

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

О проекте

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

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

Суть

Веб-приложение для сотрудника и HR: профиль, покрытие требований карьерной цели, до трёх рекомендаций обучения с объяснением, отметка выполнения с пересчётом, HR-обзор дефицитов навыков и импорт данных.

Как устроено

Чистая функция recommend отбирает доступные события по роли и грейду, prerequisites, будущим сессиям, обязательности и завершениям. Полезный прирост ограничен gain, max_level и оставшимся разрывом. Ранжирование взвешенное: критичность 0.35, разрыв 0.30, эффект 0.20, история 0.15. Покрытие = Σmin(текущий, требуемый) / Σтребуемый. Объяснения строятся из детерминированных шаблонов, опциональный адаптер локального Ollama добавляет пояснение с резервным ответом.

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

  • rule-based фильтрация активностей
  • взвешенное ранжирование 0.35/0.30/0.20/0.15
  • метрика покрытия траектории
  • PBKDF2-HMAC-SHA256
  • CSRF
  • одноразовые приглашения (SHA-256)

Особенности

Прозрачная формула без ML и зависимостей, с раскрываемым пояснением «Как рассчитана оценка». Подготовлены проверочные профили жюри (JURY_A/B/C) с ожидаемым TOP-3. Защита от повторного начисления и регистрация только по одноразовому приглашению.

Стек

Python · http.server · SQLite · HTML/CSS/JS · unittest

Модели

Ollama (локальная модель, опционально)


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

README

README.md

Career Quest

1. Название проекта

Career Quest — платформа карьерного развития для хакатона HackAlem AI.

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

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

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

  • Вход сотрудника и HR с разграничением доступа на сервере.
  • Профиль: роль, грейд, навыки, история и покрытие требований карьерной цели.
  • До трёх рекомендаций: компактные блоки цели, разрыва, эффекта и истории; полное объяснение раскрывается отдельно.
  • Раскрытие всех навыков и истории, поиск сотрудников в HR-обзоре.
  • Отметка выполнения с обновлением навыков, истории и рекомендаций; сохранение в SQLite.
  • HR-обзор: дефициты навыков, сотрудники без следующего шага, неактивность и участие.
  • Расширенный список HR: рекомендации, последняя активность, основной skill gap и статус развития.
  • Импорт employees.json, events.json, skills.json и activity_history.csv через HR-интерфейс.
  • Регистрация сотрудников по одноразовому персональному приглашению HR для конкретного профиля.
  • Получение истории сотрудника через отдельный защищённый API endpoint.
  • Автоматические проверки и демонстрационные профили с ожидаемыми результатами.
  • Опциональный адаптер локальной LLM для дополнительного объяснения с резервным ответом.

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

  1. При первом запуске сервер загружает синтетический kit из ai/data в SQLite. HR может добавлять проверочные профили и историю через импорт и создавать одноразовое приглашение, привязанное к конкретному сотруднику.
  2. Сотрудник входит и открывает свой профиль. Движок определяет карьерную цель и восстанавливает уровни навыков с учётом завершённых активностей.
  3. Движок сравнивает навыки с требованиями цели, отбирает доступные активности и ранжирует их по четырём факторам.
  4. Интерфейс показывает до трёх шагов: причину выбора, текущий и прогнозируемый уровень навыка, требуемый уровень и историю участия.
  5. После отметки выполнения сервер сохраняет результат и пересчитывает прогресс. HR видит обновлённую сводку по сотрудникам.

Расчёт рекомендаций

Чистая функция ai.recommendation.recommend выбирает 0–3 доступных события. Проверяются роль/грейд, prerequisites, будущая сессия, обязательность, завершения и текущие участия. Полезный прирост ограничен gain, max_level и оставшимся разрывом. Критичность, разрыв, эффект и история имеют веса 0.35/0.30/0.20/0.15. Это прозрачный алгоритм по правилам, а не обученная модель. Подробная схема, формула и интерфейс: ai/README.md.

Доля покрытия траектории = сумма min(текущий, требуемый) по целевым навыкам / сумма требований × 100. Это не вероятность повышения, а покрытие требований. Прогнозируемый прирост не записывается до добровольной отметки о выполнении.

5. Технологии

КомпонентРеализация
BackendPython 3.9+, стандартный http.server.ThreadingHTTPServer, JSON API
ХранениеSQLite через стандартный модуль sqlite3
FrontendHTML, CSS, JavaScript, браузерный Fetch API; без сборщика и UI-фреймворка
AI-слойСобственный алгоритм правил и взвешенного ранжирования на Python
ОбъясненияДетерминированные русскоязычные шаблоны
Опциональная LLMHTTP-адаптер Ollama на localhost; конкретная модель не поставляется
ДоступCookie-сессии, CSRF, хеширование паролей PBKDF2-HMAC-SHA256
ТестированиеСтандартный unittest

Для основного сценария внешние библиотеки, облачные API и ключи не нужны. Веса рекомендателя заданы вручную; обученной ML-модели в репозитории нет.

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

Браузер: index.html + app.js + styles.css
    → HTTP / JSON + cookie + CSRF
Backend/main.py: маршруты, сессии, права доступа
    → Backend/store.py: профили, выполнение, импорт, HR-сводка
        → SQLite: сохранённые профили и история
        → ai/profile.py: навыки и карьерная траектория
        → ai/recommendation.py → scoring.py + explain.py

Первоначальные данные: ai/data → Backend/store.py → SQLite
Дополнительное объяснение: /explanations → ai/local_llm.py → локальный Ollama

Интерфейс и API обслуживаются одним сервером с одного адреса. Рекомендатель получает данные от слоя хранения и возвращает структурированный результат; сам модуль ai не записывает данные в базу.

ai/                 Движок, объяснения, траектория и неизменённый kit
Backend/main.py     HTTP, сессии, права, API, локальная раздача frontend
Backend/store.py    SQLite, выполнение, импорт, HR-агрегаты
index.html          Вход, профиль, рекомендации, HR и импорт
app.js, styles.css  Интерфейс команды, подключённый к API
tests/              Интеграционные тесты
.local/             Состояние и доступы конкретного запуска; игнорируется Git

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

Шаг 1. Получить код

Нужны Git, доступ к репозиторию команды и Python 3.9+ с SQLite. Финальная интегрированная версия находится в ветке main; ai содержит ту же сборку.

git clone --branch main https://github.com/BAITC-Hacks/hack-edd3c6c3-kvaslovers.git
cd hack-edd3c6c3-kvaslovers
python3 --version

Если репозиторий уже клонирован, откройте актуальную ветку main в своей рабочей копии.

Шаг 2. Запустить сервер и войти

Нужен Python 3.9+ с SQLite (обычная установка Python). Внешних Python-пакетов, Node.js, сборки frontend и ключей облачных сервисов для основного сценария не нужно.

Из корня клонированного репозитория:

python3 -m Backend.main

Откройте http://127.0.0.1:8000. Не открывайте index.html как файл. На Windows вместо python3 можно использовать py -3.

При первом запуске создаются локальная база .local/career_quest.sqlite3 и случайные учебные пароли в .local/credentials.json. Откройте этот файл в VS Code либо выполните в другом терминале:

cat .local/credentials.json

Доступы:

  • hr: все профили, HR-аналитика, импорт проверочных данных;
  • E0002, E0004, E0151: каждый видит только свой профиль и историю.

Логины не являются паролями. Пароли не прописаны в коде и не отправляются в Git. Исходный dataset не изменяется. Прогресс сохраняется после перезапуска сервера. Сессии истекают через 8 часов и не сохраняются после остановки сервера.

Новая учётная запись сотрудника создаётся только по одноразовому приглашению, которое HR выдаёт из списка сотрудников. Код привязан к одному employee_id, истекает через 7 дней, хранится в базе только как SHA-256 и погашается при регистрации. Публичного списка свободных профилей нет. Для регистрации нового аккаунта HR задайте переменную CAREER_QUEST_HR_REGISTRATION_CODE до запуска и используйте её как отдельный код приглашения HR.

CAREER_QUEST_HR_REGISTRATION_CODE=private-invite-code python3 -m Backend.main

Для отдельного чистого прогона без удаления текущего прогресса:

python3 -m Backend.main --port 8001 --db .local/rehearsal/state.db

Это отдельная база и отдельный файл паролей .local/rehearsal/credentials.json. По умолчанию сервер слушает localhost. Для устройств в одной доверенной сети:

python3 -m Backend.main --host 0.0.0.0 --port 8000

На другом устройстве откройте http://<локальный-IP-сервера>:8000. Компьютер с сервером должен оставаться включённым; брандмауэр и сеть должны разрешать соединение. Это общий экземпляр с одной базой. Межустройственная проверка сети пока не проводилась. Публичный HTTPS deployment не настроен.

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

Начните с новой базы без предыдущих выполнений: числовые ожидания ниже относятся к исходным данным. Команда отдельного прогона приведена в разделе запуска.

  1. Войти как E0002: Middle → Senior, покрытие требований 62%.
  2. Показать System Design Fundamentals (EV_005, score 0.6120): два критических навыка, API Design и System Design, 1 → 2, требуется 4. Раскрыть «Как рассчитана оценка»: критичность, разрыв, эффект и история.
  3. Нажать «Отметить выполненной»: покрытие становится 66%, появляется запись истории; новые рекомендации учитывают достигнутые уровни. Обновить страницу — изменения сохраняются. Повторный HTTP-запрос не начисляет прирост повторно.
  4. Выйти и войти как hr. Открыть «Обзор команды»: дефициты навыков, сотрудники без шага, отсутствие добровольных завершений за 90 дней, участие по всем 40 активностям и всем статусам.
  5. Загрузить docs/jury-sample/employees.json и docs/jury-sample/activity_history.csv через форму HR. Полный набор также принимает events.json и skills.json. Можно вставить содержимое в поля. Открыть импортированные профили:
    • JURY_A: три неявки Public Speaking, но критичен System Design; ожидаемый TOP-3: EV_006, EV_005, EV_007;
    • JURY_B: переход Data Analyst → Product Manager; ожидаемый TOP-3: EV_026, EV_021, EV_027;
    • JURY_C: требования закрыты, корректное пустое состояние.
  6. Проверить приватность: в аккаунте сотрудника нет HR-вкладки и выбора чужих профилей; прямой запрос к чужому ID также возвращает 403. Без персонального приглашения зарегистрироваться на существующий employee_id нельзя; HR может выдать одноразовый код из списка команды.

Ещё три исходных примера: python3 -m ai.demo, сценарий в ai/demo/README.md. CLI читает исходный kit, веб-приложение — сохранённую SQLite-базу. После отметок о выполнении веб-результаты закономерно отличаются от исходного CLI.

Автоматические проверки

python3 -m unittest discover -v
python3 -m ai.demo

Проверяются 200 исходных профилей, сложные случаи ранжирования, права, HTTP API, регистрация и защита персонального приглашения, история, загрузка четырёх файлов, транзакции, одновременное выполнение, перезапуск базы, импорт/откат, HR-агрегаты и fallback модели. Тестовые базы создаются во временных папках.

Матрица требований: docs/ACCEPTANCE.md.

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

Источник — предоставленный синтетический Career Quest kit в ai/data:

ФайлСодержимое
employees.json200 профилей сотрудников
events.json40 активностей, правила gain и max_level, условия участия
skills.json60 навыков и 32 профиля требований ролей/грейдов
activity_history.csv2743 записи истории участия

Дата среза — 2026-10-01. Исходный kit сохраняется без изменений; пользовательские изменения записываются в локальную SQLite-базу. Описание формата: ai/data/README.ru.md. Дополнительные демонстрационные данные: docs/jury-sample.

Данные синтетические и предназначены для хакатона. Сервер не раздаёт исходный kit, SQLite и файл паролей через статические маршруты. Облачные сервисы для работы приложения не используются; опциональный Ollama вызывается локально.

Импорт жюри

Доступен только HR. Полный набор загружается через POST /api/datasets/upload и содержит employees.json, events.json, skills.json и activity_history.csv. JSON передаётся объектами, CSV — текстом. Также поддерживается частичный импорт профилей и истории через POST /api/import. UI принимает файлы или вставленный текст, но не оба источника одного типа.

Новые employee_id добавляются, существующие профили обновляются; история объединяется по record_id. Повторная загрузка одинаковых записей безопасна. События и навыки заменяются только при совпадающей дате среза и совместимости с сохранёнными профилями, целями и историей. Каталоги и данные применяются одной SQLite-транзакцией. Список HR содержит наличие рекомендации, дату активности, основной skill gap, статус развития и прогресс. Сводка включает active employees, completion rate, средний прогресс, сотрудников без рекомендации и без активности. Конфликтующий record_id, неизвестная роль/навык/событие, неверный уровень, статус или дата отклоняют весь импорт с 422, без частичных изменений. Дата meta должна совпадать со срезом. Лимит запроса 4 MB, до 1000 профилей и 20000 записей за импорт. Профиль с уже сохранёнными выполнениями нельзя перезаписать другим снимком — используйте новый ID для проверочного профиля. Новые профили доступны HR; импорт не создаёт учётные записи и не даёт права HR.

API приложения

Все данные требуют cookie-сессию; исключения — статические файлы и /health.

МетодURLНазначение
POST/api/login{username, password} → user и csrf; HttpOnly cookie
GET/api/meТекущая сессия, csrf и дата среза
POST/api/logoutОтзыв сессии
GET/api/employeesHR: расширенный список всех; сотрудник: только свой профиль
GET/api/employees/{id}Профиль, траектория, история, рекомендации
GET/api/employees/{id}/historyИстория участия с проверкой доступа к профилю
GET/employees/{id}/recommendationsСовместимый endpoint движка; также с префиксом /api
POST/api/employees/{id}/complete{event_id} → изменения, прогресс до/после, новый профиль
GET/api/hr/summaryДефициты, active employees, прогресс, completion rate, отсутствие рекомендаций/активности
POST/api/import{employees, history}; history — CSV-строка или массив записей
POST/api/datasets/uploadПолный набор {employees, events, skills, activity_history}
POST/api/registerАккаунт employee по персональному приглашению или HR по invite code
POST/api/employees/{id}/registration-inviteHR создаёт одноразовый код для регистрации профиля
POST/api/employees/{id}/explanationsОпциональная локальная LLM с fallback

POST требует JSON и X-CSRF-Token из ответа login/me, кроме самого login. 401 — нет сессии; 403 — чужой профиль/HR/CSRF/неверное приглашение; 404 — неизвестный ID; 409 — недоступное выполнение; 422 — ошибка данных. Ошибки имеют {error: ...}. Для сотрудника неизвестный чужой ID возвращает 403, не раскрывая существование чужого профиля; HR для неизвестного ID получает 404.

Локальная LLM (опционально)

Факторы и исходные объяснения работают без LLM. Добавлен реальный HTTP-адаптер к локальному Ollama 127.0.0.1:11434/api/generate, согласно официальному API. Если Ollama уже установлена и модель загружена, задайте имя вашей локальной модели:

CAREER_QUEST_OLLAMA_MODEL=your-local-model python3 -m Backend.main

Кнопка «Дополнить объяснение локальной LLM» передаёт только выбранные события, навыки и агрегированную историю, без имени/ID сотрудника. Облачного API нет. На весь запрос отведено до 7 секунд; ошибка/некорректный ответ/тайм-аут оставляют детерминированное объяснение. LLM-текст подписан как дополнительный и не меняет оценки или навыки. Тесты проверяют протокол адаптера и fallback; живой вывод модели на машине без Ollama не проверен. Базовый рекомендатель не выдаётся за работающую LLM. Уточнение необходимости конкретной модели остаётся вопросом трактовки AI-слоя организаторами.

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

  • Реализован локальный учебный стенд: нет корпоративного SSO и TLS-терминации.
  • Геймификация, награды, календарь и прогноз оттока не реализованы.
  • Интерфейс и объяснения — на русском; локализации на английский и казахский пока нет.
  • Обучения на бизнес-результатах нет; веса ранжирования — эвристика. Покрытие навыков не является вероятностью или гарантией повышения.
  • Реальный вывод локальной LLM не проверен: модель не поставляется с проектом. Проверены протокол адаптера и резервное объяснение при ошибке/тайм-ауте.
  • Импорт не создаёт учётные записи. Регистрация HR требует кода организации; персональные коды для сотрудников нужно передавать по безопасному каналу.
  • Проверены собственные дополнительные профили, а не неизвестный набор жюри.
  • Измерения задержки относятся к локальной конфигурации и исходному kit, а не к произвольной нагрузке. Результаты и условия — в docs/ACCEPTANCE.md.

Правила учебного стенда

  • Время фиксировано на дате kit 2026-10-01. Кнопка выполнения моделирует результат на эту дату, даже если предложенная сессия позже; это явно подписано.
  • Завершения после последней оценки сначала учитываются в фактических уровнях. При новом выполнении материализуется полный снимок навыков и переносится граница снимка (skill_snapshot_date). Дата реальной оценки сохраняется; исторические приросты не учитываются дважды.
  • Повторный клуб EV_036 разрешён, но один зачёт на дату среза. Прочие добровольные активности после завершения не повторяются.
  • Явная карьерная цель имеет приоритет над следующим грейдом своей роли. Для Lead без цели используются требования Lead. Это решения продукта, а не обещания о реальном повышении.
  • Для self-paced в исходном CSV нет даты завершения: используется доступная дата записи, что ограничивает точность восстановления старых уровней.
  • Пустой список допустим, если подходящих мероприятий нет. HR отдельно видит таких сотрудников. Нерелевантные активности не добавляются ради количества.

11. Deployed-версия

Ссылка на публичную deployed-версию в текущем репозитории не указана. После локального запуска приложение доступно по адресу http://127.0.0.1:8000. Этот адрес работает только на компьютере, где запущен сервер, и не является ссылкой на публичный deployment.

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

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

Karis_Senpai 13Gaemon 11Адилет Досаев 7Akylbek Daniyal 4

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

  • 2026-09-23 17:57Publish integrated application on main retaining frontendАдилет Досаев
  • 2026-09-23 17:56Integrate final Career Quest app with protected registration and verified UIАдилет Досаев
  • 2026-09-23 17:34Save early frontend API integration draftAkylbek Daniyal
  • 2026-09-23 17:21Merge backend integration into backKaris_Senpai
  • 2026-09-23 17:05Merge origin/ai and secure employee registrationKaris_Senpai
  • 2026-09-23 16:57Publish final hackathon README on mainАдилет Досаев
  • 2026-09-23 16:36Complete backend data import and employee analyticsKaris_Senpai
  • 2026-09-23 16:35Polish frontend profile and directory interactionsAkylbek Daniyal
Все коммиты (35)
  • 2026-09-23 16:29Document Career Quest against hackathon README requirementsАдилет Досаев
  • 2026-09-23 16:27Complete employee and HR frontend flowsAkylbek Daniyal
  • 2026-09-23 15:51Complete Career Quest web app integrationKaris_Senpai
  • 2026-09-23 15:41Build complete Career Quest app with progress, HR view and protected importsАдилет Досаев
  • 2026-09-23 15:22Merge branch 'back' into frontKaris_Senpai
  • 2026-09-23 15:21Integrate frontend with backend API routesGaemon
  • 2026-09-23 15:16Add backend API integrated with AI recommenderKaris_Senpai
  • 2026-09-23 15:14Connect frontend to employee and AI recommendation APIGaemon
  • 2026-09-23 15:09Remove frontend file from main: app.jsGaemon
  • 2026-09-23 15:09Remove frontend file from main: styles.cssGaemon
  • 2026-09-23 15:09Remove frontend file from main: index.htmlGaemon
  • 2026-09-23 15:08Add Career Quest frontend: app.jsGaemon
  • 2026-09-23 15:08Add Career Quest frontend: styles.cssGaemon
  • 2026-09-23 15:08Add Career Quest frontend: index.htmlGaemon
  • 2026-09-23 15:07Merge remote-tracking branch 'origin/main' into aiАдилет Досаев
  • 2026-09-23 15:04feat : implement appAkylbek Daniyal
  • 2026-09-23 15:00Add Career Quest frontend: app.jsGaemon
  • 2026-09-23 15:00Add Career Quest frontend: styles.cssGaemon
  • 2026-09-23 15:00Add Career Quest frontend: index.htmlGaemon
  • 2026-09-23 14:29Complete AI implementation merge and add test fileKaris_Senpai
  • 2026-09-23 14:15Add Career Quest recommendation engine and dataset testsАдилет Досаев
  • 2026-09-23 14:10finallyKaris_Senpai
  • 2026-09-23 14:08testKaris_Senpai
  • 2026-09-23 14:07test cleaningKaris_Senpai
  • 2026-09-23 14:05Rename directory from src to coreKaris_Senpai
  • 2026-09-23 13:59Merge remote changesKaris_Senpai
  • 2026-09-23 13:55Fix embedded repository and add all filesKaris_Senpai
Структура репозитория (38 файлов)
.gitignore
Backend/.gitignore
Backend/README.md
Backend/__init__.py
Backend/main.py
Backend/store.py
FRONTEND.md
README.md
ai/.gitignore
ai/README.md
ai/__init__.py
ai/__main__.py
ai/data.py
ai/data/README.kz.md
ai/data/README.md
ai/data/README.ru.md
ai/data/activity_history.csv
ai/data/employees.json
ai/data/events.json
ai/data/skills.json
ai/demo.py
ai/demo/README.md
ai/demo/results.json
ai/explain.py
ai/local_llm.py
ai/profile.py
ai/recommendation.py
ai/scoring.py
ai/test_recommendation.py
app.js
docs/ACCEPTANCE.md
docs/TEAM_HANDOFF.md
docs/jury-sample/activity_history.csv
docs/jury-sample/employees.json
index.html
styles.css
tests/__init__.py
tests/test_application.py
Ветки (7)

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

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

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