qwen-audio-3.0-realtime-plus
Modell för röstsamtal i realtid som tar emot tal och text och svarar med röst eller text. Utformad för ett naturligt samtalstempo och samverkan med verktyg.
Om modellen
Den här beskrivningen omfattar modellens förmågor. Tillgängliga indata, utdata och alternativ i Ailoot anges nedan för den valda metoden.
Qwen-Audio-3.0-Realtime-Plus är en modell från Alibaba för röstsamtal i realtid. Den tar emot tal och text, svarar med ljud och text och stöder samtal i båda riktningarna med naturlig turtagning. Ljud kan skickas och tas emot i delar, så att samspelet utvecklas under samtalets gång.
När samtalspartnern har talat färdigt
Det finns flera sätt att avgöra gränserna för en replik: ljudaktivitet, semantisk avslutning och uttrycklig styrning. Hos tillverkaren väljs läget innan det första ljudet skickas. För att ändra det efter att samtalet har börjat krävs en ny anslutning. Stödet för denna styrning beror på den valda metoden. Det semantiska läget tar hänsyn till pauser och utfyllnadsord: en kort tvekan behöver inte betyda att användaren har talat färdigt. Användarens nya tal kan avbryta ett svar som håller på att skapas så att samtalet fortsätter med hänsyn till nästa replik. I det semantiska läget går det att rikta igenkänningen mot ett röstprov från den valda samtalspartnern för att minska störningar från andra röster och bakgrundsljud.
Instruktionerna anger assistentens roll och samtalsstil. Röstuttrycket kan ta hänsyn till ton, tempo och känsla. Version 3.0 har fem systemröster och röster baserade på röstprov. Modellen stöder 11 språk, inklusive ryska, samt de kinesiska dialektvarianter som tillverkaren anger. Hos tillverkaren anges rösten vid den första uppdateringen av sessionsinställningarna. Om en ny röst sedan skickas i samma samtal ignoreras den. Dessa inställningar kräver stöd i det valda anropssättet.
Verktyg och samtalshistorik
Funktionsanrop stöds. Modellen formulerar den åtgärd som behövs, den anslutna applikationen utför den och återför resultatet till dialogen. Det gör det möjligt att bygga samtalet kring faktiska uppgifter och fortsätta efter den utförda åtgärden. Röstassistenten kan använda verktygsresultaten och samtidigt behålla samtalets sammanhang. Tillverkarens möjligheter omfattar även inbyggd webbsökning om den valda metoden tillhandahåller den. Webbsökning och funktionsanrop kan inte aktiveras samtidigt i samma session.
Som standard innehåller historiken 20 samtalsturer, med ett tillåtet intervall från en till 50. För samlat ljud finns en gräns på 300 sekunder. Äldre delar av historiken tas bort när gränserna överskrids. Detta skiljer sig från en enskild repliks längd: historiken avgör vilket tidigare material som finns kvar när dialogen fortsätter.
Textkontext och ljud
Den formella kontexten är 40 960 token. Maximal indatalängd är 16 384 token och maximal utdatalängd 8192. Samma in- och utdatagränser anges för resonemangsläget, med en separat gräns för resonemangskedjan på 1024 token.
Strömmande ljud använder enkanalig PCM med 16-bitars representation: 16 kHz på ingången och 24 kHz på utgången. Text och ljud hör till samma samtal. Visuell indata och generering av bilder har inte uppgetts för just den här modellen. Dess specialisering är tal, text och röstbaserad interaktion.
Ailoot · Röst i realtid GET /v1/realtime?model=qwen-audio-3.0-realtime-plus qwen-audio-3.0-realtime-plus
qwen-audio-3.0-realtime-plusStart
Modell för röstsamtal i realtid som tar emot tal och text och svarar med röst eller text. Utformad för ett naturligt samtalstempo och samverkan med verktyg.
- Godkända indata
- Text · Ljud
- Resultat
- Text · Ljud
Tillgängligt i Ailoot · indata & metoder
Ailoot · Röst i realtid GET /v1/realtime?model=qwen-audio-3.0-realtime-plus
- Indatatyper
text,audio- Utdatatyper
text,audio- Utdataformat
- sessionshändelser
| Fält | Typ | Krav | Värden & gränser | Standard |
|---|---|---|---|---|
Fältquery.model | Typstring | KravObligatoriskt | Värden & gränser qwen-audio-3.0-realtime-plus | Standard— |
Fältsession.input_audio_format | Typstring | KravValfritt | Värden & gränser pcm16, pcm | Standard— |
Fältsession.output_audio_format | Typstring | KravValfritt | Värden & gränser pcm16, pcm | Standard— |
Fältsession.instructions | Typstring | KravValfritt | Värden & gränser Gränsen gäller för: vald sessionspolicy | Standard— |
Fältsession.max_history_turns | Typinteger | KravValfritt | Värden & gränser Minimum: 1 Gränsen gäller för: vald sessionspolicy | Standard— |
Fältinput_audio_buffer.append.audio | Typbase64_string | KravObligatoriskt | Värden & gränser Indatainnehåll: PCM16 mono; 16 kHz indata, 24 kHz utdata; icke-tom och jämn bytelängd | Standard— |
Kombinationer av indatamaterial
realtime_text_audio
Metodparametrar och livscykel
| Parameter | Avtal |
|---|---|
Parametermaterial_types | Avtaltext, audio |
Parameterrequired | Avtalnull |
Parameteroptional_controls | Avtalnull |
Parametercontent_type | AvtalWebSocket |
Livscykel: exact retained published method
Metodernas strukturer och ID:n är exakta; leverantörens funktioner är åtskilda från att begäran tillåts.
Priser
Priser för Ailoot-metoder
GET /v1/realtime?model=qwen-audio-3.0-realtime-plus- Indata
- 0,0008 US$ / 1K
- Utdata
- 0,0064 US$ / 1K
- Indata
- 0,0048 US$ per minut ljud
- Utdata
- 0,018 US$ per minut utdataljud
Ailoot reserverar ett uppskattat belopp före en begäran. Efter resultatet slutregleras avgiften utifrån uppmätt förbrukning. Slutreglering för strömning använder den slutliga förbrukningsposten. Så fungerar reservation och slutreglering →
Exempelbegäranden
Ailoot · Röst i realtid
# 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)
Ta emot och spara resultat
Ailoot · Röst i realtid
sessionshändelser
Behåll alla färdiga resultat
Behåll varje fullständigt returnerat svar, fil och innehållsdel.
Sammanfoga alla returnerade ljuddelta och alla text- eller händelseresultat för varje faktiskt svars-ID.
Om det ursprungliga svaret behöver kontrolleras
Behåll faktiska sessions-, svars- och händelse-ID:n samt kvittenser.
Fel och nästa steg
| Svar | Villkor | Nästa steg |
|---|---|---|
Svar426 · invalid_request_error | VillkorIngen WebSocket-uppgradering | Nästa stegAnvänd en WebSocket-klient med Upgrade: websocket. |
Alias
Modellalias
Ailoot qwen-audio-3.0-realtime-plus
Alias för metodsökvägar
Använd metodsökvägarna som visas ovan.
Relaterade anropar-ID:n
FAQ · qwen-audio-3.0-realtime-plus
- Vilka indata och resultat finns?
GET /v1/realtime?model=qwen-audio-3.0-realtime-plus·qwen-audio-3.0-realtime-plus:text,audio→text,audio- Vilka gränser gäller?
GET /v1/realtime?model=qwen-audio-3.0-realtime-plus·qwen-audio-3.0-realtime-plus:session.max_history_turns.minimum:1