Компонент CPD (детектор ответов)
Описание
Применяется в исходящих кампаниях для детекции ответа "живого" человека.
Записывает начало разговора в течение указанного времени (по умолчанию до 7 секунд) и за это время определяет тип источника звука: человек, робот/IVR, тональный сигнал, факс или тишина.
Анализ выполняется в три этапа.
Первый этап — быстрый статистико-эвристический анализ сигнала. Параллельно с ним второй этап ищет в звуке характерные частоты, заранее заданные инженером.
Третий этап выполняется только если по итогам первых двух распознан человек: записанный звук сравнивается с базой аудиоотпечатков известных роботов и автоответчиков, чтобы отсеять ложные срабатывания.
Алгоритм не требователен к ресурсам системы. Параметры первого этапа можно дообучить на собственных размеченных записях, а базу отпечатков — построить на собственных шаблонах.
Индекс |
|
Краткое название |
|
Типы сценариев |
|
Стартовый модуль |
|
Режим |
Асинхронный |
Иконка |
|
Характер разветвления |
Разветвляющий, замыкающий |
Свойства
| Спецификация | Описание |
|---|---|
Название: |
Аргумент, содержащий время в секундах. Определяет сколько времени будет накапливаться запись разговора для дальнейшего анализа детектором ответа. |
Название: |
Признак сохранения файла записи, отправленного сервису детектора ответа. Сохранение выполняется в каталог
|
Название: |
Переменная, куда заносится причина завершения работы компонента. |
Название: |
Компонент, которому передается управление после обнаружения "живого" человека детектором ответа. |
Название: |
Компонент, которому передается управление в случае если детектор ответа не обнаружил в записи "живого" человека. |
Название: |
Компонент, которому передается управление в случае возникновения ошибки. |
Принцип работы
Анализ выполняет консольное приложение cpd, входящее в состав платформы (./era_env/priv/bin/cpd/cpd).
Компонент запускает cpd в режиме анализа и передает ему звук вызываемой стороны через стандартный ввод (stdin).
Приложение "слушает" начало разговора и отвечает на единственный вопрос: ответил ли на звонок живой человек.
Это позволяет автоматизированному дозвону подключать оператора только тогда, когда с высокой вероятностью на линии человек, а не тишина, факс, гудки или робот.
Компонент завершается успехом только при результате human.
Входные данные и результат
На вход cpd принимает сырые PCM-данные без заголовка: 8000 Гц, 16 бит, моно.
Данные читаются порциями по мере поступления и сразу пропускаются через анализатор.
Результат выводится в stdout одной строкой:
| Результат | Значение |
|---|---|
|
Ответил живой человек. Единственный результат, при котором компонент завершается успехом. |
|
Робот, автоответчик, голосовое меню, музыка при ожидании. |
|
Тональный сигнал: гудки, сигнал "занято", сигнал автоответчика и т. п. |
|
Факс. |
|
За время анализа не обнаружено ни одной значимой реплики. |
Условия завершения
cpd завершает работу и выдает результат при первом из событий:
-
Текущий этап анализа принял решение.
-
Данные в stdin не поступают дольше, чем
--recv-timeout(по умолчанию 3000 мс). -
cpdработает дольше, чем--timeout(по умолчанию 7000 мс). -
Поток stdin закрыт отправителем.
При завершении по таймауту результат выдается по тем данным, что успели накопиться. Если значимых реплик не было, результат silence.
Этапы анализа
Этап 1. Статистико-эвристический анализ
Легковесный алгоритм, работающий в потоке по мере поступления данных. Он выделяет в звуке реплики и паузы между ними и по их длительности и характеру принимает решение:
-
человек определяется после паузы, следующей за короткой приветственной репликой абонента;
-
робот или IVR определяется по длинной непрерывной реплике;
-
тональный сигнал и факс определяются по стабильной амплитуде сигнала, факс — по большей длительности;
-
тишина определяется по истечении таймаута без значимых реплик.
Алгоритм использует набор параметров. Значения по умолчанию зашиты в программу и не оптимальны. Их можно подобрать под собственные записи в режиме обучения (см. Режим обучения (learn)). Подобранные значения сохраняются в файле SettingsML.json, который передается cpd ключом --ml-settings-path.
Этап 2. Поиск характерных частот
Работает параллельно с первым этапом на тех же данных. В отличие от первого этапа, здесь ничего не подбирается автоматически: искомые признаки задает инженер. Рассмотрев запись робота в аудиоредакторе, он отмечает, на каких частотах и в каком временном интервале виден характерный всплеск, и описывает это в файле SettingsSpectrum.json (см. SettingsSpectrum.json). cpd проверяет каждый описанный интервал, как только тот полностью принят, и при совпадении немедленно завершает анализ с результатом, указанным для этого интервала.
Если файл не задан, поиск характерных частот не выполняется.
Этап 3. Поиск по базе аудиоотпечатков
Первые два этапа работают одновременно, и анализ завершается, как только один из них принял решение. Третий этап выполняется, только если это решение — human (то есть первый этап распознал человека, а второй не нашел характерных частот) и задана база отпечатков (--fingerprints-db). Цель этапа — отсеять роботов и автоответчики, которые по характеру реплик похожи на человека.
Вся принятая запись сравнивается с базой отпечатков, построенной заранее из шаблонных записей роботов (см. Режим построения базы отпечатков (rebuild-fingerprints)). Отпечатки — это подробное автоматически построенное описание характерных частот записи во времени, то есть то же, что инженер делает вручную на втором этапе, но без участия человека и с большей детализацией.
Если запись совпала с шаблоном, результат заменяется на тип этого шаблона. Если совпадений нет, результат остается human.
Если база не задана, третий этап не выполняется.
Файлы настроек
SettingsML.json
Параметры первого этапа. Файл формируется автоматически в режиме обучения, вручную не редактируется. Если файл не задан, используются значения по умолчанию.
SettingsSpectrum.json
Описания характерных частот для второго этапа. Файл составляется инженером вручную и представляет собой JSON-массив, каждый элемент которого описывает один временной интервал:
| Поле | Тип | Смысл |
|---|---|---|
|
строка |
Произвольное имя для удобства инженера. |
|
число |
Начало интервала в мс от начала данных, поступающих в stdin. |
|
число |
Конец интервала в мс от начала данных, поступающих в stdin. Должен быть больше |
|
массив |
Список диапазонов частот |
|
строка |
Результат при совпадении: |
Интервалы отсчитываются от момента, когда компонент начал передавать звук в cpd, поэтому размечать в аудиоредакторе нужно ту же запись, что уходит в cpd, с тем же началом.
Пример: робот, у которого в интервале 0.5…1.5 с и 1…2 с от начала данных два самых сильных пика лежат около 100 Гц и 200 Гц.
[
{
"name": "Robot1",
"from": 500,
"to": 1500,
"spectrum": [{"min": 195, "max": 205}, {"min": 97, "max": 103}],
"result": "IVR"
},
{
"name": "Robot1-late",
"from": 1000,
"to": 2000,
"spectrum": [{"min": 195, "max": 205}, {"min": 97, "max": 103}],
"result": "IVR"
}
]
База отпечатков
Бинарный файл cpd_fingerprint.db, формируемый cpd в режиме построения базы. Путь к нему передается ключом --fingerprints-db. Базу нужно перестраивать после любого изменения набора шаблонов.
Размещение на платформе
Файлы SettingsML.json, SettingsSpectrum.json и база отпечатков cpd_fingerprint.db располагаются в каталоге :SYNC/domains/<YOUR_DOMAIN>/data/cpd, где <YOUR_DOMAIN> — имя домена. Компонент передает пути к ним в cpd при каждом запуске.
Чтобы применить новые настройки, достаточно заменить файлы в каталоге: cpd читает их при каждом запуске, перезапуск платформы не требуется.
Режимы работы cpd
Режим задается ключом --mode:
| Режим | Назначение |
|---|---|
|
Анализ звука из stdin. Результат — тип источника звука. |
|
Подбор параметров этапа 1 по размеченным записям. Результат — |
|
Построение базы аудиоотпечатков из шаблонных записей. Результат — файл базы. |
Режим analyze компонент запускает автоматически при каждом вызове, вмешательство инженера не требуется.
Режимы rebuild-fingerprints и learn инженер запускает вручную при каждом обновлении набора размеченных записей: базу отпечатков перестраивать необходимо, обучение повторять желательно. Полученные файлы размещаются на платформе вручную (см. Размещение на платформе).
Ключ --help выводит справку по всем параметрам.
Режим анализа (analyze)
Пример того, как компонент вызывает cpd для анализа:
cpd \
--mode=analyze \
--ml-settings-path=/var/lib/era_files/syncroot/domains/pbx.era-platform.ru/data/cpd/SettingsML.json \
--spectrum-settings-path=/var/lib/era_files/syncroot/domains/pbx.era-platform.ru/data/cpd/SettingsSpectrum.json \
--fingerprints-db=/var/lib/era_files/syncroot/domains/pbx.era-platform.ru/data/cpd/cpd_fingerprint.db \
--timeout=7000 \
--recv-timeout=3000
| Параметр | По умолчанию | Описание |
|---|---|---|
|
не задан |
Путь к |
|
не задан |
Путь к |
|
не задан |
Путь к базе аудиоотпечатков. Необязательный. Если не задан, третий этап не выполняется. |
|
7000 |
Общий таймаут работы в мс. По его истечении выдается результат по накопленным данным. |
|
3000 |
Таймаут ожидания очередной порции данных в stdin в мс. Если данных нет дольше этого времени, выдается результат по накопленным данным. |
|
выключен |
Выводить расширенный результат (см. ниже). |
Вывод в stdout — одна строка с результатом. С ключом --verbose выводятся три строки:
-
результат (
human,ivr,tone,fax,silence); -
путь к совпавшему шаблону из базы отпечатков, либо пустая строка, если совпадения не было;
-
степень совпадения с шаблоном (число от 0 до 1), либо
0.
Если необходимо проверить работоспособность cpd на конкретной записи, можно воспользоваться таким bash-скриптом, который отрезает от wav-файла (PCM, 8000 Гц, 16 бит, моно) заголовок в 44 байта и подает оставшиеся сырые PCM-данные в stdin cpd:
#!/bin/bash
CPD_DIR=/var/lib/era_files/syncroot/domains/pbx.era-platform.ru/data/cpd
SAMPLE_FILE=/some/path/to/sample.wav
dd if=$SAMPLE_FILE skip=44 bs=64 status=none | \
cpd \
--mode=analyze \
--ml-settings-path=$CPD_DIR/SettingsML.json \
--spectrum-settings-path=$CPD_DIR/SettingsSpectrum.json \
--fingerprints-db=$CPD_DIR/cpd_fingerprint.db \
--timeout=7000 \
--recv-timeout=3000 \
--verbose
Так можно увидеть, как cpd отработает конкретную запись, сработал ли третий этап и с каким шаблоном совпала запись.
Режим обучения (learn)
Обучение — это подбор параметров первого этапа по заранее размеченному (разложенному по папкам) набору записей с учетом биаса (приоритета). Биас задает, какая ошибка дороже: потерять живого абонента или передать оператору не-человека.
Как проходит обучение:
-
Записи из каталога данных загружаются в память. Из каждой используются только первые 10 секунд.
-
Первая итерация выполняется на значениях по умолчанию. Существующий
SettingsML.jsonв режиме обучения не читается: каждый запуск начинается с нуля. -
На каждой следующей итерации подбирается новый набор параметров, все записи прогоняются через первый этап, и вычисляется оценка качества с учетом биаса.
-
Лучший набор сохраняется в выходной файл сразу, как только он найден, поэтому прерванное обучение не теряет результат.
В обучении участвует только первый этап. Характерные частоты и база отпечатков в нем не используются.
Подбор параметров случайный, поэтому результаты разных запусков могут отличаться. При необходимости обучение можно запустить несколько раз и выбрать лучший результат по отчету.
Пример командной строки:
cpd \
--mode=learn \
--learn-bias=0 \
--learn-iterations=10000 \
--learn-data-dir-path=/some/path/to/wavs/ \
--learn-output-file-path=/var/lib/era_files/syncroot/domains/pbx.era-platform.ru/data/cpd/SettingsML.json
| Параметр | По умолчанию | Описание |
|---|---|---|
|
0 |
Приоритет от −9 до +9. −9 — допускать потерю живых ответов, +9 — допускать плохие звонки на операторов, 0 — нейтрально. |
|
10000 |
Количество итераций. 1 — только вывод текущей статистики на значениях по умолчанию, 10000 — реальное обучение. |
|
— |
Путь к каталогу с размеченными данными (см. Данные для обучения). Обязательный. |
|
не задан |
Путь к выходному |
Выходной файл записывается только если найден набор параметров лучше значений по умолчанию. Если улучшения не было (в том числе при --learn-iterations=1), файл не создается.
По ходу обучения в консоль выводятся число записей каждого класса, каждое найденное улучшение и итоговый отчет: достигнутая точность, доли потерянных людей и плохих звонков на операторов, среднее время определения и матрица ошибок (строка — истинный класс по имени папки, столбец — результат анализатора).
Готовый SettingsML.json следует разместить в каталоге :SYNC/domains/<YOUR_DOMAIN>/data/cpd, заменив предыдущий.
Режим построения базы отпечатков (rebuild-fingerprints)
Строит базу аудиоотпечатков из каталога шаблонных записей. Шаблоны — это записи роботов, автоответчиков, голосовых меню и других сигналов, которые нужно уверенно отсеивать на третьем этапе анализа.
Пример командной строки:
cpd \
--mode=rebuild-fingerprints \
--templates-dir=/some/path/to/templates/ \
--fingerprints-db=/var/lib/era_files/syncroot/domains/pbx.era-platform.ru/data/cpd/cpd_fingerprint.db
| Параметр | По умолчанию | Описание |
|---|---|---|
|
— |
Путь к каталогу с шаблонными записями (см. Шаблоны для базы отпечатков). Обязательный. |
|
— |
Путь к создаваемому файлу базы. Обязательный. Существующий файл перезаписывается целиком. |
Требования к шаблонным записям описаны в разделе Шаблоны для базы отпечатков.
По завершении в консоль выводится время построения в миллисекундах.
Готовую базу cpd_fingerprint.db следует разместить в каталоге :SYNC/domains/<YOUR_DOMAIN>/data/cpd, заменив предыдущую.
Подготовка записей
Записи нужны в двух случаях: для обучения параметров первого этапа и для построения базы отпечатков. Требования к формату и разметке общие, требования к содержимому записей различаются и описаны отдельно.
Формат файлов
Формат: *.wav, PCM, 8000 Гц, 16 бит, моно.
Записи должны быть теми же, что приходят в реальных звонках, без последующей обработки (нормализации, шумоподавления, сжатия). Лучший источник — записи реальных вызовов кампании, сделанные платформой. Если запись получена из другого источника, ее нужно привести к требуемому формату, например:
ffmpeg -i source.wav -ar 8000 -ac 1 -c:a pcm_s16le result.wav
Правила разметки
Файлы раскладываются по подпапкам, имя подпапки задает класс записи. Регистр имени не важен, вложенность произвольная: значение имеет только имя папки, непосредственно содержащей файл. Имена самих файлов произвольные.
| Папка | Что кладется |
|---|---|
|
Живые ответы людей: человек берет трубку и отвечает приветствием. |
|
Роботы, автоответчики, голосовые меню, музыка при ожидании, речевые сообщения оператора связи. |
|
Тональные сигналы: гудки, сигнал "занято", сигнал автоответчика перед записью и т. п. |
|
Факс. |
|
Тишина или фоновый шум без речи и сигналов. |
Класс определяется по тому, что слышно в первые секунды записи, то есть по тому результату, который cpd должен выдать для этого звонка. Если запись начинается с робота, а через несколько секунд отвечает человек, это IVR. Если человек отвечает позже, чем длится анализ (по умолчанию 7 секунд), такую запись лучше не использовать вовсе.
Каждая запись должна относиться ровно к одному классу. Записи, в которых класс неочевиден (сильные помехи, обрыв, наложение сигналов), в набор не включаются: одна неверно размеченная запись портит результат сильнее, чем ее отсутствие.
Данные для обучения
Обучение подбирает параметры под то, как реально выглядит начало звонка, поэтому записи должны воспроизводить именно поток, который cpd получает от компонента:
-
запись начинается с момента ответа на вызов (кто бы или что бы ни ответило), то есть с того момента, когда компонент начинает передавать звук в
cpd. Начало не обрезается до первой реплики и не дополняется тишиной: анализатор учитывает паузу перед первым словом; -
полезная длительность — первые 10 секунд, остальное игнорируется. Записи короче 2–3 секунд малоинформативны;
-
никаких посторонних звуков после начала анализа: речь оператора, сигналы перевода вызова и т. п. должны быть отрезаны;
-
нужны примеры всех пяти классов, в первую очередь
HumanиIVR. Чем разнообразнее записи внутри класса (разные люди, разные роботы, разное качество связи), тем лучше подобранные параметры переносятся на реальные звонки; -
объем классов должен быть сопоставим. Если записей
Humanв десять раз больше, чемIVR, оценка качества будет искажена.
Файлы из папок с именами, не совпадающими с классами, в обучении не участвуют.
Шаблоны для базы отпечатков
Шаблон — эталонная запись конкретного робота, автоответчика или голосового меню. По шаблону строятся отпечатки, с которыми сравнивается реальный звонок, поэтому шаблон должен содержать только то, что звучит в реальном звонке от этого источника:
-
запись содержит саму реплику робота от ее начала: приветствие, музыкальную заставку, голосовое меню. Тишина перед репликой не мешает, но и не нужна;
-
в шаблон не должно попасть ничего, кроме источника: ни гудков до соединения, ни речи человека, ни звуков после окончания реплики. Все лишнее отрезается в аудиоредакторе;
-
длительность шаблона — несколько секунд, достаточных, чтобы охватить ту часть реплики, которая успевает прозвучать за время анализа (по умолчанию 7 секунд). Очень короткие или почти беззвучные записи в поиске не участвуют;
-
на каждого робота достаточно одного шаблона. Если у робота несколько разных приветствий, для каждого нужен отдельный файл;
-
в базу имеет смысл класть только записи, совпадение с которыми должно менять результат: роботов и автоответчики. Совпадение с шаблоном типа
Humanрезультат не изменит.
Тип шаблона определяется именем подпапки по тем же правилам разметки. Файлы из подпапок с другими именами получают тип IVR.