Добавление потоковой передачи токенов и обработки прерываний в интеграцию Twilio Voice и Anthropic

Источник: Twilio•

Добавление потоковой передачи токенов и обработки прерываний в интеграцию Twilio Voice и Anthropic

Узнайте, как с помощью JavaScript добавить потоковую передачу токенов и локальное управление прерываниями в интеграцию Claude (ИИ-ассистента от Anthropic) и Twilio Voice ConversationRelay.

28 октября 2026 г.

Автор

Рецензент

Conversation Relay от Twilio позволяет создавать голосовые приложения в реальном времени, похожие на человеческую речь, с использованием больших языковых моделей на ваш выбор. Она открывает WebSocket-соединение с вашим приложением, что позволяет интегрировать любой выбранный вами ИИ API с Twilio Voice.

В своей предыдущей статье я показал один из способов интеграции Anthropic с Twilio Voice с помощью Conversation Relay на Node.js. Эта настройка позволяла создать базового голосового помощника в реальном времени с использованием моделей Claude от Anthropic. Однако у этого базового приложения были некоторые недостатки, особенно в отношении задержки и обработки прерываний во время разговора.

В этой статье я покажу вам, как реализовать потоковую передачу токенов для снижения голосовой задержки и добавить локальное отслеживание для управления репликами разговора с учетом прерываний. Давайте погрузимся в процесс!

Предварительные требования

Прежде чем начать, вам понадобятся несколько учетных записей (и кое-что еще):

установлена

  • Телефонный номер Twilio (Зарегистрируйтесь в Twilio)

Телефонный номер Twilio (Зарегистрируйтесь в Twilio)

  • IDE или текстовый редактор

IDE или текстовый редактор

для публикации вашего сервера

Учетная запись Anthropic и ключ API

  • Телефон, чтобы совершить звонок для тестирования интеграции!

Телефон, чтобы совершить звонок для тестирования интеграции!

Имея все это под рукой, давайте начнем...

Добавление потоковой передачи токенов

Первая проблема базового приложения, которую вы решите, — это задержка. Если вы отправите базовому приложению запрос, требующий более длинного ответа (например, «назови десять событий, произошедших в 1999 году»), вы заметите, что проходит несколько секунд, прежде чем вы услышите ответ ИИ. Часть этой паузы возникает из-за того, что мы ждем полного ответа от ИИ (а с таким запросом вы гарантировали длинный ответ!).

Вы уменьшите задержку, передавая токены из Claude от Anthropic в режиме реального времени (streaming), вместо того чтобы ждать полного ответа.

Что такое потоковая передача токенов?

Потоковая передача токенов (Token streaming) — это техника отправки частей ответа модели по мере их генерации. В вашем базовом приложении вы ждали весь ответ, включая все токены, прежде чем отправить текст ИИ нашим провайдерам преобразования текста в речь.

Но ожидание целого ответа — не единственный режим, поддерживаемый Anthropic и другими провайдерами. Вы можете также получать частичные ответы от модели и постепенно передавать токены в свое приложение. Оттуда вы можете перенаправить их в Conversation Relay в виде текстовых токенов с атрибутом last: true, и пользователь услышит ответ ИИ еще до того, как тот будет полностью сформирован.

Изменение реакции ИИ

В нашем репозитории с демонстрационными примерами есть ветки, показывающие каждый шаг, предпринятый нами для улучшения базового руководства. Если вы застрянете в этой статье, вы можете клонировать ветку 1 и ветку 2 из нашего репозитория. В этой продолжении статьи блога обсуждается вызов инструментов и функций (Tool/Function Calling).

Вам нужно внести два изменения в наш код, чтобы добавить потоковую передачу токенов. Сначала вы измените способ обращения к Anthropic и ожидания ответа, а затем измените способ обработки типа сообщения «prompt» в Conversation Relay.

Изменение функции aiResponse()

Откройте файл server.js и найдите функцию aiResponse(). Вы измените ее имя на aiResponseStream, так как теперь оно более описательно, и напишете немного кода для обработки передаваемых потоком токенов.

Вот код до изменений:

Copy code

После того как вы нашли этот блок, измените код следующим образом:

Copy code

Когда вы используете функцию stream() библиотеки Anthropic, Anthropic переключается в режим потоковой передачи токенов и отправляет по одному токену за раз. Затем ваше приложение пересылает токены в Conversation Relay с параметром last: false, чтобы Conversation Relay знала, что ожидаются новые токены.

И наконец, когда ответ готов, этот код отправляет пустое текстовое сообщение с параметром last: true и возвращает окончательный накопленный ответ от ассистента с помощью stream.finalMessage().

Изменение обработки сообщения «prompt» в Conversation Relay

В файле server.js найдите конструкцию case "prompt": в блоке switch внутри метода fastify.register(). Поскольку теперь вы вызываете асинхронную функцию, возвращающую Promise, вам нужно дождаться возврата Promise, прежде чем добавлять ответ «assistant» в разговор.

Вот код до изменений:

Copy code

Измените этот код следующим образом:

Copy code

Как видите, теперь вы ожидаете возврата от функции aiResponseStream() и добавляете роль и контент от языковой модели в локальное хранилище разговора.

Добавление отслеживания разговора и обработки прерываний

Отличная работа! Если вы снова протестируете приложение и попробуете свой открытый запрос «назови десять событий, произошедших в 1999 году», вы заметите значительное улучшение задержки. Но если вы попытаетесь прервать ИИ, вы можете заметить другую проблему: хотя на слух кажется, что вы прервали его ответ, ИИ не знает, какую часть ответа вы услышали!

На этом этапе вы будете отслеживать разговор локально и покажете один из способов обработки таких прерываний, держа ваш ИИ в курсе с помощью атрибута utteranceUntilInterrupt Conversation Relay в сообщениях о прерываниях и индексации локального хранилища разговора.

Снова изменим функцию ответа ИИ

Вернитесь к функции aiResponseStream(). Вы обновите ее дальше, чтобы накапливать токены по мере их поступления:

Copy code

Теперь вы одновременно пересылаете токены в Conversation Relay и накапливаете их в массиве assistantSegments. Когда ответ ИИ завершен, вы добавляете полный ответ в sessionData.conversation, где мы сохраняем все реплики разговора. Как вы увидите через минуту, мы будем использовать индексы этих реплик разговора, чтобы определить момент прерывания. Но сначала: еще больше изменений в обработчик сообщений «prompt».

Изменение управления сообщением «prompt»

Вы снова меняете способ отслеживания разговора. Поскольку aiResponseStream() теперь обрабатывает накопление токенов и добавление их в историю разговора сеанса, вы можете упростить кейс сообщения «prompt» в вашем блоке case.

Измените кейс «prompt» на следующий:

Copy code

…а затем перейдите к сообщениям «interrupt» (прерывание).

Обработка сообщений «interrupt»

Теперь измените обработку WebSocket для более эффективной обработки сообщения прерывания от Conversation Relay. Начните с вызова новой функции handleInterrupt(), когда мы получаем сообщение о прерывании от Conversation Relay:

Copy code

Теперь обратите внимание на эту новую функцию. Она принимает параметр utteranceUntilInterrupt из сообщения о прерывании вместе с callSid, который приложение использует для индексации реплик разговора.

Вот функция, которую нужно добавить:

Copy code

Как вы видели, функция handleInterrupt() вызывается только тогда, когда голосовое взаимодействие прерывается — то есть когда Conversation Relay отправляет сообщение о прерывании. Этот код находит utteranceUntilInterrupt в вашем локальном хранилище разговора и заменяет эту часть реплики ИИ тем, что Conversation Relay сообщила вашему приложению о том, что услышал пользователь. Затем, в следующий раз, когда вы передадите разговор в Anthropic (с помощью aiResponseStream(conversation, ws)), ИИ будет «знать», докуда дослушал вызывающий абонент. Круто, правда?

Если вы пропустили какой-то шаг и у вас ничего не работает, вы можете посмотреть полный код для этого шага здесь.

Тестирование вашего ИИ-приложения

Пришло время пожинать плоды; вы готовы к тестированию!

Возможно, вы уже заучили (или выполнили) эти первые шаги для базового руководства. Если это так, можете пропустить этап настройки.

Настройте ИИ-приложение

В своем терминале откройте соединение с помощью ngrok:

Копировать код

Теперь обновите файл .env, указав новый URL ngrok (не включайте схему «https://» или «http://»):

Копировать код

Теперь запустите сервер:

Копировать код

Зайдите в консоль Twilio и найдите телефонный номер, который будете использовать. Задайте конфигурацию в разделе A call comes in, выбрав опцию Webhook и HTTP GET в поле HTTP.

Для URL добавьте ваш URL ngrok (на этот путь с «https://») и добавьте /twiml. Например: https://abcdefgh.ngrok.app/twiml.

Нажмите Save, все готово к тестированию.

Позвоните Claude

Наберите настроенный номер Twilio. Вскоре вы услышите приветствие — пообщайтесь с вашим новым, усовершенствованным Claude, ИИ-ассистентом от Anthropic!

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

Следующие шаги

Поздравляем с созданием нового, более мощного голосового ИИ-ассистента с помощью Node.js, Conversation Relay, Claude и всего нескольких строк кода! В следующей статье мы рассмотрим вызовы инструментов или функций, чтобы еще немного расширить возможности вашего ИИ-ассистента.

Пол Камп (Paul Kamp) — технический главный редактор Twilio Blog. Ему было неловко постоянно перебивать ИИ. Вы можете связаться с Полом (не беспокойтесь, вы его не перебьете) по адресу pkamp [at] twilio.com.

О чём эта статья

Ещё в разделе «Телеком и сети»

Все →

Ещё от Twilio