Всем привет! Меня зовут Наумов Герман, я работаю в Лаборатории машинного обучения Альфа-Банка, и я расскажу, как мы автоматизировали внутренние процессы, упростили работу операторов чата с физическими лицами. Задача не особо простая и тюнингом гиперпараметров как на Kaggle не решается. Но решается.

Небольшое вступление
Когда клиент обращается в чат или звонит на горячую линию, его встречает чат-бот (или войс-бот, голосовой помощник). Если бот не может решить проблему, клиента переключают на оператора. После завершения разговора оператор заполняет специальную форму, где отвечает на несколько вопросов:
По какому продукту обращался клиент (например, Дебетовая карта).
По какому подпродукту обращался клиент (например, платежный стикер).
Какая была тема обращения (блокировка/разблокировка).
Какая была подтема обращения (блокировка по причине утери).
Канал, где произошла проблема (сайт банка).
Статус решения вопроса (например, «Вопрос решён»).
Задачу с этой формой мы и решали, о чём и пойдёт речь в статье.
Хотя форма состоит всего из 6 вопросов, но на данный момент у нас 20 Продуктов (классов). И в них:
140 подпродуктов,
120 тем,
630 подтем,
35 каналов,
18 статусов,
1000+ (сочетаний) продукт x тема x подтема.
Каждый продукт, подпродукт, тема, подтема связаны иерархией, которая представлена на картинке:

Это значит, например, что у каждого продукта есть свои темы, а у каждой такой темы существуют свои подтемы. Статус же, наоборот, не зависит от продукта или темы.
Примечание. Класс — это возможные варианты и подварианты продуктов, например, ипотека, дебетовая карта, кредитная карта, счёт, детская карта. Всё, что продукт, это всё класс.
И заполнение отчёта, где так много классов, занимает у оператора в среднем 30 секунд (например, ему надо мысленно пройтись по этой иерархии). Соответственно, в течение 30 секунд оператор не может приступить к решению нового запроса от клиента. Клиенты ждут, они недовольны, даже если оператора нет минуту. Ну вы сами в курсе — минутное ожидание может казаться вечностью.
С этой проблемой бизнес пришёл в виде запроса (бизнес-задачи):
Необходимо автоматизировать процесс заполнения отчета об обращении физического лица в чат.
Задача в том, чтобы освободить оператора от заполнения отчёта.
Если мы придумаем эффективное решение, то:
Облегчим работу оператора.
Снизим Average Handling Time — среднее время сессии с оператором (a.k.a AHT).
Повысим качество заполнения отчёта (классификации). Уровень экспертизы у операторов разный и отчёты от опытных операторов яснее, по ним бизнес может быстрее разобраться с проблемой. И не стоит забывать о снижении производительности к концу рабочего дня/недели.
С наскока не получилось: «тут вам не Kaggle»
Задача поступила, мы приступили к работе.
Первым делом решили определить, что мы считаем за единицу данных, учитывая, что во время диалога клиент общается с ботом, затем происходит трансфер на оператора и в случае необходимости происходят другие трансферы на специалистов с нужными скиллами.
Для первой итерации решили остановиться на следующем эвристическом алгоритме:
Сообщения хранятся в БД и помечены тегами (метаданные, id, время и т.п.). Но в единый диалог они не собраны. Берём все сообщения за час (или день), в которых получатель или отправитель — это уникальный клиент, сортируем по времени, склеиваем, отмечаем фразы клиента и оператора.
То есть составляем обучающую выборку.
Вполне очевидным и довольно «дешёвым» вариантом является переиспользование уже существующих данных — ответы операторов на формы за последние месяцы.
И вот у нас есть диалоги и соответствующая диалогу разметка (формы) от операторов. Осталось обучить безлайны и выбрать лучшее решение. И вот мы уже тестируем несколько моделей на основе рекуррентных нейронных сетей и пару трансформер – based моделей
Делюсь результатами лучшей модели за время экспериментов:
Таргет | Точность на тесте, % |
Продукт | 75 |
Тема | 67 |
Подтема | 47 |
Может в текущем процессе у нас что-то не так? Ведь начинать тюнинг гиперпараметров при текущем качестве не очень хочется. Мы же решаем продуктовую задачу, а не соревнование на Кагле. Возможно, дело в качестве обучающей выборки?
Перепроверим
Провалидируем качество нашей обучающей выборки.
Способ №1 — отдаём экспертам (самым опытным операторам) подвыборку для бинарной перепроверки и просим ответить, правильно ли разметил оператор или нет.
Таргет | Точность, % |
Продукт | 78 |
Тема | 68 |
Подтема | 64 |
Способ 2 — скроем разметку от оператора, попросим экспертов разметить заново и замерим согласованность.
Таргет | Согласованность, % |
Продукт | 65 |
Тема | 52 |
Подтема | 41 |
Какие выводы из этого можно сделать?
Модель не так уж и плоха — качество примерно совпадает с разметкой оператора.
Разница между бинарной перепроверкой и полной переразметкой велика. Скорее всего, это произошло, потому что согласиться с чем-то проще, чем размечать с нуля. Ещё одной причиной может быть наличие схожих классов: при перепроверке контроллер согласится с предоставленной разметкой, а при переразметке может уже выбрать какой-то схожий класс.
В процессе переразметки мы заметили, что текущий алгоритм составления диалога далеко не идеален. Мы не учли, что клиент может написать по уже другой теме через некоторое время, и в текущей реализации всё это склеится в один диалог. В таких ситуациях мы договорились размечать первое обращение, с которым обратился клиент.
Отсутствие логирования изменений классификатора ведёт к наличию неактуальных данных (изменилось > 20 % тематик).
Что мы сделали, чтобы всё получилось?
Меняем подход к сбору данных.
Использование диалога с момента инициации его клиентом до закрытия оператором вместо time-based фильтрации сообщений.
Организуем процесс переразметки обучающей выборки
Решили не использовать эксельки, где было много опечаток, макросов, постоянно ехавших полей, и развернули платформу разметки. На ранних этапах использовали Label Studio, а затем перешли на собственное решение.
Также нам выделили людей для разметки — бывших операторов, которых мы обучили.
Размечали с перекрытием и считали, что разметка правильная, если хотя бы два оператора проставили одинаковые классы на всех уровнях. Ещё вели аналитику по точности, согласованности и переразмечали несогласованные кейсы.
Процесс разметки выглядел вот так:

И вот, спустя 6 месяцев, у нас 50 000+ примеров при согласованности в 65–80%. Всё это руками 3–6 экспертов. Проблем с актуальностью некоторых тематик у нас теперь нет. Если и появляется новая тема/подтема, мы переразмечаем кейсы со старой тематикой.
Перейдем к модельной части
Мы решили обучить ruBERT на банковском домене и сверху поставили 6 голов — полносвязанных слоев для задачи классификации.

Некоторые важные детали:
Использовали символы разграничители для фраз клиентов и операторов.
Шеринг весов, регуляризация, layer-wise learning rate, learning rate warmup помогают с переобучением. Об этих и других методах мои коллеги подробно рассказывали на курсе «NLP in practice».
Маскирование логитов на инференсе для соответствия иерархии. Так как в процессе обучения мы нигде не учитываем, какие подтемы могут быть у определенной темы, то, соответственно, логитам «несуществующих» подтем мы присвоим -Inf, а значит, модель её не предскажет. Ещё поэкспериментировали с иерархическим лоссом, но большого прироста в данной задаче это не дало.
Теперь, когда мы починили процессы и обучили модель, замерим точность на тесте.
Таргет | Точность, % |
Продукт | 92 |
Подпродукт | 89 |
Тема | 86 |
Подтема | 77 |
Канал | 97 |
Статус | 85 |
Вот теперь хорошо.
Внедряем модель в production

После внедрения важно провести мониторинг, чтобы удостовериться, что качество примерно сопоставимо с замерами на тесте и что у нас нет просадки по какому-то определённому классу.
Ведь мониторинг показал, что качество предсказания подпродукта сильно просело…Хмм.
Смотрим кейсы, где модель неправильно предсказала подпродукт и получаем очень важный инсайт. Видим, что вопросы клиента можно разбить на несколько категорий:
Вопросы общего характера. В них клиент просто интересуется условиями кредитов, ипотек. Предсказать метку здесь довольно сложно, если клиент не спрашивает про какой-то конкретный продукт, а просит рекомендацию у оператора.
Вопросы по открытым продуктам клиента. В таких обращениях клиент очень редко уточняет, по какому именно продукту у него вопрос. Он просто спрашивает: «Подскажите условия по моему вкладу». Даже оператор не в силах понять, что конкретно имел в виду клиент: «Альфа-Вклад Максимальный» или «Альфа-Вклад новые деньги». Для этого он смотрит, какие вклады есть у этого клиента.
В процессе предсказания мы точно не знаем, к какой категории относится обращение, поэтому договорились на следующее упрощение — замаскируем те продукты, которых у клиента нет. И теперь модели предстоит сделать выбор из 2-3 классов вместо 15.
Наибольшую сложность вызвала необходимость в сжатые сроки собрать витрину данных с активными продуктами и их статусами на заданную дату для каждого клиента.
Реализовав это, получаем такой буст в качестве:

Итоговый процесс теперь выглядит так:

Результаты в цифрах.
Таргет | Точность оператора | Точность модели |
Продукт | 88 | 94 |
Подпродукт | 78 | 81 |
Тема | 77 | 87 |
Подтема | 66 | 79 |
Канал | 83 | 97 |
Статус решения | 69 | 88 |
Итоги
Задача довольно сложна, ещё и с нуля. Но мы справились, прошли от постановки задачи до промышленной эксплуатации, построили процесс разметки, придумали, как в сжатые сроки можно обновлять модель.
После внедрения модели Average Handling Time снизили на 30 секунд, а 80% операторов освобождены от обязательного заполнения классификатора. А сейчас и все 90% (не убираем оставшиеся 10%, чтобы была возможность майнить данные с новыми классами).
Коллеги от таких цифр очень обрадовались и обратились к нам с задачей автоклассификации чатов юридических лиц. А затем мы начали обрабатывать и транскрипты звонков, которые поступали к нам в колл-центр. Но уже нам было достаточно просто переиспользовать опыт и не повторить прошлых ошибок.
Так как теперь мы пристально следим за всеми изменениями классификатора и логируем изменения, то переименования, объединения, удаления тематик мы можем автоматизировать. При изменении бизнес-логики или появлении какого-то разбиения одной тематики на несколько, мы переразмечаем в соответствии с пайплайном разметки из середины статьи. Если же вводятся новые тематики, то контрагенты и команда разметки сами находят нужные кейсы с помощью сервиса для поиска диалогов, отправляют их нам, и мы переобучаем модель.
Красота.
Реализованными проектами, новостями, вакансиями также делимся в канале команды Центра продвинутой аналитики Alfa Advanced Analytics.
А чтобы не пропускать анонсы наших статей и других новостей из мира DS - обязательно переходите в Телеграмм-канал «Нескучный Data Science»
Подписывайтесь на Телеграм-канал Alfa Digital — там мы постим новости, опросы, видео с митапов, краткие выжимки из статей, иногда шутим.