Узнаете, когда заглянете под кат. Для затравочки: речь пойдёт про инструмент ЮMoney для транскрибации аудио с внутренних созвонов в тексты и про кое-что ещё для наших клиентов.

Меня зовут Макс, я аналитик в ЮMoney. Недавно перед моей командой стояло две цели:
● Повысить качество взаимодействия пользователя и бизнеса за счёт аналитики данных аудио.
● Снизить время на рутину у коллег.
Так родились два проекта:
● Саммаризация (от англ. summary — резюме) Zoom-конференций. После завершения конференции участники получают протокол с основными тезисами разговора.
Предвосхищая, что в комментариях зададут вопрос об аналогичной функции в самом Zoom, скажу, что мы специально хотели разработать собственное решение. Слишком уж высок сегодня риск потерять доступ к внешнему продукту.
● Дашборд обращений. Помогает анализировать звонки в колл-центры ЮMoney и определять самые частые проблемы пользователей.
Самые популярные задачи в аудио
● STT (speech-to-text) — сделать из аудио текст (распознавание речи).
● TTS (text-to-speech) — преобразовать текст в речь.
● Audio classification — классифицировать звук. Это когда мы на похожих аудио выделяем паттерн или группу определённых звуков. Например, можно по пению птицы узнать её вид.
● Source Separation — разделить звуки по источникам. Например, когда играет оркестр и нужно выделить какой-то конкретный инструмент.
● Diarization — разделить диалог на речь отдельных спикеров.
● Voice Activity Detection — определить наличие речи на каком-то участке аудиозаписи.
● Audio Enhancement — улучшить качество звука.
Саммаризация звонков в Zoom
Разделим эту задачу на несколько подзадач:
● Транскрибация — вытаскиваем текст из аудио.
● Диаризация — определяем по таймкодам, какой спикер говорит.
● Идентификация — идентифицируем выступающего человека.
● Саммаризация — создаём краткое изложение записи.
Для транскрибации мы используем Whisper от OpenAI. На рынке есть множество решений, но эта модель показывает лучшие результаты при работе с аудио на всех языках. У неё хорошая библиотека с документацией, понятно, как работать с гиперпараметрами и как их настраивать.
Состоит Whisper из Transformer-блока, включающего блоки Decoder и Encoder. Encoder получает на вход спектрограмму, Decoder — специальные токены (язык, задача, таймкод), а также транскрибированные (для предсказания следующих токенов).

Гиперпараметры
Помогают увеличить качество транскрибации в проектах. Вот самые важные из них:
● initial_prompt — контекст. Это строка, в которой можно указать специфичные для домена термины — те, которые, вероятнее всего, не попадались Whisper в обучающей выборке. В таком случае Whisper научится хорошо их предсказывать.
● language — код языка аудио. Указывать код языка не обязательно, но лучше это сделать.
● task — тип задачи, например transcribe или detect.
● condition_on_previous_text — гиперпараметр, который прокидывает информацию из предыдущего чанка (фрагмента). Так при транскрибации следующего будет соблюдаться контекст.
● beam_size — гиперпараметр, который позволяет увеличить количество гипотез, которые мы валидируем при предсказании следующего токена.
● temperature — температура для семплирования, по умолчанию имеет значение 0. Beam size работает только при нулевой температуре. Если температура выше, нужно использовать гиперпараметр best_of. Температура отвечает за распределение токенов: когда наша модель предсказывает следующий, она строит распределения и выбирает из них наиболее вероятное. Чем выше температура, тем равномернее будет распределение.
● length_penalty — штраф за длину последовательности. По умолчанию равен 0, диапазон от -1 до +1. Чем length_penalty меньше, тем короче будут транскрибации, чем больше — тем длиннее.
Диаризация
Следующая задача в нашем пайплайне — диаризация, или разделение аудиозаписи по спикерам.
Процесс диаризации такой:
● Whisper решает задачу next speaker prediction внутри. Это позволяет нам удобно задизайнить собственную диаризацию.
● Далее мы делаем voice embeddings (эмбеддинги голоса) из каждого чанка и кластеризацию. При такой кластеризации в Whisper нужно указать гиперпараметр word_timestamp=True для получения точных таймкодов каждого слова.
В результате диаризации мы получаем таймкоды с номерами спикеров.


Идентификация
Полученные кластеры мы сравниваем с данными из внутреннего войс-банка или с векторизированной многоканальной записью. Войс-банк — это база голосов, где ключ — имя сотрудника, а значение — вектор его голоса. Сравнив, мы берём топ по cosine similarity (косинусное сходство).
-
Как только к нам попадает аудио, оно конвертируется в формат WAV с частотой дискретизации 16 кГц.
-
Затем аудио обрабатывается, происходит препроцессинг. Например, из записи удаляется шум и нормализуется громкость.
-
Создаются чанки (фрагменты) по 25-30 секунд. Разделение происходит в моменты падения амплитуды, чтобы не разрезать слова. Whisper сам умеет разбивать аудио на фрагменты, но у него есть особенность — он может переключиться на другой язык или зациклиться в одном чанке.
-
Транскрибация выполняется с помощью Whisper. В ответе он выдаёт текст, извлечённый из аудио.
-
Диаризация проводится с использованием библиотеки pyannote (не очень хорошо работает без дообучения) или собственной кластеризации за счёт выходов Whisper.
-
Вывод диаризации — получаем таймкоды и номера спикеров.
-
Идентификация — узнаём имена спикеров из номеров.
Примеры выходов транскрибации и диаризации


Саммаризация
На этапе саммаризации у нас есть информация о том, что говорил каждый спикер. Эту информацию необходимо передать в большую языковую модель (LLM). Но из-за ограниченного input-контекста LLM мы не всегда можем передать всё, поэтому нужно разрезать текст на небольшие фрагменты, стараясь при этом сохранить суть абзаца в пределах одного чанка (использовать семантическое разбиение).
Каждый чанк отправляется в LLM с системным запросом на саммаризацию. Затем собираем все саммари и просим LLM сделать на их основе одно общее.

Результат саммаризации
Вот что получилось, когда представленная аудиозапись прошла через наш пайплайн.

Также на выходе мы получили полную стенограмму (расшифровку) аудио.
Метрики
Мы отслеживаем три основных показателя:
1. Транскрибация: измеряем WER (Word Error Rate, процент ошибок на уровне слов) и CER (Character Error Rate, процент ошибок на уровне символов).
Пример: есть предложение: «Мама мыла раму». Попробуем транскрибировать его с ошибкой в первом слове: «Мамы мыла раму». В этом случае WER = 1/3, так как одно слово из трёх транскрибировано неверно. CER при этом будет равен 1/12.
2. Саммаризация: используем метрику ROUGE-N, где N означает N-грамм — это скользящее окно по символам или словам.
Пример: для фразы из предыдущего примера про маму при размере N-граммы 2 мы получим три N-граммы: МА, АМ и МА. При размере N-граммы 3 получим две N-граммы — МАМ и АМА.
Таким образом, у нас есть эталонная саммаризация, которую сделали асессеры, заказчики или даже мы сами. Мы только меряем пересечение N-грамм между сгенерированной и эталонной саммаризацией.
3. Классификация (для идентификации): используем стандартные метрики F-score, accuracy, precision и recall.
Дашборд обращений
Также мы анализируем звонки в наши колл-центры. Когда звонит клиент, мы извлекаем тему его обращения, и она отображается на дашборде. Это позволяет отслеживать всплески активности по разным темам. Дашборд можно обновлять ежедневно и еженедельно, чтобы отслеживать динамику показателей и решать проблемы пользователей.
Вот как выглядит наш дашборд:

Какой инструмент вы используете для перевода звука в текст: внешний или собственный? Пишите в комментариях. А если хотите вместе с нами заниматься машинным обучением и искусственным интеллектом, откликайтесь на вакансию системного аналитика и присоединяйтесь к команде Макса.
Автор: izzyleet