Cet article explique comment implémenter une fonctionnalité d'interruption de conversation à l'aide de l'API OpenAI Realtime.
Les détails de l'implémentation sont disponibles dans le référentiel GitHub.
Cette implémentation est basée sur le code d'Azure-Samples/aoai-realtime-audio-sdk. Une explication détaillée du code peut être trouvée dans cet article.
Dans cette implémentation, nous utilisons le microphone et le haut-parleur du PC local pour l'entrée et la sortie audio.
L'audio capturé par le microphone est envoyé au serveur API OpenAI Realtime pour traitement.
Pour capturer l'audio du microphone du PC local, nous utilisons la fonctionnalité de flux de la bibliothèque pyaudio. Le code suivant configure un flux pour l'entrée audio :
p = pyaudio.PyAudio() input_default_input_index = p.get_default_input_device_info()['index'] input_stream = p.open( format=STREAM_FORMAT, channels=INPUT_CHANNELS, rate=INPUT_SAMPLE_RATE, input=True, output=False, frames_per_buffer=INPUT_CHUNK_SIZE, input_device_index=input_default_input_index, start=False, ) input_stream.start_stream()
La capture audio est effectuée à l'aide de threading.Thread pour le traitement parallèle. Les données audio obtenues à partir du microphone sont codées au format base64 et stockées dans une file d'attente.
def listen_audio(input_stream: pyaudio.Stream): while True: audio_data = input_stream.read(INPUT_CHUNK_SIZE, exception_on_overflow=False) if audio_data is None: continue base64_audio = base64.b64encode(audio_data).decode("utf-8") audio_input_queue.put(base64_audio) threading.Thread(target=listen_audio, args=(input_stream,), daemon=True).start()
Les chaînes base64 stockées dans la file d'attente sont envoyées au serveur OpenAI Realtime API sous forme de messages "input_audio_buffer.append".
async def send_audio(client: RTLowLevelClient): while not client.closed: base64_audio = await asyncio.get_event_loop().run_in_executor(None, audio_input_queue.get) await client.send(InputAudioBufferAppendMessage(audio=base64_audio)) await asyncio.sleep(0)
La lecture audio est effectuée via les haut-parleurs du PC local en utilisant les données audio reçues du serveur API OpenAI Realtime.
Les données audio sont reçues sous forme de messages "response.audio.delta" du serveur. Puisque les données reçues sont codées en base64, elles sont décodées, stockées dans une file d'attente et converties dans un format jouable.
async def receive_messages(client: RTLowLevelClient): while True: message = await client.recv() if message is None: continue match message.type: case "response.audio.delta": audio_data = base64.b64decode(message.delta) for i in range(0, len(audio_data), OUTPUT_CHUNK_SIZE): audio_output_queue.put(audio_data[i:i+OUTPUT_CHUNK_SIZE]) await asyncio.sleep(0)
Les données stockées dans la file d'attente sont lues via les haut-parleurs du PC local en utilisant un traitement parallèle. Ce processus de lecture utilise le threading.Thread pour garantir que les données audio sont lues de manière fluide en temps réel.
def play_audio(output_stream: pyaudio.Stream): while True: audio_data = audio_output_queue.get() output_stream.write(audio_data) p = pyaudio.PyAudio() output_default_output_index = p.get_default_output_device_info()['index'] output_stream = p.open( format=STREAM_FORMAT, channels=OUTPUT_CHANNELS, rate=OUTPUT_SAMPLE_RATE, input=False, output=True, frames_per_buffer=OUTPUT_CHUNK_SIZE, output_device_index=output_default_output_index, start=False, ) output_stream.start_stream() threading.Thread(target=play_audio, args=(output_stream,), daemon=True).start()
L'API OpenAI Realtime détecte automatiquement les segments de conversation côté serveur. Cela permet la détection de nouvelles paroles et la création de réponses en temps réel même pendant que l'IA répond.
Cependant, lors de la lecture audio sur un PC local, il est important d'arrêter la lecture de l'audio en cours pour obtenir une interruption naturelle de la conversation. Ce point mérite attention. La détection de la parole de l'utilisateur est reçue du serveur OpenAI Realtime API sous la forme d'un message « input_audio_buffer.speech_started ». Lorsque ce message est reçu, la lecture est arrêtée en effaçant les données audio stockées dans la file d'attente.
async def receive_messages(client: RTLowLevelClient): while True: message = await client.recv() # print(f"{message=}") if message is None: continue match message.type: case "input_audio_buffer.speech_started": print("Input Audio Buffer Speech Started Message") print(f" Item Id: {message.item_id}") print(f" Audio Start [ms]: {message.audio_start_ms}") while not audio_output_queue.empty(): audio_output_queue.get()
En ce qui concerne la sortie audio, aucune modification n'est nécessaire ; il fonctionne comme décrit dans le code expliqué précédemment.
Cette fois, j'ai introduit une implémentation Python pour l'interruption de conversation.
J'espère que cet article s'avérera utile à tous ceux qui sont confrontés à des difficultés pour arrêter efficacement la parole de l'IA, comme je l'ai fait.
De plus, la définition et la configuration des instances de flux peuvent affecter la qualité de la lecture audio. Si vous rencontrez des interruptions dans la lecture audio, la révision de ces paramètres peut aider à améliorer la situation.
Merci d'avoir lu jusqu'au bout.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!