Career Quest
Веб-приложение для сотрудника и HR: 1–3 добровольных шага развития с обоснованием, прогресс к карьерной цели, AI-помощник по карьере и HR-обзор…
О проекте
Команда: Flower Power
Кейс HackAlem.ai: Менеджмент — Halyk Bank · кейс 1
Стадия: Доведённый продукт
Задача кейса: «Career Quest»: AI-навигатор, связывающий навыки сотрудника с шагами развития
Суть
Веб-приложение для сотрудника и HR: 1–3 добровольных шага развития с обоснованием, прогресс к карьерной цели, AI-помощник по карьере и HR-обзор отстающих навыков.
Как устроено
Из четырёх файлов датасета (профили, требования ролей по грейдам, каталог активностей, история участия) считаются текущие навыки: последняя оценка плюс приросты завершённых после неё активностей. Кандидаты фильтруются по пререквизитам и доступности, затем ранжируются прозрачной взвешенной формулой (критичный/требуемый разрыв, грейд, цель, пропуски в истории, вовлечённость, отзывы, доступность, длительность). В выдачу попадает рекомендация, которая закрывает разрыв и опирается минимум на 3 ненулевых фактора. LLM (OpenAI Responses API со строгой JSON-схемой) только формулирует объяснения и ответы помощника по рассчитанным фактам, а код проверяет ID и числа. Без ключа работает офлайн-фолбэк.
Ключевые решения
- взвешенный скоринг факторов (WEIGHTS)
- OpenAI Responses API structured outputs (strict JSON schema)
- проверка чисел/ID в ответе LLM
- профили-ловушки для тестов
- ролевой доступ сотрудник/HR
Особенности
Ранжирует формула, которую можно проверить, а не LLM. Демо-профили-ловушки показывают, где наивное правило «подтяни самый слабый навык» проигрывает. Если подходящего шага нет, сотрудник попадает в HR-список «нет следующего шага», и система ничего не выдумывает. Цель меняется только после подтверждения кнопкой. Помощник на RU/KK/EN.
Стек
Python 3.12 · FastAPI · Uvicorn · Pydantic 2 · vanilla JS/HTML/CSS · structlog · pytest · ruff · mypy · uv · Docker · Docker Compose · GitHub Actions
Модели
gpt-4.1-mini
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-ce23e8c4-flower-power.
README
README.md🌱 Career Quest — команда Flower Power
HackAlem AI · трек Halyk Bank · кейс Career Quest.
1. Кратко о проекте
Проблема. Сотрудник видит длинный каталог обучения, но не понимает, какой шаг приблизит его к следующему грейду или к желаемой роли. HR видит отдельные записи об обучении, но не картину по навыкам команды. Простое правило «подтяни самый слабый навык» ошибается: этот навык может быть не нужен для цели, человек мог уже несколько раз пропускать такие занятия, а оценка навыков могла устареть.
Для кого:
- сотрудник — получает 1–3 добровольных шага развития с понятной причиной и видит свой прогресс к цели;
- HR — видит, какие навыки отстают чаще всего, у кого нет подходящего следующего шага и как сотрудники участвуют в активностях.
2. Что реализовано
- Рекомендации 1–3 добровольных активностей с обоснованием минимум из трёх факторов: разрывы до требований цели, критичные навыки, грейд, карьерная цель, история участия (пропуски, завершения, оценки), доступность и длительность.
- Понятный карьерный путь: у каждого сотрудника — в списке и в шапке профиля — видно, кто он сейчас и кем хочет стать (своя цель, в том числе в другой профессии) или какой у него следующий уровень.
- Учёт актуальных навыков: к уровням из последней оценки добавляются приросты активностей, завершённых после неё.
- Отметка о прохождении: уровни навыков, прогресс к цели и рекомендации пересчитываются сразу.
- Карьерный AI-помощник (отдельный чат внутри каждой карточки занятия): разбирает недостающие навыки, объясняет рекомендации, подбирает альтернативы и предлагает карьерную цель из справочника ролей. Понимает русский, казахский и английский, учитывает последние шесть сообщений. Цель меняется только после подтверждения кнопкой.
- AI-объяснение рекомендации на русском, казахском или английском — только из рассчитанных фактов.
- Геймификация без давления: кольцо прогресса к цели, «+N% к цели» на каждой рекомендации, квест по навыкам ниже цели, 7 личных достижений, иконки уровня 🌱 🌿 🌸. Рейтингов и сравнения с коллегами нет.
- HR-обзор: отстающие навыки, сотрудники без следующего шага, участие и доля завершений по активностям.
- Роли и доступ: сотрудник видит только свой профиль, HR — агрегаты и профили; цель меняет только сам сотрудник. Без настроек — помеченный демо-режим.
- Загрузка данных жюри (доп. профили и история или полный набор из четырёх файлов) и экспорт ZIP-снимка.
- Три проверочных профиля-ловушки в
demo/, на которых правило «самый слабый навык» проигрывает.
3. Как работает решение
-
Входные данные — четыре файла датасета: профили сотрудников, требования ролей по грейдам, каталог активностей, история участия.
-
Текущие навыки = уровни из последней оценки + приросты активностей, завершённых после неё (с учётом
max_level, в порядке дат). -
Цель =
career_goalсотрудника (в том числе в другой роли) или следующий грейд своей роли; для Lead без цели — текущий профиль. Сотрудник может выбрать новую цель через AI-помощника. -
Кандидаты — только добровольные активности для роли и грейда сотрудника или цели, с выполненными пререквизитами, с сессией в будущем или в своём темпе. Пройденные не повторяются (кроме клуба
EV_036). -
Оценка — взвешенная сумма факторов (веса в
WEIGHTS,career_quest/scoring.py):Фактор Вес Смысл critical_gap+3.0 за уровень закрывает критичный навык цели required_gap+1.5 за уровень закрывает другой требуемый навык цели target_alignment+1.0 активность рассчитана на целевую роль и грейд grade_fit+0.5 активность для текущего грейда, база для следующего goal_alignment+0.5 служит явной карьерной цели сотрудника history_avoidance−1.0 / −0.5 за запись пропуски, отказы, брошенные активности по тем же навыкам / того же типа engagement+0.5 за завершение (до 2), +0.25 завершал похожие активности, в том числе по своей инициативе feedback±0.5 средняя оценка похожих активностей ≥ 4 или ≤ 2 availability+0.5 в своём темпе или сессия в ближайшие 14 дней duration−0.05 за час сверх 8 длинные программы чуть ниже -
Результат — до трёх рекомендаций, каждая закрывает хотя бы один разрыв к цели, имеет положительную сумму и не меньше трёх ненулевых факторов. Если подходящей активности нет, сотрудник попадает в HR-список «нет следующего шага» — система не выдумывает шаг.
-
Прогресс — отметка «пройдено» добавляет запись
completedна дату среза; повторная отметка той же активности в тот же день отклоняется.
«Сегодня» для системы — дата среза датасета 2026-10-01, а не системные часы.
Где AI, а где формула
Выбор и ранжирование активностей делает прозрачная формула: её можно проверить по цифрам. AI работает с языком на основе рассчитанных фактов:
- Карьерный помощник (
career_quest/assistant.py). Сервер проверяет доступ,scoring.pyсчитает навыки, разрывы и рекомендации. LLM получает эти факты, каталог ролей, вопрос и до шести предыдущих сообщений и выбирает одно действие: разобрать пробелы, объяснить, предложить альтернативы, предложить цель, уточнить вопрос или вернуть разговор к карьерной теме. Модель формулирует короткий ответ на вопрос; код проверяет идентификаторы и числа. Исходные расчёты доступны отдельно. Эти проверки не гарантируют смысловую точность каждого утверждения. Приветствия обрабатываются без API; режим языка «Авто» учитывает язык сообщения. Внутренние коды навыков и занятий в тексте ответа заменяются понятными названиями. Предложение цели используетcareer_quest/coach.py: роль и грейд только из справочника, это задано строгой JSON-схемой и повторно проверяется в коде. - AI-объяснение (
career_quest/explain.py) получает только рассчитанные факторы; ответ проверяется — каждое утверждение ссылается на свой фактор и сохраняет его числа, идентификаторы и грейды. - Без ключа или при ошибке (ключ, доступ, квота, сеть, невалидный ответ) показывается причина и явно помеченный локальный ответ без LLM.
Подробнее — docs/ai-assistant.md.
4. Технологии
| Слой | Что используется |
|---|---|
| Язык | Python 3.12 (сервер и логика), JavaScript, HTML, CSS (клиент) |
| Сервер | FastAPI, Uvicorn, python-multipart (загрузка файлов) |
| Модели данных | Pydantic 2 |
| Веб-клиент | собственный интерфейс без фреймворков и сборки: web/index.html, web/styles.css, web/app.js |
| AI | OpenAI Responses API со строгой JSON-схемой, модель по умолчанию gpt-4.1-mini (меняется через OPENAI_MODEL), store: false |
| Логирование | structlog |
| Качество | pytest (122 теста), Node.js node:test (5 тестов клиента), ruff, mypy (strict), httpx |
| Запуск | uv, Docker, Docker Compose; workflow GitHub Actions .github/workflows/ci.yml |
5. Архитектура
Браузер (web/: HTML + CSS + JS)
│ fetch JSON, cookie сессии
▼
career_quest/api.py — FastAPI: сессии, роли, JSON API, раздача web/
│
├── scoring.py текущие навыки, цель, кандидаты, факторы, рекомендации, завершение
├── quest.py прогресс к цели, квест, личные достижения
├── assistant.py карьерный помощник ─────┐
├── coach.py цель из свободного текста ┴─► llm.py ─┐
├── explain.py AI-объяснение ────────────────────────┴─► OpenAI Responses API (если задан ключ)
├── factor_text.py русский текст факторов
├── labels.py русские названия
├── access.py роли сотрудник/HR, демо-режим
├── snapshot.py импорт доп. профилей / полного набора, экспорт ZIP
└── data.py + models.py загрузка и проверка четырёх файлов датасета (data/)
- Каждая сессия браузера получает на сервере свою копию данных и диалога: отметки о прохождении и смена цели не видны другим сессиям и переживают перезагрузку страницы.
- Доступ проверяется на сервере: сотрудник открывает только свой профиль, HR-отчёты и загрузка данных доступны только HR, помощник и смена цели — только самому сотруднику.
6. Установка и запуск
Нужен Docker или uv (Python 3.12 uv установит сам).
git clone https://github.com/BAITC-Hacks/hack-ce23e8c4-flower-power.git
cd hack-ce23e8c4-flower-power
# (необязательно) ключ OpenAI для помощника и AI-объяснений
cp .env.example .env # затем впишите OPENAI_API_KEY=...
# Вариант 1: Docker (читает .env сам)
docker compose up --build # http://localhost:8501
# Вариант 2: локально
uv sync
uv run --env-file .env uvicorn career_quest.api:app --host 127.0.0.1 --port 8501 # http://localhost:8501
- Без
.envлокально:uv run uvicorn career_quest.api:app --host 127.0.0.1 --port 8501. Без ключа всё работает офлайн. - После изменения
.envперезапустите сервер: при обычномuvicornфайл не загружается автоматически. - Наличие ключа не гарантирует доступ к модели: результат проверяется при каждом запросе.
- Если порт 8501 занят другим приложением:
CQ_PORT=8600 docker compose up --build— приложение откроется на http://localhost:8600. Внутри контейнера порт всегда 8501, поэтому на разных компьютерах конфликтов нет.
| Переменная | Зачем |
|---|---|
OPENAI_API_KEY | Включает AI в помощнике и объяснениях. Пусто — локальные ответы и объяснения из факторов |
OPENAI_MODEL | Модель, по умолчанию gpt-4.1-mini |
CQ_EMPLOYEE_ID, CQ_EMPLOYEE_PASSWORD, CQ_HR_PASSWORD | Включают вход по паролю; сотрудник видит только свой профиль. Задаются все три вместе. Пусто — демо-режим |
CQ_DATA_DIR | Другой каталог с данными (по умолчанию data/) |
CQ_PORT | Порт для Docker (по умолчанию 8501) |
Документация API (Swagger): http://localhost:8501/api/docs.
7. Как проверить решение
Сценарий на 5–7 минут, всё в браузере на http://localhost:8501:
-
Сотрудник. «Я сотрудник» → «Войти». Под именем — «Сейчас → Хочу стать». В шапке — кольцо прогресса к цели, обязательные навыки ниже цели, рост после оценки, достижения.
-
Помощник. Нажмите «Спросить у AI» на карточке занятия и спросите «Каких навыков мне не хватает?», затем «Почему выбран этот курс?» и «А есть другой вариант?». Напишите «хочу через год стать тимлидом в аналитике» — помощник предложит цель; профиль меняется только после кнопки «Сделать целью и пересчитать шаги».
-
Рекомендации. У карточки: «+N% к цели», навыки, которые вырастут, и факторы со знаком «+»/«−» и числами, например «Лидерство: 2 → 3, для цели нужно 4 (обязательный навык)». Кнопка «Спросить у AI» открывает чат именно об этом занятии; открытие не вызывает модель.
-
Прогресс. «Отметить как пройдено» → навыки растут, кольцо и шаги пересчитываются; за новое достижение — конфетти. Повторное нажатие в тот же день недоступно.
-
Ловушки. «выйти» → «Я HR» → «Данные» → загрузите
demo/trap_employees.jsonиdemo/trap_history.csv. В списке появятсяTRAP_1…3:Профиль Самый слабый навык Почему он не первый Первая рекомендация TRAP_1Public Speaking = 0 три пропуска таких активностей, а System Design критичен для Senior EV_006, System Design TRAP_2Cloud = 0 цель — Data Analyst Senior, для неё критичны A/B-тесты и статистика EV_021, A/B + статистика TRAP_3Public Speaking = 0 в оценке после оценки два занятия клуба подняли навык до требования EV_006, System Design Файлы жюри в том же формате загружаются через ту же форму.
-
HR-обзор. «Обзор HR»: отстающие навыки, «нет подходящего следующего шага», участие по активностям. В профиле сотрудника у HR нейтральный текст и нет помощника.
Расширенные проверки помощника (смена темы, смешанный язык, посторонний вопрос, работа без ключа) — в docs/ai-assistant.md.
Автоматические проверки:
uv run ruff format --check . && uv run ruff check . && uv run mypy . && uv run pytest
node --test tests/web_app.test.cjs
8. Данные и интеграции
- Датасет организаторов (
data/, описание вdata/README.md), синтетический: 200 сотрудников, 40 активностей (4 обязательные — никогда не рекомендуются), 2743 записи участия, 60 навыков, 8 ролей × 4 грейда. - Проверочные профили
demo/trap_employees.json,demo/trap_history.csv— в том же формате. - Загрузка через интерфейс (только HR): дополнительные
employees.jsonиactivity_history.csvили полный набор из четырёх файлов; экспорт текущего состояния в ZIP. - Внешний сервис — только OpenAI Responses API (
https://api.openai.com/v1/responses) и только при заданномOPENAI_API_KEY. Отправляются роль, грейд, рассчитанные пробелы и факторы рекомендаций, каталог ролей и сообщения пользователя — без имени, ID и полной истории сотрудника. Один вопрос — не больше одного запроса без автоматических повторов, ответ помощника ограничен 700 токенами, ожидание — 8 секунд, не больше 40 AI-вызовов на веб-сессию. Других интеграций нет; интерфейс не загружает внешних шрифтов и скриптов.
9. Ограничения
- Прогресс и диалог хранятся в памяти сервера. Переживают перезагрузку страницы, но сбрасываются при перезапуске сервера. Сохранить данные: «Данные» → «Скачать снимок (ZIP)», восстановить — «Заменить весь набор данных».
- Лимит 40 AI-вызовов считается на сессию и сбрасывается новой сессией — это не денежный лимит аккаунта.
- Помощник может ошибиться в выборе действия. Структура ответа и ссылки на данные проверяются кодом, но качество понимания живой моделью тестами с подставными ответами не доказывается. Локальный режим без LLM использует простые признаки запроса и может попросить уточнение.
- Строгая проверка AI-объяснений иногда отклоняет ответ модели, если в нём изменилось хоть одно число; тогда показываются рассчитанные факторы.
- Вход упрощённый. Пароль сотрудника привязан к одному
CQ_EMPLOYEE_ID— это демонстрация разделения ролей, а не корпоративная аутентификация. В демо-режиме можно открыть любой профиль. - Веса подобраны вручную под логику кейса и проверены на ловушках, а не обучены: в датасете нет меток «рекомендация была полезной».
- Каталог ограничен. Если подходящие активности пройдены или закрыты пререквизитами, рекомендаций нет — такие сотрудники видны HR.
- Интерфейс только на русском; на ru/kk/en работают помощник и AI-объяснения.
- Шкала грейдов и типы активностей заданы в коде (Junior → Middle → Senior → Lead).
- Данные синтетические, реальных людей нет.
10. Deployed-версия
Публичной развёрнутой версии нет. Решение запускается локально одной командой: docker compose up --build.
11. Развитие
- Другие организации. Логика не зависит от банка: нужны четыре файла в формате датасета. Например, для госслужбы есть прямые аналоги: квалификационные требования к должностям, каталог обучения, учёт прохождения.
- Веса на реальных исходах (рост навыка на следующей оценке, повышение) при сохранении объяснимых факторов.
- Внутренняя мобильность: показывать, к какой соседней роли сотрудник уже близок.
- Локальная LLM для контуров, где данные не могут покидать организацию; без модели всё уже работает офлайн.
- Промышленная инфраструктура: корпоративный вход (SSO), хранение прогресса и диалога в базе данных, интерфейс на казахском и английском.
Команда
Flower Power: Eldana и Ayazhan.
Авторы коммитов
История коммитов
- 2026-09-23 17:40Merge pull request #30 from BAITC-Hacks/docs/final-readmesuperjklilos
- 2026-09-23 17:38docs: final README update (career path, test counts)kayindyos
- 2026-09-23 17:35Merge pull request #29 from BAITC-Hacks/feat/clear-career-pathsuperjklilos
- 2026-09-23 17:35feat: show current role and career target for every employeekayindyos
- 2026-09-23 17:27Merge pull request #28 from BAITC-Hacks/fix/chat-answer-qualitysuperjklilos
- 2026-09-23 17:26fix: Russian names and no internal codes in chat answers, formal address, no invented sourceskayindyos
- 2026-09-23 17:21fix: understand conversational turns and reply in user language (#27)withayazh
- 2026-09-23 17:07feat: ask AI directly inside activity cards (#26)withayazh
Все коммиты (58)
- 2026-09-23 17:06Merge pull request #25 from BAITC-Hacks/chore/repo-cleanupsuperjklilos
- 2026-09-23 17:04chore: ignore editor folders and document port overridekayindyos
- 2026-09-23 16:57Merge pull request #24 from BAITC-Hacks/fix/plan-polishsuperjklilos
- 2026-09-23 16:57fix: show level growth and local date in assistant plans; update spec after Streamlit removalkayindyos
- 2026-09-23 16:53Merge pull request #23 from BAITC-Hacks/chore/remove-streamlitsuperjklilos
- 2026-09-23 16:52chore: remove the unused Streamlit interfacekayindyos
- 2026-09-23 16:50fix: readable career plans and pending goal continuity (#22)withayazh
- 2026-09-23 16:47Merge pull request #21 from BAITC-Hacks/fix/assistant-fallbacksuperjklilos
- 2026-09-23 16:46fix: offline goal when AI is unavailable, one-language assistant replies, per-profile dialoguekayindyos
- 2026-09-23 16:26Merge pull request #20 from BAITC-Hacks/docs/readme-web-appsuperjklilos
- 2026-09-23 16:24merge main into docs/readme-web-app, combine README with the AI assistant sectionkayindyos
- 2026-09-23 16:19docs: restructure README to the jury checklistkayindyos
- 2026-09-23 16:18fix: grounded career dialogue and reliable AI results (#19)withayazh
- 2026-09-23 16:17docs: describe the web app, AI coach and gamification in READMEkayindyos
- 2026-09-23 16:12Merge pull request #18 from BAITC-Hacks/fix/ui-polishsuperjklilos
- 2026-09-23 16:11fix: neutral HR wording, level-based skill icons and Russian factor detailskayindyos
- 2026-09-23 15:52Merge pull request #17 from BAITC-Hacks/feat/web-appsuperjklilos
- 2026-09-23 15:51feat: add FastAPI backend and standalone web clientkayindyos
- 2026-09-23 15:47refactor: move display labels to a shared module and add FastAPI dependencieskayindyos
- 2026-09-23 15:47Merge remote-tracking branch 'origin/feat/product-ui' into feat/web-appkayindyos
- 2026-09-23 15:43feat: show goal progress per recommendation and celebrate new badgeskayindyos
- 2026-09-23 15:35Merge pull request #16 from BAITC-Hacks/feat/product-uisuperjklilos
- 2026-09-23 15:34feat: add AI career coach that sets a catalog goal from free textkayindyos
- 2026-09-23 15:32feat: add personal career quest and product-style interfacekayindyos
- 2026-09-23 15:19feat: readable career interface and skill garden (#15)withayazh
- 2026-09-23 15:04Merge pull request #14 from BAITC-Hacks/docs/readme-applicabilitysuperjklilos
- 2026-09-23 15:03docs: add applicability and roadmap section to READMEkayindyos
- 2026-09-23 14:54Merge pull request #13 from BAITC-Hacks/docs/readmesuperjklilos
- 2026-09-23 14:52docs: add README with launch, demo scenario and trap profileskayindyos
- 2026-09-23 14:42feat: add employee HR app, OpenAI explanations and Docker launch (#8)withayazh
- 2026-09-23 14:34Merge pull request #12 from BAITC-Hacks/fix/progress-edge-casessuperjklilos
- 2026-09-23 14:33fix: count app completions after same-day reviews and once per daykayindyos
- 2026-09-23 14:22Merge pull request #11 from BAITC-Hacks/feat/scoringsuperjklilos
- 2026-09-23 14:20test: add trap profiles and recommendation ruleskayindyos
- 2026-09-23 14:19feat: add employee access and jury data import (#10)withayazh
- 2026-09-23 14:18feat: add recommendation scoring and activity completionkayindyos
- 2026-09-23 14:17Merge pull request #9 from BAITC-Hacks/feat/scoringsuperjklilos
- 2026-09-23 14:16feat: add effective skills and career targetkayindyos
- 2026-09-23 13:57feat: implement validated career recommendations and progressAyazhan
- 2026-09-23 13:56Merge pull request #5 from BAITC-Hacks/docs/agent-contextsuperjklilos
- 2026-09-23 13:55docs: add project spec and shared agent contextkayindyos
- 2026-09-23 13:53Merge pull request #4 from BAITC-Hacks/feat/data-modelssuperjklilos
- 2026-09-23 13:52feat: add dataset models and loaderkayindyos
- 2026-09-23 13:38Merge pull request #3 from BAITC-Hacks/chore/project-setupsuperjklilos
- 2026-09-23 13:36chore: add project config and toolingkayindyos
- 2026-09-23 13:06Merge pull request #2 from BAITC-Hacks/docs/root-agent-rulessuperjklilos
- 2026-09-23 13:05docs: add root agent instructionskayindyos
- 2026-09-23 13:01Merge pull request #1 from BAITC-Hacks/docs/agent-guidelinessuperjklilos
- 2026-09-23 12:59docs: add agent coding and git guidelineskayindyos
- 2026-09-23 11:41Test commitkayindyos
Структура репозитория (50 файлов)
.agents/git-workflow.md .agents/guidelines.md .agents/project-spec.md .dockerignore .env.example .github/workflows/ci.yml .gitignore .python-version AGENTS.md CLAUDE.md Dockerfile README.md career_quest/__init__.py career_quest/access.py career_quest/api.py career_quest/assistant.py career_quest/coach.py career_quest/conversation.py career_quest/data.py career_quest/explain.py career_quest/factor_text.py career_quest/labels.py career_quest/llm.py career_quest/models.py career_quest/quest.py career_quest/scoring.py career_quest/snapshot.py data/README.md data/activity_history.csv data/employees.json data/events.json data/skills.json demo/trap_employees.json demo/trap_history.csv docker-compose.yml docs/ai-assistant.md pyproject.toml tests/test_access_snapshot.py tests/test_api.py tests/test_assistant.py tests/test_coach.py tests/test_data.py tests/test_explain.py tests/test_quest.py tests/test_scoring.py tests/web_app.test.cjs uv.lock web/app.js web/index.html web/styles.css
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.