Голосові агенти й виправлення: чому мало правильно почути номер замовлення
Голосовий агент повторив виправлений номер замовлення, але змінив не те замовлення. Розбираємо, як застарілі виклики інструментів переживають перебивання і як їх ловлять скінченні автомати й трасування.
Підтвердження, яке звучало правильно
Клієнт просить голосового агента перенести доставку замовлення 4821 на п'ятницю. Не давши агентові договорити, клієнт уставляє поправку: номер 4281, а не 4821. Агент зупиняється на півслові, погоджується й обіцяє оновити замовлення 4281.
Дзвінок закінчується на добрій ноті. Але система змінила замовлення 4821, а замовлення 4281 так ніхто й не торкнувся.
Розпізнавання мовлення правильно вловило обидва номери. Агент навіть дослівно повторив виправлений. У транскрипті немає жодної помилки, і все ж щось зламалося.
Чому транскрипт — це не стан
Налагодження починається з виключення очевидних підозрюваних. Це не помилка розпізнавання, і агент не вигадав номер. Конвеєр просто поводився з чотирма різними речами так, ніби це одне й те саме:
Conversation history → 4821, then a correction to 4281
Active intent → the order the customer currently means
Pending action → the order ID already loaded into the tool call
Backend state → the order that was actually written
Транскрипт — це журнал подій. Він назавжди фіксує все сказане по черзі. Обидва номери замовлення там на своєму місці, адже обидва прозвучали. Але після виправлення в активному стані задачі має лишитися тільки один із них, а якщо транскрипт водночас слугує станом, позначити старе значення як застаріле нічим.
Запис про те, що було сказано, виявився точним. Зламався перехід стану.
Як вижило застаріле значення
Щоб так сталося, досить трьох звичайних проєктних рішень, і в більшості голосових стеків є всі три.
Історія, що тільки росте
Виправлення надходить як ще одне повідомлення, і ніхто явно не анулює старе значення. На кожному ході моделі доводиться з'ясовувати, яке з кількох правдоподібних значень актуальне. Коли затримку жорстко обмежено, це міркування може програти перегони наступній дії.
Інструменти, підготовлені зарано
Голосові агенти налаштовані на чуйність, тому виклики інструментів часто починають заповнювати аргументи ще до того, як клієнт договорив фразу. Перебивання глушить звук. Але воно не скасовує автоматично запит до API, який уже в дорозі.
Кілька копій одного факту
Розмовна модель, шар оркестрації та шар виклику інструментів часто зберігають кожен свою копію ідентифікатора замовлення, і оновлення однієї не оновлює решти. Звідси найнеприємніший результат. Уголос агент оголошує 4281, а інструмент усе ще тримає 4821, тож дзвінок звучить правильно, а дія хибна.
Що показує трасування
Ні транскрипт, ні фінальна голосова відповідь нічого з цього не розкривають. Це видно лише в трасуванні виконання з мітками часу:
10:03:12.100 Customer mentions order 4821
10:03:12.420 Active state set: order_id = 4821
10:03:13.000 Update tool prepared: order_id = 4821
10:03:13.250 Customer interrupts: "Sorry, I meant 4281."
10:03:13.510 Conversation state updated: order_id = 4281
10:03:13.700 Previously prepared tool executes: order_id = 4821
10:03:14.100 Agent says: "I've updated order 4281."
Виправлення надійшло о 13.510, а виклик інструмента було зафіксовано ще о 13.000. Усе після цієї фіксації, зокрема голосове підтвердження, відбиває значення, яке більше не збігається з бажанням клієнта. Оцінювання, яке перевіряє, чи вловив транскрипт виправлення або чи назвала відповідь правильне замовлення, цей дзвінок пропустило б. Розбіжність видає лише трасування.
Виправлення має скасовувати незавершену роботу
Ліки — не хитріший промпт. Розмова має йти як поетапний скінченний автомат, і виправлення зобов'язане відкочувати кожен крок, що залежав від значення, яке замінюється:
→ Intent detected
→ Parameters collected
→ Parameters validated
→ Customer confirmation
→ Action committed
→ Backend result verified
Коли змінюється ідентифікатор замовлення, застаріває цілий ланцюжок: завантажений запис замовлення, результат перевірки допустимості, аргументи в черзі до інструмента, уже дане клієнтом підтвердження і будь-який незавершений запис. Потік повертається на етап «параметри зібрано» і знову йде вперед. На практиці для цього потрібно кілька речей, що працюють разом:
- структурований стан задачі замість стану, виведеного з транскрипту
- номери версій у стану, щоб застарілий запис можна було виявити й відхилити
- ключі ідемпотентності, щоб дубльовану або замінену дію не можна було застосувати двічі непомітно для всіх
- явне скасування викликів інструментів, що виконуються, за кожного перебивання
- підтвердження, прив'язане до поточного стану, а не до стану на момент початку підтвердження
- перевірка за бекендом після виконання замість довіри до того, що повернув інструмент
Як це тестувати
Тест, що вимірює точність транскрипту, ніколи не знайде помилки цього класу, бо з транскриптом усе гаразд. Щоб її впіймати, потрібні синтетичні дзвінки з перебиванням у три конкретні моменти: до підготовки інструмента, під час підготовки й після надсилання. Проганяти їх варто на кількох видах виправлень: номер замовлення, кількість, дата доставки, адреса, особа клієнта й заперечення, коли клієнт просить підтвердити й одразу ж каже, що не треба.
Кожен прогін оцінюється за сімома запитаннями:
- Чи було вловлено виправлення?
- Чи оновився активний стан?
- Чи було анульовано старе значення?
- Чи отримав інструмент правильні аргументи?
- Чи була спроба дубльованої або застарілої дії?
- Чи був підсумковий стан бекенду правильним?
- Чи збіглося голосове підтвердження з бекендом?
Розрив між шостим запитанням і перевірками голосового підтвердження на рівні транскрипту — це саме те місце, де ховається такий збій. Він стає помітним лише з набором тестів, який вимірює істину бекенду, а не правдоподібність розмови.
Почути — не означає застосувати
Голосовий агент не заслуговує на похвалу за те, що почув виправлення або чисто його повторив. Це твердження рівня розмови. Щоб виправлення зарахувалося, воно має оновити активний стан, скасувати або замінити дію, що очікує, дійти до інструмента з правильними аргументами і зрештою з'явитися в бекенді.
У голосовому ШІ фраза «я вас почув» — твердження про розмову, а «виправлення застосовано» — твердження про керування станом. Продакшен-системи мусять перевіряти друге, бо якщо цього не робити, транскрипт нічого не покаже.