Распознавание речи ВКонтакте: инфраструктура

Публикуем расшифровку последнего доклада с онлайн-митапа от Команды ВКонтакте VK Tech Talks | ASR. В этот раз спикер Сергей Ларионенко расскажет о том, как проектировали бэкенд-сервис ASR для сотен миллионов запросов в день, с какими проблемами и трудностями пришлось столкнуться, как их решали, а также о дальнейшем пути развития сервиса.

Распознавание речи ВКонтакте: инфраструктура, image #1

С чего всё начиналось?

Изначально было:

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

С самого начала понималось, что этот сервис будет высоконагруженным — нужно обрабатывать около двухсот миллионов аудиосообщений в день, это нужно делать быстро — всего за несколько минут нужно обрабатывать любое аудиосообщение, также всё это должно делаться на 90 видеокартах Nvidia Tesla T4.

Вначале общий алгоритм выглядел достаточно просто:

  • нужно было забрать из очереди ссылку на аудиосообщение;
  • скачать с сервера это аудиосообщение;
  • раздекодить, то есть сконвертировать из opus-формата в pcm-семплы;
  • прогнать сырой звук через модели (AM, LM, PM);
  • отдать в результирующую очередь получившийся распознанный текст.

Проблемы

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

Первая проблема — слишком много C++. Дело в том, что инфраструктура в основном написана на Go, и, соответственно, реализовывать библиотеки на C++ не очень хочется. Это значит что нужно каким-нибудь способом подружить C++ с Go. Также понимается, что «плюсовая» часть остаётся, которая относительно сложна в отладке и профилировании.

Решение проблемы достаточное простое: для связки C++ и Go используется расширение языка CGO, то есть верхнеуровневый код пишется на Go, а непосредственное обращение к моделям, декодинг и так далее уже реализовывается на C++. Потом берётся общий «плюсовый» код, разбивается на маленькие функции, помещается это всё в библиотеки, обкладывается тестами, и, соответственно, появлялась возможность для того, чтобы дебажить и профилировать «плюсовую» часть в отрыве от остального сервиса.

Распознавание речи ВКонтакте: инфраструктура, image #2

Следующая проблема — батчинг. Обычно, когда используются вычисления на карточке, применяются два основных типа ресурсов — память и Cuda-ядра. Дело в том, что если посылать, допустим, лишь одно аудиосообщение на видеокарточку для обсчёта, то, соответственно, проигрывается в перфомансе. Грубо говоря, гораздо эффективней посылать некий батч, то есть группу аудиофайлов для обсчёта на карточку. Это должно дать буст касаемо производительности — лучше будут утилизироваться и Cuda-ядра, и память.

Распознавание речи ВКонтакте: инфраструктура, image #3

Однако, стоит отметить, что все аудиофайлы в батче должны быть выравнены. Это означает, что если в одном батче, который посылается на видеокарту, нужно сгруппировать аудиодорожку длиной в одну секунду, и второй — длиной в две секунды, то первую придётся добивать нулями — для того, чтобы аудиозаписи были выровнены по одной длине. Момент padding, выравнивания нулями, можно только минимизировать. Полностью от него уйти невозможно — размер аудиосообщений VK никак не ограничен.

Решение этой проблемы было в группировании аудиофайлов в большие метабатчи. Затем — сортировка внутри в метабатча файлов по длине аудио, и потом разделение метабачей на маленькие батчи, которые попадают на видеокарту. Что же делать с большими аудиофайлами? Тут всё просто: если по каким-то причинам нет возможности обрабатывать большие файлы, то просто не нужно этого делать. Для этого нужно фильтровать по длине аудиозапись, которая будет обрабатываться. Единственное, что для этого нужно, — выбрать длину, по которой фильтровать. По статистике в 90 % случаев пользователи отправляют аудиосообщения VK длинной менее 30 секунд. Соответственно, эту величину выбрали как порог для фильтрации.

Распознавание речи ВКонтакте: инфраструктура, image #4

Система мониторинга

Стоит отметить, что когда делается большой высоконагруженный сервис, то не стоит забывать про систему мониторинга. Она нужна для того, чтобы на ранних стадиях можно было детектить какие-либо аномалии и быстро определять, что пошло не так и в каком конкретном месте. Например, один раз в VK моргнула сеть до серверов, на которых лежали аудиофайлы, и, соответственно, время скачивания аудиосообщения возросло с 7 миллисекунд до 70. В итоге начали скапливаться аудиосообщения входящей очереди, о чём был сразу получен алерт, и буквально в течение 10 минут, посмотрев на графики, было определено, что конкретно и где пошло не так, и было быстро всё пофикшено.

Распознавание речи ВКонтакте: инфраструктура, image #5

Первая версия

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

Распознавание речи ВКонтакте: инфраструктура, image #6

Чтобы развернуть первую версию не дожидаясь серверов, решили использовать видеокодировщик. VK обрабатывает очень большие объёмы видеофайлов — пользователи льют гигабиты, и это надо как-то обрабатывать, кодировать. Делается это на видеокодировщиках. По факту это сервер, на котором крутятся PHP-скрипты, которые дёргают FFmpeg, а тот — модуль NVENC от Nvidia. Кодирование, происходящее на этом модуле, никак не затрагивает Cuda-ядра, то есть они простаивают, и памяти используется очень мало.

Распознавание речи ВКонтакте: инфраструктура, image #7

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

Для совмещения трёх сервисов, которые по максимуму утилизируют и память, и Cuda-ядра, было выбрано решение от Nvidia — MPS-технология. Грубо говоря, это прослойка между клиентским приложением, драйвером и видеокарточкой. Именно MPS берёт на себя основную работу по шерингу ресурсов видеокарточки.

Распознавание речи ВКонтакте: инфраструктура, image #8

Итоги первой версии

  • Работоспособный сервис показан пользователям;
  • аудиосообщения быстро обрабатываются (около трёх секунд);
  • спокойно выдерживается нагрузка в 150–170 миллионов сообщений в день;
  • этот сервис стал очень надёжным — с момента запуска никаких серьёзных проблем не было.

Проблемы первой версии

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

Распознавание речи ВКонтакте: инфраструктура, image #9

Для решения всех проблем было переписано приложение. В нём отказались от вертикальных Worker, от тредов исполнений в программе. Теперь всё приложение выглядит как единый пайплайн с унифицированными Step, каждый из которых отвечает за свою фазу обработки. На выходе получилось, что стали быстрее избавляться от плохих данных в пайплайне, быстрее стала отдача транскрипции пользователям.

Распознавание речи ВКонтакте: инфраструктура, image #10

Итоги второй версии

  • По факту было улучшено 90 перцентиль при обработке, что примерно составляет 30 %, то есть стали гораздо быстрее обрабатывать аудиосообщения.
  • Получили легко расширяемый пайплайн благодаря унифицированным шагам.
  • Более детальная обработка и мониторинг ошибок на каждом из этапов.

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

Однако здесь есть нюанс — нельзя вслепую разрезать аудиосообщение на этапе декодинга. Поэтому пришли к VAD-алгоритму (англ. Voice Activity Detection), который решает проблему идентификации голоса на каком-то куске аудио. Грубо говоря, можно с какой-то вероятностью сказать, что на 30 миллисекундах аудио есть голоc человека или нет. VAD-алгоритмы выбрали, потому что они давно используются, а также достаточно быстрые, широко представлены как в кодеках, так и в протоколах работы с голосом.

Разрезание аудио уже на этапе бета-тестирования, и в скором времени это даст возможности использования сервиса ASR в других целях. Например, транскрипция подкастов или автогенерирование субтитров к видеофайлам.

Распознавание речи ВКонтакте: инфраструктура, image #11

В конце подведём выводы.

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

Вот и всё! Посмотреть видео можно тут:

Распознавание речи ВКонтакте: инфраструктура, image #12

The Brown Room — независимое интернет-издание про социальные сети и современные технологии.

340 views·2 shares