qwen-audio-3.0-realtime-plus
Modèle de dialogue vocal en direct qui accepte la parole et le texte, puis répond oralement ou par écrit. Il est conçu pour des échanges à un rythme naturel et pour utiliser des outils.
À propos du modèle
Cette description présente les capacités du modèle. Les entrées, sorties et options disponibles dans Ailoot pour la méthode sélectionnée figurent ci-dessous.
Qwen-Audio-3.0-Realtime-Plus est un modèle d’Alibaba pour le dialogue vocal en direct. Il accepte la parole et le texte, répond en audio et en texte et permet une conversation bidirectionnelle avec un échange naturel de répliques. Le son peut être envoyé et reçu par fragments : l’interaction évolue donc au fil de la conversation.
Déterminer quand l’interlocuteur a terminé
Plusieurs moyens permettent de délimiter une prise de parole : l’activité sonore, l’achèvement du sens de la phrase et un contrôle explicite. Chez le fabricant, le mode est choisi avant l’envoi du premier audio ; le modifier après le début de la conversation nécessite une nouvelle connexion. La prise en charge de ce contrôle dépend de la méthode choisie. Le mode sémantique tient compte des pauses et des hésitations : un bref moment d’incertitude ne signifie pas nécessairement que l’utilisateur a terminé. Une nouvelle prise de parole de l’utilisateur peut interrompre la réponse en cours de génération pour poursuivre la conversation en tenant compte de la réplique suivante. En mode sémantique, un échantillon vocal de l’interlocuteur choisi peut orienter la reconnaissance afin de réduire les distractions dues aux autres voix et au bruit de fond.
Les instructions définissent le rôle de l’assistant et le style de la conversation. Le rendu vocal peut tenir compte du ton, du rythme et de l’émotion ; la version 3.0 propose cinq voix système et des voix fondées sur un échantillon de parole. Le modèle prend en charge 11 langues, dont le russe, ainsi que les variantes dialectales chinoises indiquées par le fabricant. Chez le fabricant, la voix est définie lors de la première mise à jour des paramètres de session ; l’envoi ultérieur d’une nouvelle voix dans la même conversation est ignoré. Ces réglages nécessitent la compatibilité de la méthode d’accès choisie.
Outils et historique de la conversation
Les appels de fonctions sont pris en charge. Le modèle formule l’action nécessaire, l’application connectée l’exécute et renvoie le résultat dans la conversation. Cela permet de fonder le dialogue sur des données réelles et de le poursuivre après une opération. L’assistant vocal peut utiliser les résultats des outils en conservant le contexte de l’échange. Les capacités du fabricant comprennent également une recherche web intégrée si la méthode choisie la fournit. La recherche web et les appels de fonctions ne peuvent pas être activés simultanément dans une même session.
L’historique contient par défaut 20 tours de conversation ; une plage allant d’un à 50 est prévue. L’audio accumulé est limité à 300 secondes ; les parties anciennes de l’historique sont supprimées lorsque les limites sont dépassées. Cela diffère de la durée d’une réplique : l’historique détermine quels éléments précédents restent disponibles pour continuer le dialogue.
Contexte textuel et son
Le contexte formel est de 40 960 tokens. L’entrée est limitée à 16 384 tokens et la sortie à 8192 ; les mêmes limites d’entrée et de sortie sont indiquées pour le mode de raisonnement, avec une limite distincte de 1024 tokens pour la chaîne de raisonnement.
Le streaming audio utilise du PCM mono sur 16 bits : 16 kHz en entrée et 24 kHz en sortie. Le texte et les données audio appartiennent à la même conversation. Ni l’entrée visuelle ni la génération d’images ne sont annoncées pour ce modèle précis ; il est spécialisé dans la parole, le texte et l’interaction vocale.
Ailoot · Voix en temps réel GET /v1/realtime?model=qwen-audio-3.0-realtime-plus qwen-audio-3.0-realtime-plus
qwen-audio-3.0-realtime-plusPremiers pas
Modèle de dialogue vocal en direct qui accepte la parole et le texte, puis répond oralement ou par écrit. Il est conçu pour des échanges à un rythme naturel et pour utiliser des outils.
- Entrées acceptées
- Texte · Audio
- Résultats
- Texte · Audio
Disponible dans Ailoot · entrées et méthodes
Ailoot · Voix en temps réel GET /v1/realtime?model=qwen-audio-3.0-realtime-plus
- Types d’entrée
text,audio- Types de sortie
text,audio- Format de sortie
- événements de session
| Champ | Type | Exigence | Valeurs et limites | Par défaut |
|---|---|---|---|---|
Champquery.model | Typestring | ExigenceObligatoire | Valeurs et limites qwen-audio-3.0-realtime-plus | Par défaut— |
Champsession.input_audio_format | Typestring | ExigenceFacultatif | Valeurs et limites pcm16, pcm | Par défaut— |
Champsession.output_audio_format | Typestring | ExigenceFacultatif | Valeurs et limites pcm16, pcm | Par défaut— |
Champsession.instructions | Typestring | ExigenceFacultatif | Valeurs et limites La limite s’applique à: politique de session sélectionnée | Par défaut— |
Champsession.max_history_turns | Typeinteger | ExigenceFacultatif | Valeurs et limites Minimum: 1 La limite s’applique à: politique de session sélectionnée | Par défaut— |
Champinput_audio_buffer.append.audio | Typebase64_string | ExigenceObligatoire | Valeurs et limites Contenu en entrée: PCM16 mono ; entrée à 16 kHz, sortie à 24 kHz ; longueur non nulle et paire en octets | Par défaut— |
Combinaisons d’éléments d’entrée
realtime_text_audio
Paramètres et cycle de vie de la méthode
| Paramètre | Contrat |
|---|---|
Paramètrematerial_types | Contrattext, audio |
Paramètrerequired | Contratnull |
Paramètreoptional_controls | Contratnull |
Paramètrecontent_type | ContratWebSocket |
Cycle de vie : exact retained published method
Les structures des méthodes et les identifiants sont exacts ; la capacité du fournisseur est distincte de l’admission.
Tarifs
Tarifs des méthodes Ailoot
GET /v1/realtime?model=qwen-audio-3.0-realtime-plus- Entrée
- 0,0008 USD / 1K
- Sortie
- 0,0064 USD / 1K
- Entrée
- 0,0048 USD par minute d’audio
- Sortie
- 0,018 USD par minute d’audio en sortie
Ailoot réserve un montant estimé avant une requête. Après le résultat, le montant final est débité selon l’utilisation mesurée. Pour le streaming, le montant final à débiter est calculé à partir du relevé final d’utilisation. Fonctionnement de la réservation et du débit →
Exemples de requêtes
Ailoot · Voix en temps réel
# Install the documented client once: python3 -m pip install websockets
import base64, json, os, time, wave
from pathlib import Path
from websockets.sync.client import connect
key = os.environ.get("AILOOT_API_KEY", "")
if not key.strip():
raise SystemExit("Set your AILOOT_API_KEY before connecting")
file = Path(os.environ.get("AILOOT_TEXT_FILE", ""))
if not file.is_file(): raise SystemExit("Set AILOOT_TEXT_FILE to your actual UTF-8 material")
material = file.read_text(encoding="utf-8")
if not material.strip(): raise SystemExit("Text material must not be empty")
out = Path("realtime-results")
out.mkdir(exist_ok=True)
audio, texts, complete = {}, {}, []
current_response = None
pending = False
deadline = time.monotonic() + 570 # Local client bound; lower server/session limits still apply.
def receive(ws, log):
global current_response, pending
left = deadline - time.monotonic()
if left <= 0:
raise TimeoutError("Client session limit; preserve IDs and partial results, do not replay")
event = json.loads(ws.recv(timeout=min(60, left)))
log.write(json.dumps(event, ensure_ascii=False) + "\n")
log.flush()
kind = event.get("type")
if kind == "error":
raise RuntimeError(json.dumps(event, ensure_ascii=False))
if kind == "response.created":
current_response = event["response"]["id"]
if kind in {"response.audio.delta", "response.output_audio.delta", "response.text.delta", "response.output_text.delta", "response.audio_transcript.delta", "response.output_audio_transcript.delta", "response.text.done", "response.audio_transcript.done"}:
identity = (event["response_id"], event["item_id"], event["output_index"], event["content_index"])
if kind in {"response.audio.delta", "response.output_audio.delta"}:
raw = base64.b64decode(event["delta"], validate=True)
if len(raw) % 2: raise ValueError("Output PCM16 chunk must have an even byte length")
audio.setdefault(identity, bytearray()).extend(raw)
elif kind.endswith(".done"):
texts[identity] = event.get("text", event.get("transcript", ""))
else:
texts[identity] = texts.get(identity, "") + event["delta"]
print(event["delta"], end="", flush=True)
if kind == "response.done":
response = event["response"]
complete.append(response)
if current_response is None: current_response = response["id"]
if response["id"] == current_response: pending = False
return event
def wait_for(ws, log, kind):
while True:
event = receive(ws, log)
if event.get("type") == kind: return event
def send(ws, event):
ws.send(json.dumps(event, ensure_ascii=False))
try:
# One exact model query; no reconnect/retry loop and no provider credentials.
with connect("wss://api.ailoot.ai/v1/realtime?model=qwen-audio-3.0-realtime-plus", additional_headers={"Authorization": "Bearer " + key}) as ws:
with (out / "events.jsonl").open("w", encoding="utf-8") as log:
wait_for(ws, log, "session.created")
send(ws, {"type":"session.update", "session":{"modalities":["audio","text"], "input_audio_format":"pcm", "output_audio_format":"pcm", "turn_detection":None}})
wait_for(ws, log, "session.updated")
send(ws, {"type":"conversation.item.create", "item":{"type":"message", "role":"user", "content":[{"type":"input_text", "text":material}]}})
send(ws, {"type":"response.create"})
pending = True
try:
while pending: receive(ws, log)
except KeyboardInterrupt:
# Cancel the actual current inference, then preserve its returned status.
send(ws, {"type":"response.cancel"})
while pending: receive(ws, log)
if not complete or complete[-1].get("status") != "completed":
raise RuntimeError("Response did not complete normally; inspect saved events and status")
finally:
manifest = {"responses":complete, "parts":[]}
for number, identity in enumerate(dict.fromkeys(list(audio) + list(texts))):
record = {"response_id":identity[0], "item_id":identity[1], "output_index":identity[2], "content_index":identity[3]}
if identity in audio:
raw = bytes(audio[identity])
pcm_file = out / ("audio-" + str(number) + ".pcm")
wav_file = out / ("audio-" + str(number) + ".wav")
pcm_file.write_bytes(raw)
with wave.open(str(wav_file), "wb") as wav:
wav.setnchannels(1); wav.setsampwidth(2); wav.setframerate(24000); wav.writeframes(raw)
record.update({"pcm":str(pcm_file), "wav":str(wav_file), "sample_rate_hz":24000})
if identity in texts:
text_file = out / ("text-" + str(number) + ".txt")
text_file.write_text(texts[identity], encoding="utf-8")
record["text"] = str(text_file)
manifest["parts"].append(record)
(out / "results.json").write_text(json.dumps(manifest, ensure_ascii=False, indent=2), encoding="utf-8")
print("\nSaved every received event and result in", out)
# Install the documented client once: python3 -m pip install websockets
import base64, json, os, time, wave
from pathlib import Path
from websockets.sync.client import connect
key = os.environ.get("AILOOT_API_KEY", "")
if not key.strip():
raise SystemExit("Set your AILOOT_API_KEY before connecting")
file = Path(os.environ.get("AILOOT_AUDIO_FILE", ""))
if not file.is_file(): raise SystemExit("Set AILOOT_AUDIO_FILE to your raw PCM16 mono 16-kHz recording")
material = file.read_bytes()
if not material or len(material) % 2 or material.startswith(b"RIFF"):
raise SystemExit("Use nonempty signed little-endian PCM16 mono 16-kHz bytes, not a WAV header")
out = Path("realtime-results")
out.mkdir(exist_ok=True)
audio, texts, complete = {}, {}, []
current_response = None
pending = False
deadline = time.monotonic() + 570 # Local client bound; lower server/session limits still apply.
def receive(ws, log):
global current_response, pending
left = deadline - time.monotonic()
if left <= 0:
raise TimeoutError("Client session limit; preserve IDs and partial results, do not replay")
event = json.loads(ws.recv(timeout=min(60, left)))
log.write(json.dumps(event, ensure_ascii=False) + "\n")
log.flush()
kind = event.get("type")
if kind == "error":
raise RuntimeError(json.dumps(event, ensure_ascii=False))
if kind == "response.created":
current_response = event["response"]["id"]
if kind in {"response.audio.delta", "response.output_audio.delta", "response.text.delta", "response.output_text.delta", "response.audio_transcript.delta", "response.output_audio_transcript.delta", "response.text.done", "response.audio_transcript.done"}:
identity = (event["response_id"], event["item_id"], event["output_index"], event["content_index"])
if kind in {"response.audio.delta", "response.output_audio.delta"}:
raw = base64.b64decode(event["delta"], validate=True)
if len(raw) % 2: raise ValueError("Output PCM16 chunk must have an even byte length")
audio.setdefault(identity, bytearray()).extend(raw)
elif kind.endswith(".done"):
texts[identity] = event.get("text", event.get("transcript", ""))
else:
texts[identity] = texts.get(identity, "") + event["delta"]
print(event["delta"], end="", flush=True)
if kind == "response.done":
response = event["response"]
complete.append(response)
if current_response is None: current_response = response["id"]
if response["id"] == current_response: pending = False
return event
def wait_for(ws, log, kind):
while True:
event = receive(ws, log)
if event.get("type") == kind: return event
def send(ws, event):
ws.send(json.dumps(event, ensure_ascii=False))
try:
# One exact model query; no reconnect/retry loop and no provider credentials.
with connect("wss://api.ailoot.ai/v1/realtime?model=qwen-audio-3.0-realtime-plus", additional_headers={"Authorization": "Bearer " + key}) as ws:
with (out / "events.jsonl").open("w", encoding="utf-8") as log:
wait_for(ws, log, "session.created")
send(ws, {"type":"session.update", "session":{"modalities":["audio","text"], "input_audio_format":"pcm", "output_audio_format":"pcm", "turn_detection":None}})
wait_for(ws, log, "session.updated")
for offset in range(0, len(material), 640):
send(ws, {"type":"input_audio_buffer.append", "audio":base64.b64encode(material[offset:offset+640]).decode("ascii")})
time.sleep(0.02)
send(ws, {"type":"input_audio_buffer.commit"})
wait_for(ws, log, "input_audio_buffer.committed")
send(ws, {"type":"response.create"})
pending = True
try:
while pending: receive(ws, log)
except KeyboardInterrupt:
# Cancel the actual current inference, then preserve its returned status.
send(ws, {"type":"response.cancel"})
while pending: receive(ws, log)
if not complete or complete[-1].get("status") != "completed":
raise RuntimeError("Response did not complete normally; inspect saved events and status")
finally:
manifest = {"responses":complete, "parts":[]}
for number, identity in enumerate(dict.fromkeys(list(audio) + list(texts))):
record = {"response_id":identity[0], "item_id":identity[1], "output_index":identity[2], "content_index":identity[3]}
if identity in audio:
raw = bytes(audio[identity])
pcm_file = out / ("audio-" + str(number) + ".pcm")
wav_file = out / ("audio-" + str(number) + ".wav")
pcm_file.write_bytes(raw)
with wave.open(str(wav_file), "wb") as wav:
wav.setnchannels(1); wav.setsampwidth(2); wav.setframerate(24000); wav.writeframes(raw)
record.update({"pcm":str(pcm_file), "wav":str(wav_file), "sample_rate_hz":24000})
if identity in texts:
text_file = out / ("text-" + str(number) + ".txt")
text_file.write_text(texts[identity], encoding="utf-8")
record["text"] = str(text_file)
manifest["parts"].append(record)
(out / "results.json").write_text(json.dumps(manifest, ensure_ascii=False, indent=2), encoding="utf-8")
print("\nSaved every received event and result in", out)
Recevoir et enregistrer les résultats
Ailoot · Voix en temps réel
événements de session
Conserver tous les résultats terminés
Conservez chaque réponse, fichier et partie de contenu renvoyés dans leur intégralité.
Assemblez chaque fragment audio renvoyé et chaque résultat de texte ou d’événement pour chaque identifiant réel de réponse.
Si la réponse d’origine doit être vérifiée
Conservez les identifiants réels de session, de réponse et d’événement ainsi que les justificatifs.
Erreurs et étapes suivantes
| Réponse | Condition | Étape suivante |
|---|---|---|
Réponse426 · invalid_request_error | ConditionAucune mise à niveau WebSocket | Étape suivanteUtilisez un client WebSocket avec Upgrade: websocket. |
Alias
Alias du modèle
Ailoot qwen-audio-3.0-realtime-plus
Alias des chemins de méthode
Utilisez les chemins de méthode indiqués ci-dessus.
ID d’appel associés
FAQ · qwen-audio-3.0-realtime-plus
- Quelles entrées et quels résultats sont disponibles ?
GET /v1/realtime?model=qwen-audio-3.0-realtime-plus·qwen-audio-3.0-realtime-plus:text,audio→text,audio- Quelles limites s’appliquent ?
GET /v1/realtime?model=qwen-audio-3.0-realtime-plus·qwen-audio-3.0-realtime-plus:session.max_history_turns.minimum:1