Я не ML-инженер. А собрал сервис аудита звонков из двух чужих API
Как маркетолог без ML-команды собрал ИИ-аудит звонков под ключ: диаризация, оценка A–F с цитатами, грабли с фейк-стерео и модели, ломающие JSON.
Слушай, короче. Руководитель языковой школы не мог физически прослушивать сотни звонков своих менеджеров. Я собрал ему сервис: кидаешь аудио → получаешь расшифровку с ролями → и отчёт A–F с разбором и цитатами прямо из разговора. Внутри два чужих API и аккуратный промпт. Ни одной модели я не учил. Зато словил полтора десятка граблей, которые хочу рассказать по-человечески.
Сразу честно: я не учу модели, я их применяю
Давай без понтов с самого начала. Я не ML-инженер. Вся «магия» этого аудита звонков — это склейка двух готовых API и правильно собранный промпт оценки. Если ждёшь рассказ про обучение модели на корпусе разговоров — закрывай вкладку, тут другое кино.
И ещё честнее. Большую часть кода я вайб-кодил с агентом. Садился, объяснял задачу, смотрел, что он принёс, правил, гонял дальше. В 2026-м это уже не стыдно — именно так сейчас выглядит «разработка под ключ» для тех, у кого нет в штате ML-команды. Маркетолог, который понимает код-базу и умеет внятно поставить задачу агенту, закрывает целый пласт работы, который ещё пару лет назад требовал отдельного разработчика. Я как раз такой маркетолог (я ж маркетолог, да).
Пишу я это не как образец крутой архитектуры. Пишу, потому что путь от «кинул mp3» до «получил адекватный отчёт» оказался цепочкой совершенно неочевидных граблей. И почти каждая — не про ИИ, а про скучные детали реальности: битрейт записи, числовые ключи в JavaScript, формат стерео-контейнера. Про них и поговорим, как с другом на кухне.
Держи в голове одну линию с самого начала: сервис я делал под одну студию — чтобы руководитель мог наконец контролировать качество звонков своих менеджеров. А закончилось тем, что им заинтересовалась целая франшизная сеть, и теперь по тому же движку оценивают уже администраторов в студиях-партнёрах.
Зачем это вообще
Представь руководителя в языковой школе. Команда менеджеров целый день звонит родителям: рассказывают про методику, закрывают возражения, записывают детей на пробные. От качества этих звонков напрямую зависит выручка.
А прослушать их физически некому. Их сотни в неделю. Один звонок — двадцать минут внимательного прослушивания с блокнотом. Перемножи на сотни — и получишь вторую полноценную ставку, которой ни в одной небольшой школе нет. Поэтому обучение менеджеров идёт «на ощущениях»: кажется, что Маша звонит хорошо, а Петя — так себе. Данных под этим ощущением нет.
Задача: чтобы каждый звонок проходил через автоматический контроль качества по корпоративному стандарту. Не выборочно, когда дойдут руки, — а по каждому. Чтобы у руководителя был балл, разбор по этапам и конкретная цитата: «вот тут менеджер не выявил потребность, послушай».
Что снаружи и как устроено внутри
Снаружи просто. Кидаешь аудиофайл (MP3, WAV, OGG, M4A, AAC, WebM — до 50 МБ) в веб-интерфейс. Сервис распознаёт речь, раскладывает её на «Менеджер» и «Клиент», отдаёт расшифровку языковой модели и возвращает отчёт: итоговый балл и буква (A–F), сильные стороны, зоны роста, следующие шаги и таблица по критериям — каждый с комментарием и цитатой. Шкала: A ≥ 90%, B — 75–89%, C — 60–74%, D — 40–59%, F < 40%.
Самое ценное — кликабельные цитаты. Модель не просто пишет «контакт установлен слабо», а вытаскивает конкретный фрагмент: вот эта реплика менеджера. Клик по реплике в расшифровке перематывает аудио-плеер ровно туда. Это снимает главное возражение к любой автоматической оценке — «откуда система это взяла». Система не выносит приговор, она показывает, на что смотреть.
Если убрать всю обвязку, схема влезает в одну строчку: аудио → распознавание речи → расшифровка → оценка моделью → отчёт A–F.
Распознавание речи — Yandex SpeechKit. Русская речь, плюс диаризация: размечает, кто из двух говорящих сейчас в эфире.
Оценка — через OpenRouter. Дешёвая модель работает основной, дорогая подключается запасной, когда дешёвая выдала что-то кривое.
Обвязка — Next.js, база данных, Docker, деплой по SSH. Ничего экзотического.
Ещё раз честно: я не строил ML-пайплайн. Распознавание — чужое, оценочная модель — чужая. Моя работа — склеить их так, чтобы на входе был кривой mp3 из CRM, а на выходе — отчёт, которому можно верить. Вся сложность спряталась в слове «склеить».
Грабли, на которых я сидел вечерами
Дальше — не список фич, а хронология столкновений с реальностью. По собственной git-истории. Показательная история: почти ни одна грабля не была про «ИИ сложный». Все — про детали.
Кто тут менеджер, а кто клиент
Начинал с Whisper — его все хвалят. На русских записях из реального колл-центра он повёл себя хуже, чем на демках: плюс региональные блокировки на доступ к API. Переехал на Yandex SpeechKit. Российский провайдер, русская речь — родная задача.
Грабля раз: они поменялись местами. Расшифровка выглядит идеально, роли разнесены — но менеджер и клиент поменялись местами. Система уверенно пишет «Клиент: Здравствуйте, меня зовут [менеджер], я из школы…». Первая мысль — у Yandex плохая диаризация. Я почти смирился.
А потом полез в сырой ответ API и увидел причину. Yandex размечает говорящих метками `0` и `1`. А я по наивности ждал `1` и `2` — и завязал на это маппинг ролей. В итоге мой код брал говорящего под номером `1` — а это, в терминах Yandex, уже второй человек. Лечится тривиально — маппинг по порядку появления, а не по номеру тега. Но пока не упрёшься носом в сырой ответ — не догадаешься.
Грабля два: язык сам всё переставил. Думал, разобрался. Баг вернулся — реже, исподтишка. Я держал слоты говорящих в объекте с числовыми ключами. А JavaScript, когда у объекта ключи — числа, любит молча отсортировать их по-своему, по возрастанию. То есть порядок появления, который я честно сохранял, движок языка втихую переставлял за меня. Перевёл хранение на массив, где порядок гарантирован, — отпустило. Вечер потерял.
Грабля три, моя любимая: фейк-стерео. Эта — чемпион по издевательству. Часть записей приходила в стерео-контейнере, но по факту с одним реальным каналом: моно, упакованное как стерео. На глаз и на слух — обычный файл, метаданные гордо сообщают «2 канала». А диаризация по таким записям просто не работала — Yandex возвращал всё одним говорящим.
Первый диагноз снова увёл в сторону: я грешил на плохую запись, думал — голоса наложились. Слушаю — нормальная запись, два разных голоса прекрасно различимы. Почему модель видит одного? Дошло, когда начал смотреть не на расширение, а на реальное содержимое каналов. SpeechKit при диаризации опирается на то, что в стереозаписи левый и правый каналы разные. А тут оба канала были побитово одинаковые — то самое «фейк-стерео». Модель честно не могла развести говорящих по каналам, потому что разводить было нечего.
Теперь я прогоняю каждый файл через `ffprobe` — смотреть реальное число каналов, битрейт, кодек, а не верить расширению. Для фейк-стерео добавил детект и сведение в честное моно перед отправкой.
Из всех трёх граблей выросла одна привычка — retry-логика. Если с первого раза диаризация не удалась, сервис не падает с ошибкой в лицо пользователю, а повторяет распознавание в облегчённом режиме. Именно эта обвязка вокруг чужого API и отличает «демо, которое я показал заказчику» от «сервиса, в который заказчик каждый день заливает файлы».
Модель, которая ломает JSON
С распознаванием более-менее разобрались. Дальше расшифровку надо отдать языковой модели — и тут я налетел на главный инсайт всего проекта.
Мне от модели нужна не «умная» свободная форма. Мне нужна строго заданная структура: по каждому критерию — балл, комментарий, цитата. Эта структура разбирается кодом и рисуется в отчёт. Если модель вернула красивый текст, но с поехавшей структурой или лишней болтовнёй, — весь конвейер встаёт.
Я взял три реальных звонка и прогнал через три разных модели одним промптом:
gpt-4.1-mini: 3 валидных из 3, структура с первого раза — 3 из 3, прошло гейт — 3 из 3.
deepseek-v4-pro: 0 из 3 / 0 из 3 / 0 из 3.
kimi-k2.6: 0 из 3 / 0 из 3 / 0 из 3.
Скромная по «уму» модель отработала идеально. А две модели, про которые пишут «монстры рассуждений», не вернули ни одного пригодного ответа из трёх попыток. Не потому что глупые. На задаче «отдай мне строго вот такую структуру» — они стабильно ломали формат: заворачивали в лишние пояснения, «улучшали» схему по своему вкусу, добавляли поля, которых я не просил.
«В продакшене стабильность валидного структурированного ответа важнее «ума» модели.»
Самая умная модель бесполезна, если один ответ из трёх роняет тебе разбор. Руководителю всё равно, насколько глубоко модель «поняла» звонок, если в трети строк вместо оценки — ошибка.
Отсюда родилась двухстадийная схема: дешёвая надёжная модель работает основной, дорогая подключается запасной — когда основная выдала что-то не прошедшее проверку. Экономика сходится: подавляющее большинство звонков закрывает дешёвая модель, фолбэк включается на считанных процентах, и средняя стоимость оценки одного разговора остаётся копеечной.
Как штука уехала из одной студии в целую сеть
Сервис я начинал под одну языковую студию. Классическая разработка под ключ: один клиент, одна задача, один корпоративный стандарт. Встал на прод, им начали пользоваться старшие менеджеры. Уже успех по исходному ТЗ.
А дальше случилось то, чего я не закладывал. У студии есть франшизная сеть — партнёры по тем же стандартам. Для сети контроль качества звонков — головная боль на порядок больше, чем для одной студии. Управляющая компания не может физически прослушивать звонки администраторов в десятках партнёрских точек. А качество этих звонков бьёт по бренду всей сети.
Оказалось, что инструмент «для себя» закрывает ровно эту боль — только этажом выше. Тот же движок, который оценивал менеджеров одной студии, оценивает администраторов в студиях-партнёрах по стандарту сети. Контроль качества из «руководитель студии слушает свою команду» вырос в «сеть видит уровень сервиса по всем точкам».
Для меня это был сигнал — и как для разработчика, и как для маркетолога. Когда штука, собранная под одного клиента, без переделки нужна на уровне сети — значит, попал не в частную хотелку, а в системную боль.
И вот тут выстрелили две вещи, заложенные «на всякий случай». Корпоративный стандарт я с самого начала вынес в настраиваемый шаблон, а не зашил в код. И сделал мультитенант: разные аккаунты — разные брендинги, разные шаблоны оценки, общий движок. На старте это выглядело как «избыточная гибкость для проекта с одним клиентом». На деле — ровно то, что позволило сервису переехать из студии в сеть без переписывания половины кода.
Что я понял на этом проекте
Для огромного класса бизнес-задач сегодня не нужен ML-инженер. Нужен человек, который умеет три вещи: внятно сформулировать, что должна делать система; собрать промпт, который выжимает из готовой модели стабильный структурированный ответ; и аккуратно склеить чужие API так, чтобы они пережили реальные кривые данные. Это не профессия дата-сайентиста — скорее, инженерная насмотренность плюс дисциплина довести до прода. Я зашёл как маркетолог, который понимает код. И этого хватило.
Самым важным техническим решением оказался не выбор «самой мощной модели», а та маленькая сравнялка на трёх звонках. Полчаса замера — и всё встало на места. Будешь делать что-то подобное — меряй надёжность формата на своих данных раньше, чем споришь про IQ моделей.
По ощущениям: на «магию ИИ» ушло процентов двадцать времени, на «склеить и не уронить» — все восемьдесят. Промпт я собрал за день. А фейк-стерео, числовые ключи в JavaScript и модели, ломающие структуру, — на них и ушла настоящая работа. Если идёшь в подобный проект с ожиданием «ну там же просто промпт» — закладывай время на восемьдесят процентов, которые про водопровод.
И ещё одно. Я недооценил, как быстро частный кейс становится продуктом. Гибкость, заложенная «на всякий случай», — это то, что превратило разовый заказ в масштабируемый сервис. Если собираешь решение под одного клиента и видишь, что задача системная, — закладывай точки гибкости там, где её дешевле заложить сразу.
И ремарка, чтобы не подумали лишнего. Никаких автоматических санкций «балл F → штраф менеджеру» я делать не стал и не советую. Как только система из «помощника, который показывает, на что смотреть» превращается в «надзирателя, который наказывает» — доверие схлопывается, и менеджеры начинают играть против метрики. Это не техническое ограничение — продуктовое решение.
P.S. Мне правда интересно, кто что ловил на стыке распознавания речи и языковых моделей в проде. Диаризация, которая врёт; модели, которые ломают структуру; форматы аудио из ада — если у тебя были свои грабли, напиши в комментариях или в личку.
P.P.S. Если хочется самому пощупать ИИ и понять, что он умеет, — у меня на сайте лежит бесплатный курс Prompt.exe. 22 урока, без регистраций и «премиум-разблокировок» — заходишь и проходишь. А если по работе нужно собрать что-то похожее под свою задачу — пиши в личку, обсудим.