Career Quest
AI-навигатор карьеры: для сотрудника показывает разрывы навыков относительно цели, предлагает 1–3 шага развития с объяснением и пересчитывает…
О проекте
Команда: baursaq
Кейс HackAlem.ai: Менеджмент — Halyk Bank · кейс 1
Стадия: Доведённый продукт
Задача кейса: «Career Quest»: AI-навигатор, связывающий навыки сотрудника с шагами развития
Суть
AI-навигатор карьеры: для сотрудника показывает разрывы навыков относительно цели, предлагает 1–3 шага развития с объяснением и пересчитывает готовность. HR видит дефициты компетенций.
Как устроено
Данные: 200 синтетических сотрудников, 60 навыков, 40 мероприятий. Эффективный уровень навыка = оценка плюс прирост от активностей после last_review_date. Готовность — взвешенное покрытие требований, у критичных вес 2. Движок фильтрует кандидатов (пререквизиты, расписание, завершения, «Не сейчас») и скорит их эвристиками по разрывам, истории и формату. План строится последовательно с симуляцией роста. LLM (OpenAI Responses API) работает в двух режимах: single выбирает и объясняет кандидатов на ru/kk/en; tools вызывает list_candidates, get_history_signals, simulate_plan. Сервер валидирует план, при сбое срабатывает fallback на движок.
Ключевые решения
- function calling
- эвристический скоринг
- симуляция плана
- readiness score
- детерминированный fallback
- trace агента
Метрики
Задержка рекомендации: single 4–7 с, tools 5.6–8.6 с; E0072 готовность 53% → 59% после шага
Особенности
Учтены «ловушки» данных: обучение после последней оценки, пререквизиты, remote+offline, срывы похожих мероприятий. Есть 5 тестовых профилей с ожидаемыми свойствами и HTTP-eval. LLM выбирает только из разрешённых движком кандидатов, все числа считает сервер.
Стек
Python · FastAPI · React 19 · TypeScript · Vite · Tailwind 4 · Docker Compose · uv · pytest
Модели
OpenAI (Responses API, модель задаётся OPENAI_MODEL)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-5fe3ca84-baursaq.
README
README.mdCareer Quest
AI-навигатор развития сотрудника · HackAlem AI 2026 · Halyk Bank, кейс 1 · команда baursaq
Career Quest связывает обучение с карьерной целью: показывает разрывы навыков, предлагает 1–3 добровольных шага, объясняет выбор и пересчитывает готовность после завершения. HR видит дефициты компетенций и участие в активностях. Публичных рейтингов сотрудников нет.
Запуск одной командой
Из корня клонированного репозитория, при запущенном Docker Engine и Docker Compose 2.24+:
docker compose up --build
Открыть http://localhost:8000. API: http://localhost:8000/api/health · Swagger: http://localhost:8000/docs. Без .env и ключа приложение запускается с детерминированным fallback. Первый запуск скачивает образы и зависимости; интернет нужен для сборки. Остановка: docker compose down.
Без Docker
Нужны Python 3.11+ (на macOS/Linux команда может называться python3), uv, Node.js ≥ 22.12 и npm в PATH:
python run.py
Скрипт выполняет uv sync --frozen, npm ci, production build и запускает FastAPI, который отдаёт также UI. python run.py --skip-build повторно использует сборку; --setup-only только устанавливает и собирает; --port 8001 меняет порт. Если 8000 занят другим приложением, остановите его либо используйте другой порт локального launcher.
Ключ и режимы
Скопировать backend/.env.example в backend/.env (PowerShell: Copy-Item backend/.env.example backend/.env; Linux/macOS: cp backend/.env.example backend/.env). Заполнить ключ локально:
OPENAI_API_KEY=<ваш ключ>
USE_MOCKS=false
AGENT_MODE=single
Модель и reasoning задаются OPENAI_MODEL / OPENAI_REASONING_EFFORT по образцу конфигурации и доступу аккаунта. Ключ не вводится во фронтенд, не включается в Docker-образ и не коммитится. Compose читает .env при старте; после изменения: docker compose up -d --force-recreate.
USE_MOCKS=true: LLM не вызывается, работает движок; удобно для бесплатной воспроизводимой проверки.AGENT_MODE=single(по умолчанию): один структурированный LLM-вызов выбирает и объясняет кандидатов движка; замеры команды — 4–7 с.AGENT_MODE=tools: модель сама выбирает и вызывает инструменты, затем возвращает структурированный план; два раунда Responses API, замеры команды — 5.6–8.6 с; ближе к лимиту 10 с, поэтому при медленном API чаще уходит в fallback — для стабильной проверки используйтеsingle.- Указанные времена — результаты демонстрационных прогонов команды, не гарантия задержки: она зависит от модели, сети и нагрузки API.
- При отсутствии ключа, таймауте или ошибке используется fallback. Смотрите поле
sourceи статус в UI; fallback не является доказательством вызова OpenAI. - В
singleпредусмотрен дополнительный OpenAI-совместимый провайдер черезFALLBACK_*. Вtoolsошибка ведёт к движку без дополнительного раунда к другому провайдеру.
Проверка жюри за 90 секунд
- 0–15 с: открыть E0072, язык RU. Показать текущую роль, цель и процент готовности. Ожидаемо без ключа: готовность 53%, первый шаг API & Performance Testing Workshop, после отметки — 59% (с LLM порядок шагов может отличаться).
- 15–40 с: «Подобрать шаги». Показать источник LLM/fallback, факторы и раскрыть trace. Назвать три основания рекомендации: целевой грейд, разрыв навыка, история/формат.
- 40–55 с: отметить первый доступный шаг пройденным; показать изменение навыков и готовности. Это прогресс обучения, не автоматическое повышение должности.
- 55–70 с: HR обзор: дефициты компетенций, участие и загрузка файлов.
- 70–90 с: в HR выбрать вместе
data/test_profiles/employees.jsonиdata/test_profiles/activity_history.csv; открыть T001 и показать, почему самый низкий навык не определяет весь план.
Дополнительные сценарии: E0052 + KK для казахского объяснения; E0028 для ловушки обучения после оценки: System Design уже включает прирост EV_006. Скриншоты и фактические результаты — проверка. Публичный деплой и резервное видео пока не подготовлены.
Как работает рекомендация
- Цель берётся из
career_goal(включая смену роли), иначе следующий грейд своей роли; Lead без цели сравнивается с текущим профилем. - Эффективный уровень = оценка навыка + прирост от активностей, пройденных после
last_review_date. Завершения учитываются в порядке дат с ограничением каждого мероприятия:new = max(current, min(current + gain, max_level)); отсутствующий навык = 0. Например, у E0028 System Design в оценке равен 2, но EV_006 завершён после оценки и даёт +1: эффективный уровень — 3. Повторно рекомендовать этот уже пройденный курс нельзя. - Готовность:
100 × Σ(weight × min(effective, required) / required) / Σ(weight)для положительных требований, округлённая до целого; вес критичных требований = 2, остальных = 1. Это покрытие требований, не вероятность повышения. - Кандидаты проходят ограничения роли/грейда, пререквизитов, расписания, завершений и отказов «Не сейчас». Mandatory исключены. Повтор завершённого курса запрещён, кроме повторяемого EV_036.
- План строится последовательно: после каждого шага симулируется рост, проверяются новые пререквизиты и пересчитываются следующие кандидаты.
- LLM выбирает из разрешённых кандидатов и формулирует объяснения на ru/kk/en; сервер проверяет план и считает все числа. Инструменты ограничены текущим сотрудником.
Веса скоринга
Источник — engine.py. Баллы складываются; это эвристика, не обученная оценка вероятности успеха.
| Фактор | Вклад |
|---|---|
| Закрытый уровень требования цели | +1.0 за уровень |
| Критичный навык цели | ещё +1.0 за закрытый уровень |
| Отставание от текущего грейда | +0.75 за закрытый уровень |
| Рост вне требований | +0.2 за уровень |
| Явная карьерная цель при закрытии разрыва | +0.2 |
| Срыв того же мероприятия | −1.0 за случай, максимум −3.0 |
| Срыв похожего мероприятия по навыку | −0.6 за случай, максимум −2.4 |
| Негативный опыт формата: ≥2 других мероприятия и ≥50% неудач | −0.8 |
| Remote + offline | −0.8 |
| Продолжительность >16 ч | −0.2 |
| ≥2 успешных добровольных активности этого типа | +0.4 |
| Средняя собственная оценка этого типа ≥4 | +0.3 |
| Добровольное завершение по тому же навыку | +0.3 |
| Активность уже in_progress | +0.6 |
| Сессия в ближайшие 21 день / self-paced | +0.2 / +0.15 |
Что делает агент
В режиме tools первый раунд модели выбирает от 1 до 6 вызовов:
list_candidates— доступные кандидаты и факторы;get_history_signals— история текущего сотрудника;simulate_plan— проверка порядка event_id и прогноз роста.
Второй раунд возвращает 1–3 шага и объяснение; третьего раунда нет. Общий бюджет LLM по конфигурации — 9 секунд, целевой предел HTTP-рекомендации — 10 секунд. Фактические вызовы записываются в trace. Режим и инструменты реализованы в agents и llm.py. В single последовательность вычислений движка также видна, но она не является выбором инструментов моделью.
Архитектура
flowchart LR
User[Сотрудник / HR] --> UI[React + TypeScript]
UI -->|/api| API[FastAPI]
API --> Store[JSON/CSV в памяти]
API --> Engine[Правила, скоринг, симуляция]
Engine --> Agent[LLM и инструменты]
Agent --> Check[Проверка плана и fallback]
API --> HR[HR-аналитика]
Store --> Engine
Store --> HR
Данные: data/career_quest — 200 синтетических сотрудников, 60 навыков, 40 мероприятий, 2743 записи истории. Дата среза 2026-10-01 используется как «сегодня». Схема датасета.
Загрузка и API
HR загружает JSON профилей и CSV истории в исходном формате; также поддерживаются events.json и skills.json. Для сотрудников, упомянутых в CSV, история заменяется содержимым файла — загружайте полную историю этих сотрудников. Всё хранится в памяти одного процесса.
| Действие | API |
|---|---|
| Статус, каталог | GET /api/health, GET /api/catalog |
| Справочник, профиль | GET /api/employees?q=, GET /api/employees/{id} |
| Рекомендации | POST /api/employees/{id}/recommendations, тело {"language":"ru"} |
| Завершение | POST /api/employees/{id}/complete, тело {"event_id":"…"} |
| «Не сейчас» | POST /api/employees/{id}/feedback, тело {"event_id":"…","action":"not_now"} |
| HR | GET /api/hr/overview |
| Загрузка / сброс | POST /api/dataset/upload (multipart files), POST /api/dataset/reset |
«Не сейчас» исключает шаг до сброса/перезапуска и не записывает наказание в историю.
Приватность и права
В демо используется переключатель ролей вместо входа через SSO, чтобы жюри могло открыть любого сотрудника и проверить сценарии ТЗ, включая загруженные тестовые профили. Все данные синтетические.
Сервер проверяет права для выбранной роли и идентификатора: запрос от сотрудника не получает чужой профиль или HR-данные. Это проверяется в test_permissions. Демо передаёт X-Role: employee|hr и X-Employee-Id: E0072; поскольку эти заголовки задаёт клиент, переключатель не подтверждает личность пользователя и не заменяет производственную авторизацию.
В продакшене — SSO/JWT с ролями: сервер получает подтверждённую личность и роль из проверенного токена, ограничивает доступ к профилям и HR-аналитике и ведёт аудит. Публичных рейтингов сотрудников нет.
Тестовые профили и проверки
Пять ловушек и ожидаемые свойства: lowest-skill/no-show, обучение после оценки, пререквизиты, remote/офлайн, отсутствие полезного шага.
# Против работающего приложения; добавляет только синтетические T001–T005
python scripts/eval_profiles.py
# Если приложение запущено на другом порту (например, python run.py --port 8011)
python scripts/eval_profiles.py --base-url http://127.0.0.1:8011
# Требует реальный LLM для четырёх непустых сценариев
python scripts/eval_profiles.py --require-llm
# Модульные и API-тесты, без сети
cd backend
uv run pytest -q
# Сборка UI из отдельного терминала в корне
cd frontend
npm ci
npm run build
Eval проверяет свойства, а не фиксированный event_id: последовательную доступность, корректный прирост, отсутствие mandatory/повторов и причины выбора. PASS в mock-режиме не подтверждает качество реального LLM. Протокол проверок и ограничения.
Ценность и ограничения
Ожидаемая ценность: сотрудник понимает следующий добровольный шаг, HR может обсуждать бюджет обучения по дефицитам компетенций. Эффект на вовлечённость и удержание пока не измерен. Для пилота измерять добровольное завершение, долю принятых рекомендаций и изменение покрытия навыков; не использовать сигналы вовлечённости как автоматическую оценку сотрудников.
- Импорты, прогресс и «Не сейчас» теряются при перезапуске; один процесс, без постоянной БД.
- Языки объяснений ru/kk/en; основной интерфейс русский.
- Зависимость от сети, доступа к API и бюджета времени; fallback виден явно.
- Веса эвристические; нужны HR-валидация, оценка качества объяснений и пилот.
- GitHub Actions ранее не запускался из-за блокировки биллинга организации. Локальные проверки не подменяют зелёный CI.
Что дальше
- Интеграция с LMS и журналом посещаемости, чтобы обновлять завершения и эффективные навыки без ручного ввода.
- Конструктор мероприятий для HR: аудитория, развиваемые навыки, пререквизиты и расписание.
- Прогноз оттока как сигнал для поддержки сотрудника, с проверкой качества и приватности; без автоматических кадровых решений.
- Добровольные награды без рейтингов и публичного сравнения сотрудников.
- Календарь и мессенджер: запись на выбранный шаг и напоминания по согласию сотрудника.
Это план развития; перечисленные интеграции и функции пока не реализованы.
Команда и вклад
| Участник | Зона |
|---|---|
| Azamat Zhenisov | Backend/AI, многофакторный движок, агент, инструменты и тесты |
| Umar Kumyrkan | Интерфейс сотрудника/HR, интеграция API, состояния и trace |
| Aniyar Baibossyn | Docker и launcher, профили жюри, HTTP eval, README и проверка запуска |
План команды · Правила работы · Вклад Анияра.
Как мы использовали Codex
Каждый участник работал со своей AI-сессией в согласованной зоне файлов. Codex помогал писать, проверять и исправлять код; решения и приоритеты согласовывали участники. Изменения помечены [codex], авторство видно в Git. Доказательства и инструкции для скриншотов. Снимки интерфейса приложения показывают результат, но не заменяют скриншоты сессий Codex; их участники добавляют из своих сессий.
Авторы коммитов
История коммитов
- 2026-09-23 17:55Merge remote-tracking branch 'origin/design/polish'azhensio
- 2026-09-23 17:53feat(frontend): focus career journey on the next action [codex]azhensio
- 2026-09-23 17:53docs(design): capture before and after interface screenshots [codex]azhensio
- 2026-09-23 17:52feat(i18n): ru/kk/en dictionary and useT [codex]ukumyrka
- 2026-09-23 17:52feat(frontend): Halyk Bank logo as favicon and header markazhensio
- 2026-09-23 17:44docs(readme): fixes from reproducibility auditazhensio
- 2026-09-23 17:44fix(backend): uploads never 500 on malformed items and keep the dataset dateazhensio
- 2026-09-23 17:40audit: umar reportukumyrka
Все коммиты (41)
- 2026-09-23 17:39audit: aniyar reportabaiboss
- 2026-09-23 17:38audit: azamat reportazhensio
- 2026-09-23 17:24fix(frontend): label language switch as AI answer languageazhensio
- 2026-09-23 17:08docs(readme): clarify demo permissions skill gains and roadmap [codex]abaiboss
- 2026-09-23 17:02fix(frontend): limit factor chips and clarify demo progress [codex]ukumyrka
- 2026-09-23 16:54docs(submission): document launch agent modes and verified QA [codex]abaiboss
- 2026-09-23 16:36feat(qa): add five jury profiles and HTTP property eval [codex]abaiboss
- 2026-09-23 16:30feat(frontend): polish HR filters uploads and mobile reports [codex]ukumyrka
- 2026-09-23 16:30fix(frontend): default to E0072 and handle loading failures [codex]ukumyrka
- 2026-09-23 16:29feat(agent): scope engine tools and validate plans with fallback [codex]azhensio
- 2026-09-23 16:29feat(agent): add bounded Responses tool transport [codex]azhensio
- 2026-09-23 16:24feat(platform): add one-command Docker and local launch [codex]abaiboss
- 2026-09-23 16:21feat(frontend): expose recommendation source and real agent trace [codex]ukumyrka
- 2026-09-23 16:09docs: parallel tasks for Azamat/Umar/Aniyar agents, roles, status; fix(backend): per-loop OpenAI clientazhensio
- 2026-09-23 16:00fix(backend): atomic history import, eligibility check on complete, «Не сейчас» endpointazhensio
- 2026-09-23 15:58docs: scaffold Career Quest README [codex]ukumyrka
- 2026-09-23 15:54Document main review and updated team delivery planabaiboss
- 2026-09-23 15:47fix(frontend): focus target skills and recent history [codex]ukumyrka
- 2026-09-23 15:39feat(frontend): employee journey and HR dashboard [codex]ukumyrka
- 2026-09-23 15:31Build Career Quest foundation and three-person delivery planabaiboss
- 2026-09-23 15:19docs: neutral wording in data-trap noteazhensio
- 2026-09-23 15:18docs: live status after foundation; fix(frontend): drop BOM from index.htmlazhensio
- 2026-09-23 15:16feat(frontend): typed API client and contract types mirroring backend/app/models/api.pyazhensio
- 2026-09-23 15:15feat(backend): Career Quest API — store, explainable engine, HR analytics, LLM agent with fallbackazhensio
- 2026-09-23 15:02docs: case context (Career Quest), data traps, API contract, file ownership and 3-person planazhensio
- 2026-09-23 15:01data: add Career Quest dataset (Halyk Bank track, case 1)azhensio
- 2026-09-23 15:01chore(frontend): scaffold Vite 8 + React 19 + TS + Tailwind 4, proxy /api to :8000azhensio
- 2026-09-23 15:01chore: import pre-hackathon harness notes (AGENTS.md) and repo hygieneazhensio
- 2026-09-23 14:42Merge branch 'main' of https://github.com/BAITC-Hacks/hack-5fe3ca84-baursaqabaiboss
- 2026-09-23 14:42Add .gitignore to exclude files directoryabaiboss
- 2026-09-23 14:42azaazhensio
- 2026-09-23 14:39first initializatonukumyrka
- 2026-09-23 14:14Add Aniyar Baibossyn to participantsabaiboss
Структура репозитория (93 файлов)
.dockerignore .gitattributes .gitignore AGENTS.md Dockerfile README.md backend/.env.example backend/app/__init__.py backend/app/agents/__init__.py backend/app/agents/recommender.py backend/app/agents/tools.py backend/app/config.py backend/app/llm.py backend/app/main.py backend/app/models/__init__.py backend/app/models/api.py backend/app/models/dataset.py backend/app/routers/__init__.py backend/app/routers/dataset.py backend/app/routers/employees.py backend/app/routers/hr.py backend/app/routers/meta.py backend/app/security.py backend/app/services/__init__.py backend/app/services/engine.py backend/app/services/hr.py backend/app/services/i18n.py backend/app/services/store.py backend/app/state.py backend/pyproject.toml backend/tests/__init__.py backend/tests/conftest.py backend/tests/test_agent.py backend/tests/test_smoke.py backend/uv.lock data/career_quest/README.kz.md data/career_quest/README.md data/career_quest/README.ru.md data/career_quest/activity_history.csv data/career_quest/employees.json data/career_quest/events.json data/career_quest/skills.json data/test_profiles/EXPECTED.md data/test_profiles/activity_history.csv data/test_profiles/employees.json docker-compose.yml docs/TEAM_PLAN.md docs/codex/README.md docs/contributions/aniyar.md docs/design/after-employee.png docs/design/after-hr-mobile.png docs/design/after-hr.png docs/design/after-mobile.png docs/design/after-recommendations.png docs/design/before-employee.png docs/design/before-hr.png docs/design/before-mobile.png docs/design/before-recommendations.png docs/tasks/ANIYAR.md docs/tasks/AZAMAT.md docs/tasks/UMAR.md docs/verification/README.md docs/verification/employee-progress.png docs/verification/eval-docker.json docs/verification/eval-mock.json docs/verification/hr-overview.png frontend/.gitignore frontend/.oxlintrc.json frontend/index.html frontend/package-lock.json frontend/package.json frontend/public/favicon.svg frontend/public/halyk-logo.png frontend/public/icons.svg frontend/src/App.tsx frontend/src/api/client.ts frontend/src/api/types.ts frontend/src/api/view.ts frontend/src/components/LoadingSkeleton.tsx frontend/src/components/Readiness.tsx frontend/src/components/RecommendationDetails.css frontend/src/components/RecommendationDetails.tsx frontend/src/components/SkillChart.tsx frontend/src/index.css frontend/src/main.tsx frontend/src/pages/EmployeePage.tsx frontend/src/pages/HrPage.tsx frontend/tsconfig.app.json frontend/tsconfig.json frontend/tsconfig.node.json frontend/vite.config.ts run.py scripts/eval_profiles.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.