Как мы учили систему слышать тихого клиента на АЗС: двухмодальная аналитика для контроля сервиса

от автора

Распознать «здравствуйте» в записи — задача, которая уже решена. Труднее понять, кому это «здравствуйте» сказано, кто стоит у кассы в этот момент, и было ли приветствие вообще, если клиент коротко ответил «ага» на фоне работающего холодильника.

Дано: сеть АЗС, ручной аудит покрывает несколько процентов смен. Всё остальное — «слепая зона». Заказчик хотел её закрыть с помощью существующих камер и микрофонов: взять архивные записи, автоматически выделить сессии обслуживания, проверить по чек-листу. Никакого нового оборудования, только то, что уже есть на точках.

Ограничение, которое определило всю архитектуру: кассир у микрофона говорит громко и развёрнутыми фразами. Клиент отвечает коротко, тихо и иногда вообще кивает. Стандартный ASR-пайплайн из этой пары слышит только одну сторону.

Видео первично: без стабильного ID клиента и временных границ сессии аудиоаналитика работает вхолостую. Начали с трекинга. 

Почему одномодальный подход не работает

Первая гипотеза — просто прогнать аудиопоток через ASR и искать ключевые фразы. И она ломается: система слышит «Здравствуйте», но не знает, кому это сказано. В зале может стоять несколько человек, кто-то из персонала разговаривает с коллегой или курьером. Без привязки к визуальной сцене приветствие нельзя отнести к конкретной клиентской сессии.

Вторая гипотеза — поставить только видеоаналитику. Камера видит, что клиент подошёл к кассе и стоит там 40 секунд, но не знает, предложил ли кассир кофе или приложение. Детекция визуальных жестов с существующих камер под таким углом не работает надёжно.

Поэтому архитектура двухмодальная: видео дает хронологию сцены и идентификацию ролей, аудио дает содержание диалога. Сессия обслуживания собирается только после синхронизации обоих потоков.

Видеочасть: роли и стабильный трекинг

Первая задача модуля видеоаналитики — разделить людей в кадре по ролям: клиент, кассир, стажёр, заправщик. Классов именно четыре, потому что у каждой роли своя зона перемещения и своя ответственность в чек-листе. Стажёр при этом исключается из оценки в течение первых 14 дней — это требование заказчика, маркер стажёра виден визуально (браслет, нагрудный знак).

Детектор обучали под конкретные прикладные классы на реальных данных с АЗС. Стандартные веса здесь не подходят: кассир и стажёр визуально похожи, заправщик выглядит как сотрудник, но работает в другой зоне.

Вторая задача — удерживать ID клиента на протяжении всей сессии. Типичная проблема: клиент на секунду перекрывается стойкой или витриной, трекер открывает новый ID, и одна сессия распадается на две. Все бизнесовые метрики при этом ломаются — система фиксирует «две сессии без приветствия» вместо одной корректной.

Для ReID использовали визуальные эмбеддинги, пороги дорабатывали под конкретный ракурс камеры. Добавили два правила: два одновременно существующих трека не могут иметь один ID, и вход нового трека в ROI кассовой зоны проверяется по зональному гейтингу — случайное появление человека на периферии кадра не открывает сессию.

ROI кассовой зоны и прилегающих областей задаётся вручную под планировку каждой станции. Конфигурация хранится отдельно, это позволяет переносить модель на новую АЗС без переобучения, меняя только разметку зон.

Аудиочасть: проблема тихого клиента

Типичный диалог на кассе выглядит так:

[кассир, громко] Здравствуйте, кофе в дорогу?

[клиент, тихо]   нет

[кассир] Какая колонка?

[клиент, тихо]  девятая

[кассир] Есть наше приложение?

[клиент, очень тихо] нет

[кассир] С вас 1894. Картой?

[клиент] (кивает)

Кассир говорит близко к микрофону, длинными фразами, с высоким уровнем сигнала.

Клиент — короткими ответами длиной меньше секунды, на несколько децибел тише.

Стандартный VAD настроен на то, чтобы не пропускать шум: в условиях АЗС с фоном холодильников, кофе-машины и кассового оборудования тихая реплика клиента акустически неотличима от шума.

Первый прогон через базовые ASR-модели это подтвердил: кассир распознавался нормально, клиент терялся систематически.

Почему мы выбрали GigaAM v3

Для русского ASR мы рассматривали несколько вариантов. GigaAM v3 выбрали по трём причинам:

  • модель заточена именно под русский язык, а не является мультиязычной; 

  • есть RNN-T вариант, который в наших тестах лучше держит короткие фрагменты; 

  • есть документированная процедура дообучения на доменных данных.

Базовый WER на реальных записях — около 49%. 

Это сдвиг домена: модель не слышала такой акустики в обучении. Собрали и вручную разметили около 5 часов диалогов. Объём небольшой, но цель была не переобучить модель, а сместить распределение в сторону конкретной лексики и акустики.

В обучающую выборку добавили:

  • короткие реплики клиента («да», «нет», «девятая», «наличными»);

  • числа с единицами («восемь литров», «колонка три»);

  • доменную лексику АЗС;

  • шумную среду без стерильной очистки — специально, чтобы модель не разваливалась на фоновом шуме.

Обучали CTC и RNN-T версии параллельно. CTC проще и быстрее, но в классическом виде делает условно независимые предсказания между токенами. На коротких тихих репликах контекста почти нет: модель принимает решение по очень маленькому фрагменту на фоне шума. RNN-T добавляет авторегрессионный слой и использует уже распознанный контекст. На валидации RNN-T давал около 2–3 процентных пунктов абсолютного WER лучше CTC именно на коротких фрагментах.

Предобработка и двойной VAD

Дообучение не помогает, если VAD уже выкинул нужный сегмент как тишину. Поэтому предобработка отдельная: извлечение аудио, выбор лучшего канала, подавление низкочастотного гула (компрессоры, вентиляция), нормализация громкости.

Для VAD сделали два прохода. Первый — на исходном аудио со стандартными порогами. Второй — на усиленном аудио с пониженными порогами чувствительности. Окна второго прохода добавляются к первому без замены. Прирост покрытия речевых сегментов на тихих участках — около 15–25% в наших тестах. Часть спасённых окон ASR всё равно не распознаёт уверенно, но без этого шага тихий клиент вообще не попадает в модель.

Whisper как судья

Whisper Large v3 не заменяет GigaAM — он включается только на сложных фрагментах. Условия три: GigaAM выдала низкую уверенность, фрагмент слишком короткий, или результат подозрительно пустой при явном наличии речи. В таких случаях тот же участок прогоняется через Whisper.

Если Whisper уверенно фиксирует слово, которое GigaAM пропустила — создаётся кандидат на добавление. Если обе модели расходятся без явного перевеса — фрагмент отклоняется. Итоговая транскрипция остаётся за GigaAM, Whisper только закрывает дыры. 

Сборка сессии

После того как оба модуля отработали, система собирает бизнес-сессию. Сессия начинается, когда новый клиент появляется в ROI кассы и рядом по времени звучит приветствие или другой стартовый маркер. Завершается, когда клиент покидает ROI и рядом есть прощание, оплата или длинная пауза.

Привязка аудиособытий к видеосессии идёт по временному окну с допуском: системы не идеально синхронизированы, особенно на архивных записях.

Чек-лист после сборки проверяется по таблице:

Триггер

Что ищем

Источник

Приветствие

«Здравствуйте», «Добрый день» в начале сессии

Аудио + появление клиента в ROI

Прощание

«Спасибо», «Всего доброго», «До свидания» в конце

Аудио + уход клиента из ROI

Предложение кофе

Упоминание кофе или напитков

ASR + доменный лексикон

Нецензурная лексика

Список стоп-слов

ASR, независимо от ролей

Правила чек-листа хранятся в конфигурации отдельно от кода —заказчик менял чек-лист несколько раз в ходе пилота; правка конфига, перезапуск сервиса, без изменений в коде.

Ряд случаев система не оценивает по условиям заказчика: дети и подростки, клиенты не говорящие по-русски, глухонемые, мотоциклисты в шлемах, клиенты в состоянии опьянения, стажёры первые две недели. Фильтрация стажёров идёт через видеомодуль (маркер на одежде), остальные исключения частично визуальные, частично требуют отдельной логики детекции.

Формат доказательной базы

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

Выгрузка результатов — JSON, Excel, CSV. Интерфейс MVP даёт просмотр результатов по смене и по конкретной АЗС.

Ограничения

  • Тихий клиент — основной источник False Negative. Даже после дообучения и двойного VAD часть реплик короче 0.5 секунды на фоне высокого шума не восстанавливается.

  • Нестандартные конструкции приветствия. Кассир, который говорит «Чем помочь?» вместо «Здравствуйте», формально нарушает стандарт, но семантически приветствует клиента. Текущий лексикон на такие вариации не настроен.

  • Быстрый клиент — клиент, который разворачивается сразу после озвучивания заказа и уплаты наличными. Видеомодуль фиксирует короткое присутствие в ROI, аудиоокно не успевает закрыться, сессия либо не открывается, либо открывается и сразу закрывается с пустым чек-листом. Заказчик такие случаи из оценки исключил, но детектировать их автоматически с нужной точностью пока не получается стабильно.

Записи ночных смен с высоким фоновым шумом дают более высокий WER по всем меткам.

Что получилось

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

Человек остаётся нужен на апелляциях (клиент может оспорить автоматическое нарушение), на нестандартных ситуациях и на записях плохого качества. Логику исключений — стажёры, специальные категории клиентов — система выполняет частично, часть случаев попадает в серую зону и требует ручной проверки.

Два места, где у нас нет хорошего решения: автоматическая детекция «быстрого клиента» без ложных срабатываний и семантически корректное приветствие вне фиксированного лексикона.

Если сталкивались с похожими задачами в аудио или трекинге — интересно услышать, как решали.

ссылка на оригинал статьи https://habr.com/ru/articles/1044914/