ИИ-агент для HR-сервиса: как подключить внешнюю LLM и не выпустить наружу чувствительные данные

В статье расскажу, как спроектировала и реализовала ИИ-помощника для HR-сервиса компании. ИИ-помощник ищет ответы документам компании, базам данных, а также отвечает на общие, не относящиеся к работе вопросы. Работает по двухпроходной схеме с классификатором, при этом не передает чувствительные данные во внешнюю LLM.


Задача: добавить в HR-сервис ИИ-помощника

Заказчиком задачи был HR-отдел. Коллеги просили добавить в ИИ-помощника в существующий HR-сервис. Основной целью было повысить лояльность сотрудников: предоставить поддержку касательно внутренних регламентов, упростить поиск по внутренним документам и справочникам, дать доступ к ИИ из внутреннего ресурса компании.

В результате обсуждения с HR сформировали требования:

  • Поиск по внутренним документам компании. Сотрудник спрашивает «как оформить отпуск», «где взять бланк заявления», «какой порядок согласования обучения», и получает ответ на основе регламентов и справочных материалов.
  • Поиск по подразделениям и сотрудникам. Чтобы человек мог найти почту и телефон отдела или сотрудника.
  • Ответы на общие вопросы. Если сотрудник спрашивает что-то не про работу, например: «как приготовить блины», «столица Камбоджи» и др., то ИИ должен корректно отвечать на такие вопросы.
  • Обращение к живому HR как запасной вариант. Если вопрос про работу, но ответа в документах нет, помощник предлагает написать HR-менеджеру через форму.


Ограничение: внешняя LLM и чувствительные данные

Генерировать ответы должна была внешняя LLM. А значит, всё, что пользователи отправляют в неё, физически уходит за пределы компании на чужие серверы. Важно было фильтровать или маскировать чувствительные данные, которые могут быть в запросах пользователей или в контексте для LLM.

LLM (Large Language Model, большая языковая модель) — это тип нейросети, обученной на огромных объёмах текста предсказывать следующее слово в последовательности.


Решение: развернуть RAG, фильтровать вход, часть запросов не отдавать LLM вообще

Всё, что уходит в LLM, предварительно обезличивается. В запросе пользователь может написать имя и фамилию сотрудника для поиска, а это персональные данные. Поэтому запрос пользователя проходит через фильтр, который находит имена и заменяет их на плейсхолдеры (NAME_1, NAME_2), прежде чем текст уйдёт в нейросеть.

Поиск контактов выполняется программно, вне LLM. Контакты сотрудников — самые чувствительные данные, и их нельзя отдавать вовне. Поэтому LLM здесь работает только как классификатор: она понимает, что человек ищет контакт, и возвращает HR-сервису команду выполнить поиск по справочнику. Сам поиск и выдачу контактов выполняет другая, не связанная с LLM программа.

Для документов разворачиваем RAG. Чтобы отвечать по внутренним материалам, я подготовила поисковый индекс. Документы и FAQ векторизуются и складываются в векторную базу. Если у пользователя вопрос по документам, то сначала в векторной базе находятся релевантные фрагменты, и потом передаются в LLM как контекст. Нейросеть отвечает строго по найденным документам.

FAQ (Frequently Asked Questions) — раздел с часто задаваемыми вопросами и готовыми ответами на них.

RAG (Retrieval-Augmented Generation) — технология, при которой языковая модель перед ответом ищет нужную информацию во внешней базе знаний и генерирует ответ на её основе. База — это обычно векторное хранилище, например, Qdrant. Исходные документы заранее разбиваются на небольшие фрагменты – чанки. Затем каждый фрагмент преобразуется в многомерный вектор с помощью специальной модели-эмбеддера. Все векторы сохраняются в базе. Когда пользователь задаёт вопрос, он тоже переводится в вектор, и система ищет математически близкие к нему векторы — то есть фрагменты, наиболее схожие по смыслу. Найденные фрагменты передаются языковой модели вместе с вопросом, и она формирует ответ, опираясь на них.

Подстраховка живым HR. Если вопрос корпоративный, но в документах ответа нет, помощник честно говорит, что не нашёл, и предлагает написать HR через форму обратной связи.

Для лояльности — отвечаем на все вопросы и генерируем картинки. Общие вопросы уходят в LLM как есть: в них нет корпоративных данных, обезличивать нечего, и она отвечает из общих знаний. Дополнительно добавила генерацию изображений — сотрудник может попросить «нарисуй кота», и агент сгенерирует картинку.


Источники данных

У агента три источника, откуда берётся ответ:

  • Сама LLM — для общих вопросов, не связанных с работой. Здесь источник знаний — это обученная модель, корпоративный контекст не нужен.
  • FAQ — таблица готовых пар «вопрос-ответ» в сервисе NocoDB. Ее ведет HR-менеджер. Сюда попадают частые вопросы, на которые нужен выверенный ответ.
  • Документы (RAG) — регламенты, бланки, справочные материалы. Лежат в файловом хранилище, их метаданные — в табличном сервисе NocoDB. Содержимое индексируется в векторную базу Qdrant с помощью Open Source модели multilingual-e5-large.

FAQ и документы агент ищет одним запросом сразу по всем, не выбирая источник заранее — ответ может оказаться в любом из них.


Реализация: двухпроходная схема

На каждый вопрос агент по двухпроходной схеме решает, как ответить. Первый проход (Pass 1) — классификатор: выбирает инструмент – tool call. Второй проход (Pass 2) — формирует ответ.

Тулколы, которыми может ответить классификатор на первом шаге:

  • Поиск во внутренних источниках (search_internal) — ищет по подготовленной таблице FAQ, документам.
  • Команда поиска (search_contacts, search_ats_mavis, search_ats_votonia, search_shop, search_drugstore) — агент возвращает инструкцию выполнить поиск по справочнику и передает строку для поиска. Далее поиск выполняется программно, без участия LLM.
  • Общий ответ (answer_general) — если вопрос не про работу в компании, LLM отвечает из общих знаний.
  • Изображение (generate_image) — генерирует изображение по тексту через Alice AI ART.
  • Форма HR (suggest_hr_form) — если по корпоративному вопросу ничего не нашлось, агент предлагает обратиться к живому HR.


Контекст диалога через Redis

Для LLM каждый запрос новый, история автоматически не подтягивается. Чтобы помощник понимал уточняющие вопросы, например, «а где его найти?» после предыдущего ответа, нужна память о диалоге. Для этого история переписки пользователя записывается в Redis. Затем при каждом запросе история передается в Pass 2, чтобы нейросеть отвечала с учётом контекста.


Индексация документов

Корпоративные документы лежат в файловом хранилище, а поиск выполняется по векторной базе данных. Чтобы текстовые документы перевести в многомерные векторы, нужна индексация.

Индексация работает так. Администратор ведет в таблице NocoDB список документов, которые нужно проиндексировать, сами документы кладет в файловое хранилище. ИИ-агент забирает список документов, скачивает их из хранилища, а также получает FAQ. Далее индексатор проходит по записям FAQ и документам в хранилище, превращает текст в векторы и складывает все в Qdrant. Индексация инкрементальная: для каждой записи сравнивается дата изменения в NocoDB с датой, когда её проиндексировали. Если запись не менялась — пропускается.

Отдельно решается задача синхронизации: если запись удалили или переименовали в NocoDB, старый вектор нужно убрать из Qdrant, иначе накопятся «призраки» — ссылки на несуществующие документы. После цикла обновления индексатор сверяет, что реально есть в NocoDB, с тем, что лежит в Qdrant, и удаляет лишнее.


Архитектура

Схематично сервис устроен так:



HR-сервис – получает запрос от пользователя и обращается в ИИ-агента по HTTP на POST /api/v1/ask. Контракт между HR-сервисом и ИИ-агентом описан в docs/openapi.yaml.

Внешняя LLM — Yandex AI Studio как основной провайдер и GigaChat как запасной. LLM-клиент абстрагирован: чтобы перейти на другого провайдера, достаточно переписать один модуль-клиент, вся остальная логика остается нетронутой.

RAG — Qdrant как векторная база и локальная модель эмбеддингов multilingual-e5-large.

NocoDB – таблицы с FAQ и метаданными документов, сами файлы лежат в файловом хранилище.

Redis – хранит историю переписки с пользователями.

👉 Посмотреть код можно здесь.


Стек технологий

  • Python 3.12 — основной язык.
  • FastAPI — веб-фреймворк для сервиса агента, с эндпоинтами и валидацией запросов и ответов через Pydantic.
  • Qdrant — векторная база для RAG.
  • Redis — хранение истории диалогов.
  • multilingual-e5-large — локальная модель эмбеддингов для векторизации.
  • Docker Compose — сборка и запуск всего стека.


Совместимость и развитие

Агент спроектирован так, чтобы отдельные части можно было заменить, не переписывая остальное. Например, провайдер LLM меняется переписыванием одного модуля-клиента. Бизнес-логика – классификация, RAG, обезличивание, не зависит от того, какая нейросеть под капотом. Векторную базу или модель эмбеддингов тоже можно поменять — они написаны в отдельном слое.


Демонстрация работы


👉 Ранее писала о разработке сервиса для HR-отдела.

Next Post Previous Post