Дата публикации
ai_products

Как собрать продакшн-голосового ассистента за вечер: Stream Vision Agents и Amazon Nova 2 Sonic

Что нового

Stream и AWS предлагают связку из трёх компонентов для реальных голосовых ассистентов, которые работают в браузере и на мобильных устройствах в режиме реального времени:

  1. Amazon Nova 2 Sonic через Amazon Bedrock

    • Фундаментальная speech‑to‑speech‑модель.
    • Принимает аудио и отдаёт аудио — без отдельного STT и TTS.
    • Поддерживает двунаправленный стриминг: модель одновременно слушает и отвечает.
    • Встроенное определение границ реплик (turn detection).
    • Встроенный function calling: модель может вызывать ваши Python‑функции (доступ к БД, API, CRM и т.д.) прямо в ходе разговора.
    • Обработка контекста по ходу сессии, в том числе с учётом результатов вызванных функций.
  2. Stream Vision Agents (open source, Python)

    • Фреймворк для реальных голосовых и видео‑агентов.
    • Плагинная архитектура с 25+ интеграциями: Amazon Bedrock, Deepgram, Cartesia, Amazon Polly и другие.
    • Готовые клиентские SDK: React, iOS, Android, Flutter, React Native.
    • Декораторы для регистрации функций, которые может вызывать модель (tool calling).
    • Встроенная поддержка Voice Activity Detection (Silero VAD), автоматического переподключения и управления жизненным циклом сессий.
    • Можно использовать как с реальным времени (Nova 2 Sonic), так и с обычными LLM (например, Claude через Bedrock) с отдельными STT/TTS.
  3. Глобальная edge‑сеть Stream

    • SFU‑инфраструктура (Selective Forwarding Unit) для WebRTC‑звонков.
    • Типичные показатели:
      • время входа в звонок — менее 500 мс,
      • аудио‑латентность — менее 30 мс на транспортном уровне.
    • Передача аудио по RTP поверх UDP для предсказуемой задержки и отсутствия head‑of‑line blocking.

Ключевой практический результат: в примере из поста полноценный голосовой ассистент на Nova 2 Sonic поднимается менее чем в 30 строках Python‑кода, а Stream даёт 333 000 participant‑минут в месяц для Audio API без доплаты.

Как это работает

Архитектура на высоком уровне

Роли распределены жёстко:

  • Stream отвечает за:

    • WebRTC, SFU, TURN/STUN, сигналинг;
    • доставку аудио между браузером/мобилкой и бэкендом агента;
    • edge‑узлы, которые принимают RTP и пересылают его дальше.
  • Vision Agents живёт в AWS и отвечает за:

    • приём аудио от Stream как «ещё один участник звонка»;
    • декодирование в PCM и стриминг в Amazon Bedrock;
    • отправку ответного аудио обратно в звонок;
    • VAD, обработку барж‑ина (когда пользователь перебивает ассистента), вызовы функций, управление контекстом.
  • Amazon Nova 2 Sonic в Amazon Bedrock:

    • получает PCM‑аудио по realtime‑API;
    • определяет границы реплик, распознаёт речь, понимает запрос, формирует ответ и синтезирует голос;
    • при необходимости инициирует toolUse — запрос на вызов вашей функции.

Поток аудио end‑to‑end

  1. Пользователь подключается из веба или мобильного приложения.
    Клиентский SDK Stream запрашивает микрофон (и при необходимости камеру) и присоединяется к звонку с включённым AI‑участником.

  2. Аудио уходит в ближайший SFU Stream:

    • WebRTC‑соединение устанавливается с edge‑узлом в ближайшем регионе.
    • Аудио идёт как RTP по UDP — это даёт низкую задержку и устойчивость к потере пакетов.
    • SFU занимается NAT‑traversal, оценкой пропускной способности, simulcast.
  3. SFU пересылает трек в Vision Agent:

    • Для SFU агент — просто ещё один peer в звонке.
    • Vision Agent worker держит собственный PeerConnection для этой сессии.
  4. Vision Agent декодирует аудио и стримит в Bedrock:

    • Аудио декодируется в сырой PCM.
    • Плагин aws.Realtime открывает realtime‑сессию к Amazon Nova 2 Sonic.
    • PCM‑фреймы примерно по 32 мс отправляются как audioInput‑события.
  5. Nova 2 Sonic обрабатывает разговор:

    • Сессия стартует с sessionStart (maxTokens, temperature, top‑p, turn detection).
    • Затем идёт promptStart: формат аудио (24 kHz PCM), выбор голоса, описание доступных инструментов.
    • Системные инструкции приходят как блок с ролью SYSTEM.
    • По мере прихода аудио Nova 2 Sonic:
      • определяет, когда пользователь закончил фразу;
      • при необходимости вызывает функции (toolUse);
      • продолжает разговор с учётом контекста и результатов функций;
      • стримит ответ как audioOutput.
  6. Vision Agent пакует ответ обратно в RTP:

    • Аудиофреймы от Nova 2 Sonic режутся на куски, упаковываются в RTP.
    • Таймстемпы растут монотонно, чтобы не было разрывов и дрейфа.
    • Пакеты уходят обратно через SFU в браузер/мобилку.
  7. Клиент воспроизводит звук:

    • WebRTC‑стек декодирует аудио и проигрывает с задержкой до 500 мс от голоса пользователя до ответа ассистента.

VAD, барж‑ин и эхо

  • Vision Agents использует Silero VAD для детекции начала и конца речи и для барж‑ина.
  • Эхо‑подавление в браузере снижает риск, что голос ассистента снова сработает как входной сигнал.
  • Когда пользователь перебивает ассистента, клиент отправляет сигнал по RTCDataChannel.
    Worker останавливает стриминг ответа Nova 2 Sonic и сбрасывает локальный буфер, чтобы не доигрывать «старую» реплику.

Как устроен realtime‑API Amazon Nova 2 Sonic

Плагин aws.Realtime в Vision Agents оборачивает довольно сложный событийный протокол. В упрощённом виде поток выглядит так:

  1. sessionStart — конфигурация инференса:
def _create_session_start_event(self) -> Dict[str, Any]:
    return {
        "event": {
            "sessionStart": {
                "inferenceConfiguration": {
                    "maxTokens": 1024,
                    "topP": 0.9,
                    "temperature": 0.7,
                }
            },
            "turnDetectionConfiguration": {
                "endpointingSensitivity": "MEDIUM"
            },
        }
    }
  1. promptStart — формат аудио, голос, список инструментов.
  2. System‑инструкции — текстовый блок с ролью SYSTEM.
  3. audioInput — поток PCM‑фреймов ~32 мс.
  4. audioOutput — поток ответных аудиофреймов.
  5. promptEnd и sessionEnd — корректное завершение сессии.

Любой контент идёт в паттерне contentStart → payload → contentEnd. Это позволяет модели корректно вести контекст и чередовать речь, текст и tool‑результаты.

Function calling: как Nova 2 Sonic вызывает ваши функции

  1. Модель решает, что ей нужен внешний инструмент, и отправляет toolUse с именем функции и аргументами.
  2. Плагин Vision Agents перехватывает это событие, десериализует аргументы и вызывает зарегистрированную Python‑функцию.
  3. Результат отправляется обратно в Nova 2 Sonic как toolResult в том же паттерне contentStart → toolResult → contentEnd.
  4. Модель использует результат в следующей реплике и продолжает разговор.

Это работает и для простых вычислений, и для сложных цепочек: запрос к БД, проверка инвентаря, создание заказа — всё в рамках одной голосовой сессии.

Что это значит для вас

Где это реально помогает

  1. Голосовые интерфейсы там, где экран неудобен или опасен
    Примеры сценариев:

    • вождение;
    • выездное обслуживание и ремонт;
    • логистика и склад;
    • медицина и госпитали;
    • любые «грязные» или шумные производства, где руки заняты.

    Что даёт связка Vision Agents + Nova 2 Sonic:

    • разговор в реальном времени без явных пауз между репликами;
    • возможность перебить ассистента и скорректировать запрос;
    • сохранение контекста: не нужно повторять адрес, номер заказа или диагноз каждый раз;
    • интеграция с бэкендом через function calling: ассистент не просто отвечает, а меняет состояние систем (обновляет статус задачи, логирует заметки, вызывает человека).
  2. Масштабируемый inbound‑саппорт по телефону
    Архитектура SFU + Nova 2 Sonic хорошо подходит для контакт‑центров:

    • низкая задержка — разговор не ощущается «роботизированным» только из‑за лагов;
    • встроенный function calling — ассистент может:
      • проверять баланс или статус заказа;
      • создавать тикеты;
      • переключать на живого оператора, если сценарий вышел за рамки;
    • Vision Agents берёт на себя reconnection, обработку сбоев и таймаутов.
  3. Внутренние голосовые ассистенты и workflow‑автоматизация

    • Быстрый доступ к документации, базе знаний, аналитике.
    • Голосом запускать пайплайны: «создай отчёт за вчера», «запусти тесты», «создай задачу в issue‑трекере».
    • Возможность строить кастомные пайплайны: отдельный STT, LLM и TTS, если Nova 2 Sonic вам не подходит по цене или возможностям.
  4. Мультиязычные ассистенты

    • Nova 2 Sonic поддерживает несколько языков (в посте перечисление языков не приводится, но архитектура построена под мультиязычность).
    • Vision Agents не ограничивает вас одним провайдером: можно комбинировать Amazon Bedrock, Deepgram, Cartesia, Amazon Polly и другие, чтобы собрать нужный стек.

Кому это особенно полезно

  • Продуктовым и платформенным командам, которые:

    • не хотят сами собирать WebRTC, SFU и reconnection‑логику;
    • хотят управлять логикой ассистента в своём AWS‑аккаунте;
    • готовы писать минимальное количество Python‑кода.
  • Стартапам и R&D‑командам, которым важно быстро собрать прототип голосового ассистента и протестировать сценарии на реальных пользователях.

  • Enterprise‑командам, которым критично, чтобы данные и бизнес‑логика оставались в их AWS‑аккаунте, а провайдер реального времени отвечал только за медиа‑транспорт.

Где это может не подойти

  • Если у вас нет доступа к Amazon Bedrock или AWS Nova 2 Sonic в вашем регионе.
  • Если юридические или комплаенс‑ограничения не позволяют использовать внешнюю edge‑сеть (Stream) для медиа‑трафика.
  • Если вам нужен полностью on‑prem стек без внешних SaaS‑компонентов.
  • Если проект чувствителен к затратам на inference: Nova 2 Sonic тарифицируется по вызовам Bedrock, и это нужно учитывать при большом трафике.

Доступность из России

Amazon Bedrock и Stream официально ориентируются на глобальный рынок, но доступ к AWS и связанным сервисам из России может требовать VPN и может нарушать локальные ограничения. Перед использованием такой архитектуры для продакшн‑систем стоит отдельно проверить юридические и инфраструктурные риски.

Место на рынке

С точки зрения архитектуры это не «ещё один бот на LLM», а связка из:

  • специализированной speech‑to‑speech‑модели (Amazon Nova 2 Sonic);
  • продакшн‑готовой RTC‑инфраструктуры (Stream SFU);
  • open source‑фреймворка для glue‑кода (Vision Agents).

В оригинальном материале нет прямых сравнений с GPT‑4o, Gemini Live, Claude Voice или другими голосовыми стеками, поэтому можно говорить только о том, что явно описано:

  • По латентности транспорта:

    • Stream заявляет <500 мс end‑to‑end задержки разговора и <30 мс аудио‑латентности на своём edge‑уровне.
    • Это укладывается в требования к естественному диалогу и соответствует уровню других крупных провайдеров RTC.
  • По архитектуре:

    • Nova 2 Sonic не требует отдельного STT и TTS — это упрощает интеграцию и снижает количество точек отказа.
    • Для сравнения: многие существующие решения до сих пор собирают пайплайн из трёх сервисов (STT → LLM → TTS), что усложняет управление задержкой и ошибками.
  • По инструментам для разработчиков:

    • Vision Agents даёт Python‑фреймворк с плагинами для Bedrock, Deepgram, Cartesia, Amazon Polly и других.
    • Есть готовые SDK для популярных клиентских платформ, что сокращает время до первого прототипа.

Если вам нужен именно «комбайн» для голосовых ассистентов с готовой RTC‑инфраструктурой и функциями, которые модель вызывает в реальном времени, эта связка закрывает большую часть задач без необходимости собирать низкоуровневый стек самостоятельно.

Установка

Ниже — шаги из оригинального поста, полностью и без сокращений.

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

Перед стартом нужно:

  • Настроенные AWS‑креденшалы через переменные окружения, IAM‑роль или профиль AWS CLI.

    • Для продакшна лучше использовать IAM‑роли, привязанные к compute‑ресурсам.
    • Для локальной разработки — AWS CLI профили (aws configure) или AWS SSO.
    • Не коммить .env с ключами в Git.
  • Аккаунт Stream с Audio API key и secret.

    • Ожидаемый лимит — 333 000 participant‑минут в месяц без доплаты.
  • Python 3.12+.

  • Пакетный менеджер uv:

pip install uv
  • Установленный Vision Agents:
uv add vision-agents

Шаг 1. Создаём проект и ставим Vision Agents с AWS‑плагином

mkdir voice-agent
cd voice-agent
uv init
uv add "vision-agents[getstream,aws]" python-dotenv

Экстра vision-agents[aws] подтянет Amazon Bedrock‑плагин и зависимости: boto3, aws-sdk-bedrock-runtime и Silero VAD.

Шаг 2. Настраиваем переменные окружения

Создайте файл .env в корне проекта. Рекомендуемый подход — указывать AWS_PROFILE, а не прямые ключи.

# Stream API credentials
STREAM_API_KEY=test/geststream/api_key
STREAM_API_SECRET=test/getstream/api_secret

# AWS credentials
AWS_PROFILE=your_aws_profile_name
AWS_REGION=us-east-1

Vision Agents автоматически подхватывает эти переменные при старте, их не нужно передавать вручную в каждый клиент.

Как запустить

Шаг 3. Первый голосовой ассистент на Nova 2 Sonic

Создайте main.py со следующим содержимым:

import asyncio
from dotenv import load_dotenv
from vision_agents.core import Agent, User, Runner
from vision_agents.core.agents import AgentLauncher
from vision_agents.plugins import aws, getstream

load_dotenv()


async def create_agent(**kwargs) -> Agent:
    agent = Agent(
        edge=getstream.Edge(),
        agent_user=User(name="Helpful Assistant", id="agent"),
        instructions="You are a helpful voice assistant. Be concise and friendly.",
        llm=aws.Realtime(
            model="amazon.nova-2-sonic-v1:0",
            region_name="us-east-1",
            voice_id="matthew",
        ),
    )
    return agent


async def join_call(agent: Agent, call_type: str, call_id: str, **kwargs) -> None:
    call = await agent.create_call(call_type, call_id)

    async with agent.join(call):
        await asyncio.sleep(2)

        await agent.llm.simple_response(
            text="Greet the user warmly and ask how you can help."
        )

        await agent.finish()


# Run until the call ends
if __name__ == "__main__":
    Runner(AgentLauncher(create_agent=create_agent, join_call=join_call)).cli()

Шаг 4. Запуск ассистента

uv run main.py run

На этом этапе у вас есть рабочий голосовой ассистент в реальном времени на Amazon Nova 2 Sonic, доступный из клиента Stream. Всё это — меньше чем в 30 строках кода.

Function calling: примеры кода

Ниже — пример, как добавить функции, которые Nova 2 Sonic может вызывать в ходе разговора.

import asyncio
from dotenv import load_dotenv
from typing import Dict, Any

from vision_agents.core import Agent, User, Runner
from vision_agents.core.agents import AgentLauncher
from vision_agents.plugins import aws, getstream

load_dotenv()


async def create_agent(**kwargs) -> Agent:
    agent = Agent(
        edge=getstream.Edge(),
        agent_user=User(name="Weather Assistant", id="agent"),
        instructions="""You are a helpful weather assistant. When users ask about weather, use the get_weather function to fetch current conditions. You can also help with simple calculations.""",
        llm=aws.Realtime(
            model="amazon.nova-2-sonic-v1:0",
            region_name="us-east-1",
        ),
    )

    @agent.llm.register_function(
        name="get_weather", description="Get the current weather for a given city"
    )
    async def get_weather(location: str) -> Dict[str, Any]:
        # In production, call a real weather API
        return {
            "city": location,
            "temperature": 72,
            "condition": "Sunny",
            "humidity": "45%",
        }

    @agent.llm.register_function(
        name="calculate", description="Perform a mathematical calculation"
    )
    def calculate(operation: str, a: float, b: float) -> dict:
        operations = {
            "add": lambda x, y: x + y,
            "subtract": lambda x, y: x - y,
            "multiply": lambda x, y: x * y,
            "divide": lambda x, y: x / y if y != 0 else None,
        }
        result = operations.get(operation, lambda x, y: None)(a, b)
        return {"operation": operation, "a": a, "b": b, "result": result}

    return agent


async def join_call(agent: Agent, call_type: str, call_id: str, **kwargs) -> None:
    await agent.create_user()
    call = await agent.create_call(call_type, call_id)

    async with agent.join(call):
        await asyncio.sleep(2)

        await agent.llm.simple_response(
            text="Greet the user and let them know you can check the weather."
        )

        await agent.finish()


if __name__ == "__main__":
    Runner(AgentLauncher(create_agent=create_agent, join_call=join_call)).cli()

Как это работает в рантайме

  • Nova 2 Sonic решает, что нужно вызвать get_weather или calculate, и отправляет toolUse с аргументами.
  • Vision Agents вызывает соответствующую Python‑функцию.
  • Результат возвращается в модель как toolResult.
  • Модель озвучивает ответ уже с учётом полученных данных.

Кастомные пайплайны: отдельный LLM, STT и TTS

Если Nova 2 Sonic по каким‑то причинам не подходит, AWS‑плагин Vision Agents позволяет собрать собственный конвейер.

Пример: LLM через Bedrock + Deepgram STT + Cartesia TTS

from vision_agents.core import Agent, User
from vision_agents.plugins import aws, getstream, cartesia, deepgram, smart_turn

agent = Agent(
    edge=getstream.Edge(),
    agent_user=User(name="Custom Pipeline Agent"),
    instructions="Be helpful and concise.",
    llm=aws.LLM(
        model="anthropic.claude-3-haiku-20240307-v1:0",
        region_name="us-east-1"
    ),
    tts=cartesia.TTS(),
    stt=deepgram.STT(),
    turn_detection=smart_turn.TurnDetection(
        buffer_duration=2.0,
        confidence_threshold=0.5,
    ),
)

aws.LLM поддерживает:

  • стриминг ответов через converse_stream();
  • хранение истории диалога;
  • vision‑входы для моделей вроде Claude;
  • мультирундовый tool calling — до трёх раундов функций на один запрос.

Text‑to‑speech через Amazon Polly

Если вы используете не realtime‑LLM, а обычный текстовый, можно подключить Amazon Polly для TTS:

from vision_agents.plugins import aws

tts = aws.TTS(
    region_name="us-east-1",
    voice_id="Joanna",
    engine="neural",  # 'standard' or 'neural'
    language_code="en-US"
)

Polly даёт:

  • стандартный и neural‑движки;
  • поддержку SSML для тонкой настройки речи;
  • множество языков и голосов.

Neural‑движок звучит более естественно и хорошо подходит для кастомных пайплайнов STT → LLM → TTS на инфраструктуре AWS.

Управление ресурсами и стоимость

Для остановки Stream‑звонка и завершения процессов Vision Agent:

uv run main.py stop

Amazon Bedrock тарифицирует все вызовы к Amazon Nova 2 Sonic. Активные сессии продолжают стоить денег, пока вы их явно не завершите. Команда остановки помогает избежать лишних расходов.

Практические сценарии использования

  1. No‑screen / low‑attention интерфейсы

    • Водители: запрос следующей точки маршрута, отметка выполненной доставки, звонок в диспетчерскую — всё голосом.
    • Полевые инженеры: запрос инструкции, логирование выполненных шагов, создание тикетов.
    • Медперсонал: голосовое внесение заметок, запрос истории пациента, вызов коллег.
  2. Контакт‑центры и горячие линии

    • Обработка типовых запросов без участия оператора.
    • Автоматическое заполнение CRM по итогам разговора.
    • Интеллектуальная маршрутизация к нужному отделу по голосовому описанию проблемы.
  3. Внутренние ассистенты для сотрудников

    • Быстрый доступ к базе знаний и документации.
    • Голосовой интерфейс к BI‑системам и отчётам.
    • Запуск внутренних пайплайнов и автоматизация рутинных задач.
  4. Обучение и онбординг

    • Голосовые тренажёры для новых сотрудников.
    • Сценарии «разговор с клиентом» с автоматической оценкой ответов.
    • Интерактивные FAQ с живым голосом.

Эта связка особенно интересна тем, кто не хочет тратить месяцы на собственный WebRTC‑стек и при этом не готов мириться с ограничениями «чёрных ящиков» вроде простых телефонных ботов без доступа к коду. Здесь вы управляете логикой в своём AWS‑аккаунте, а Stream и Vision Agents берут на себя тяжёлую инфраструктуру для реального времени.


Читайте также