Поступающий в колл-центр звонок должен быть переадресован одному из свободных консультантов, которых на профессиональном сленге принято называть агентами. Эта функциональность реализуется подсистемой маршрутизации входящих звонков, обычно входящей  в пакет услуг для корпоративных клиентов операторов IP телефонии. Правильная маршрутизация это то начало от которого начинается непростой путь к компании, умеющей работать с клиентами.
В статье мы представляем модель дискретно-временного типа, предназначенную для сравнения трех базовых стратегий маршрутизации:

  • Sequential - последовательный индексный перебор свободных агентов от начала до конца.

  • Round Robin - циклический обход с запоминанием последнего ответившего  и пропуском занятых агентов.

  • Longest Idle - выбор агента по максимуму времени простоя (idle_time).

Сравнение проводится по ключевым показателям производительности (KPI) и справедливости распределения нагрузки на агентов - fairness-метрикам.

Варианты использования модели

1. На стороне разработчиков систем маршрутизации.

Модель может служить "песочницей" для быстрого прототипирования и отладки. С ней можно  визуально оценить поведение новых стратегий, выявить логические ошибки и неэффективные паттерны на самом раннем этапе.

2. На стороне тестировщиков для валидации и стресс-тестирования.

Она позволяет:

  • Сравнивать поведение симуляции с данными из реальной системы, создавая "цифрового двойника" для проверки точности.

  • Генерировать экстремальные сценарии (резкий всплеск звонков, внезапный выход из строя части операторов), чтобы найти узкие места и пределы прочности системы.

3. На стороне конечных пользователей (клиентов) системы маршрутизации.

 Модель может использоваться как  сервис, который позволяет клиентам (например, руководителям колл-центров) проводить "What if?" анализ и подбирать оптимальную стратегию маршрутизации под свои нужды:

  • "Что будет, если мы переключимся на стратегию X? Сократится ли время ожидания?"

  • "Как справится система, если мы наймём ещё 10 операторов?"

  • "Как изменится равномерность нагрузки операторов для разных стратегий  в условиях различной интенсивности звонков?"

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

Описание модели

Ключевые особенности

  • Сравнительный анализ: Модель одновременно оценивает три базовые стратегии: Sequential, Round Robin и Longest Idle и позволяет напрямую сравнить их влияние на систему при идентичных входящих потоках звонков.

  • Гибкость и воспроизводимость: Все параметры симуляции (интенсивность звонков, число агентов, длительность вызовов и т.д.) вынесены в единый конфигурационный файл config.py. Использование фиксированного seed для разных генераторов обеспечивает воспроизводимость экспериментов.

  • Комплексные метрики: Собираются как стандартные KPI (уровень обслуживания (SLA), среднее время ожидания, длина очереди), так и метрики справедливости (индекс Джини, коэффициент вариации, эффективное число агентов). Метрики справедливости рассчитываются раздельно для двух показателей:

    • общего количества звонков принятых агентом и

    • суммарного времени загрузки агента.

    Это позволяет оценить не только общую эффективность, но и равномерность загрузки операторов, что важно для планирования ресурсов и мотивации персонала.

  • Архитектура для Colab и локальной разработки: Проект изначально спроектирован для запуска в Google Colab, где все модули создаются в сессионном хранилище при первом запуске. Это позволяет развертывать его и без установки среды Python. При этом структура проекта соответствует  подходу src-layout, что делает его легко переносимым в среды разработки.

Краткое описание модулей и элементов архитектуры

Проект имеет модульную структуру, где каждый компонент отвечает за свою часть логики:

  • src/ccsim/config.py: Центральный модуль для всех настроек симуляции. Использует dataclass со строгой типизацией параметров моделирования и включает методы для сериализации/десериализации в JSON, что удобно для сохранения конфигурации каждого запуска.

  • src/ccsim/agents.py: Определяет класс Agent  с его состояниями (свободен, занят, недоступен) и поведением. Здесь же реализованы функции для генерации стохастических событий, таких как поступление звонков (на основе пуассоновского процесса) и их длительности.

  • src/ccsim/strategies.py: Реализует логику выбора оператора. Все стратегии наследуются от абстрактного базового класса RoutingStrategy, что позвол��ет легко добавлять новые стратегии без изменения основного кода симуляции. Это ключевой элемент, обеспечивающий расширяемость модели.

  • src/ccsim/simulation.py: Ядро проекта. Содержит основной цикл дискретно-временного моделирования. На каждом шаге  симуляции обрабатываются события: поступление новых звонков, проверка освободившихся операторов, распределение вызовов из очереди и сбор промежуточных данных.

  • src/ccsim/metrics.py: Вычисляет метрики справедливости и вариабельности по собранным данным (индекс Джини, коэффициент вариации и др.).

  • src/ccsim/visualization.py: Отвечает за создание всех графиков: распределения нагрузки, динамики очереди, времени ожидания. Визуализации создаются как для отдельных прогонов, так и для сводного сравнения стратегий.

  • main.py: Точка входа, которая оркестрирует весь процесс. Она инициализирует симуляцию, запускает ее для каждой стратегии, собирает и сохраняет все артефакты (данные в CSV, графики в PNG, конфигурацию в JSON) в уникальную папку для каждого запуска runs/<timestamp>, обеспечивая  прослеживаемость экспериментов.

  • tests/test_strategies.py: Набор модульных тестов для pytest, проверяющих корректность работы каждой стратегии маршрутизации в различных сценариях, включая граничные случаи (нет свободных операторов, пустой список агентов и т.д.).

  • pyproject.toml: Задаёт систему сборки через setuptools, хранит метаданные, включает автопоиск пакетов под src‑layout и минимальные опции pytest для запуска тестов из каталога tests. Такой конфигурационный файл делает проект устанавливаемым (в том числе в editable‑режиме) и предотвращает «теневые» импорты.

  • Запуск проекта в Colab: Editable-установка  пакета и запуск main.py из корня проекта, с сохранением артефактов в runs/<timestamp>.

  • Запуск pytest: формируются отчеты покрытия в консоли и  HTML/JUnit.

Рабочий процесс

  • Загрузка и запуск блокнота "HABR_call_center_simulation_Python_Project.ipynb" в Google Colab. В результате осуществляется генерация структуры и исходников из блокнота Colab с записью файлов в сессионное хранилище, последующей установкой пакета и запуском сценария main.py из корня проекта. Если хотите сохранить свои изменения - сделайте копию загруженного блокнота и работайте с ней.

  • Запуск тестов - запуск ячейки Запуск pytest.

  • Мульти‑прогоны с разными параметрами из модуля конфигурации и сравнением стратегий по  fairness-метрикам  и SLA, включая комбинированные визуализации и отчёты в runs/<timestamp>.

    • Для повторных запусков с измененным набором параметров достаточно перезапустить ячейку модуля конфигурации src/ccsim/config.pyи ячейку Запуск проекта в Colab.

    • В качестве примера можно выполнить три цикла моделирования последовательно задавая значения параметра  lambda_rate из списка [0.65, 0.75, 0.85] в модуле config.py. Для  дефолтного набора значений остальных параметров это соответствует низкой,  пороговой и чрезмерной нагрузке на систему.

    • Видно, что в варианте с низкой нагрузкой стратегии имеют существенные различия в распределениях времени занятости агентов и fairness-метриках, для пороговой нагрузки — разница меньше, при чрезмерной — разница минимальна.

    • Для рассматриваемого примера  из fairness-метрик лучшую чувствительность демонстрирует коэффициент вариации.

    • Наиболее наглядно разница между стратегиями видна на графиках распределений времени суммарной занятости агентов: combined_busy_times_kde.png.

Рисунок 1. Распределения времени общей занятости агентов при lamda rate 0.70.
Рисунок 1. Распределения времени общей занятости агентов при lamda rate 0.70.
Рисунок 2. Визуализация равномерности распределения количества звонков между агентами для двух стратегий при lambda rate 0.65.
Рисунок 2. Визуализация равномерности распределения количества звонков между агентами для двух стратегий при lambda rate 0.65.

Параметры моделирования

Параметры в src/ccsim/config.py описывают поток вызовов, поведение агентов, ограничения очереди и критерии SLA, а также управляют длиной и детальностью симуляции для воспроизводимых экспериментов. Они заданы в dataclass SimulationConfig и  сериализуются в JSON для фиксации настроек каждого прогона.

Параметры модели

  • seed: инициализация генераторов случайных чисел NumPy и Python.

  • lambda_rate: интенсивность поступления звонков (ед/сек) для пуассоновской генерации времени поступления звонка.

  • num_agents: количество операторов, участвующих в маршрутизации вызовов.

  • num_calls: общее число синтетически сгенерированных звонков за прогон симуляции.

  • max_idle_time: верхняя граница времени простоя агента в модели, используемая для начальной инициализации агентов.

  • min_call_duration, max_call_duration: минимальная и максимальная длительность разговора в секундах для дискретной генерации продолжительностей.

  • agent_logout_prob, agent_login_prob: вероятности выхода агента «в офлайн» и возвращения «в онлайн» на каждом шаге симуляции.

  • agent_response_prob: вероятность того, что выбранный стратегией агент примет назначенный вызов.

  • max_queue_size: максимальный размер очереди ожидания; при превышении входящий вызов фиксируется как пропущенный.

  • service_level_threshold: SLA‑порог по времени ожидания (в секундах), в который должен уложиться ответ, чтобы быть засчитанным.

  • max_wait_before_abandonment: максимальное время ожидания до сброса вызова клиентом.

  • max_simulation_steps: ограничение длины симуляции по шагам; если не задано, устанавливается автоматически как num_calls × 10 в post_init - предотвращение бесконечного цикла.

  • verbose: флаг включения подробных визуализаций и отчётных графиков в ходе симуляции.

Что дальше

В статье описана модель начального уровня. Она может быть расширена в нескольких направлениях:

Повышение реалистичности:

  • Более сложные модели поведения: Добавить неоднородность агентов (разные уровни, графики работы, усталость, агенты-роботы),  более сложное поведение клиентов (повторные звонки, разные уровни терпения, интенсивность входящих звонков с учетом различных цикличностей и влияния экзогенных факторов).

  •  Новые стратегии маршрутизации: Реализовать skill-based routing (маршрутизация на основе навыков), predictive routing (с использованием прогностических моделей для предсказания времени обработки) или гибридные подходы.

Интеграция и инструменты:

  • CLI (Command-Line Interface): Перейти от гибридного варианта Colab  к  полноценному интерфейсу командной строки для запуска симуляций с параметрами, что упростит автоматизацию и интеграцию в CI/CD пайплайны.

  • Интерактивный дашборд: Разработать веб-дашборд (например, с помощью Dash или Streamlit) для интерактивного анализа результатов, где пользователи могли бы менять параметры и сразу видеть "what-if" сценарии.

  • Интеграция с СУБД: Для масштабных экспериментов  можно настроить сохранение результатов не в CSV-файлы, а в колоночную базу данных (например,  DuckDB)  для более эффективного быстрого анализа.

Углубленный анализ:

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

  • Оптимизация параметров: Использовать методы оптимизации (например, байесовскую оптимизацию) для автоматического подбора наилучших параметров колл-центра (число операторов, размер очереди) для достижения заданных KPI.

Смена парадигмы моделирования:

  • От дискретно-временной перейти к дискретно-событийной: использовать в качестве основы один из фреймворков дискретно‑событийного (DES) моделирования.

Заключительные соображения

В русском языке термин "Моделирование" обладает полисемией. В зависимости от контекста он может обозначать и этап построения модели и этап ее применения. Статья ограничена только первым из них.

Ссылка на блокнот Colab

Открыть блокнот Colab


Владимир Сюр, Сергей Сюр