Автоматическая Система Обзвона Клиентов

Как сделать автоматический звонок уже много написано, в том числе и на этом сайте.

Гибкость звездочка не имеет границ.

О реализации простых действий с помощью встроенных инструментов или с помощью сторонних продуктов и решений написано огромное количество статей.

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



Фон

На данный момент прошло уже больше года с момента внедрения.

Сейчас переписано около 90-95% всего программного кода системы и я имею четкое представление о том, как система развивается и как она должна развиваться.

Но на тот момент, когда мне дали задание, я имел смутное представление о том, как должен выглядеть код по техническому заданию, и у меня не было опыта общения с asterisk. Скажу сразу, основная идея не моя, моей задачей было реализовать или даже точнее изобразить то, что было описано в условиях задачи.

Но при этом самое главное то, что я был практически неограничен в выборе технологий и методов решения – что, на мой взгляд, позволило мне привести всю схему к тому виду, который я хотел.

На тот момент у компании уже был работающий колл-центр.

Около 10 очередей, от 4 до 20 операторов в каждой и около 12-15 тысяч звонков круглосуточно.

5 провайдеров для местных, междугородных и международных звонков.

За долгое время колл-центр приобрел большое количество различного функционала и собственных разработок.

Основная программная платформа — серверы на астерисках, база данных со статистикой звонков и бизнес-логикой на MySQL , а также строку скриптов на А.

Г.

И.

.



Задача

Время от времени возникает необходимость звонить клиентам по разного рода вопросам.

Это может быть необходимо периодически, например, раз в месяц (долговые, рекламные или рекламные уведомления) или время от времени (нерешенные проблемы, технические проблемы).

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

Если большая очередь звонков, операторов возвращают на входящие звонки и они помогают снять нагрузку, потом снова возвращаются обратно.

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

Машина должна напрямую связывать оператора и клиента, чтобы клиент сразу начинал разговор с живым человеком, не проходя через IVR или ожидание в очереди.

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

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

задача.

Плановая нагрузка – 2000 звонков в месяц, а в перспективе – до 10 000 – 15 000.

План реализации

На основе описания проблемных условий формируем техническую модель:
  • Требуется планировщик задач.

    Вам нужно создавать сами задания, выдавать их как в любое время, так и в определенное время (информация о балансе в 3 часа ночи никому не понадобится).

    Необходимо следить за загрузкой очереди, чтобы вызывающие задания не заполняли все слоты и не мешали регулярным входящим звонкам.

  • Нужен механизм прямого соединения оператора и клиента.

    В первую очередь при выборе свободного оператора поднимается плечо оператора и только потом плечо клиента.

    На время вызова вся логика обработки очереди должна сохраняться.

    Оператор должен быть занят и звонок должен быть засчитан в статистике.

  • По возможности требуется минимальное участие оператора.

    В данном случае я имею в виду максимальную автоматизацию со стороны оператора.

    Ему должен прийти входящий звонок, на него отвечает оператор и система сама осуществляет звонок клиенту, выбирая как направление, так и меняя статус самой задачи, независимо от того, дошли мы до клиента или нет. Подробнее я объясню ниже.

  • Требуется балансировка и резервирование как исходящих направлений, так и самих серверов asterisk. Также при выборе исходящего провайдера нужно учитывать, что помимо принадлежности к зоне существует еще и разная стоимость звонка.

  • Требуется резервирование логики отслеживания вызовов.

    Если оператор не отвечает на звонок – компьютер завис или передумал, звонок не должен просто отвалиться и потеряться.

    Если во время обычного входящего звонка мы получаем событие «АгентРингНетАнсвер» , мы можем просто выбрать другого оператора, тогда в этом случае мы получим узкое место в интервале между ответом оператора и дозвоном клиенту.



Воплощая это в жизнь



Планирование
Сейчас, с течением времени, уже трудно вспомнить хронологию исполнения, но первое, что я сразу решил, — все планирование должно быть в биллинге.

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

Мы можем задать вопрос каждому, кто, подключив какую-либо услугу, не пользуется ею.

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

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

Но такая задача с технической стороны телефонии выглядит просто как номер телефона и причину, по которой мы звоним.

Мы можем позвонить по банальной проблеме, но может потребоваться и более срочная связь с клиентом – например, звонок прервался во время разговора.

Нам необходимо максимально быстро связаться с клиентом и решить его вопрос.

Поэтому нам нужен такой параметр, как приоритет. Вы можете позвонить ему в любое время и в первую очередь.

Каждая проблема имеет свое решение.

Если у нас возникает административная проблема, мы решаем ее через клиентский отдел.

Техническая проблема решается через техподдержку.

Соответственно, при создании задачи вам необходимо выбрать, какой сервис получит задачу.

В результате через внутреннюю логику биллинга было создано представление, из которого можно получить задачу в виде: id задачи, номер телефона, приоритет и очередь, для которой была сформирована задача.

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

Например, задачи с низким приоритетом требуют 0% загрузки очереди и как минимум 1 свободного оператора.

Если приоритет выше, то нагрузка не более 70%.

Для более высокого приоритета загрузка не 100%.

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

Номер задачи записывается в локальный кэш демона, который используется для мониторинга задачи в словарной таблице в нашей базе данных вида: идентификатор задачи -> статус набора .

Если статус появился, то меняем статус задачи в биллинге и удаляем задачу из словаря и локального кеша.

Соответственно, при запуске демона все задачи со статусом собираются из биллинга.

«казнен» следить за их состоянием.



Работаем с оператором
При разработке схемы работы с оператором я выделил основные характеристики:
  • Процесс выбора и связи с оператором должен быть максимально быстрым.

    Любой занятой оператор должен быть проверен как незанят и готов к звонку не более чем за 3-5 секунд.

  • Если произошел сбой и оператор не отвечает на звонок или компьютер зависает. Необходимо сопроводить звонок обратно в очередь, и удалить из очереди проблемного оператора.

  • Необходимо отслеживать статус звонка, чтобы по завершению звонка можно было указать статус задачи либо выполнено, либо нет.
Когда я начал искать решение, то сразу понял, что текущая статистика не будет корректно видеться и не будет считать звонок оператору успешным, кроме того, было непонятно, как вытащить оператора, чтобы он принимал такие специальные звонки.

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

Собранные схемы были рабочими, но крайне нестабильными и трудоемкими при сборе статистики.

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

Выбран механизм работы с оператором Создавать .

Многие люди выступают в оппозиции вызов файла Конечно, технология классная, и имеет право на существование для своего рода задач, но для моей задачи она бы не подошла: для связи с оператором требуется моментальная реакция; сможет ли оператор принять вызов; в случае с файлом нужно следить за самим файлом, что с моей точки зрения не удобно и не рационально.

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

Также для файлов характерна локальная работа на той астериске, для которой они созданы.

То есть нам понадобится на каждом сервере локальный скрипт, который будет локально генерировать файл, попутно выясняя, какой из коллег по серверу в данный момент наименее загружен.

Полная децентрализация управления.

В моем случае я просто запрашиваю нагрузку на все сервера и, выбрав наименее загруженный, отправляю ему ами-запрос.

Библиотека использовалась для работы.

Звездочка::АМИ .

После того как оператор ответил на звонок, в сформированном звонке через локальные переменные выбираем "продлить" для звонка, где тайм-аут установлен через "Ждать" до "Набирать номер" .

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

Поэтому, когда приходит статус набора "Отмена" вызов считается необработанным и возвращается в очередь.

Деактивируем оператора из очереди.

Что происходит дальше в диалплане Набирать номер с дополнительным параметром "г" для продолжения выполнения после завершения вызова.

По завершении таймаута после разговора через "вешать трубку" exten, в словарь добавляется запись — идентификатор задания и статус набора, вставлять запрос.

Таким образом, имея рабочую машину и клиент, потягивающий ее, включение функции "автоматический ответ" — оператор только комментирует задачи в интерфейсе, вся обработка звонков происходит за ним.

Возможно, кто-то скажет, что это плохая идея, но сделано это было по нескольким причинам.

Если мы хотим, чтобы клиенты гарантированно пытались дозвониться в течение 30 секунд, то мы просто устанавливаем таймаут на команду дозвона, и не ждем никаких действий от оператора.

Опять же, мы получаем схему, сокращающую монотонную работу для людей.

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



Балансировка и резервирование
Если поискать в Интернете информацию на тему, как зарезервировать исходящие звонки, когда один из провайдеров недоступен, чаще всего вы встретите такую рекомендацию, как сделать в плане набора несколько Дозвонов один за другим.

Со своей стороны, мне хотелось сделать что-то более гибкое и динамичное.

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

Основная идея заключалась в работе с агрегированной информацией.

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

Но помимо выбора направления нужно учитывать, что любой из стволов может упасть, поэтому нужно выбирать альтернативу.

В моем случае это были voip-провайдеры, но у них тоже есть свои цены, поэтому балансировку следует выбирать от самого дешевого до самого дорогого (по качеству они абсолютно равноценны).

Для такой выборки я составил свой вес или стоимость для каждого провайдера.

В результате получился такой список ключей и значений:

  • Локальная зона => 10
  • VoIP-провайдер А => 20
  • Voip-провайдер B => 30
  • Voip-провайдер C => 40
Итак, если один из провайдеров недоступен, ищем замену от низшего к высшему или подороже.

Но помимо этого существует еще и распределение в зависимости от принадлежности номера.

То есть, например, звонить на номера Москвы следует через местного провайдера, в Сибирь или другие страны - через своего, если он у вас есть, или по междугородным и международным направлениям.

Здесь возникает необходимость определить, к какому региону относится номер.

Для этого я написал парсер Российский реестр связи в базу данных.

Выглядит как:

   

mysql> select local.get_region(903599****); +-------------------------------------+ | voicecon_new.get_region(903599****) | +-------------------------------------+ | Moskva i Moskovskaya oblast | +-------------------------------------+



Общая схема работы и различные нюансы

  • Для каждой задачи на текущий момент можно задать количество попыток, которое уменьшается с каждым статусом.

    "не выполнено" .

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

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

  • Демон агрегации нагрузки по voip-провайдерам руководствуется префиксом в названии sip-каналов.

    Можно использовать, например группы , но пока все работает отлично.

  • Он периодически пингует как VoIP-провайдеров, так и все оборудование на пути к транкам; если один из них недоступен, провайдер снимается с балансировки.

  • После выбора свободного оператора он помечается как занятый и происходит следующая логика:
  1. Запрашиваем все сервера asterisk, находящиеся в балансировке.

  2. Параметры вызова запрашиваются для текущей очереди.

    Это время ожидания ответа от оператора и клиента, "источник" номер, который увидит клиент при входящем звонке – у каждой услуги он разный.

  3. По номеру клиента выбираем направление через таблицу с регистром номеров.

  4. Выберите восходящий канал для вызова.

    Если вы установите значение 0, восходящий канал не будет участвовать в выборе; соответственно, можно балансировать, сместив приоритет провайдерам.

    Выбранный багажник будет проверен на наличие, а затем на загрузку.

    Если условия не выполняются, восходящий канал пропускается и переходим к следующему по весу.

  5. Далее выбираем сервер asterisk с наименьшим количеством каналов.

    Сколько в Редис храним все каналы со всех серверов, просто получаем общее количество через встроенную функцию хлен .

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

  6. Наконец, для параметра "переменная" формируется массив служебных переменных, на основе которых учитывается как вызов, так и выбирается направление.

    Также используется привязка текущего звонка оператора к задаче, по которой осуществляется звонок.



Заключение

Несмотря на заявленную нагрузку, за последний месяц этот показатель достиг порядка 30 785 звонков.

Изначально схема планировалась только для узкого круга задач, но переросла в сервис, способный решать широкий круг задач и справляться с большой нагрузкой.

На данный момент работа над ним не остановлена — я постоянно что-то добавляю и расширяю функционал, а также планирую провести очередной рефакторинг.

Теги: #asterisk #voip #voip #asterisk #Разработка систем связи

Вместе с данным постом часто просматривают: