Voice Agent API — Spanish conversation tutor with native-accent voice
# Voice Agent API: Spanish conversation tutor with native-accent voice
import asyncio, json, websockets
API_KEY = "YOUR_API_KEY"
async def run_tutor():
async with websockets.connect(
"wss://agents.assemblyai.com/v1/ws",
additional_headers={"Authorization": f"Bearer {API_KEY}"},
) as ws:
await ws.send(json.dumps({
"type": "session.update",
"session": {
"system_prompt": (
"You are a friendly B1-intermediate Spanish tutor. "
"Speak Spanish, keep replies under 2 sentences, and ask "
"follow-up questions. When the learner mispronounces a "
"word, call pronunciation_feedback with the word and a "
"short tip — do not correct out loud."
),
"greeting": "¡Hola! Cuéntame sobre tu fin de semana. ¿Qué hiciste?",
"input": {"keyterms": ["mercado", "frutas", "fin de semana", "compré"]},
"output": {"voice": "lucia"}, # Spanish native-accent voice
"tools": [{
"type": "function",
"name": "pronunciation_feedback",
"description": "Send a pronunciation tip to the learner UI.",
"parameters": {
"type": "object",
"properties": {
"word": {"type": "string"},
"tip": {"type": "string"},
},
"required": ["word", "tip"],
},
}],
},
}))
async for msg in ws:
handle(json.loads(msg)) # transcript.user, reply.audio, tool.call, ...
Universal-3.5 Pro Realtime — word-level pronunciation scoring
# Universal-3.5 Pro Realtime: word-level pronunciation scoring
import asyncio, json, websockets
from urllib.parse import urlencode
API_KEY = "YOUR_API_KEY"
params = urlencode({
"sample_rate": 16000,
"speech_model": "u3-rt-pro",
"language_detection": "true", # tag each turn with detected language
"keyterms_prompt": json.dumps([
"mercado", "frutas", "fin de semana",
"ayer", "compré", "ir al",
]),
"format_turns": "true",
})
CONFIDENCE_THRESHOLD = 0.70 # tune per learner level
async def score_pronunciation(audio_iter, send_to_learner_ui):
url = f"wss://streaming.assemblyai.com/v3/ws?{params}"
async with websockets.connect(
url, additional_headers={"Authorization": API_KEY},
) as ws:
async def send_audio():
async for chunk in audio_iter:
await ws.send(chunk)
asyncio.create_task(send_audio())
async for raw in ws:
evt = json.loads(raw)
if evt.get("type") == "Turn" and evt.get("end_of_turn"):
words = evt.get("words", [])
low_conf = [
w for w in words
if w.get("confidence", 1.0) < CONFIDENCE_THRESHOLD
]
send_to_learner_ui({
"transcript": evt["transcript"],
"needs_practice": [{"word": w["text"], "score": w["confidence"]}
for w in low_conf],
})