Кейс RAG для HR: гибридный поиск резюме (BM25 + embeddings + reranker), сокращение времени подбора на 60%. Архитектура, ROI и инструкция внедрения.
VibeLab
Поделиться

Рекрутер тратит 3–5 минут на один поисковый запрос в базе кандидатов. При 20 вакансиях в работе это 2–3 часа в день только на поиск — без оценки, без звонков, без офферов. Разбираем гибридную RAG-архитектуру, которая решает задачу — с конкретными метриками, стоимостью владения и подводными камнями.
Представьте HR-платформу с базой в 50 000+ резюме. Форматы — PDF, DOCX, выгрузки из LinkedIn, ручной ввод. Языки — русский, английский, смешанные. Структура — от идеально размеченных профилей до сплошного текста без разделов.
Рекрутер вбивает «product manager fintech опыт от 3 лет» и получает 200+ результатов. Из первых 10 — релевантны 2–3. Остальные — менеджеры продуктов из FMCG, финансовые аналитики и один продавец из «Финтех-Маркета».
По данным LinkedIn Talent Solutions, среднее время закрытия вакансии в IT — 36–42 дня. До 40% этого времени уходит на sourcing. При этом до 60–70% результатов поиска в типовых ATS-системах оказываются нерелевантными. Рекрутер физически не может обработать всю базу и работает с верхушкой выдачи — теряя сильных кандидатов, которые не попали в топ из-за формулировок.
Это не проблема конкретной платформы — это системное ограничение keyword-based поиска при масштабе.
BM25 — рабочая лошадка большинства ATS. Разбить текст на токены, построить инвертированный индекс, ранжировать по частоте совпадений. Для базы в 5 000 резюме с однородной структурой — достаточно.
На масштабе 50К+ начинаются проблемы:
Можно навесить стемминг, словари синонимов, фильтры. Но каждый костыль — ручная работа, которая не масштабируется. BM25 отвечает на вопрос «какие слова встречаются в документе». Рекрутеру нужен ответ на другой: «какой кандидат подходит под эту роль».
Semantic search на базе embeddings — логичный следующий шаг. Каждое резюме превращается в вектор, запрос — тоже, ищем ближайших соседей. Модель «понимает», что «ML-инженер» и «специалист по машинному обучению» — одно и то же.
Но на практике — набор новых проблем:
Дрейф смысла на коротких запросах. «Python senior» проецируется в область «опытный Python-разработчик», но захватывает и «senior QA с автотестами на Python», и «руководитель отдела, где команда пишет на Python».
Чувствительность к длине документа. Резюме junior — 300 слов, senior-архитектора — 2000. При преобразовании в единый вектор ключевые навыки растворяются в описании проектов и сертификатов. Точность поиска по длинным резюме падает на 15–25%.
Стоимость переиндексации. Сменили модель — переиндексация всей базы. Для 50К документов это ~40М токенов = $4–5 на один проход.
Bias в embedding-моделях. Языковые модели наследуют предвзятости из обучающих данных. В контексте HR это особенно чувствительно — embeddings могут систематически ранжировать определённые демографические группы выше.
Гибридная RAG-система объединяет сильные стороны обоих подходов и добавляет reranker для финального ранжирования.
Оба потока возвращают top-K результатов (K=50–100). Результаты объединяются через Reciprocal Rank Fusion (RRF) — алгоритм, комбинирующий ранги из разных источников без нормализации скоров.
Объединённый список (100–200 кандидатов) проходит через cross-encoder, который получает на вход пару (запрос, резюме) и возвращает скор релевантности. В отличие от bi-encoder, cross-encoder «видит» запрос и документ одновременно — на порядок точнее, но дороже.
Сравнение моделей:
| Модель | NDCG@10 | Latency (100 docs) | Стоимость |
|---|---|---|---|
| cross-encoder/ms-marco-MiniLM-L-6 | 0.71 | ~120 мс | Self-hosted |
| Cohere Rerank v3 | 0.78 | ~200 мс | $1/1000 запросов |
| bge-reranker-v2-m3 | 0.76 | ~150 мс | Self-hosted |
| cross-encoder/ms-marco-MiniLM-L-12 | 0.74 | ~180 мс | Self-hosted |
Оптимальный баланс — bge-reranker-v2-m3 на self-hosted или Cohere Rerank при ограниченных ресурсах.
Top-10–20 после reranking передаются в LLM с контекстом вакансии. Модель формирует структурированный ответ: обоснование релевантности каждого кандидата, ключевые совпадения и потенциальные риски.
Рекомендация для 50К–500К документов: Qdrant при наличии DevOps или pgvector для минимизации компонентов.
Главная ошибка — индексировать резюме как единый документ. Длинное резюме после эмбеддинга превращается в «средний» вектор, где навыки размываются.
Чанкинг по смысловым блокам:
Каждое резюме разбивается на секции:
Каждый чанк индексируется отдельно, но сохраняет ссылку на resume_id. При поиске совпадение по любому чанку поднимает всё резюме.
Pipeline предобработки:
PyMuPDF для PDF, Tesseract для сканов, python-docx для DOCXМультиязычные embeddings: оптимальный выбор — multilingual-e5-large или BGE-M3. Обе хорошо работают с code-switching — типичная ситуация для IT-резюме.
Качество RAG-системы на 30–40% зависит от формулировки запроса к LLM. Рекрутер пишет свободным текстом — LLM превращает это в структурированный запрос.
Двухэтапный prompt:
Этап 1 — извлечение требований:
Этап 2 — генерация расширенного запроса: основной запрос для векторного поиска, ключевые слова для BM25, негативные фильтры, весовые коэффициенты для reranker.
Разница между «сырым» запросом и структурированным — +20–35% к precision@10. A/B-тест на 200 сессиях: без промпт-инжиниринга precision@10 = 0.45, с двухэтапным промптом — 0.68.
Cold start. Гибридный поиск оправдывает себя от 5 000–10 000 документов. До этого порога BM25 с фильтрами работает не хуже.
Дублирование резюме. Один кандидат — три версии в базе. MinHash + LSH решают для точных дублей, «почти дубли» требуют порога косинусного сходства >0.92.
Bias в результатах. Модели на англоязычных данных могут ранжировать англоязычные резюме выше. Гендерный и возрастной bias — реальная проблема. Решение — регулярный аудит по демографическим срезам.
Latency при reranking. Cross-encoder на 200 документах — 300–500 мс. Рекомендуем ограничивать вход до 50–100 документов: NDCG@10 падает на 2–3%, latency сокращается вдвое.
Обновление индекса. Для BM25 — тривиально. Для векторного — нужен pipeline: документ → чанкинг → embedding → upsert. При 100–500 новых резюме в день задержка 5–15 минут допустима.
Бенчмарки на тестовой выборке из 500 поисковых запросов с экспертной разметкой:
| Метрика | До (BM25) | После (Hybrid RAG) | Δ |
|---|---|---|---|
| Время поиска кандидата | 3–5 мин | 40–60 сек | -70–80% |
| Precision@10 | 0.30–0.35 | 0.68–0.75 | +100–115% |
| Recall@50 | 0.40 | 0.82 | +105% |
| Время закрытия вакансии | 38 дней | 16 дней | -58% |
| Нерелевантные в top-10 | 60–70% | 15–25% | -65% |
Precision@10 = 0.72 означает: из 10 кандидатов 7 релевантны. Разница между «просмотреть 30 карточек ради 5 подходящих» и «просмотреть 10 и получить 7».
Breakdown для 50К резюме, ~1 000 запросов/день:
Embedding: индексация базы — ~$1.50 разово, обновление — ~$0.01/день, запросы — ~$0.004/день. Итого: $5–10/мес.
Reranker: self-hosted GPU (T4) — $150–300/мес, или Cohere API — $30/мес.
LLM-генерация: GPT-4o-mini ~$9/мес, Claude Haiku ~$8/мес.
Векторная БД: Qdrant Cloud от $25/мес, self-hosted $50–100/мес, pgvector — $0 дополнительно.
Elasticsearch: managed от $50/мес, self-hosted $30–70/мес.
| Вариант | Стоимость/мес |
|---|---|
| Минимальный (pgvector + Cohere + GPT-4o-mini) | $70–120 |
| Оптимальный (Qdrant + self-hosted reranker + Claude Haiku) | $250–500 |
| Enterprise (managed + GPU-кластер) | $500–1500 |
Сокращение времени закрытия вакансии с 38 до 16 дней при 20 вакансиях в месяц:
ROI за первый квартал (оптимальный вариант ~40 000 ₽/мес): экономия ~250 000 ₽ при затратах ~120 000 ₽ = ROI ~110% за 3 месяца.
Данные:
Инфраструктура:
Команда:
Сроки:
Если рекрутеры тонут в базе, а релевантные кандидаты теряются на третьей странице — имеет смысл разобрать, применим ли гибридный RAG к вашим данным.
Команда VibeLab реализовала более 20 проектов, включая внедрения RAG и ИИ-агентов для поиска и классификации в коммерческих платформах. Мы готовы провести бесплатный 30-минутный разбор вашей архитектуры поиска — оценим стек, объём данных и покажем, какой прирост точности реалистичен.
Напишите нам — обсудим, стоит ли вашей компании внедрять ИИ в рекрутинг и какой будет ROI в вашем случае.
Подписывайтесь на наш канал: @vibelogia
Поделимся опытом
8 800 201 85 68