Compartilhar via


APIs multimodais em tempo real

A primeira integração de API em tempo real para Kernel Semântico foi adicionada, ela está atualmente disponível apenas no Python e considerada experimental. Isso ocorre porque os serviços subjacentes ainda estão sendo desenvolvidos e estão sujeitos a alterações e talvez seja necessário fazer alterações significativas na API no Kernel Semântico à medida que aprendemos com os clientes como usar isso e à medida que adicionamos outros provedores desses tipos de modelos e APIs.

Abstração do cliente em tempo real

Para dar suporte a APIs diferentes em tempo real de diferentes fornecedores, usando protocolos diferentes, uma nova abstração do cliente foi adicionada ao kernel. Esse cliente é usado para se conectar ao serviço em tempo real e enviar e receber mensagens. O cliente é responsável por lidar com a conexão com o serviço, enviar mensagens e receber mensagens. O cliente também é responsável por lidar com os erros que ocorrem durante o processo de envio/recebimento de mensagens ou de conexão. Considerando a maneira como esses modelos funcionam, eles podem ser considerados mais agentes do que simples conclusões de chat, pois, ao contrário de uma mensagem do sistema, eles recebem instruções, mantêm seu próprio estado interno e podem ser invocados para trabalhar em nosso nome.

API em tempo real

Qualquer cliente em tempo real implementa os seguintes métodos:

Método Descrição
create_session Cria uma nova sessão
update_session Atualiza uma sessão existente
delete_session Exclui uma sessão existente
receive Esse é um método de gerador assíncrono que escuta mensagens do serviço e as produz à medida que chegam.
send Envia uma mensagem para o serviço

Implementações do Python

A versão python do Kernel Semântico atualmente dá suporte aos seguintes clientes em tempo real:

Cliente Protocolo Modalidades Chamada de função habilitada Descrição
OpenAI WebSocket Texto e Áudio Sim A API do OpenAI Realtime é uma API baseada em websocket que permite enviar e receber mensagens em tempo real, esse conector usa o pacote OpenAI Python para se conectar e receber e enviar mensagens.
OpenAI WebRTC Texto & Áudio Sim A API do OpenAI Realtime é uma API baseada em WebRTC que permite enviar e receber mensagens em tempo real, ela precisa de uma faixa de áudio compatível com WebRTC no momento da criação da sessão.
Azul Websocket Texto & Áudio Sim A API do Azure Realtime é uma API baseada em websocket que permite enviar e receber mensagens em tempo real, que usa o mesmo pacote que o conector websocket OpenAI.

Primeiros Passos

Para começar a usar a API de tempo real, você precisa instalar o pacote semantic-kernel com o pacote extra realtime.

pip install semantic-kernel[realtime]

Dependendo de como você deseja lidar com áudio, talvez seja necessário ter pacotes adicionais para interface com alto-falantes e microfones, como pyaudio ou sounddevice.

Clientes Websocket

Em seguida, você pode criar um kernel e adicionar o cliente em tempo real a ele, isso mostra como fazer isso com uma conexão AzureRealtimeWebsocket, você pode substituir AzureRealtimeWebsocket por OpenAIRealtimeWebsocket sem nenhuma alteração adicional.

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="")

Há duas coisas importantes a serem observadas, a primeira é que o realtime_client é um gerenciador de contexto assíncrono, isso significa que você pode usá-lo em uma função assíncrona e usar async with para criar a sessão. A segunda é que o método receive é um gerador assíncrono, isso significa que você pode usá-lo em um loop for para receber mensagens conforme elas chegam.

Cliente WebRTC

A configuração de uma conexão WebRTC é um pouco mais complexa e, portanto, precisamos de um parâmetro extra ao criar o cliente. Esse parâmetro, audio_track precisa ser um objeto que implementa o protocolo MediaStreamTrack do pacote aiortc, isso também é demonstrado nos exemplos que estão vinculados abaixo.

Para criar um cliente que usa o WebRTC, você faria o seguinte:

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="")

Ambos os exemplos recebem o áudio como RealtimeAudioEvent e, em seguida, passam para um objeto audio_player não especificado.

Retorno de chamada de saída de áudio

Ao lado disso, temos um parâmetro chamado audio_output_callback no método receive e na criação da classe. Este callback será chamado primeiro, antes de qualquer manipulação adicional do áudio, e obtém um array numpy dos dados de áudio. Em vez de serem analisados em AudioContent e retornados como um RealtimeAudioEvent que você posteriormente pode manipular, é isso que acontece acima. Tem-se mostrado que isso proporciona uma saída de áudio mais suave, porque há menos sobrecarga de processamento entre os dados de áudio que chegam e quando são entregues ao reprodutor.

Este exemplo mostra como definir e usar o 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="")

Amostras

Há quatro exemplos em nosso repositório, eles abrangem os conceitos básicos usando websockets e WebRTC, bem como uma configuração mais complexa, incluindo chamada de função. Por fim, há uma demonstração mais complexa que usa Serviços de Comunicação do Azure para permitir que você chame sua API avançada de Kernel Semântico em tempo real.