Разработка AI-системы предиктивного набора номера (Predictive Dialer)

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
Разработка AI-системы предиктивного набора номера (Predictive Dialer)
Сложная
~1-2 недели
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    853
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825

Разработка AI-системы предиктивного набора номера (Predictive Dialer)

Predictive Dialer автоматически набирает номера и соединяет с оператором только готовые звонки (когда клиент ответил). Ключевая задача: максимизировать productive talk time операторов, минимизируя abandoned calls и время ожидания.

Алгоритм предиктивного набора

from dataclasses import dataclass
from typing import Callable
import asyncio
import numpy as np

@dataclass
class DialerMetrics:
    active_calls: int
    available_agents: int
    avg_call_duration: float     # средняя продолжительность разговора
    avg_answer_rate: float       # 0.3 = 30% контактов отвечают
    avg_ring_time: float         # среднее время до ответа
    abandonment_rate: float = 0  # % брошенных звонков (целевой: <3%)

class PredictiveDialer:
    MAX_ABANDONMENT_RATE = 0.03  # 3% по стандарту FCC/регуляторам
    PACING_ADJUSTMENT_STEP = 0.05

    def __init__(self):
        self.pacing_factor = 1.2  # начальный коэффициент
        self.metrics_window = []

    def calculate_calls_to_initiate(self, metrics: DialerMetrics) -> int:
        """Вычисляем сколько звонков инициировать"""
        available = metrics.available_agents - metrics.active_calls

        if available <= 0:
            return 0

        # Базовое предсказание: учитываем answer rate
        predicted = int(available * self.pacing_factor / metrics.avg_answer_rate)

        # Корректировка по abandonment rate
        if metrics.abandonment_rate > self.MAX_ABANDONMENT_RATE:
            self.pacing_factor = max(1.0, self.pacing_factor - self.PACING_ADJUSTMENT_STEP)
        elif metrics.abandonment_rate < self.MAX_ABANDONMENT_RATE * 0.5:
            self.pacing_factor = min(3.0, self.pacing_factor + self.PACING_ADJUSTMENT_STEP)

        return max(0, predicted - metrics.active_calls)

    async def run_dialing_loop(
        self,
        contacts: list[dict],
        get_metrics: Callable[[], DialerMetrics],
        initiate_call: Callable[[dict], None]
    ):
        """Основной цикл набора"""
        contact_index = 0

        while contact_index < len(contacts):
            metrics = await get_metrics()
            calls_to_make = self.calculate_calls_to_initiate(metrics)

            for _ in range(calls_to_make):
                if contact_index >= len(contacts):
                    break
                contact = contacts[contact_index]
                if await self.should_call(contact):
                    await initiate_call(contact)
                contact_index += 1

            await asyncio.sleep(1)  # пересчёт каждую секунду

ML-предикция answer rate

class AnswerRatePredictor:
    """Предсказываем вероятность ответа для каждого контакта"""

    FEATURES = [
        "hour_of_day",        # лучшее время суток для звонка
        "day_of_week",
        "previous_attempts",  # число предыдущих попыток
        "last_contact_days",  # дней с последнего контакта
        "phone_type",         # мобильный/городской
        "timezone_offset",    # часовой пояс контакта
        "segment",            # сегмент клиента
    ]

    def predict_answer_probability(self, contact: dict, now: datetime) -> float:
        """Возвращает вероятность ответа 0–1"""
        features = self.extract_features(contact, now)
        return self.model.predict_proba([features])[0][1]

Оптимальное время звонка

OPTIMAL_CALL_WINDOWS = {
    "B2C": {
        "monday-friday": [(9, 12), (17, 20)],
        "saturday": [(10, 13)],
        "sunday": []  # не звоним в воскресенье
    },
    "B2B": {
        "monday-friday": [(10, 12), (14, 17)],
    }
}

Сроки: базовый предиктивный дайлер — 6–8 недель. Полная система с ML-оптимизацией — 3–4 месяца.