Разработка AI-цифрового рекрутера (AI Recruiter)

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1Все 1566 услуг
Разработка AI-цифрового рекрутера (AI Recruiter)
Средний
от 2 недель до 3 месяцев
Часто задаваемые вопросы

Направления AI-разработки

Этапы разработки AI-решения

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1284
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1196
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    901
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1119
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    586
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    853

AI Рекрутер — цифровой сотрудник для найма

AI Рекрутер автоматизирует полный цикл подбора персонала: парсинг вакансий в job description, публикация на платформах, скрининг входящих резюме, scheduling интервью, персонализированная коммуникация с кандидатами, ведение воронки в ATS. Позволяет одному рекрутеру управлять значительно большим объёмом вакансий без потери качества.

Генератор Job Description

from openai import AsyncOpenAI
from pydantic import BaseModel

client = AsyncOpenAI()

class JobDescription(BaseModel):
    title: str
    department: str
    level: str
    responsibilities: list[str]
    required_skills: list[str]
    preferred_skills: list[str]
    about_team: str
    compensation_range: str

async def generate_job_description(
    hiring_manager_brief: str,
    similar_jd_examples: list[str] = None,
) -> str:
    """Генерирует JD из краткого брифинга от нанимающего менеджера"""

    examples_context = ""
    if similar_jd_examples:
        examples_context = f"\nПримеры похожих вакансий для стиля:\n{similar_jd_examples[0][:500]}"

    response = await client.chat.completions.create(
        model="gpt-4o",
        messages=[{
            "role": "system",
            "content": f"""Ты — опытный HR. Пиши job descriptions, которые привлекают сильных кандидатов.
Избегай: требований-списков из 20 пунктов, нереалистичных требований, корпоративного новояза.
Фокус: что будет делать человек, почему это интересно, кто нам нужен.{examples_context}"""
        }, {
            "role": "user",
            "content": f"Бриф от нанимающего менеджера:\n{hiring_manager_brief}",
        }],
        temperature=0.4,
    )

    return response.choices[0].message.content

Мульти-платформенная публикация

class JobBoardPublisher:

    async def publish_to_all_boards(self, jd: JobDescription) -> dict:
        """Публикует вакансию на всех платформах одновременно"""

        results = await asyncio.gather(
            self.publish_hh(jd),
            self.publish_avito_rabota(jd),
            self.publish_linkedin(jd),
            self.publish_superjob(jd),
            return_exceptions=True,
        )

        return {
            "hh.ru": results[0] if not isinstance(results[0], Exception) else str(results[0]),
            "avito": results[1] if not isinstance(results[1], Exception) else str(results[1]),
            "linkedin": results[2] if not isinstance(results[2], Exception) else str(results[2]),
            "superjob": results[3] if not isinstance(results[3], Exception) else str(results[3]),
        }

    async def publish_hh(self, jd: JobDescription) -> str:
        response = await hh_api.post(
            endpoint="/vacancies",
            data={
                "name": jd.title,
                "area": {"id": "1"},  # Москва
                "description": format_for_hh(jd),
                "key_skills": [{"name": s} for s in jd.required_skills[:10]],
                "employment": {"id": "full"},
                "schedule": {"id": "fullDay"},
            }
        )
        return response["id"]

Скрининг и ранжирование кандидатов

class CandidateScreener:

    async def screen_batch(
        self,
        candidates: list[dict],
        job_description: JobDescription,
        required_skills: list[str],
    ) -> list[dict]:
        """Параллельный скрининг кандидатов"""

        semaphore = asyncio.Semaphore(10)

        async def screen_one(candidate: dict) -> dict:
            async with semaphore:
                return await self._screen_single(
                    candidate, job_description, required_skills
                )

        results = await asyncio.gather(*[screen_one(c) for c in candidates])
        return sorted(results, key=lambda x: -x["score"])

    async def _screen_single(
        self,
        candidate: dict,
        jd: JobDescription,
        required_skills: list[str],
    ) -> dict:

        from pydantic import BaseModel
        from typing import Literal

        class ScreeningResult(BaseModel):
            score: int                   # 0-100
            recommendation: Literal["strong_yes", "yes", "maybe", "no"]
            required_skills_match: int   # процент совпадения
            experience_match: str
            red_flags: list[str]
            green_flags: list[str]
            personalized_question: str   # Вопрос для интервью

        result = await client.beta.chat.completions.parse(
            model="gpt-4o",
            messages=[{
                "role": "system",
                "content": f"""Оцени кандидата объективно. Требуемые навыки: {required_skills}.
НЕ делай предположений о скрытых навыках. Учитывай ТОЛЬКО явно указанный опыт."""
            }, {
                "role": "user",
                "content": f"Вакансия:\n{jd.title}\n\nРезюме:\n{candidate['resume_text']}"
            }],
            response_format=ScreeningResult,
            temperature=0,
        )

        return {
            "candidate_id": candidate["id"],
            "name": candidate["name"],
            "email": candidate["email"],
            **result.choices[0].message.parsed.model_dump(),
        }

Автоматизация коммуникации

class CandidateCommunicator:

    async def send_invite(self, candidate: dict, vacancy: dict) -> None:
        invite_text = await client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[{
                "role": "system",
                "content": "Напиши приглашение на интервью. Тон: уважительный, конкретный. 3-4 предложения."
            }, {
                "role": "user",
                "content": f"Кандидат: {candidate['name']}, вакансия: {vacancy['title']}, компания: {vacancy['company']}"
            }],
        )

        await email_service.send(
            to=candidate["email"],
            subject=f"Приглашение на интервью — {vacancy['title']} в {vacancy['company']}",
            body=invite_text.choices[0].message.content + f"\n\nДля записи: {CALENDLY_URL}",
        )

    async def send_rejection(self, candidate: dict, reason: str) -> None:
        """Персонализированный отказ с конкретной причиной"""
        rejection = await client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[{
                "role": "system",
                "content": "Напиши вежливый отказ. Без клише. Укажи конкретную причину (уважительно). 2-3 предложения."
            }, {
                "role": "user",
                "content": f"Кандидат: {candidate['name']}, причина отказа: {reason}"
            }],
        )
        await email_service.send(
            to=candidate["email"],
            subject="Статус вашей заявки",
            body=rejection.choices[0].message.content,
        )

Практический кейс: IT-компания, 30 открытых вакансий

Ситуация: 3 рекрутера, 30 активных вакансий, 200+ резюме/день, time-to-hire 52 дня.

Автоматизировано AI Рекрутером:

  • Парсинг резюме с hh.ru каждые 2 часа
  • Скрининг и скоринг (первичная фильтрация 70%)
  • Автоматические отказы нерелевантным кандидатам
  • Приглашения топ-30% с Calendly-ссылкой
  • Напоминания кандидатам не ответившим на интервью-запрос

Результаты:

  • Time-to-hire: 52 → 31 день
  • Скорость ответа кандидату: 3.2 дня → 40 минут
  • Рекрутеры тратят время на: интервью, оффер, онбординг
  • Concordance (AI vs рекрутер на 300 совместно оцененных): 87%

Сроки

  • JD-генератор и публикация: 1–2 недели
  • Скрининг и ранжирование: 2–3 недели
  • Коммуникационные шаблоны и интеграция с email: 1 неделя
  • ATS-интеграция (HH, Huntflow и пр.): 1–2 недели
  • Итого: 5–8 недель