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 | Sì | 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 | Sì | 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 | Sì | 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.