Обратно в блог
  • AI
  • backend

Будьте в курсе всех событий

Масштабируем контроль качества звонков с 5% до 100% через Speech-to-Text и динамические промпты

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

Привет! Меня зовут Стас Заботин, я CPO В2В продукта Яндекс Доставки. Наша команда отвечает в том числе за внутренний продукт, включающий СRM и клиентский профиль, в котором работают команды привлечения новых клиентов и развития текущих. За оценку эффективности этих команд отвечает группа контроля качества также работающая в нашем внутреннем продукте.

Ребята из контроля качества отлично справляются со своей задачей. Они рандомно отслушивают звонки и по подробным чек-листам оценивают работу менеджеров — выявил ли потребность, не было ли слов-паразитов, как изменилась тональность сложного разговора. Но в таком большом продукте, как Яндекс Доставка, коммуникаций слишком много. Физически команда может покрывать около 5% всех взаимодействий. Это даёт срез по отделу, но оставляет некоторое количество слепых зон при оценке конкретных сотрудников. Например, в случайную выборку может попасть короткий звонок, где клиент просто попросил перезвонить. Формально всё отлично, галочки стоят. Но вот почему один менеджер продаёт на 100 рублей, а другой на 1000 — тимлидам приходилось выяснять вручную.

Мы замахнулись на амбициозную цель — покрыть проверками все 100% коммуникаций, чтобы дать менеджерам инструмент для повышения собственной эффективности. Как это сделать? Ну, например, можно в 20 раз увеличить штат команды контроля качества. Идея, конечно, интересная, но уж очень дорогая. А раз мы все тут работаем в IT-компании, то и решение нашли соответствующее — автоматизировать процессы с помощью нейросетей.

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

В этой статье я расскажу, как устроена архитектура такого решения и как мы интегрировали LLM в устоявшиеся процессы контроля качества. И начнём с базы — как мы получаем и подготавливаем данные для аналитики.

Выстраиваем Speech-to-Text пайплайн

Любая автоматизация контроля качества начинается с данных, а в нашем случае исходные данные — это голос. Наша инфраструктура построена так: в качестве CRM мы используем BPMSoft, известная внутри Яндекса как YaCRM, а звонки проходят через платформу YaCalls. Чтобы анализировать эти разговоры, их сперва нужно качественно превратить в текст.

Для этого мы инициировали интеграцию YaCalls с платформой речевой аналитики SpeechSense. При этом отправлять на транскрибацию абсолютно все гудки, сбросы и автоответчики бессмысленно — это пустая трата ресурсов.

01.png

Поэтому прямо в интерфейсе YaCalls мы настроили правила фильтрации. В систему аналитики улетают только те звонки, которые продлились не менее 30 секунд. Также мы фильтруем звонки по результату: забираем только те, что завершил оператор, завершил клиент или где произошёл трансфер. Вместе с аудиопотоком в SpeechSense обязательно пробрасываются метаданные — уникальный идентификатор звонка call_id и название юнита unit_yacalls. Это нужно для того, чтобы потом безошибочно связать текстовую расшифровку с конкретной карточкой в CRM.

Что отдаёт речевая аналитика

SpeechSense не просто переводит голос в текст. На выходе мы получаем подробную структуру диалога. В ней есть чёткое разделение реплик по спикерам — кто клиент, а кто оператор, с привязкой к таймкодам. Кроме того, сервис сразу делает базовую работу: собирает суммаризацию разговора, выделяет ключевые слова обеих сторон и размечает текст начальными тегами — где было приветствие, где прощание, а где проскочили слова-паразиты.

Пайплайн загрузки данных через Nirvana

Дальше эти расшифровки нужно забрать из SpeechSense и централизованно сложить в YTsaurus — наше основное хранилище. Только после этого с текстами сможет работать языковая модель. Всю оркестрацию процесса мы настроили через Nirvana.

По расписанию Nirvana cron запускает наш Python-скрипт. Сначала этот скрипт идёт в витрину YT, которая наполняется данными из CRM, и смотрит список всех актуальных call_id. Он фильтрует записи и оставляет только те, которые требуют обработки.

02.png

Затем обращается к API SpeechSense. Получение данных разбито на два этапа:

  1. Скрипт делает GET-запрос по call_id. Система ищет этот звонок и возвращает внутренний идентификатор записи — talk_id.
  2. Следом уходит POST-запрос уже по полученному talk_id, который запрашивает непосредственно текст и метаданные.

Поскольку звонков много, отправлять запросы сплошным потоком нельзя. На этом этапе в скрипте реализован строгий контроль RPS и разбиение списка на чанки. Так мы не кладём внутренние сервисы своими запросами.

На последнем шаге полученная транскрибация и метаданные из SpeechSense записываются в YT. В итоге мы имеем чистое хранилище текстовых диалогов, готовое к глубокому анализу.

Динамические промпты и строгий JSON

Когда тексты транскрипций надёжно лежат в хранилище, начинается самое интересное — этап ИИ-оценки. И здесь мы сразу отказались от идеи жёстко хардкодить правила. Нам не хотелось писать громоздкие регулярки или заставлять систему искать конкретные слова-паразиты по словарю. Основная задача — научить модель самостоятельно считывать контекст. Она должна понимать тональность разговора, оценивать вежливость менеджера и видеть, попытался ли он перевести негативный диалог в позитивное русло.

А ещё метрики и критерии оценки сильно зависят от этапа работы с клиентом. Если это первичная продажа, менеджеру критически важно выявить потребности и отработать базовые возражения. Но если это развитие уже действующего клиента, то тут нужно глубоко погружаться в проблематику конкретного бизнеса — почему клиент делает только 10 доставок в день, а не 100, и как наши продукты могут это исправить.

Чтобы гибко управлять этими условиями, мы спроектировали пайплайн из двух параллельных потоков — динамической сборки промптов и генерации строгих схем ответа.

Динамическая сборка промптов

За этот шаг отвечает компонент PromptBuilder. На вход он получает текст транскрибированного диалога и системную папку нужного критерия оценки. В этой папке лежат конфигурационные файлы — guide.json с правилами и examples.json с примерами нарушений.

03.png

Скрипт читает базовый markdown-шаблон evaluate_criterion_dynamic.md и начинает собирать из него итоговый промпт. В системной части мы задаём роль — говорим модели, что она эксперт по оценке качества работы менеджеров по продажам. И следом подставляем человекочитаемые блоки:

  • название критерия на русском языке (criterion_name_ru);
  • склеенный текст из всех гайдов по проверке каждого подкритерия (subcriteria_section);
  • примеры реальных ошибок для улучшения анализа (violation_examples_section).

В пользовательскую часть (user prompt) мы добавляем дополнительную информацию из CRM (useful_info_section), если она есть, и сам текст диалога.

Генерация Pydantic-схемы и строгий JSON

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

Для этого параллельно с билдером промптов запускается DynamicSchemaGenerator. Он читает тот же самый guide.json из внутреннего реестра и на лету строит Pydantic-модель. По сути, он формирует строгий шаблон ответа, которую ИИ обязан заполнить.

После этого мы делаем один запрос к LLM. В нём передаётся собранный промпт и требование вернуть JSON строго по сгенерированной Pydantic-схеме.

04.png

Из чего состоит оценка модели

На выходе мы получаем объект результата, где каждый проверенный чек содержит четыре обязательных поля:

  • violated — логический флаг, найдена ошибка или нет;
  • reasoning — рассуждение модели о том, почему она приняла такое решение;
  • evidence — прямая цитата из текста диалога, подтверждающая нарушение;
  • confidence — уверенность модели в своей оценке по шкале от 0 до 10.

Мы не стали ограничиваться бинарным ответом «да/нет», а специально ввели шкалу уверенности. Если модель везде ставит десятки, значит, считаем, что она отработала максимально чётко. Дальше эти данные мапятся на уровень подкритериев, формируют итоговый флаг is_violated для всего критерия целиком и отправляются на следующий этап пайплайна.

Тройная валидация запросов

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

А как убедиться, что решение модели объективно? Ответ прост — нужно повторить запрос несколько раз. Мы пропускаем каждую коммуникацию по каждому критерию через LLM ровно три раза. Это нужно для того, чтобы убедиться, что при каждой итерации модель одинаково оценивает качество диалога.

Итоговый вердикт формируется механизмом голосования. В хранилище YT агрегируется отдельное поле — verifier_reasoning. Логика голосования максимально простая: если алгоритм выдаёт результат «3 not_violated, 0 violated», итоговое решение фиксируется как отсутствие нарушения.

05.png

Дополнительно система вычисляет verifier_confidence. Это среднее значение уверенности алгоритма в согласованном решении, собранное на основе баллов из всех трёх прогонов. Если мы видим стабильные десятки во всех итерациях, значит, модель полностью уверена в собственных выводах.

Точная настройка

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

Этот набор данных мы и отдавали нейросети в качестве ориентира. И дальше начался долгий процесс калибровки. На протяжении полугода мы прогоняли диалоги через систему, а сотрудники контроля качества руками валидировали результаты — подтверждали или отклоняли вердикты модели. Итераций было очень много, пока мы не вышли на приемлемое качество.

Расставляем приоритеты

Важно понимать, что критерии не равнозначны. У нас есть оценки формата nice-to-have — например, стиль речи менеджера. А есть строгие, так называемые блокирующие критерии. Например, если сотрудник вообще не смог нормально продать наш продукт. Очевидно, что без продажи вся остальная коммуникация теряет смысл.

Нам было критически важно добиться максимальной точности именно по таким блокерам. Если алгоритм просто неправильно интерпретировал стиль речи — это одно. А вот если по ошибке был выставлен блокирующий критерий, хотя на самом деле его не было — это уже совсем другое. И вот именно таких грубых ошибок нейросети мы и старались избежать. Поэтому основной фокус при тюнинге точности у нас был именно на критические точки продаж.

Интегрируем результаты в бизнес-процессы

И вот у нас есть размеченные данные, которые бережно сложены в хранилище. Как теперь показать их конечным пользователям — специалистам контроля качества? Мы решили не усложнять без необходимости и не писать кастомные решения с нуля, а вместо этого переиспользовать уже готовые внутренние инструменты. Поэтому процесс доставки данных в рабочие интерфейсы мы построили через серию ETL-шагов, буквально собрав всё по кирпичикам.

ETL и маршрутизация через Processium

Сначала скрипт на YQL забирает нужные данные из витрины. Он тянет огромный массив параметров — привязывает к конкретному call_id флаги нарушений, такие как activity_violated, ethics_violated и другие. Затем этот массив отправляется в Reactor для стандартной обработки и передаётся в Processium.

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

После этого система автоматически создаёт кейс контроля качества — у нас эта сущность называется GoQualityCheck. Processium дёргает API CRM-системы обычными POST-запросами с TVM-авторизацией. В JSON-пейлоаде передаются значения, которые мы вытащили из алгоритма. Если модель нашла нарушение этики, в соответствующее поле улетит значение true. Если всё чисто — false. По итогу скрипт обновляет созданный кейс, и задача падает на команду QA.

Human-in-the-loop

А теперь давайте посмотрим на этот флоу с другой стороны — глазами менеджера контроля качества. ИИ берёт на себя всю рутину по прослушиванию 100% трафика звонков, а человек подключается только там, где реально требуется его экспертиза.

Специалист открывает карточку в YaCRM и видит уже предзаполненный интерфейс. Что изменилось:

  • Общий рейтинг диалога автоматически пересчитан — система сама снижает оценку согласно важности и весу каждого заваленного критерия.
  • В чек-листе алгоритмов уже проставлены отметки. Например, проверяющий сразу видит галочку на пункте «Назначение даты следующего шага», где модель вернула violated = true.
  • Внизу карточки есть текстовый блок «Комментарий ИИ». Модель пишет, например: «Менеджер не предложил и не обсудил с клиентом дату следующего шага. После получения контактов руководителя разговор был завершён без договорённости о дальнейшей коммуникации».

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

То есть нейросеть тут ни в коем случае не выступает в роли судьи, она лишь берёт на себя всю монотонную рутину. Окончательное решение по-прежнему остаётся за человеком.

А чтобы контролировать саму нейросеть, специалисты QA регулярно просматривают даже те звонки, где ИИ поставил высокий балл. Это даёт нам постоянную обратную связь для тюнинга промптов.

Мониторинг, метрики и следующий уровень

Любую ML-систему, да и не только ML, нужно постоянно мониторить. Чтобы следить за здоровьем нашего конвейера и анализировать результаты, мы собрали AI Quality Check Dashboard. Это единая панель, куда стекается вся статистика по проверкам.

Метрики качества

Главная техническая метрика для нас — средняя точность модели. Мы стараемся держать её на уровне выше 90%. Почему это критично? Если точность упадёт, проверяющие начнут тратить слишком много времени на разбор ложных срабатываний. В таком случае поддержка системы станет дороже, чем польза от неё. Поэтому на отдельном графике мы пристально следим за метрикой avg overall fp rate — долей false positive результатов.

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

Реальный импакт

Свою изначальную амбициозную цель мы выполнили — покрыли 100% звонков без найма новых специалистов. Но для бизнесового продукта простая экономия бюджета не может быть главной целью. Наша конечная цель — рост выручки, GMV и количества успешных доставок.

Мы рассчитываем, что на длинной дистанции такая тотальная аналитика поднимет общую конверсию продаж. Потому что теперь оценка работы стала абсолютно прозрачной. Если у менеджера возникает вопрос о размере премии, тимлид просто открывает CRM и показывает конкретные звонки с детализацией: вот здесь ты не отработал возражение, а здесь не предложил нужный продукт.

В ближайшем будущем планируем серию А/Б тестов, где ожидаем увидеть прокрас конверсии в первую доставку благодаря внедрению автоматизации контроля качества.

Что дальше

Но на сделанном мы останавливаться не планируем. Анализ уже завершённых звонков — это только первый этап. Совсем недавно мы вывели в прод real-time суфлёр.

Мы научили ИИ анализировать аудиопоток прямо во время разговора. Алгоритм слушает клиента и реагирует с задержкой всего в одну секунду. Пока менеджер ведёт диалог, у него прямо в CRM появляются контекстные подсказки. Модель на лету подсвечивает, на что нужно обратить внимание и что важно проговорить прямо сейчас — например, помогает грамотно отработать возникшее возражение или более точно выявить потребность. Первые данные, что мы собрали, уже подтверждают нашу гипотезу: эффективность менеджеров существенно выросла, а сам инструмент показывает отличные результаты. Инструмент получился настолько удачным, что им уже заинтересовались коллеги из соседних сервисов. Но об этом расскажем уже в следующих статьях, так что следите за обновлениями.

  • AI
  • backend

Будьте в курсе всех событий

Ещё по этой теме