Я разработал инструмент для автоматизации подбора специалистов. Основная его задача сократить время первичного отбора кандидатов за счет автоматического анализа резюме, GitHub-репозиториев и применения RAG(Retrieval-Augmented Generation) подхода.

Архитектура

Система построена из 5 модулей:

  1. Backend: Python, FastApi (оркестрация пайпланов)

  2. Frontend: TS, React

  3. ChromaDB (хранение эмбеддингов и семантический поиск)

  4. SQLite (хранение структурированных профилей для каждого резюме)

  5. Mistral API (формирование эмбеддингов, анализ и переранжирование результатов)

Пайплайны

В инструменте используется всего 2 основных пайплайна: Indexing (Выполняется каждый раз для индексации новых резюме) и Search (Выполняется при каждом запросе о поиске кандидатов).

Детальная схема пайплайнов
Детальная схема пайплайнов

Процесс индексации резюме

Для индексации резюме система выполняет следующие этапы:

  1. Извлекает текст из PDF

  2. Разбивает его на чанки (текст делится на чанки по 500 символов с перекрытием 100 символов)

  3. Генерация эмбеддингов (вызовом Mistral Embedding API получаем векторное представление каждого чанка)

  4. Сохранение в ChromaDB (эмбеддинги и метаданные записываем в векторную базу данных)

  5. Анализ GitHub репозиториев (если кандидат указывал ссылку на GitHub - система получает данные о репозиториях и примерах кода)

  6. Формирование профиля (Mistral LLM формирует для каждого кандидата структурированный json профиль с основной информацией)

Многоэтапный поиск кандидатов

Главная фишка инструмента - двухэтапное ранжирование кандидатов.

1. Семантическая оценка

Преобразуем запрос пользователя в вектор, после чего в ChromaDB находим наиболее близкие фрагменты резюме по косинусному расстоянию.

best_chunk_distance - лучший чанк
avg_chunk_distance - среднее по файлу

EmbeddingScore = 0.7 × best + 0.3 × avg

Тем самым, получаем оценку семантической близости между запросом пользователя и резюме кандидата. Чем ниже значение, тем выше семантическое соответсвие.

2. Оценка LLM на основе контекста

Находим 10 лучших кандидатов на основе EmbeddingScore и получаем их профиля из SQLite, включая результаты анализа GitHub.

Одним вызовом LLM оценивает каждого кандидата от 1 до 10 с учетом:

  • Технического стека;

  • Релевантного опыта;

  • Проектов и достижений;

  • Качества кода на GitHub;

  • Архитектурных навыков.

И подставляем все в итоговую формулу:

FinalScore = 0.3 × EmbeddingScore  +  0.7 × (1 − LLM Rating / 10)

Чем ниже финальный результат, тем выше соответствие кандидата с запросом. Таким образом, система объединяет семантический поиск с оценкой LLM на основе контекста.

Интеграция GitHub анализа

Такой же уникальной фичей является интеграция анализа кода кандидата через MCP (Machine Communication Protocol)

Во время анализа система:

  1. Извлекает ссылки на GitHub из резюме;

  2. Получает README и структуру проектов;

  3. Анализирует примеры кода;

  4. Оценивает качество архитектуры, используемые паттерны и уровень владения технологиями;

  5. Добавляет результаты в поле github_analysis профиля.

Это позволяет нам сравнивать реальный код кандидата с заявленными навыками в резюме.

Q&A по базе кандидатов

Помимо поиска кандидатов инструмент также может отвечать на любые вопросы по базе с резюме.

Например:

«Сколько кандидатов на данный момент имеют высшее образование?» или «Приведи краткое описание всех кандидатов владющих тем или иным навыком»

В этом режиме мы извлекаем все профиля и анализируется одним вызовом LLM, который формирует формирует ответ.

Количество вызовом к API Mistral

1. При индексации:

  • ~5-10 Вызовов эмбеддингов (зависит от длины резюме).

  • 1 Вызов анализа GitHub (если найдена ссылка).

  • 1 Вызов создания профиля.

    Итого: ~7-12 вызовов на одно резюме.

2. При поиске:

  • 1 Вызов валидации (проверка релевантности LLM).

  • 1 Вызов эмбеддинга.

  • 1 Вызов переранжирования (оценка llm на основе контекста).

  • 3 Вызова объяснения (по одному на каждого топового кандидата).

    Итого: 6 вызовов Mistral API на один запрос.

3. При Q&A режиме:

  • 1 вызов LLM (все профили + вопрос = ответ).

    Итого: 1 вызов Mistral API на один вопрос.

Лимиты Mistral

По дефолту в инструменте используется:

  • Mistral small ($0.15/1M input токенов и $0.6/1M output) для вопросов по базе и оценки по контексту.

  • Mistral embedding ($0.15/1M токенов) для всех эмбеддингов.

За все время разработки и тестировки инструмента я потратил:

  • Mistral small - Input tokens: 624.568 и Output tokens: 34.189.

  • Mistral embedding - Input tokens: 736.280

Это все с учетом того, что я на этапе тестировки по неосторожности закинул книгу около 150 страниц вместе со всеми резюме и где то раз 10 полностью ее проиндексировал)
Исходя из этого если мы будем хранить около 200 резюме то его 2-3 месячного стоимость интенсивного использования не будет превышать 30 центов.

Интерфейс

Для удобного пользования инструментом я создал простенькую страницу состоящую из двух чатов по бокам экрана: слева - ищем подходящих кандидатов, справа - задаем вопросы по базе с резюме.

Пример использования "AI Recruiter assistance"
Пример использования "AI Recruiter assistance"

Главный результат

Главным результатом стало объединение векторного поиска, RAG подхода и анализа кода с GitHub в едином полностью рабочем инструменте, который сможет сильно облегчить анализ большого количества резюме.

Репозиторий проекта: https://github.com/alexcfv/ai-recruiter-assistance