Career Quest
Веб-приложение, которое показывает сотруднику разрыв до следующего грейда и даёт 1–3 активности с объяснением.
О проекте
Команда: GoDo
Кейс HackAlem.ai: Менеджмент — Halyk Bank · кейс 1
Стадия: Рабочий MVP
Задача кейса: «Career Quest»: AI-навигатор, связывающий навыки сотрудника с шагами развития
Суть
Веб-приложение, которое показывает сотруднику разрыв до следующего грейда и даёт 1–3 активности с объяснением. HR видит проседающие навыки и сотрудников без шага развития.
Как устроено
Конвейер recommendations.service.ts: берёт матрицу requirementsByGrade для роли, отбрасывает навыки с 2+ пропусками или отказами и уже пройденные события, считает skill gap и прогноз прироста. TOP-5 кандидатов отправляется в OpenAI gpt-4o-mini в JSON-режиме, модель выбирает ID строго из списка. Guardrails: неверный id, битая структура или таймаут 8 с переключают на локальный рейтинг. Отметка «пройдено» атомарно повышает уровень навыка и пересчитывает готовность. Доступ по ролям через RolesGuard.
Ключевые решения
- skill-gap ранжирование
- жёсткие префильтры по истории
- LLM выбирает из shortlist
- JSON-режим + валидация
- алгоритмический fallback
- RolesGuard
Особенности
LLM получает только компактный контекст из одного сотрудника и 5 кандидатов, так что выдумать мероприятие она не может. Первые коммиты относятся к другому проекту (юридический кейс с Adilet KB и Anthropic SDK), репозиторий был переиспользован.
Стек
TypeScript · NestJS · TypeORM · PostgreSQL · Next.js · React · Tailwind CSS · Zustand · Docker Compose · Jest
Модели
gpt-4o-mini
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-c756b018-godo.
README
README.mdCareer Quest
AI-навигатор карьерного развития сотрудников (кейс Halyk Bank). Сотрудник видит, чего не хватает до следующего грейда, и получает 1–3 активности с объяснением «почему именно это». HR видит, где команда проседает, и кому стоит обсудить развитие.
Зачем и как это работает
Проблема: каталог обучения большой, сотрудник не понимает, что двигает его к следующему грейду, а часть мероприятий системно пропускает. Career Quest берёт три набора данных — профиль навыков, требования грейдов и историю участия — и превращает их в короткий персональный план.
Конвейер рекомендации (backend/src/modules/recommendations/recommendations.service.ts):
- Карта цели. Из
skills.jsonберётся матрицаrequirementsByGradeдля роли и целевого грейда сотрудника — что и на каком уровне нужно. - Жёсткие префильтры. Навык с 2+ пропусками или отказами (MISSED/REFUSED) исключается целиком — повторное предложение того, что сотрудник уже отверг, бесполезно. Далее отбрасываются пройденные события, события по навыку на
maxLevelи не подходящие по аудитории. - Разрыв (skill gap). Для каждого оставшегося события:
требуемый уровень − текущийи прогноз приростаmin(gain, maxLevel − current). - TOP-5 → LLM. В OpenAI (
gpt-4o-mini, JSON-режим) уходит только компактный контекст: один сотрудник и 5 кандидатов. Модель выбирает ID строго из этого списка и пишет короткое объяснение. - Guardrails. Ответ модели проверяется: несуществующий
eventId, сломанная структура или таймаут 8 с — ответ собирается локальным алгоритмическим рейтингом. БезOPENAI_API_KEYAPI работает так же, только сразу по локальному порядку. Демо не падает никогда. - Объяснение на фактах. В каждом ответе есть проверяемые числа — грейды, текущий и требуемый уровень, разрыв, прогноз прироста, история по навыку. Текст модели добавляется к фактам, а не заменяет их.
Отметка «пройдено» атомарно повышает навык до min(current + gain, maxLevel), пишет COMPLETED в историю и пересчитывает готовность к целевому грейду.
Что использовано и где
| Технология | Где | Зачем |
|---|---|---|
| NestJS 11 + TypeScript | backend/src | REST API: модули employee, hr, recommendations, data-importer; Swagger на /docs |
| TypeORM 0.3 + PostgreSQL 15 | backend/src/storage | 4 таблицы; навыки сотрудника и требования грейдов — JSONB; схема синхронизируется автоматически (synchronize: true) |
| class-validator / class-transformer | DTO модулей | Валидация входных данных, whitelist против лишних полей |
OpenAI Chat Completions (gpt-4o-mini) | recommendations.service.ts | Выбор 1–3 мероприятий из отфильтрованного списка и объяснение; JSON-режим, таймаут, алгоритмический fallback |
| Next.js 16 + React 19 | frontend/app | Страницы / (выбор роли), /employee, /hr, /hr/employees/[id]; запросы к backend по /api/* (BACKEND_URL) |
| Tailwind CSS 4 + lucide-react | frontend | Стиль интерфейса и иконки |
| Framer Motion, Zustand | frontend | Анимация прогресс-баров, клиентское состояние профиля |
| Docker Compose | backend/docker-compose.yml | Три сервиса: db, backend, frontend; backend/data монтируется в контейнер для импорта данных жюри |
| Jest | backend/src/**/*.spec.ts | Юнит-тесты префильтра рекомендаций, импортёра датасета и ролевого guard |
-
Backend — каталог backend/ cd backend npm install copy .env.example .env # впишите OPENAI_API_KEY (необязательно, иначе локальный рейтинг) npm run start:dev # watch-режим → API: http://localhost:3000, Swagger: http://localhost:3000/docs. При первом старте в пустую БД сам импортирует демоданные из backend/data/.
-
Frontend — каталог frontend/ (вторая вкладка терминала) cd frontend npm install npm run dev → http://localhost:3001. Все запросы идут на свой же /api/* и проксируются на backend; если backend на другом адресе — BACKEND_URL=http://localhost:3000 npm run dev.
Демо-доступ
Для хакатона — заголовки вместо SSO (осознанное ограничение демо): X-Role: employee | hr и X-Employee-Id для сотрудника. RolesGuard подключён глобально (APP_GUARD) и возвращает 403, если сотрудник лезет в HR-разделы или в чужой профиль. Переключатель роли встроен в интерфейс.
Демоданные из backend/data/ (employees.json, events.json, skills.json, activity_history.csv) импортируются автоматически при первом старте в пустую БД. Полная замена — POST /api/admin/import; дозагрузка отдельных записей — POST /api/hr/import или HR-экран (JSON и CSV разбираются на клиенте). skipped в CSV становится MISSED; история с неизвестным сотрудником или событием откатывает транзакцию импорта.
API
Интерактивная документация: http://localhost:3000/docs. Основные маршруты (префикс /api опционален):
| Метод | Путь | Роль | Описание |
|---|---|---|---|
| GET | /employees/:id | emp / hr | Профиль: навыки с уровнями, требованиями и готовностью |
| GET | /employees/:id/recommendations | emp / hr | 1–3 рекомендации с обоснованием и breakdown по фактам |
| POST | /employees/:id/complete-event/:eventId | emp | Отметить пройденным, вернуть обновлённый профиль |
| POST | /activities/complete | emp | То же по employeeId + eventId в теле |
| GET | /hr/employees | hr | Список сотрудников с готовностью и статусом |
| GET | /hr/analytics | hr | Топ-5 проседающих навыков, сотрудники без шага, участие по событиям |
| GET | /hr/employees/:id | hr | Профиль сотрудника, только просмотр |
| POST | /hr/import | hr | Дозагрузка JSON-датасета (merge) |
| POST | /api/admin/import | hr | Полная замена данных из файлов backend/data |
Примеры:
# Профиль и рекомендации сотрудника
curl http://localhost:3000/employees/E0028 -H "X-Role: employee" -H "X-Employee-Id: E0028"
curl http://localhost:3000/employees/E0028/recommendations -H "X-Employee-Id: E0028"
# HR-аналитика
curl http://localhost:3000/hr/analytics -H "X-Role: hr"
Frontend — http://localhost:3001, backend — http://localhost:3000, Swagger — http://localhost:3000/docs.
Локально без Docker: поднять Postgres (docker compose up db), затем npm install && npm run start:dev в backend/ и npm install && npm run dev в frontend/.
Переменные backend: DB_URL (или DB_HOST/DB_PORT/DB_USER/DB_PASSWORD/DB_NAME), AI_PROVIDER=openai, OPENAI_API_KEY, опционально OPENAI_MODEL (по умолчанию gpt-4o-mini) и OPENAI_MAX_TOKENS.
Проверка
cd backend && npm run build && npm test -- --runInBand
cd frontend && npm run typecheck
Ручной сценарий: откройте сотрудника E0028 — Public Speaking (3 пропуска в истории) не должен попасть в рекомендации, а System Design с разрывом 2 до Senior — должен. Отметьте активность пройденной: уровень навыка вырастет, готовность пересчитается. Запрос /hr/analytics с ролью employee возвращает 403.
Ограничения демо
Роль передаётся заголовком и подделывается вручную — для банка нужен SSO/JWT и серверная проверка личности; схема БД синхронизируется автоматически вместо миграций. Эти места помечены в коде и меняются без перестройки остальной логики.
Авторы коммитов
История коммитов
- 2026-09-23 18:00Update README.mdJasulan
- 2026-09-23 17:58readmeJasulan
- 2026-09-23 17:51fixJasulan
- 2026-09-23 17:41feat: slight gamificationJasulan
- 2026-09-23 17:11fixJasulan
- 2026-09-23 17:06merge: integrate HR read-only profile access from remotevcffff
- 2026-09-23 17:05merge: integrate local RolesGuard work into remote backend/frontend layoutvcffff
- 2026-09-23 17:03Show role-specific career and HR workflowsJasulan
Все коммиты (42)
- 2026-09-23 17:01Add HR read-only employee profile accessJasulan
- 2026-09-23 16:54added some filesvcffff
- 2026-09-23 16:46merge: resolve README conflict, keep updated docs with screenshotvcffff
- 2026-09-23 16:43feat: role-based access (RolesGuard), dataset import endpoint and updated READMEvcffff
- 2026-09-23 16:41feat: restucture foldersJasulan
- 2026-09-23 16:37Keep root limited to app directories and READMEJasulan
- 2026-09-23 16:35Move backend into dedicated directoryJasulan
- 2026-09-23 16:32Seed demo data and explain missing recommendationsJasulan
- 2026-09-23 16:26Clean up README.md by removing extra textMagzhan Skakov
- 2026-09-23 16:26Add README for Career Quest web applicationMagzhan Skakov
- 2026-09-23 16:20Document and package Career Quest data workflowJasulan
- 2026-09-23 16:19Wire explainable recommendations progress and HR analyticsJasulan
- 2026-09-23 16:19Add PostgreSQL storage and dataset importerJasulan
- 2026-09-23 16:08chore: trace OpenAI recommendation requests and usageJasulan
- 2026-09-23 15:59fix: allow standalone activity history CSV importJasulan
- 2026-09-23 15:51chore: update next-env.d.ts type imports for dev modevcffff
- 2026-09-23 15:49docs: add reproducible demo dataset and run guideJasulan
- 2026-09-23 15:48feat: add activity history and CSV upload to updated UIJasulan
- 2026-09-23 15:48feat: ground career recommendations and support dataset importsJasulan
- 2026-09-23 15:41updated frontendvcffff
- 2026-09-23 15:12feat: db connection env fixJasulan
- 2026-09-23 15:02added frontendvcffff
- 2026-09-23 14:33added backendvcffff
- 2026-09-23 12:59test: AI role validation unit tests and full MVP e2e scenarioJasulan
- 2026-09-23 12:59feat(app): Supabase Postgres wiring and .env bootstrapJasulan
- 2026-09-23 12:57feat(documents): draft generation, retrieval and user editingJasulan
- 2026-09-23 12:57feat(evidence): evidence upload and listingJasulan
- 2026-09-23 12:57feat(cases): case pipeline with state machine and full REST APIJasulan
- 2026-09-23 12:56feat(db): TypeORM entities for cases, messages, evidence, documentsJasulan
- 2026-09-23 12:56feat(legal): Adilet KB and LegalResearchService abstractionJasulan
- 2026-09-23 12:55feat(ai): AI module with 7 roles, mock and anthropic providersJasulan
- 2026-09-23 12:55chore(deps): anthropic sdk, pg, dotenv, @nestjs/config, jest toolingJasulan
- 2026-09-23 12:55feat(common): domain interfaces, AI JSON validation, draft templates, configsJasulan
- 2026-09-23 10:54feat: initial backend commitJasulan
Структура репозитория (85 файлов)
README.md backend/.dockerignore backend/.env.example backend/.gitignore backend/Dockerfile backend/data/activity_history.csv backend/data/employees.json backend/data/events.json backend/data/skills.json backend/docker-compose.yml backend/nest-cli.json backend/package-lock.json backend/package.json backend/src/app.module.ts backend/src/common/decorators/current-user.decorator.ts backend/src/common/decorators/roles.decorator.ts backend/src/common/enums/activity-status.enum.ts backend/src/common/enums/role.enum.ts backend/src/common/guards/roles.guard.ts backend/src/common/roles.decorator.ts backend/src/common/roles.guard.ts backend/src/config/ai.config.ts backend/src/entities/activity-history.entity.ts backend/src/entities/employee-skill.entity.ts backend/src/entities/employee.entity.ts backend/src/entities/event.entity.ts backend/src/entities/skill.entity.ts backend/src/main.ts backend/src/modules/ai/ai.module.ts backend/src/modules/ai/ai.service.spec.ts backend/src/modules/ai/ai.service.ts backend/src/modules/data-importer/data-importer.controller.ts backend/src/modules/data-importer/data-importer.module.ts backend/src/modules/data-importer/data-importer.service.ts backend/src/modules/employee/activities.controller.ts backend/src/modules/employee/dto/complete-activity.dto.ts backend/src/modules/employee/employee.controller.ts backend/src/modules/employee/employee.module.ts backend/src/modules/employee/employee.service.spec.ts backend/src/modules/employee/employee.service.ts backend/src/modules/hr/dto/import-dataset.dto.ts backend/src/modules/hr/hr.controller.ts backend/src/modules/hr/hr.module.ts backend/src/modules/hr/hr.service.ts backend/src/modules/progress/progress.module.ts backend/src/modules/progress/progress.service.spec.ts backend/src/modules/progress/progress.service.ts backend/src/modules/recommendations/dto/llm-recommendation.dto.ts backend/src/modules/recommendations/dto/recommendations-query.dto.ts backend/src/modules/recommendations/recommendations.module.ts backend/src/modules/recommendations/recommendations.service.spec.ts backend/src/modules/recommendations/recommendations.service.ts backend/src/storage/entities/activity-history.entity.ts backend/src/storage/entities/employee.entity.ts backend/src/storage/entities/event.entity.ts backend/src/storage/entities/skill-requirement.entity.ts backend/src/storage/grade-requirements.ts backend/test/jest-e2e.json backend/tsconfig.build.json backend/tsconfig.json backend/types/index.ts frontend/.gitignore frontend/.omc/state/agent-replay-7fb159bd-39bd-40da-b6a7-bda64369a95a.jsonl frontend/.omc/state/last-tool-error.json frontend/Dockerfile frontend/Dockerfile.dockerignore frontend/app/employee/page.tsx frontend/app/globals.css frontend/app/hr/employees/[id]/page.tsx frontend/app/hr/page.tsx frontend/app/layout.tsx frontend/app/page.tsx frontend/components/app-shell.tsx frontend/contract_frontend.md frontend/eslint.config.mjs frontend/image.png frontend/lib/api.ts frontend/lib/demo-role.ts frontend/lib/store.ts frontend/next-env.d.ts frontend/next.config.ts frontend/package-lock.json frontend/package.json frontend/postcss.config.mjs frontend/tsconfig.json
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.