API для мультимодальных взаимодействий в реальном времени
Добавлена первая интеграция API реального времени для семантического ядра, она в настоящее время доступна только в Python и считается экспериментальной. Это связано с тем, что базовые службы по-прежнему разрабатываются и могут изменяться, и нам может потребоваться внести критические изменения в API в Семантическом Ядре, по мере того как мы учимся у клиентов, как использовать это, и по мере добавления других поставщиков таких моделей и API.
Абстракция клиента в режиме реального времени
Для поддержки различных API в режиме реального времени от разных поставщиков, используя разные протоколы, в ядро добавлена новая абстракция клиента. Этот клиент используется для подключения к службе реального времени и отправки и получения сообщений. Клиент отвечает за обработку подключения к службе, отправку сообщений и получение сообщений. Клиент также отвечает за обработку ошибок, возникающих во время подключения или отправки или получения сообщений. Учитывая принцип работы этих моделей, их можно считать скорее агентами, чем обычными завершениями чата, поэтому они также принимают инструкции вместо системного сообщения, сохраняют собственное внутреннее состояние и могут быть активированы для выполнения работы от нашего имени.
API реального времени
Любой клиент в режиме реального времени реализует следующие методы:
Метод | Описание |
---|---|
create_session |
Создание нового сеанса |
update_session |
Обновляет существующий сеанс |
delete_session |
Удаляет существующий сеанс |
receive |
Это асинхронный метод генерации, который прослушивает сообщения из службы и выводит их по мере поступления. |
send |
Отправляет сообщение в службу |
Реализации Python
Версия Python семантического ядра в настоящее время поддерживает следующие клиенты в режиме реального времени:
Клиент | Протокол | Условия | Включен вызов функции | Описание |
---|---|---|---|---|
OpenAI | Вебсокет | Текст & Аудио | Да | API OpenAI Realtime — это API на основе websocket, который позволяет отправлять и получать сообщения в режиме реального времени, этот соединитель использует пакет OpenAI Python для подключения и получения и отправки сообщений. |
OpenAI | WebRTC | Текст и аудио | Да | API OpenAI Realtime — это API на основе WebRTC, который позволяет отправлять и получать сообщения в режиме реального времени, он нуждается в совместимой с webRTC звуковой дорожке во время создания сеанса. |
Лазурный | Вебсокет | Текст & аудио | Да | API Azure Realtime — это API на основе websocket, который позволяет отправлять и получать сообщения в режиме реального времени, в этом случае используется тот же пакет, что и соединитель OpenAI websocket. |
Начало работы
Чтобы приступить к работе с API Realtime, необходимо установить пакет semantic-kernel
с дополнением realtime
.
pip install semantic-kernel[realtime]
В зависимости от способа обработки звука может потребоваться дополнительный пакет для взаимодействия с динамиками и микрофонами, например pyaudio
или sounddevice
.
Клиенты Websocket
Затем вы можете создать ядро и добавить к нему клиента в режиме реального времени. Ниже показано, как сделать это с подключением AzureRealtimeWebsocket. Вы можете заменить AzureRealtimeWebsocket на OpenAIRealtimeWebsocket без каких-либо дополнительных изменений.
from semantic_kernel.connectors.ai.open_ai import (
AzureRealtimeWebsocket,
AzureRealtimeExecutionSettings,
ListenEvents,
)
from semantic_kernel.contents import RealtimeAudioEvent, RealtimeTextEvent
# this will use environment variables to get the api key, endpoint, api version and deployment name.
realtime_client = AzureRealtimeWebsocket()
settings = AzureRealtimeExecutionSettings(voice='alloy')
async with realtime_client(settings=settings, create_response=True):
async for event in realtime_client.receive():
match event:
# receiving a piece of audio (and send it to a undefined audio player)
case RealtimeAudioEvent():
await audio_player.add_audio(event.audio)
# receiving a piece of audio transcript
case RealtimeTextEvent():
# Semantic Kernel parses the transcript to a TextContent object captured in a RealtimeTextEvent
print(event.text.text, end="")
case _:
# OpenAI Specific events
if event.service_type == ListenEvents.SESSION_UPDATED:
print("Session updated")
if event.service_type == ListenEvents.RESPONSE_CREATED:
print("\nMosscap (transcript): ", end="")
Во-первых, важно отметить, что realtime_client
является асинхронным диспетчером контекста, это означает, что вы можете использовать его в асинхронной функции и использовать async with
для создания сеанса.
Во-вторых, метод receive
является асинхронным генератором, это означает, что вы можете использовать его в цикле для получения сообщений по мере их поступления.
Клиент WebRTC
Настройка подключения WebRTC немного сложнее, поэтому при создании клиента нам нужен дополнительный параметр. Этот параметр audio_track
должен быть объектом, реализующим протокол MediaStreamTrack
пакета aiortc
, это также демонстрируется в примерах, связанных ниже.
Чтобы создать клиент, использующий WebRTC, выполните следующие действия:
from semantic_kernel.connectors.ai.open_ai import (
ListenEvents,
OpenAIRealtimeExecutionSettings,
OpenAIRealtimeWebRTC,
)
from aiortc.mediastreams import MediaStreamTrack
class AudioRecorderWebRTC(MediaStreamTrack):
# implement the MediaStreamTrack methods.
realtime_client = OpenAIRealtimeWebRTC(audio_track=AudioRecorderWebRTC())
# Create the settings for the session
settings = OpenAIRealtimeExecutionSettings(
instructions="""
You are a chat bot. Your name is Mosscap and
you have one goal: figure out what people need.
Your full name, should you need to know it, is
Splendid Speckled Mosscap. You communicate
effectively, but you tend to answer with long
flowery prose.
""",
voice="shimmer",
)
audio_player = AudioPlayer
async with realtime_client(settings=settings, create_response=True):
async for event in realtime_client.receive():
match event.event_type:
# receiving a piece of audio (and send it to a undefined audio player)
case "audio":
await audio_player.add_audio(event.audio)
case "text":
# the model returns both audio and transcript of the audio, which we will print
print(event.text.text, end="")
case "service":
# OpenAI Specific events
if event.service_type == ListenEvents.SESSION_UPDATED:
print("Session updated")
if event.service_type == ListenEvents.RESPONSE_CREATED:
print("\nMosscap (transcript): ", end="")
Оба этих примера получают звук в виде RealtimeAudioEvent, а затем передают его в объект audio_player, который не указан.
Обратный вызов аудиовыхода
Рядом с этим у нас есть параметр с именем audio_output_callback
в методе receive
и создании класса. Этот обратный вызов будет вызываться первым перед любой дальнейшей обработкой звука и получает массив звуковых данных numpy
. Это происходит вместо того, чтобы преобразовывать данные в AudioContent и возвращать их как RealtimeAudioEvent, который затем можно обрабатывать, как это описано выше. Это показало, что это обеспечивает более гладкий звуковой поток, так как меньше накладных расходов между поступлением звуковых данных и их передачей проигрывателю.
В этом примере показано, как определить и использовать audio_output_callback
:
from semantic_kernel.connectors.ai.open_ai import (
ListenEvents,
OpenAIRealtimeExecutionSettings,
OpenAIRealtimeWebRTC,
)
from aiortc.mediastreams import MediaStreamTrack
class AudioRecorderWebRTC(MediaStreamTrack):
# implement the MediaStreamTrack methods.
class AudioPlayer:
async def play_audio(self, content: np.ndarray):
# implement the audio player
realtime_client = OpenAIRealtimeWebRTC(audio_track=AudioRecorderWebRTC())
# Create the settings for the session
settings = OpenAIRealtimeExecutionSettings(
instructions="""
You are a chat bot. Your name is Mosscap and
you have one goal: figure out what people need.
Your full name, should you need to know it, is
Splendid Speckled Mosscap. You communicate
effectively, but you tend to answer with long
flowery prose.
""",
voice="shimmer",
)
audio_player = AudioPlayer
async with realtime_client(settings=settings, create_response=True):
async for event in realtime_client.receive(audio_output_callback=audio_player.play_audio):
match event.event_type:
# no need to handle case: "audio"
case "text":
# the model returns both audio and transcript of the audio, which we will print
print(event.text.text, end="")
case "service":
# OpenAI Specific events
if event.service_type == ListenEvents.SESSION_UPDATED:
print("Session updated")
if event.service_type == ListenEvents.RESPONSE_CREATED:
print("\nMosscap (transcript): ", end="")
Образцы
Существует четыре примера в нашем репозитории, они охватывают как основы использования websockets, так и WebRTC, а также более сложную настройку, включая вызов функций. Наконец, существует более сложная демонстрация, которая использует Службы коммуникации Azure для вызова API расширенного семантического ядра реального времени.