Condividi tramite


API multimodali in tempo reale

È stata aggiunta la prima integrazione dell'API in tempo reale per il kernel semantico, attualmente disponibile solo in Python e considerata sperimentale. Ciò è dovuto al fatto che i servizi sottostanti sono ancora in fase di sviluppo e sono soggetti a modifiche e potrebbe essere necessario apportare modifiche di rilievo all'API nel kernel semantico man mano che si apprende dai clienti come usarlo e man mano che vengono aggiunti altri provider di questi tipi di modelli e API.

Astrazione del client in tempo reale

Per supportare API in tempo reale diverse da fornitori diversi, usando protocolli diversi, è stata aggiunta una nuova astrazione client al kernel. Questo client viene usato per connettersi al servizio in tempo reale e inviare e ricevere messaggi. Il client è responsabile della gestione della connessione al servizio, dell'invio di messaggi e della ricezione di messaggi. Il client è inoltre responsabile della gestione di eventuali errori che si verificano durante il processo di invio/ricezione di messaggi o di connessione. Considerando il modo in cui questi modelli funzionano, possono essere considerati più agenti che semplici completamenti chat; pertanto accettano quindi istruzioni, anziché un messaggio di sistema. Mantengono il proprio stato interno e possono essere richiamati per svolgere il lavoro per conto nostro.

API in tempo reale

Qualsiasi client in tempo reale implementa i metodi seguenti:

Metodo Descrizione
create_session Crea una nuova sessione
update_session Aggiorna una sessione esistente
delete_session Elimina una sessione esistente
receive Si tratta di un metodo generatore asincrono che resta in ascolto dei messaggi dal servizio e li restituisce man mano che arrivano.
send Invia un messaggio al servizio

Implementazioni di Python

La versione python del kernel semantico supporta attualmente i client in tempo reale seguenti:

Cliente Protocollo Modalità Funzione di chiamata abilitata Descrizione
OpenAI WebSocket Testo e audio L'API OpenAI Realtime è un'API basata su websocket che consente di inviare e ricevere messaggi in tempo reale, questo connettore usa il pacchetto Python OpenAI per connettersi e ricevere e inviare messaggi.
OpenAI WebRTC Testo & audio L'API OpenAI Realtime è un'API basata su WebRTC che consente di inviare e ricevere messaggi in tempo reale, richiede una traccia audio compatibile con WebRTC in fase di creazione della sessione.
Azzurro WebSocket Testo & audio L'API Azure Realtime è un'API basata su Websocket che consente di inviare e ricevere messaggi in tempo reale, che usa lo stesso pacchetto del connettore Websocket OpenAI.

Iniziare

Per iniziare a usare l'API realtime, è necessario installare il pacchetto semantic-kernel con il realtime aggiuntivo.

pip install semantic-kernel[realtime]

A seconda di come gestire l'audio, potrebbero essere necessari pacchetti aggiuntivi per interfacciarsi con altoparlanti e microfoni, ad esempio pyaudio o sounddevice.

Clienti Websocket

È quindi possibile creare un kernel e aggiungervi il client in tempo reale, che illustra come eseguire questa operazione con una connessione AzureRealtimeWebsocket, è possibile sostituire AzureRealtimeWebsocket con OpenAIRealtimeWebsocket senza ulteriori modifiche.

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

Ci sono due aspetti importanti da notare, il primo è che il realtime_client è un gestore del contesto asincrono, questo significa che è possibile usarlo in una funzione asincrona e usare async with per creare la sessione. Il secondo è che il metodo receive è un generatore asincrono, ciò significa che è possibile usarlo in un ciclo for per ricevere i messaggi quando arrivano.

Client di WebRTC

La configurazione di una connessione WebRTC è un po' più complessa e pertanto è necessario un parametro aggiuntivo durante la creazione del client. Questo parametro, audio_track deve essere un oggetto che implementa il protocollo MediaStreamTrack del pacchetto aiortc, illustrato anche negli esempi collegati di seguito.

Per creare un client che usa WebRTC, eseguire le operazioni seguenti:

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

Entrambi questi esempi ricevono l'audio come RealtimeAudioEvent e quindi lo passano a un oggetto audio_player non specificato.

Callback dell'output audio

Accanto a questo è disponibile un parametro denominato audio_output_callback nel metodo receive e nella creazione della classe. Questo callback verrà chiamato prima di gestire ulteriormente l'audio e ottiene una matrice numpy dei dati audio, invece di essere analizzata in AudioContent e restituita come evento audio in tempo reale che è possibile gestire, come accade nella sezione precedente. Questo ha dimostrato di fornire un output audio più fluido perché c'è meno sovraccarico tra i dati audio ricevuti e la loro trasmissione al lettore.

Questo esempio illustra come definire e usare il 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="")

Campioni

Sono disponibili quattro esempi nel repository , che illustrano sia le nozioni di base che utilizzano Websockets e WebRTC, sia una configurazione più complessa, inclusa la chiamata alle funzioni. Infine è disponibile una demo più complessa che usa servizi di comunicazione di Azure per consentire di chiamare l'API in tempo reale avanzata del kernel semantico.