Строим STT + LLM пайплайн на Python для обработки телефонных звонков

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

Я потратил полгода на то, чтобы построить пайплайн, который берёт аудиозапись телефонного звонка и выдаёт структурированный JSON: кто звонил, чего хотел, какие суммы называл, что договорились делать дальше.

Архитектура: четыре этапа, один сюрприз

Пайплайн выглядит просто: STT (Speech-to-Text), диаризация, LLM-извлечение сущностей и валидация.

Этап 1. Аудио: почему 8 кГц — это боль

Источник аудио — SIP-транк облачной АТС. Большинство провайдеров отдают записи через API или webhook. Формат на входе — обычно PCM 16kHz mono или G.711 (8kHz).

Этап 2. Speech-to-Text: Whisper, SpeechKit и честные бенчмарки

Я протестировал четыре варианта на корпусе из 200 телефонных записей на русском языке.

Этап 3. Диаризация: кто это сказал?

Если аудио в моно — нужна speaker diarization. Я использую pyannote-audio 3.1.

Этап 4. LLM-извлечение сущностей: prompt engineering на стероидах

Самая интересная часть. Берём размеченный транскрипт и просим LLM извлечь структурированные данные.

Собираем пайплайн

Оптимизация: с 40 секунд до 8

Первая версия обрабатывала 3-минутный звонок за 40 секунд. Вот что помогло: параллелизация STT + диаризация, кэширование моделей в памяти, оптимизация промпта, chunking для длинных звонков.

Грабли, которые сэкономят вам время

LLM генерирует невалидный JSON, Whisper повторяет фразы, диаризация путает спикеров между звонками, кодировка номеров телефонов.

Мониторинг: как понять, что всё сломалось

Пайплайн без мониторинга — бомба замедленного действия. Ключевые алерты: avg_confidence < 0.6, processing_time > 30 сек, error_rate > 5%.

Читать оригинал