вступ
Наш голосовий продукт мав дві скарги, які ми не могли узгодити всередині. Англомовні корпоративні клієнти сприймали штучний інтелект швидко. Клієнти, які розмовляють мандаринською мовою, і дедалі частіше клієнти, які розмовляють в’єтнамською, тагальською та хінді, відчували млявість ШІ. Розрив, виміряний від кінця до кінця від мовчання абонента до першого складу ШІ, становив 260 мс на англійській мові та 540 мс на китайській мові. Обидва показники були в межах опублікованого бюджету затримки.
Лише один із них почувався прийнятним під час телефонної розмови.
Інстинкт будь-якої команди інженерів, яка бачить прогалину в затримці, полягає в тому, щоб переробити модель. Швидший висновок. Менша модель. Краще квантування. Ми все це зробили. Це дало нам 60 мс за всіма напрямками, що нічого не зменшило — відносний розрив все ще був, а англійська залишалася вдвічі швидшою.
Справжнє виправлення прийшло в результаті іншого спостереження: ми розглядали затримку як модельну проблему, тоді як насправді це була проблема маршрутизації.
Куди насправді йдуть мілісекунди
Розбиття відповіді Mandarin 540 мс на сегменти було першим, що прояснило проблему. Бухгалтерський облік виглядав приблизно так:
- Захоплення аудіо та кінцева точка — 80 мс
- Перший маркер перетворення мови в текст — 140 мс
- Намір + конвеєр пошуку — 90 мс
- Велика модель першого токена (покоління) — 180 мс
- Синтез мовлення - спочатку аудіо — 50 мс
На шляху англійської мови ті самі сегменти були 80 / 60 / 90 / 80 / 40. Два сегменти, які різко розходилися, були перетворення мови в текст і створення великої моделі. STT був повільнішим у мандарині, оскільки акустичну модель було навчено з довшим контекстним вікном — необхідним для тонального усунення неоднозначності — яке зрушувало перший маркер на 80 мс.
Генерація моделі була повільнішою, оскільки токенізатор виробляв більше токенів на символ еквівалентного значення китайською мовою, ніж англійською.
Також не було дефекту моделі. Обидва були компромісами, які були тихо накопичені незалежними командами, які оптимізували власні показники — STT для точності, LLM для якості генерації. Вартість затримки була реальною, але це не були нічиї прибутки та збитки.
Виправлення маршрутизації, яке купило 200 мс
Ми припинили маршрутизацію всіх мов через один LLM. Замість цього ми створили тонкий класифікаційний рівень перед генерацією, який визначає за менш ніж 8 мс три речі: мову вхідного висловлювання, клас розмовного наміру та те, чи є запит одним із приблизно 40 високочастотних шаблонів, які ми визначили шляхом кластеризації 2 млн сегментів виклику.
Коли класифікатор визначає високочастотний шаблон у неанглійській мові, ми направляємо генерацію до меншої моделі, спеціалізованої на певній мові, яка безпосередньо обробляє цей шаблон. Менша модель була розроблена на основі мільйонів завершень того самого шаблону, тому її якість на цих конкретних шляхах знаходиться в межах шуму великої моделі, але її затримка першого маркера становить приблизно третину.
Коли класифікатор бачить кінцевий намір — все, що не входить до 40 шаблонів — запит потрапляє до великої моделі, як і раніше. Здебільшого падіння затримки відбувається через те, що високочастотні шаблони є також моделі, на які припадає ~78% обсягу викликів. Кінцеві випадки оплачують оригінальну затримку, але вони рідкісні.
Приходу класифікатора ніхто не бачив
Тонкий класифікатор був частиною проекту, який ніхто не передбачав у бюджеті. Його створення зайняло більше часу, ніж створення самої системи маршрутизації, оскільки режими збоїв були непомітними. Класифікатор, який неправильно направляє 1% запитів до невеликої моделі, яка їх не обробляє, створює галюцинації, а не просто погіршені відповіді.
Три речі змусили класифікатор працювати. По-перше, його навчали на реальному виробничому трафіку, а не на синтетичних даних. По-друге, він повернув оцінку достовірності, яку маршрутизатор міг визначити — все, що нижче 0,91, автоматично потрапляє до великої моделі.
По-третє, ми тіньово розгортали його протягом шести тижнів проти існуючого конвеєра, причому велика модель забезпечувала базову правду, перш ніж будь-який трафік фактично було спрямовано на маленькі моделі.
Тіньове розгортання виявило чотири класи помилок, які пропустив набір офлайн-тестів. Дві з них було легко виправити в навчальних даних. Два обов’язкових правила навмисної маршрутизації — все, що стосується перевірки особи, платежів або скасування зустрічі, завжди переходить до великої моделі, незалежно від впевненості класифікатора, оскільки ціна галюцинації на цих шляхах вища, ніж виграш затримки.
Сторона проблеми TTS
Поки зміни LLM і STT проходили перевірку, паралельна команда працювала над мовленнєвим виходом. Перше аудіо 50 мс TTS англійською було фактично неперевершеним; розрив у 70–90 мс для більшості неанглійських мов був зумовлений меншими голосовими моделями, менш агресивним кешуванням і єдиним спільним пулом GPU, який надавав пріоритет англійській мові під час навантаження.
Ми розділили інфраструктуру TTS на пули, закріплені за мовою. Mandarin TTS тепер працює на власному пулі, з власними правилами масштабування, на обладнанні, розташованому поблизу регіонів, звідки надходить більшість нашого трафіку Mandarin. Затримка впала з 70-90 мс до 45 мс протягом двох тижнів після перемикання.
Нічого з цього не було розумним; це була інфраструктурна робота, яку ніхто не потрудився зробити, тому що маргінальне вдосконалення будь-якої окремої мови не виправдовувало її окремо.
Урок — і ми зараз записуємо його внутрішньо — полягає в тому, що «ми не інвестували в це, тому що жодна метрика, спрямована на користувача, не виправдовувала це» — це саме те рішення, яке призводить до розриву в 280 мс між двома мовами протягом чотирьох років.
Парність вимірювання, а не середні значення
Одна невелика, але значуща зміна, яку ми внесли внутрішньо, стосувалась способу звітування командної панелі затримок. Раніше ми відстежували p50 і p95 наскрізної затримки, усереднені для всіх мов, порівняно з одним SLO. Приладова панель більшу частину часу виглядала зеленою.
Нова приладова панель повідомляє про p50 і p95 на мову проти а паритет SLO — розрив між найповільнішою та найшвидшою підтримуваними мовами має власний бюджет, який дотримується окремо. Ми встановили паритетний бюджет на рівні 60 мс. Коли розрив перевищує бюджет, черговий отримує виклик.
Інформаційна панель паритету робить те, чого не могла зробити середня: вона робить регресії на найповільнішій мові видимими з такою ж терміновістю, як і регресії на найшвидшій. Коли ви усереднюєте 32 мови, регресія на 200 мс у в’єтнамській мові зміщує середнє значення на 6 мс. Коли ви вимірюєте паритет, він пересуває інформаційну панель на 200 мс.
Що ще повільно
Після роботи з маршрутизації, пулів TTS і інформаційної панелі парності наша найгірша мова (кантонська, насамперед через те, що допоміжний корпус акустичної моделі менший) становить 320 мс. Англійська – 220 мс. Проміжок у 100 мс, що залишився, реальний, і ми приблизно знаємо, де він живе — акустична модель Cantonese STT старіша і ще не працює на новій архітектурі, і ми перенавчимо її в третьому кварталі.
Але «найповільніша мова відстає від найшвидшої на 100 мс» — це інша розмова, ніж «найповільніша мова відстає від найшвидшої на 280 мс». Перше – це відома регресія з запланованим щоквартальним виправленням. Останній був надзвичайною ситуацією, про яку ми навіть не підозрювали.
Що б ми зробили по-іншому наступного разу
Три речі, у порядку пріоритету, якби ми відновлювали стек затримки з нуля з тим, що ми знаємо зараз.
- Спочатку побудуйте класифікатор-маршрутизатор, а потім модель. Рівень маршрутизації в кінцевому підсумку став частиною з найвищим впливом. Розглядаючи це як «ми додамо це пізніше, якщо нам це знадобиться», виявилося, що ми жили з затримкою однієї моделі на 18 місяців довше, ніж нам було потрібно.
- Встановіть парність SLO перед мовними SLO. Спокуса полягає в тому, щоб встановити мовні цілі й дозволити виникнути паритет. Парність не виникає; вона повільно розходиться в напрямку основної мови команди.
- Ресурси для кожної мови інфраструктури, як якщо б кожна мова була окремим продуктом. Mandarin TTS заслуговує на власний пул GPU з першого дня, а не з того дня, як ми виміряли розрив затримки.
Жодне з цього не є новим дослідженням. Нічого з цього не потребує паперу. Це вимагало розглядати паритет затримок як зобов’язання щодо продукту, а потім фінансувати непривабливу інфраструктуру для підтримки цього зобов’язання. Зараз ми маємо той паритет, який нам потрібен. У нас його не було чотири роки.