Sessions, événements et lifecycle
Sessions, événements et lifecycle
Chaque connexion WebSocket à la Realtime API crée une session. Cette session est l’unité fondamentale de gestion : elle encapsule la configuration du modèle, l’historique de conversation, les outils disponibles et l’état courant de l’interaction. Comprendre son cycle de vie est essentiel pour construire des agents vocaux robustes.
Le cycle de vie d’une session
Dès que la connexion WebSocket est établie, le serveur émet un événement session.created. La session passe par plusieurs phases :
Connexion → session.created
Le serveur confirme la session avec un ID unique et la configuration par défaut.
Configuration → session.update
Vous envoyez session.update pour définir les instructions, la voix, les outils et les modalités.
Conversation active
Échange d'événements audio et texte entre client et serveur.
Fermeture → déconnexion WebSocket
La session est détruite à la fermeture de la connexion. Aucun état n'est conservé côté serveur.
Configurer une session
Immédiatement après session.created, vous devez envoyer un événement session.update pour configurer le comportement du modèle :
import asyncio
import websockets
import json
async def configure_session():
headers = {
"Authorization": f"Bearer {OPENAI_API_KEY}",
"OpenAI-Beta": "realtime=v1"
}
async with websockets.connect(URL, extra_headers=headers) as ws:
# Attendre session.created
event = json.loads(await ws.recv())
session_id = event["session"]["id"]
print(f"Session créée : {session_id}")
# Configurer la session
await ws.send(json.dumps({
"type": "session.update",
"session": {
"modalities": ["text", "audio"],
"instructions": "Vous êtes un assistant vocal francophone. "
"Répondez de manière concise et naturelle.",
"voice": "alloy",
"input_audio_format": "pcm16",
"output_audio_format": "pcm16",
"input_audio_transcription": {
"model": "whisper-1"
},
"turn_detection": {
"type": "server_vad",
"threshold": 0.5,
"prefix_padding_ms": 300,
"silence_duration_ms": 500
},
"tools": [],
"temperature": 0.8,
"max_response_output_tokens": 4096
}
}))
# Confirmation
event = json.loads(await ws.recv())
print(f"Session mise à jour : {event['type']}")
Paramètres clés de la session
| Paramètre | Description | Valeur recommandée |
|---|---|---|
| modalities | Canaux d'entrée/sortie | ["text", "audio"] |
| voice | Voix de synthèse | alloy, echo, shimmer, etc. |
| turn_detection | Détection de fin de parole | server_vad avec seuil 0.5 |
| input_audio_format | Format audio entrant | pcm16 (16-bit PCM, 24kHz) |
Le système d’événements
La Realtime API est entièrement événementielle. Chaque message échangé est un objet JSON avec un champ type qui détermine sa nature. Les événements se répartissent en deux catégories :
Événements client (vous → serveur)
# Les principaux événements que vous envoyez
client_events = {
"session.update": "Modifier la configuration",
"input_audio_buffer.append": "Envoyer un chunk audio",
"input_audio_buffer.commit": "Valider le buffer audio",
"input_audio_buffer.clear": "Vider le buffer audio",
"conversation.item.create": "Ajouter un message manuellement",
"conversation.item.truncate": "Tronquer une réponse",
"conversation.item.delete": "Supprimer un message",
"response.create": "Déclencher une réponse",
"response.cancel": "Annuler la réponse en cours",
}
Événements serveur (serveur → vous)
# Les principaux événements que vous recevez
server_events = {
"session.created": "Session initialisée",
"session.updated": "Configuration appliquée",
"input_audio_buffer.speech_started": "Parole détectée",
"input_audio_buffer.speech_stopped": "Silence détecté",
"conversation.item.created": "Nouveau message dans l'historique",
"response.created": "Début de génération",
"response.audio.delta": "Chunk audio de réponse",
"response.audio_transcript.delta": "Chunk de transcription",
"response.done": "Réponse terminée",
"error": "Erreur",
}
Gestion des erreurs
Les erreurs sont émises via un événement de type error. Vous devez toujours les intercepter :
async def handle_events(ws):
async for raw_message in ws:
event = json.loads(raw_message)
event_type = event["type"]
if event_type == "error":
error = event["error"]
print(f"Erreur [{error['type']}]: {error['message']}")
if error["type"] == "invalid_request_error":
# Erreur de configuration, corriger et réessayer
pass
elif error["type"] == "server_error":
# Problème côté OpenAI, reconnecter
pass
elif event_type == "session.updated":
print("Configuration appliquée avec succès")
elif event_type == "response.done":
usage = event["response"].get("usage", {})
print(f"Tokens utilisés : {usage}")
Points clés à retenir
- Une session est créée automatiquement à la connexion WebSocket et détruite à la déconnexion
session.updatedoit être envoyé immédiatement aprèssession.createdpour configurer le modèle- Le protocole est purement événementiel : chaque message a un
typequi détermine son traitement - Les événements client pilotent l’interaction, les événements serveur rapportent les résultats
- La gestion d’erreurs est critique : toujours écouter les événements
error