- Дата публикации
AWS запустила двунаправочный стриминг в SageMaker AI: как собрать свой real-time голосовой сервис на vLLM и Voxtral
Что нового
Amazon добавила в SageMaker AI двунаправочный стриминг для real-time инференса. Это значит, что теперь можно держать одно постоянное соединение и одновременно:
- отправлять аудио на сервер;
- получать текстовую расшифровку в ответ в режиме реального времени.
Ключевые новшества и параметры:
-
Двунаправочный стриминг в SageMaker AI
- Протокол на стороне клиента: HTTP/2 event stream на порту 8443.
- Протокол внутри контейнера: WebSocket.
- SageMaker автоматически мостит HTTP/2 ⇄ WebSocket, без ручной реализации.
-
Поддержка WebSocket-стриминга в vLLM (Realtime API)
- Встроенный WebSocket-эндпоинт
/v1/realtimeдля потоковой обработки аудио. - Поддержка нескольких речевых моделей, включая Voxtral-Mini-4B-Realtime-2602 от Mistral AI.
- Реализация piecewise CUDA Graph для снижения overhead на запуск GPU-ядра и уменьшения задержки на токен.
- Встроенный WebSocket-эндпоинт
-
Голосовая модель Voxtral-Mini-4B-Realtime-2602
- Размер: 4B параметров, помещается на один GPU.
- Рекомендуемый инстанс: ml.g6.4xlarge с 1× NVIDIA L4.
- Максимальный контекст модели: 262 144 токенов.
- В примере SageMaker используют
SM_VLLM_MAX_MODEL_LEN=45000, чего хватает примерно на 1 час живой записи (3600 секунд / 0,08 сек на токен).
-
Готовый паттерн развёртывания
- Кастомный Docker-образ на базе SageMaker vLLM Deep Learning Container.
- Лейбл
com.amazonaws.sagemaker.capabilities.bidirectional-streaming=trueдля включения стриминга. - Лёгкий FastAPI-мост внутри контейнера:
/invocations-bidirectional-stream→/v1/realtime. - Прокси health-check'ов
/ping→/health.
-
Готовые клиенты
- Python-клиент на базе
aws-sdk-sagemaker-runtime-http2, который стримит WAV-файл и печатает транскрипцию по мере прихода. - Gradio-клиент с микрофоном: говорит пользователь, текст появляется в интерфейсе сразу, без ожидания конца фразы.
- Python-клиент на базе
Как это работает
Архитектура потока данных
Схема состоит из трёх слоёв:
-
Клиент → SageMaker AI
- Клиент (Python-скрипт или Gradio-приложение) подключается к runtime-эндпоинту SageMaker AI по HTTP/2 на порт 8443.
- Сообщения Realtime-протокола vLLM (например,
input_audio_buffer.append,transcription.delta) отправляются как JSON внутриRequestPayloadPartсDataType="UTF8". - Ответы приходят как
ResponsePayloadPartи другие события стрима.
-
SageMaker AI → Docker-контейнер
- SageMaker сам открывает WebSocket к контейнеру по адресу:
ws://localhost:8080/invocations-bidirectional-stream. - HTTP/2 event stream снаружи автоматически превращается в WebSocket-фреймы внутри.
- Если клиент указал
DataType="UTF8", SageMaker отправляет текстовые WebSocket-фреймы в контейнер.
- SageMaker сам открывает WebSocket к контейнеру по адресу:
-
Docker-контейнер: FastAPI-мост → vLLM
- В контейнере поднимается FastAPI-приложение на порту 8080 с маршрутом
/invocations-bidirectional-stream. - При подключении SageMaker этот мост открывает второй WebSocket к vLLM Realtime API:
ws://localhost:8081/v1/realtime. - Все текстовые сообщения прокидываются как есть, без трансформации протокола Realtime API.
- В контейнере поднимается FastAPI-приложение на порту 8080 с маршрутом
vLLM-сервер работает на порту 8081, отдаёт WebSocket-эндпоинт /v1/realtime и health-эндпоинт /health. FastAPI-прокси дополнительно обрабатывает /ping, чтобы удовлетворить требования SageMaker к health-check'ам.
Протокол Realtime API vLLM
vLLM Realtime API реализует классическую схему для потокового ASR:
- Клиент подключается к
ws://host/v1/realtime. - Сервер отправляет событие
session.created. - Клиент при необходимости шлёт
session.updateс параметрами и именем модели. - Клиент отправляет
input_audio_buffer.commit, когда готов стримить аудио. - Клиент отправляет серию
input_audio_buffer.appendс фрагментами аудио в base64 PCM16, 16 кГц, mono. - Сервер по мере накопления контекста шлёт
transcription.delta— приращения текста. - В конце сервер шлёт
transcription.doneс финальной расшифровкой и статистикой использования. - Для следующей реплики клиент снова начинает с шага 5.
Ключевой момент: модель не ждёт конца аудио. Как только контекста достаточно, она сразу выдаёт transcription.delta, пока клиент продолжает стримить новые куски.
Опционально клиент может завершить ввод аудио явным input_audio_buffer.commit с "final": true — удобно при проигрывании файлов.
Аудио-пайплайн
До того как аудио попадёт в модель, клиент обязан:
- привести звук к 16 кГц, моно, PCM16;
- нарезать на чанки подходящего размера (в примере — 4 КБ, это ≈128 мс аудио);
- закодировать каждый чанк в base64;
- упаковать в JSON-сообщение Realtime API и отправить через WebSocket (на стороне клиента) / HTTP/2 (на стороне SageMaker).
vLLM Realtime API ожидает именно такой формат, иначе транскрипция не запустится.
Как SageMaker понимает, что контейнер умеет стримить
В Dockerfile используется специальный лейбл:
LABEL com.amazonaws.sagemaker.capabilities.bidirectional-streaming=true
Без него SageMaker не будет открывать WebSocket к контейнеру и не включит двунаправочный стриминг.
CUDA Graph и производительность
vLLM внутри контейнера конфигурируется через переменные окружения SageMaker:
vllm_env = {
"SM_VLLM_MAX_MODEL_LEN": "45000",
"SM_VLLM_COMPILATION_CONFIG": '{"cudagraph_mode": "PIECEWISE"}'
}
SM_VLLM_MAX_MODEL_LEN=45000— ограничивает контекст. Этого хватает примерно на 1 час живого аудио.cudagraph_mode: "PIECEWISE"включает piecewise CUDA Graph. Это уменьшает overhead на запуск ядер GPU и снижает задержку на токен при стриминге.
Управление соединением и надёжность
SageMaker AI:
- поддерживает WebSocket-соединение ping/pong-кадрами каждые 60 секунд;
- разрывает соединение, если подряд не отвечают на 5 ping'ов;
- мониторит endpoint в CloudWatch и выполняет health-check'и контейнера через
/ping.
Клиенту приходится учитывать возможный разрыв и уметь переподключаться, особенно для длинных сессий.
Что это значит для вас
Для чего это хорошо подходит
-
Голосовые ассистенты и voice-боты
Если вы строите ассистента, который должен отвечать без длинных пауз, важно начинать транскрипцию ещё до конца реплики. Связка SageMaker AI + vLLM + Voxtral-Mini-4B-Realtime-2602 как раз делает это: вы стримите аудио, модель выдаёт текст по мере поступления. -
Живые субтитры и captioning
Для онлайн-ивентов, стримов, внутренних митингов — можно транскрибировать речь в реальном времени и показывать текст сразу. Контекст до 45 000 токенов (в примере) позволяет держать длинный разговор, не обрезая историю, а полный лимит Voxtral в 262 144 токена даёт запас для ещё более длительных сессий. -
Аналитика контакт-центров и колл-трекинг
Вариант: вы подключаете телефонию, конвертируете сигнал в 16 кГц PCM16 и стримите в SageMaker. В ответ получаете текст, который можно сразу скармливать LLM для резюме звонка, оценки качества диалога или поиска триггерных слов. -
Инструменты доступности
Приложения для людей с нарушениями слуха выигрывают от минимальной задержки. Здесь важен именно стриминг: пользователь видит текст почти синхронно с речью. -
Real-time перевод и мультимодальные пайплайны
Стек удобно использовать как первый шаг: аудио → текст. Дальше можно подключать свой LLM для перевода, суммаризации или генерации ответов. Архитектура уже рассчитана на двунаправочные сценарии.
Где лучше не использовать
-
Офлайн-пакетная транскрипция больших архивов
Если у вас тысячи часов записей, которые не нужно обрабатывать в реальном времени, проще и дешевле запускать batch-инференс или офлайн-пайплайн, а не держать real-time endpoint с GPU. -
Сценарии с жёсткими ограничениями по бюджету
Модель на 4B параметров на инстансе с L4 — это не самый дешёвый вариант, особенно если endpoint работает 24/7. Для редких задач лучше запускать его по расписанию или использовать более компактные модели. -
Сверхнизкая латентность на миллисекундном уровне
Здесь в цепочке есть HTTP/2, WebSocket и мост внутри контейнера. Для большинства продуктовых задач задержка будет приемлемой, но для экстремально чувствительных систем (например, специализированные голосовые интерфейсы в трейдинге) может потребоваться более прямое подключение к модели без managed-слоя. -
Работа без доступа к AWS
Весь стек завязан на SageMaker AI и AWS-инфраструктуру. Если вы не можете использовать AWS (по юридическим причинам, политике компании или отсутствию биллинга), этот подход не подходит.
Доступность и ограничения для России
SageMaker AI и связанные managed-сервисы AWS официально доступны в поддерживаемых регионах AWS. Для России прямой доступ может быть затруднён или невозможен из-за сетевых и юридических ограничений. В ряде случаев потребуется:
- использовать аккаунт AWS, зарегистрированный в другой юрисдикции;
- работать через корпоративную инфраструктуру с выходом в нужный регион AWS;
- учитывать возможные ограничения на оплату.
Если у вас нет стабильного доступа к AWS, рассчитывать на эту архитектуру как на основу продукта не стоит.
Место на рынке
Прямых числовых сравнений с GPT-4o, Claude 3 или другими ASR-сервисами в материале нет. Зато ясно, на чём делает ставку AWS:
-
Открытый стек на vLLM
- vLLM — open source. Вы полностью контролируете конфигурацию модели, квантование, компиляцию.
- Нет жёсткой привязки к конкретному вендору на уровне сервинга: можно менять модели, не меняя инфраструктуру.
-
Managed-инфраструктура против self-hosted
- В отличие от развёртывания vLLM на своих GPU-серверах, SageMaker AI берёт на себя: протокольный мост HTTP/2 ⇄ WebSocket, health-check'и, мониторинг через CloudWatch, управление жизненным циклом endpoint'а.
- За это вы платите стоимость инстансов SageMaker и получаете меньше операционной рутины.
-
Сравнение с готовыми API (типа "Speech-to-Text как сервис")
- Здесь вы сами выбираете модель (Voxtral-Mini-4B-Realtime-2602 или другую, совместимую с Realtime API).
- Можно настраивать контекст, компиляцию, менять версию модели, не завися от roadmap внешнего API.
- Зато нет простой поминутной тарификации "как у классического SaaS" — вы платите за выделенный GPU-инстанс, даже когда на нём мало трафика.
Если вам нужна полная управляемость и вы уже живёте в AWS, это логичный конкурент self-hosted vLLM или кастомных WebSocket-сервисов. Если вы хотите "просто API за запрос", без DevOps, проще смотреть в сторону готовых ASR-сервисов.
Установка
Ниже — ключевые шаги из оригинального примера: сборка Docker-образа, настройка среды и развёртывание endpoint'а в SageMaker AI.
Dockerfile для vLLM с двунаправочным стримингом
FROM public.ecr.aws/deep-learning-containers/vllm:0.17.1-gpu-py312-cu129-ubuntu22.04-sagemaker-v1.0-soci
# Tell SageMaker AI this container supports bidirectional streaming
LABEL com.amazonaws.sagemaker.capabilities.bidirectional-streaming=true
WORKDIR /opt/ml/code
# Install bridge dependencies
COPY requirements.txt .
RUN pip install --upgrade --no-cache-dir -r requirements.txt
# WebSocket bridge: routes /invocations-bidirectional-stream → /v1/realtime
COPY app.py .
COPY sagemaker-entrypoint.sh entrypoint.sh
RUN chmod +x entrypoint.sh
ENTRYPOINT ["./entrypoint.sh"]
HEALTHCHECK --interval=30s --timeout=10s --start-period=120s --retries=3 \
CMD curl -f http://localhost:8080/ping || exit 1
Критичные моменты:
- базовый образ — официальный SageMaker vLLM DLC с CUDA 12.9 и Python 3.12;
- лейбл включает поддержку двунаправочного стриминга;
- healthcheck смотрит на
/pingFastAPI-моста.
FastAPI-мост app.py
VLLM_WS_URL = "ws://localhost:8081/v1/realtime"
@app.websocket("/invocations-bidirectional-stream")
async def websocket_bridge(sm_ws: WebSocket):
await sm_ws.accept()
async with websockets.connect(VLLM_WS_URL) as vllm_ws:
async def sm_to_vllm():
"""Forward SageMaker AI → vLLM."""
while True:
message = await sm_ws.receive()
if "text" in message and message["text"]:
await vllm_ws.send(message["text"])
elif "bytes" in message and message["bytes"]:
# Fallback for non-UTF8 clients
await vllm_ws.send(message["bytes"].decode("utf-8"))
async def vllm_to_sm():
"""Forward vLLM → SageMaker AI."""
async for msg in vllm_ws:
if isinstance(msg, str):
await sm_ws.send_text(msg)
elif isinstance(msg, bytes):
await sm_ws.send_bytes(msg)
await asyncio.gather(sm_to_vllm(), vllm_to_sm())
Здесь:
/invocations-bidirectional-stream— путь, который ожидает SageMaker AI для стриминга;VLLM_WS_URLуказывает на реальный Realtime API vLLM;- текстовые фреймы проходят без изменений, бинарные — декодируются как UTF-8 для совместимости с клиентами без
DataType="UTF8".
Настройка окружения vLLM
vllm_env = {
"SM_VLLM_MAX_MODEL_LEN": "45000",
"SM_VLLM_COMPILATION_CONFIG": '{"cudagraph_mode": "PIECEWISE"}'
}
Эти переменные задаются в модели SageMaker и управляют поведением vLLM-сервера.
Создание модели и endpoint'а в SageMaker AI
# Create model
voxtral_model = Model.create(
model_name=model_name,
primary_container=ContainerDefinition(
image=inference_image,
model_data_source=ModelDataSource(
s3_data_source=S3ModelDataSource(
s3_uri=f"{model_artifact}/",
s3_data_type="S3Prefix",
compression_type="None",
)
),
environment=vllm_env
),
execution_role_arn=role,
)
# Create config
endpoint_config = EndpointConfig.create(
endpoint_config_name=endpoint_config_name,
production_variants=[
ProductionVariant(
variant_name="AllTraffic",
model_name=model_name,
initial_variant_weight=1.0,
instance_type=instance_type,
initial_instance_count=1,
model_data_download_timeout_in_seconds=health_check_timeout,
)
]
)
# Create endpoint
endpoint = Endpoint.create(
endpoint_name=endpoint_name,
endpoint_config_name=endpoint_config_name
)
endpoint.wait_for_status("InService")
После этого у вас есть real-time endpoint SageMaker AI с поддержкой двунаправочного стриминга, за которым скрывается vLLM с Voxtral-Mini-4B-Realtime-2602.
Как запустить
Клиент для стриминга аудиофайла
Пример из репозитория использует Python SDK aws-sdk-sagemaker-runtime-http2.
Запуск:
python sagemaker_bidi_client.py ./audio.wav \
--region us-east-1
Поведение клиента:
- отправляет
session.updateдля выбора модели; - читает WAV-файл и режет на чанки по 4 КБ PCM16;
- отправляет чанки в стриме, делая
await asyncio.sleep(chunk_duration)после каждого, чтобы имитировать real-time (≈128 мс на чанк при 16 кГц); - параллельно слушает ответы и печатает
transcription.deltaпо мере прихода.
Важно: пауза asyncio.sleep даёт event loop возможность обрабатывать входящие события. Без неё отправка чанков может быть быстрее, чем модель успевает отвечать, и стрим визуально будет выглядеть последовательным, хотя технически он двунаправочный.
Клиент также различает типы событий:
ResponseStreamEventPayloadPart— нормальные JSON-сообщения (session.created,transcription.delta,transcription.done);ResponseStreamEventModelStreamErrorиResponseStreamEventInternalStreamFailure— отдельные ветки обработки, чтобы ошибки модели и платформы не терялись в общем потоке.
Live-демо с микрофоном на Gradio
Для минимальной задержки и демонстрации живой речи используется Gradio-клиент:
python sagemaker_bidi_microphone_client.py \
--endpoint-name <имя_эндпоинта> \
--region us-east-1
Что он делает:
- в браузере поднимает интерфейс с микрофоном;
- захватывает аудио потоком, ресемплирует до 16 кГц PCM16;
- кодирует каждый чанк в base64 и отправляет через SageMaker AI bidirectional stream с
DataType="UTF8"; - отображает обновляющийся текст транскрипции по мере прихода
transcription.delta, не дожидаясь конца фразы.
Практические нюансы
-
Формат аудио
vLLM Realtime API жёстко ожидает base64-encoded PCM16, 16 кГц, mono. Если у вас другой формат (телефония, веб-аудио, записи с диктофона) — конвертируйте перед отправкой. -
Размер чанков и задержка
- Пример использует 4 КБ чанки, это ≈128 мс аудио.
- Меньше чанк — ниже задержка, но больше overhead на сообщение.
- Больше чанк — лучше throughput, но выше задержка.
Подбирать размер стоит под ваши SLA по latency.
-
Ресурсы
Voxtral-Mini-4B-Realtime-2602 помещается на один GPU, поэтому достаточно ml.g6.4xlarge с NVIDIA L4. Для более тяжёлых моделей потребуется масштабирование или другие типы инстансов. -
Долгие сессии
SageMaker отправляет ping каждые 60 секунд и закрывает соединение после 5 пропущенных ответов. Клиент должен быть готов к реконнекту и восстановлению состояния. -
Очистка ресурсов
Endpoint SageMaker AI тарифицируется по времени работы инстанса. После тестов имеет смысл:- удалить endpoint;
- удалить endpoint config и модель;
- при необходимости — почистить образ в Amazon ECR и артефакты модели в S3.
Что делать дальше
Если вы хотите применить этот стек в продакшене, логичный план такой:
-
Развернуть свой endpoint
Взять пример Dockerfile, FastAPI-мост и окружение vLLM, собрать образ, задеплоить в SageMaker AI, как в коде выше. -
Расширить Gradio-демо до продукта
- добавить экспорт транскриптов;
- прикрутить пост-обработку (пунктуация, нормализация);
- подключить LLM для суммаризации или ответа пользователю.
-
Подогнать latency и стоимость
- поиграть размерами чанков;
- протестировать разные типы инстансов;
- настроить параметры компиляции vLLM и
MAX_MODEL_LENпод ваши реальные сценарии.
-
Поменять модель
Если вам нужен другой язык, акцент или тип задачи, можно заменить Voxtral-Mini-4B-Realtime-2602 на любую модель, совместимую с Realtime API vLLM. Архитектуру и инфраструктуру при этом трогать не нужно — меняется только модель и её конфиг.