Мой блог
Локальный анализ звонков без GPU: что происходит на пути от аудио до резюме
Подробности изложены в материале первоисточника. Я решил протестировать, как ведет себя локальная языковая модель на сложных телефонных записях с фоновой музыкой, автоответчиками, перебиваниями и далеко не идеальным качеством звука. Для этого я сделал desktop приложение с использованием Tauri, Rust, React и SQLite, способное распознавать речь, разделять собеседников, оценивать тональность с эмоциями и формировать итоговые рекомендации.
Все вычисления происходят исключительно на локальном компьютере, а доступ в интернет требуется лишь на этапе загрузки необходимых весов. Поскольку телефонные разговоры часто содержат конфиденциальные данные вроде адресов, номеров договоров и имен, передавать их во внешние облачные API мне не хотелось.


Выбор оборудования и моделей
Я намеренно подбирал компоненты так, чтобы вся система могла запуститься на обычном рабочем ноутбуке без дискретной видеокарты. В качестве тестового стенда использовался процессор Intel Core i7 10870H и 16 гигабайт оперативной памяти под управлением Windows, где задействовались исключительно ресурсы центрального процессора.

Конфигурация аппаратной части
Для финального анализа текстов применялась компактная модель Qwen 2.5 с 1.5 миллиардами параметров, которой вполне хватает пары гигабайт памяти. Конечно, продемонстрировать отличные результаты на тяжелой 27-гигабайтной модели и мощной видеокарте не составляет труда, но подобным железом располагает далеко не каждый специалист. Мне было важнее выяснить, на что может рассчитывать рядовой владелец ноутбука без GPU, решивший развернуть аналогичный пайплайн для обработки реальных аудиозаписей.
Архитектура пайплайна
В процессе работы программы задействуется несколько последовательных этапов, каждый из которых решает свою узкоспециализированную задачу.
Что внутри системы
Для распознавания речи (STT) задействовались движки GigaAM v3 и Whisper Turbo, за диаризацию отвечал порт speakrs, тональность определялась через RuBERT-tiny2, а эмоции и риски анализировались с помощью DeBERTa. Все эти компоненты не удерживаются в оперативной памяти одновременно: каждая модель загружается непосредственно перед выполнением своего этапа и выгружается сразу после него. Сама LLM функционирует в изолированном процессе llama-server, а ресурсоемкие фоновые операции выполняются асинхронно.
Как проводились замеры
Для тестирования я взял три реальные аудиозаписи длительностью 3:16, 6:43 и 9:29 с естественными шумами, музыкой и перебиваниями. Каждая запись обрабатывалась двумя разными распознавателями речи, после чего поступала на вход к Qwen с параметром temperature 0.2 и контекстом в 6144 токена, причем на анализ отправлялось не более 4000 символов транскрипта.
Временные затраты и узкие места
Изначально я предполагал, что основная часть времени уйдет на размышления языковой модели, которая тратит на генерацию резюме от 25 до 62 секунд. Однако на практике оказалось, что диаризация на CPU выполняется со скоростью около 0,7–0,85 от длительности самого файла и отнимает львиную долю ресурсов — от 56% до 68% общего времени при использовании GigaAM.
Практические выводы по производительности
Движок Whisper на процессоре также требует серьезных вычислительных затрат, занимая около 90% от длины короткого звонка и до полутора раз больше на длинных записях. В результате весь пайплайн на ноутбуке отрабатывает дольше, чем длился сам разговор. Это вполне приемлемо для ретроспективного анализа архивов, но абсолютно не подходит для работы в реальном времени.
Анализ реальных телефонных разговоров
Чтобы объективно оценивать результаты, полезно понимать содержание тестовых аудиоматериалов. Первый звонок в техподдержку посвящен клиентке, возмущенной отображением почти шести десятков чужих ПК в сетевом окружении Windows. Второй звонок представляет собой обращение на горячую линию интернет-магазина по поводу бесплатной доставки и уточнения скидок. Третий разговор связан с попыткой клиента отключить услуги провайдера через многоступенчатое голосовое меню.
Случай первый: влияние автоответчика
В ситуации с провайдером первые полтора-два часа занимало голосовое меню автоответчика. Распознаватель GigaAM аккуратно перевел меню, диаризация объединила его с приветствием оператора, и LLM ошибочно решила, что абонент звонит для подключения новых услуг. Whisper справился лучше и верно определил тему отключения, но из-за ограничения в 4000 символов модель просто не увидела финал разговора, сформировав резюме по начальным репликам.
Случай второй: метафоры и искажения
При разборе звонка пожилого человека по поводу сетевого окружения оба распознавателя столкнулись с трудностями в середине диалога. GigaAM выдал фонетическую кашу, а модель восприняла слова оператора о соседи по квартире буквально, включив их в итоговое резюме. Whisper отработал точнее, но допустил другую ошибку: фразу клиентки о возможном переходе в другую компанию модель приписала оператору.
Случай третьий: посторонние звуки
На записи горячей линии в самом начале прозвучал посторонний щелчок, который Whisper интерпретировал как подпись к звуку «Звонок в дверь» и сделал ее заголовком. При этом оба движка пропустили наиболее содержательную часть беседы, касающуюся обсуждения отзывов и скидок, хотя этот текст полностью помещался в допустимый лимит контекста.
Оценка тональности и проблемы диаризации
Отсутствие пунктуации у GigaAM в моей конфигурации привело к тому, что сплиттер текстовых блоков не смог найти знаки препинания и объединил весь разговор в единый массив. Из-за этого модель тональности выдала вердикт о негативном звонке с минимальным баллом, хотя реального негатива в беседе не наблюдалось.
Специфика разделения спикеров
Диаризация дробила аудио на отрезки с высокой плотностью реплик, доходящей до 19 штук в минуту, что порой приводило к разрезанию фраз посредине. В ряде случаев метки спикеров менялись местами прямо посреди диалога, из-за чего языковая модель получала искаженные данные о ролях участников и делала неверные выводы.
Технические баги и стабильность пайплайна
В ходе отладки мне пришлось столкнуться с рядом неочевидных программных проблем, которые напрямую влияли на качество работы системы. Ошибки вроде падения процесса из-за обрезки кириллических тегов по байтам вместо символов приводили к тому, что фоновый поток завершался аварийно, а пользователь получал пустое резюме.
Служебные ограничения
Среди других выявленных трудностей стоит отметить ограничения энкодера GigaAM на длительность фрагментов около 200 секунд, проблемы с распределением токенов, вызывающие обрезку JSON-структур, а также нестабильность модуля уточнения ролей. Тем не менее, даже при возникновении подобных сбоев общая логика fail-soft позволяла сохранять валидность выходных данных, хотя их содержательная ценность могла стремиться к нулю.
