Pida a la herramienta Agent que cree y ejecute un cliente de voz y se conecte al modelo de conversación de voz en tiempo real de Token Plan.
Modelos compatibles
| Modelo | Capacidad |
|---|---|
qwen-audio-3.0-realtime-plus | Conversación de voz en tiempo real |
Para otros modelos, consulte los modelos de conversación de voz en tiempo real compatibles con Token Plan.
Requisitos previos
- Una suscripción de Token Plan. Para la Edición Personal, obtenga la clave de API
sk-sp-en My Subscription (Personal). Para la Edición de Equipo, asigne un asiento en Gestión de miembros y luego obtenga la clave de API. - Python 3.9 o posterior, un micrófono y altavoces.
Paso 1: Enviar la instrucción de integración a la herramienta Agent
Expanda la instrucción de integración siguiente y envíela a la herramienta Agent que use. La herramienta lee la clave de Token Plan ya configurada, instala las dependencias, crea qwen_realtime_voice.py y lo ejecuta. No es necesario configurar la clave manualmente ni escribir Python.
Instrucción de integración (con script del cliente de voz)
Configure el modelo de conversación de voz en tiempo real de Token Plan qwen-audio-3.0-realtime-plus en el proyecto actual:
1. Use la clave de API de Token Plan ya configurada en la herramienta Agent actual (lea primero TOKEN_PLAN_API_KEY y luego ANTHROPIC_AUTH_TOKEN). Si ninguna está disponible, pídame que configure primero una clave de Token Plan en la herramienta Agent. No muestre la clave ni la escriba en archivos o registros.
2. Instale las dependencias: pip install "websockets>=15" sounddevice certifi
3. Cree qwen_realtime_voice.py con el siguiente contenido:
```python
#!/usr/bin/env python3
import asyncio
import base64
import json
import os
import queue
import ssl
import threading
import certifi
import sounddevice as sd
import websockets
API_KEY = os.environ.get("TOKEN_PLAN_API_KEY") or os.environ.get("ANTHROPIC_AUTH_TOKEN")
if not API_KEY:
raise SystemExit("Token Plan API Key not found. Configure it in the Agent tool first.")
WS_URL = "wss://token-plan.cn-beijing.maas.aliyuncs.com/api-ws/v1/realtime?model=qwen-audio-3.0-realtime-plus"
play_queue = queue.Queue()
def play_audio():
with sd.RawOutputStream(samplerate=24000, channels=1, dtype="int16") as stream:
while True:
chunk = play_queue.get()
if chunk is None:
break
stream.write(chunk)
async def receive(ws):
transcript = []
async for message in ws:
event = json.loads(message)
event_type = event["type"]
if event_type == "conversation.item.input_audio_transcription.completed":
print(f"\n[You] {event.get('transcript', '')}", flush=True)
elif event_type == "response.audio.delta":
play_queue.put(base64.b64decode(event["delta"]))
elif event_type == "response.audio_transcript.delta":
transcript.append(event.get("delta", ""))
elif event_type == "response.audio_transcript.done":
print(f"[AI] {''.join(transcript)}", flush=True)
transcript.clear()
elif event_type == "error":
print(f"[Error] {event}", flush=True)
async def send_mic(ws):
loop = asyncio.get_running_loop()
audio_queue = asyncio.Queue()
def callback(indata, frames, time_info, status):
loop.call_soon_threadsafe(audio_queue.put_nowait, bytes(indata))
with sd.RawInputStream(
samplerate=16000,
channels=1,
dtype="int16",
blocksize=1600,
callback=callback,
):
print("Start speaking. Press Ctrl+C to stop.", flush=True)
while True:
chunk = await audio_queue.get()
await ws.send(
json.dumps(
{
"type": "input_audio_buffer.append",
"audio": base64.b64encode(chunk).decode(),
}
)
)
async def main():
context = ssl.create_default_context(cafile=certifi.where())
async with websockets.connect(
WS_URL,
ssl=context,
additional_headers={"Authorization": f"Bearer {API_KEY}"},
max_size=None,
) as ws:
await ws.recv()
await ws.send(
json.dumps(
{
"type": "session.update",
"session": {
"modalities": ["audio", "text"],
"voice": "longanqian",
"instructions": "You are a voice assistant. Keep answers concise and natural.",
"input_audio_format": "pcm",
"output_audio_format": "pcm",
"turn_detection": {
"type": "server_vad",
"threshold": 0.5,
"silence_duration_ms": 600,
},
},
}
)
)
threading.Thread(target=play_audio, daemon=True).start()
await asyncio.gather(receive(ws), send_mic(ws))
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
pass
finally:
play_queue.put(None)
```
4. Use la herramienta Bash para ejecutar python3 qwen_realtime_voice.py con un timeout de 600000 milisegundos.
5. Cuando el script se inicie, indique al usuario que comience a hablar y que presione Ctrl+C para detenerse.
NotaEn la primera ejecución, permita que la aplicación que ejecuta la herramienta Agent (como Cursor o Terminal) acceda al micrófono en la configuración del sistema. De lo contrario, el script no recibe audio. Use audífonos para evitar que el audio de los altavoces sea capturado por el micrófono e interrumpa la respuesta.
Paso 2: Iniciar la conversación de voz
Cuando la herramienta Agent inicie el script, comience a hablar al ver el mensaje de inicio. La terminal muestra la transcripción y la respuesta del modelo, y los altavoces reproducen el audio. Presione Ctrl+C para finalizar la sesión.
NotaLa herramienta Agent instala las dependencias, crea el script e inicia la sesión. Los datos de audio viajan entre el cliente local y Token Plan y no pasan por el modelo de texto de la herramienta Agent.
Guardar como extensión de la herramienta
Para usar la instrucción de nuevo, pida a la herramienta Agent que la guarde como Skill, Slash Command o configuración de Agent de la herramienta actual y luego iníciela mediante el activador de esa herramienta. Mecanismos de extensión y rutas para herramientas comunes:
| Herramienta | Mecanismo de extensión | Ruta del archivo de configuración |
|---|---|---|
| Claude Code | Slash Command | .claude/commands/voice-chat.md |
| Codex | Skill | ~/.codex/skills/token-plan-voice/SKILL.md |
| Qwen Code | Skill | ~/.qwen/skills/voice-chat/SKILL.md |
| OpenCode | Agent | .opencode/agents/voice-chat.md |
| OpenClaw | Skill | ~/.openclaw/workspace/skills/token-plan-voice/SKILL.md |
| Hermes Agent | Skill | ~/.hermes/skills/media/voice-chat/SKILL.md |
| Qoder | Skill | ~/.qoder/skills/voice-chat/SKILL.md |
Para conocer el formato del front matter de Skills y Agents, consulte Integrar modelos de generación multimodal.
Limitaciones
- Con altavoces, el audio del modelo puede ser capturado por el micrófono e interrumpir la respuesta. Use audífonos.
- Las llamadas de Bash de la herramienta Agent tienen un tiempo de espera. Para conversaciones largas, ejecute el script como un proceso independiente o envuélvalo en un servidor MCP.
- La solución actual solo maneja entrada y salida de voz.