Assistant vocal multimodal
Sur cette page
Mise à jour du 2 novembre 2026 — modèles audio. Plusieurs modèles de ce cours sont dépréciés :
tts-1,tts-1-hdetgpt-4o-mini-ttss’arrêtent le 6 janvier 2027 (remplaçant indiqué :gpt-realtime-2.1-mini, que le guide TTS d’OpenAI déclare non pris en charge par/v1/audio/speech: la migration de la synthèse vocale passe par l’API Realtime) ;gpt-realtime,gpt-4o-realtimeet les anciens modèles audio le 20 janvier 2027 (gpt-realtime-2.1,gpt-realtime-2.1-mini,gpt-audio-1.5) ;whisper-1,gpt-4o-transcribeet/v1/audio/translationsle 26 février 2027 (gpt-transcribe,gpt-live-transcribe,v1/realtime/translations). Pour la voix full-duplex, GPT-Live 1 est disponible dans l’API depuis le 10 septembre 2026.
Corrigé le 3 novembre 2026. Pour analyser une image, la leçon passait par un appel séparé à l’API Responses, puis injectait la description comme message de l’assistant avec un contenu
input_text, type réservé aux messages d’utilisateur ou système. Orgpt-realtime-2.1etgpt-realtime-2acceptent les images en entrée : l’image se joint directement, eninput_image, à un message de l’utilisateur. L’événementresponse.text.delta, de l’ancienne bêta, s’appelle désormaisresponse.output_text.delta. Formes d’événements vérifiées contre les types du SDKopenai3.42.1. Sources : Realtime conversations, Image inputs · gpt-realtime-2.1.
Assistant vocal multimodal
Un assistant vocal multimodal combine la voix avec d’autres modalités : texte, images, vidéo, données structurées. L’utilisateur parle, mais l’agent peut aussi afficher des informations visuelles, analyser des images envoyées par l’utilisateur, ou combiner plusieurs sources de données. C’est l’avenir de l’interaction homme-machine.
Texte et audio en parallèle
La Realtime API supporte nativement les modalités texte et audio simultanément. Vous pouvez injecter du texte dans la conversation tout en maintenant l’échange vocal :
async def inject_text_context(ws, context: str):
"""Ajoute du contexte textuel à la conversation vocale."""
await ws.send(json.dumps({
"type": "conversation.item.create",
"item": {
"type": "message",
"role": "user",
"content": [
{
"type": "input_text",
"text": context
}
]
}
}))
# Déclencher une réponse vocale basée sur ce contexte
await ws.send(json.dumps({"type": "response.create"}))
# L'utilisateur demande vocalement "Lis-moi mon dernier email"
# Vous injectez le contenu de l'email en texte
await inject_text_context(ws, """
Voici le dernier email reçu :
De : [email protected]
Objet : Demande de devis
Contenu : Bonjour, je souhaiterais obtenir un devis pour
l'intégration d'un agent vocal dans notre centre d'appels.
""")
Montrer une image à l’agent vocal
gpt-realtime-2.1 et gpt-realtime-2 prennent en entrée du texte, de l’audio et des images. Une image se joint comme une partie input_image d’un message de l’utilisateur, avec une Data URI Base64, sur WebSocket comme sur le canal de données WebRTC. Le modèle en tient compte dans sa réponse vocale, sans appel à une autre API :
import base64
import json
async def montrer_image(ws, chemin_image: str, question: str) -> None:
"""Joint une image et une question à la conversation, puis demande une réponse vocale."""
with open(chemin_image, "rb") as f:
image_b64 = base64.b64encode(f.read()).decode()
await ws.send(json.dumps({
"type": "conversation.item.create",
"item": {
"type": "message",
"role": "user",
"content": [
{"type": "input_image", "image_url": f"data:image/jpeg;base64,{image_b64}"},
{"type": "input_text", "text": question},
],
},
}))
await ws.send(json.dumps({"type": "response.create"}))
await montrer_image(ws, "facture.jpg", "Que dois-je payer, et avant quelle date ?")
Les images sont facturées en tokens d’image, à un tarif propre indiqué sur la fiche du modèle. Pour une analyse lourde ou un modèle de vision plus capable, vous pouvez toujours interroger l’API Responses à part, puis transmettre son résultat à la session : faites-le alors par un message system ou user (contenu input_text), jamais par un faux message de l’assistant, que le modèle prendrait pour ses propres paroles.
Interface web multimodale
Pour une application web, combinez le WebSocket Realtime avec une interface visuelle :
from fastapi import FastAPI, WebSocket
from fastapi.staticfiles import StaticFiles
app = FastAPI()
@app.websocket("/ws/agent")
async def multimodal_agent(client_ws: WebSocket):
"""Agent multimodal avec interface web."""
await client_ws.accept()
headers = {
"Authorization": f"Bearer {OPENAI_API_KEY}"
}
async with websockets.connect(REALTIME_URL, additional_headers=headers) as openai_ws:
await openai_ws.recv() # session.created
await openai_ws.send(json.dumps({
"type": "session.update",
"session": {
"type": "realtime",
"output_modalities": ["audio"],
"instructions": "Assistant multimodal. Répondez en français.",
"audio": {"output": {"voice": "marin"}}
}
}))
await openai_ws.recv()
async def client_to_openai():
async for message in client_ws.iter_text():
data = json.loads(message)
if data["type"] == "audio":
# Relayer l'audio
await openai_ws.send(json.dumps({
"type": "input_audio_buffer.append",
"audio": data["audio"]
}))
elif data["type"] == "text":
# Message texte (chat)
await openai_ws.send(json.dumps({
"type": "conversation.item.create",
"item": {
"type": "message",
"role": "user",
"content": [{
"type": "input_text",
"text": data["text"]
}]
}
}))
await openai_ws.send(json.dumps({
"type": "response.create"
}))
async def openai_to_client():
async for message in openai_ws:
event = json.loads(message)
t = event["type"]
if t == "response.output_audio.delta":
await client_ws.send_json({
"type": "audio",
"delta": event["delta"]
})
elif t == "response.output_audio_transcript.delta":
await client_ws.send_json({
"type": "transcript",
"delta": event["delta"]
})
elif t == "response.output_text.delta":
await client_ws.send_json({
"type": "text",
"delta": event["delta"]
})
await asyncio.gather(client_to_openai(), openai_to_client())
Scénarios d’utilisation multimodale
Voici comment un agent multimodal gère différents scénarios dans un outil de function calling :
tools = [
{
"type": "function",
"name": "show_chart",
"description": "Affiche un graphique de données à l'utilisateur",
"parameters": {
"type": "object",
"properties": {
"chart_type": {"type": "string", "enum": ["bar", "line", "pie"]},
"title": {"type": "string"},
"data": {"type": "object"}
},
"required": ["chart_type", "title", "data"]
}
},
{
"type": "function",
"name": "send_document",
"description": "Envoie un document au client par email",
"parameters": {
"type": "object",
"properties": {
"document_type": {"type": "string"},
"recipient": {"type": "string"}
},
"required": ["document_type", "recipient"]
}
}
]
L’utilisateur dit vocalement : « Montre-moi les ventes du dernier trimestre sous forme de graphique ». L’agent appelle show_chart, votre frontend affiche le graphique, et l’agent commente vocalement les résultats.
Points clés à retenir
- La Realtime API supporte les modalités texte et audio simultanément dans une même session
- L’injection de texte via
conversation.item.createpermet d’enrichir le contexte vocal - Les modèles Realtime acceptent les images : joignez-les en
input_imageà un message de l’utilisateur - Les outils (function calling) permettent d’afficher des éléments visuels tout en répondant vocalement
- L’architecture WebSocket côté client permet de mixer audio, texte et données structurées