Career Quest — карьерный навигатор
Локальное веб-приложение: профиль сотрудника, разрывы навыков относительно целевой роли или грейда, 1–3 варианта первого шага развития из реальных…
О проекте
Команда: Nomad AI
Кейс HackAlem.ai: Менеджмент — Halyk Bank · кейс 1
Стадия: Рабочий MVP
Задача кейса: «Career Quest»: AI-навигатор, связывающий навыки сотрудника с шагами развития
Суть
Локальное веб-приложение: профиль сотрудника, разрывы навыков относительно целевой роли или грейда, 1–3 варианта первого шага развития из реальных активностей, демо-подтверждение выполнения и HR-аналитика с импортом данных.
Как устроено
Навыки берутся из snapshot, поверх него применяются завершённые активности. Код исключает неподходящие активности (обязательные, не по роли или грейду, с нарушенными prerequisites, без сессии) и считает utility по критическим разрывам, покрытию, эффекту, истории и длительности. Единый адаптер rank_and_explain передаёт LLM только обезличенные факты и до пяти проверенных маршрутов. Модель возвращает ID маршрутов и ссылки на fact_id, код проверяет схему и наличие трёх категорий доказательств. Если вызов не удался, работает fallback.
Ключевые решения
- rule-based eligibility
- utility-ранжирование
- LLM-переранжирование с валидацией fact_id
- кэш решений (256 записей / 5 мин)
- идемпотентные подтверждения с ревизиями
- cookie-сессии с хешем токена в SQLite
Особенности
Приватность продумана: ФИО, ID и сырой CSV не передаются в модель. Модель только выбирает порядок среди вариантов, уже проверенных кодом, и ссылается на fact_id. В UI показываются шаблонные объяснения из проверенных фактов, а не свободная проза модели.
Стек
Python · SQLite · HTML/CSS/JS · PowerShell
Модели
OpenAI · NVIDIA API · локальная OpenAI-совместимая модель (порт 11434)
Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-ec77273d-nomad-ai.
README
README.mdCareer Quest — карьерный навигатор
Рабочее локальное приложение для HackAlem AI / Halyk Bank: профиль сотрудника, проверяемые сценарии обучения, история, демо-подтверждение выполнения и HR-аналитика. Интерфейс на русском; названия и описания каталога сохраняют исходный язык. Полная казахская локализация не заявляется.
Правила взяты из backend/Dataset/README.md и предоставленного текста задания.
DOCX и архив career_quest_dataset.zip в переданной рабочей папке отсутствовали:
соответствие их неизвестному содержимому не утверждается. Распакованные четыре
файла датасета присутствуют и проверены: 200 сотрудников, 40 активностей,
60 навыков, 32 профиля требований, 2743 записи истории. Новые ID поддерживаются.
Запуск одной командой
Из корня проекта, Windows + Python 3.10 или новее:
powershell -ExecutionPolicy Bypass -File .\scripts\start.ps1
Скрипт создаёт .venv при необходимости, устанавливает backend/requirements.txt
и запускает сервер на http://127.0.0.1:8000. При уже установленных зависимостях:
.\.venv\Scripts\python.exe scripts\run.py
Конфигурация загружается из корневого .env (не коммитится). Пример —
.env.example. Существующие переменные окружения имеют приоритет.
При первом запуске скрипт добавляет отсутствующий AUTH_SECRET в локальный .env.
Дата сценария берётся из meta.as_of_date — 2026-10-01. AS_OF_DATE позволяет
задать более позднюю дату; вернуться до даты исходного snapshot нельзя.
Вход и роли
После старта откройте локальный var/demo_accounts.json: это коды доступа
к синтетическим демо-профилям и отдельный код HR. Файл игнорируется Git и никогда
не раздаётся HTTP-сервером. Выберите роль и введите код в форме входа.
Для HR ID сотрудника необязателен; указав свой ID, HR получает также личный маршрут.
Коды можно переопределить через HR_ACCESS_CODE и EMPLOYEE_ACCESS_CODES в окружении.
Серверные сессии хранят хеш токена в SQLite; браузер получает HttpOnly/SameSite cookie.
Сотрудник видит только собственные профиль, рекомендации и историю. Запрос чужого
ID или HR-API возвращает 403. HR имеет доступ к агрегатам, списку сотрудников,
профилям и импорту. /boss открывает HR-обзор с теми же проверками прав, не отдельную
непроверяемую привилегию. Это локальная система демо-кодов, а не интеграция банковского SSO.
Основные сценарии
- Моё развитие: текущая роль/грейд, эффективные навыки, требования текущего, следующего и выбранного грейда, критические разрывы и история активности.
- Сравнение: 1–3 варианта первого шага. Каждый маршрут содержит одну или две
реальные активности, эффекты до/после, сроки, длительность и факторы выбора.
progress_afterотносится к первому шагу; итог маршрута —steps[-1].coverage_after. - Цель: сотрудник выбирает существующий профиль роли/грейда; расчёт обновляется.
- Выполнение: сотрудник явно подтверждает симуляцию завершения в демо. Эффект применяется один раз, версия профиля увеличивается, рекомендации пересчитываются. Подтверждение будущей сессии — условная симуляция, а не запись о реальном посещении.
- HR: разрывы компетенций с корректным знаменателем, сотрудники без следующего шага и причины, уникальные участники/статусы активностей, импорт дополнительных данных.
Активности не присваивают грейд автоматически. Нет публичных рейтингов сотрудников, очков за обязательные процессы, принудительных серий или обещаний повышения. Числа в интерфейсе всегда берутся из backend, включая при успешной работе модели.
Проверяемая логика
- Исходные skills отражают последнюю оценку. Только completed после last_review_date и не позднее даты сценария воспроизводятся поверх snapshot. Отсутствующий навык = 0.
- Эффект ограничен gain и max_level; активность никогда не уменьшает уже высокий навык. Все реальные эффекты присутствуют в impacts, включая навыки без требования цели.
- Исключаются mandatory, неподходящие роль/грейд, нарушенные prerequisites,
завершённые неповторяемые активности и события без доступной сессии.
self_pacedдоступен без сессий;EV_036повторяется только для другой сессии. - Utility учитывает критические разрывы, покрытие требований, эффект, историю формата и длительность. Это не вероятность завершения или повышения. Пропуски не превращаются в рейтинг сотрудника; причины пропусков не выводятся.
- Сроки сценария предполагают два часа обучения в день. Для self_paced историческая дата зачисления служит приближением; неизвестная дата фактического окончания не выдумывается.
Демо-прогресс сохраняется по (import_id, employee_id) и переживает повторный вход
и перезапуск. Атомарные revision/idempotency-проверки защищают от двойного начисления
и устаревших подтверждений. Источник JSON/CSV не перезаписывается. SQLite версии 1/2
обновляется до 3 добавлением таблиц; существующие данные сохраняются.
Career Navigator и приватность
Один адаптер rank_and_explain(facts) в backend/app/engine/ai_layer.py выбирает
порядок среди максимум пяти проверенных вариантов. В модель передаются только роль,
грейд, цель, разрывы, агрегированные факторы истории, допустимые маршруты и fact_id.
ФИО, employee_id, manager_id, сырой CSV и полные профили не передаются.
Модель возвращает JSON с ID маршрутов и ссылками на факты. Проверяются схема, уникальность/существование ID, разрешённые позиции перестановки и минимум три категории доказательств (грейд/цель, разрыв, история) для каждого объяснения. Свободную прозу невозможно автоматически признать истинной: в UI используются короткие шаблоны из проверенных фактов, выбранных моделью. Модель определяет ранжирование и факторы; приросты и допуск определяет код.
Провайдер конфигурируется окружением. Пример локального совместимого сервиса:
AI_PROVIDER=local
AI_MODEL=имя_установленной_локальной_модели
AI_BASE_URL=http://127.0.0.1:11434/v1/chat/completions
Модель локального сервиса должна быть установлена отдельно. Поддерживаются также
openai, nvidia, openai-compatible; используйте OPENAI_MODEL/OPENAI_API_KEY,
NVIDIA_MODEL/NVIDIA_API_KEY или общие AI_MODEL/AI_API_KEY. Имя модели задаёт
владелец проекта; код не меняет его автоматически.
Для внешнего контура производные факты допускаются только при
AI_ALLOW_EXTERNAL_DERIVED=true, после разрешения организаторов. Без флага работает
локальный endpoint либо честный fallback external_not_allowed. Страница HR
/admin/ai проверяет реальный вызов на фиксированном синтетическом примере сервера;
никакие поля загруженных сотрудников для этого теста не используются.
Общий таймаут одного вызова — 6 секунд, повторов нет. mode=llm возможен только
после настоящего успешного вызова и валидации; иначе mode=fallback и причина.
Кэш успешных решений ограничен 256 записями/5 минутами и включает employee_id,
revision, цель, факты, конфигурацию модели и версию prompt. Изменение цели,
подтверждение выполнения или импорт сбрасывают соответствующие записи.
Профиль и локальные сценарии загружаются независимо от модели. После отображения расчёта UI отдельно запрашивает AI и отвергает устаревшие результаты по revision.
Импорт для жюри
Войдите HR → Загрузка данных:
- Дополнение: employees.json (обёртка starter kit или массив сырых профилей) + activity_history.csv. Новые ID не ограничены исходными 200; ссылки/уровни проверяются.
- Замена: все четыре исходных файла либо ZIP с ними. Нужны employees.json, events.json, skills.json, activity_history.csv с одной датой snapshot.
Проверка выполняется до активации. Неверные ссылки, диапазоны, типы, даты, дубликаты и несогласованные статусы дают ошибку с путём поля. Готовый API Employee нельзя импортировать как raw snapshot: в нём навыки уже рассчитаны. Неудачный импорт не заменяет текущий набор. При успешной замене исходный набор сохраняется локально, активируется новая версия; другие сессии должны войти заново. Демо-прогресс прежнего импорта остаётся в SQLite, но не смешивается с новым snapshot.
API и модули
| Модуль | Ответственность |
|---|---|
engine/data_loader.py | Строгая проверка исходных и дополнительных данных |
engine/navigator.py | Эффективные навыки, требования, допуск, сценарии, HR |
engine/ai_layer.py | Единственная граница модели, deadline, валидация, fallback, кэш |
repository.py, schema.sql | Сессии, версии, подтверждения, сохранение demo-состояния |
application.py, access.py | Авторизация, API, импорт, обработка ошибок |
static/portal.* | Русский интерфейс сотрудника и HR |
contracts.py, contracts/contract.md | Общие модели и формат обмена |
Существующий трёхшаговый planner сохранён как совместимый модуль с тестами;
активный продукт использует navigator и маршруты из одной–двух активностей.
OpenAPI: /docs. Основные API: /api/login, /api/session, /api/me,
/api/me/recommendations?ai=false|true, /api/me/target, /api/me/completions,
/api/hr/overview, /api/employees, /api/hr/import.
Ошибка единообразна: {"error":{"code":"VALIDATION_ERROR","message":"…","details":[]}}.
401 — нет сессии; 403 — нет прав; 404 — неизвестный ID; 409 — конфликт версии/дубликат;
422 — входные данные; 503 — приложение не готово, никогда не отказ LLM.
Проверки и воспроизводимое демо
.\.venv\Scripts\python.exe -m unittest discover -s backend/tests -t . -v
.\.venv\Scripts\python.exe scripts\demo_scenario.py --output var/demo_report.json
.\.venv\Scripts\python.exe scripts\verify_demo.py --synthetic-ai
Первый запуск проверяет рискованные бизнес-правила, права, импорт, идемпотентность,
вымышленные ID модели, таймаут и кэш. demo_scenario.py не вызывает модель и не меняет
SQLite. verify_demo.py использует временную БД; флаг --synthetic-ai делает один
реальный запрос на синтетическом примере. Последний отчёт: var/verification.json.
Пошаговая демонстрация E0015 и сложного профиля E0137 — docs/demo.md. Она показывает сравнение с ошибочным однофакторным выбором и однократное начисление.
Измерение API на этом компьютере, Python 3.14.7, полный исходный датасет:
профиль 8,9–13,6 мс; локальные рекомендации 8,1–8,7 мс; первый HR-запрос 359 мс;
синтетический реальный ответ модели — 4,93 с (mode=llm, без кэша).
Это FastAPI TestClient/серверный путь, не замер отрисовки браузера.
Ограничения 2/10 секунд выполнены в этой проверке, не гарантируются для другой машины
или провайдера. Для отдельного сетевого измерения API отдаёт Server-Timing.
В текущей агентской среде доступного браузера нет, поэтому визуальная QA не выполнена.
Не публикуйте .env, локальные коды, исходный датасет и SQLite. Используйте только
синтетические профили, переданные организаторами. Раскрытый ранее ключ API нужно
отозвать у провайдера; удаление его из рабочего файла не удаляет историю Git.
Авторы коммитов
История коммитов
- 2026-09-23 17:47half-finishCopitanCat
- 2026-09-23 17:42half-finishCopitanCat
- 2026-09-23 17:19frontCopitanCat
- 2026-09-23 17:14making bdCopitanCat
- 2026-09-23 15:11making bdCopitanCat
- 2026-09-23 15:08making bdCopitanCat
- 2026-09-23 14:33Add HR overview page and implement API testsmyfiz
Структура репозитория (53 файлов)
.env.example .gitignore README.md api/Apis.txt backend/Dataset/README.kz.md backend/Dataset/README.md backend/Dataset/README.ru.md backend/Dataset/activity_history.csv backend/Dataset/employees.json backend/Dataset/events.json backend/Dataset/skills.json backend/README.md backend/__init__.py backend/app/__init__.py backend/app/access.py backend/app/application.py backend/app/catalog_api.py backend/app/contracts.py backend/app/engine/__init__.py backend/app/engine/ai_layer.py backend/app/engine/data_loader.py backend/app/engine/navigator.py backend/app/engine/openai_agent.py backend/app/engine/planner.py backend/app/importing.py backend/app/main.py backend/app/repository.py backend/app/schema.sql backend/app/schemas.py backend/app/static/ai_admin.html backend/app/static/plans.html backend/app/static/portal.css backend/app/static/portal.html backend/app/static/portal.js backend/requirements.txt backend/scripts/init_db.py backend/tests/__init__.py backend/tests/test_ai_layer.py backend/tests/test_api.py backend/tests/test_imports.py backend/tests/test_navigator.py backend/tests/test_planner.py backend/tests/test_repository.py contracts/contract.md contracts/examples.json data/.gitkeep docs/demo.md scripts/demo_scenario.py scripts/init_db.py scripts/run-codex-agent.ps1 scripts/run.py scripts/start.ps1 scripts/verify_demo.py
Обсуждение 0 комментариев
Войдите, чтобы комментироватьПока нет комментариев — будьте первым.