Language learning apps work fine on a screen, but the hardest part is the thing screens avoid: actually speaking out loud and getting immediate feedback on whether you said it right.
Most voice-based language tools either play a recording or transcribe your speech. They don't do both in an interactive loop. I wanted to build something that does — something that plays a phrase, listens to you repeat it, and tells you whether you got it right.
The Telnyx code example is:
https://github.com/team-telnyx/telnyx-code-examples/tree/main/language-learning-flashcards-python
It is a Python Flask app with a browser UI. No phone number, no webhook tunnel, no Cloud Storage.
The Loop
The app uses all three Telnyx AI primitives in one interactive round-trip:
- TTS speaks — an Ultra voice (Camila for Spanish, Valerie for French) plays a flashcard phrase. Audio autoplays.
- You repeat — click Record, speak the phrase, click Stop.
- STT transcribes — Whisper transcribes your speech.
- Inference scores — Kimi-K2.6 compares your transcription against the target phrase and returns a score: correct, close, or wrong, plus a one-sentence tip.
One platform, one API key, no external services.
Why This Is Different From a Translator
The existing ai-content-translator-python example does STT → translate → TTS. It's one-directional: you speak, the app translates. This example is interactive: the app speaks to you, you speak back, the app evaluates you. The flow is completely different even though it uses the same three Telnyx primitives.
The Voices
The app uses native Ultra voices per language, not one English voice with language_boost:
| Language | Voice |
|---|---|
| Spanish | Camila (es, Female) |
| French | Valerie (fr-FR, Female) |
To add more languages, enumerate voices via GET /v2/text-to-speech/voices and add them to LANGUAGE_VOICE_MAP in app.py.
How the Scoring Works
The Inference call uses a system prompt that tells Kimi to compare the target phrase against the user's spoken text and return JSON with a score and a tip:
{"score": "correct", "feedback": "Great job, your pronunciation matched the target phrase perfectly!"}
Kimi-K2.6 is a reasoning model — it takes ~10 seconds to think before scoring, but the result is more nuanced than a simple string comparison. It accounts for minor accent differences (correct), noticeable errors like wrong or missing words (close), and completely wrong speech (wrong).
The Decks
The app ships with 4 pre-built flashcard decks:
| Deck | Language | Cards |
|---|---|---|
| Spanish — Greetings | Spanish | 8 |
| Spanish — Numbers | Spanish | 6 |
| Spanish — Common phrases | Spanish | 8 |
| French — Greetings | French | 6 |
Add more by editing FLASHCARD_DECKS in app.py. Each card has a phrase (what TTS speaks and what you repeat) and a translation (shown as a hint).
Run It
git clone https://github.com/team-telnyx/telnyx-code-examples.git
cd telnyx-code-examples/language-learning-flashcards-python
cp .env.example .env # fill in TELNYX_API_KEY
pip install -r requirements.txt
python app.py # starts on http://127.0.0.1:5050
Open the browser, pick a deck, listen, repeat, get scored.
One Thing to Watch
Kimi-K2.6 is a reasoning model. It spends tokens thinking before it produces the JSON score. If max_tokens is too low (I tried 200 at first), it runs out of tokens during reasoning and returns empty content. The fix is max_tokens: 1000 — enough for reasoning + the short JSON response. This is a Kimi-specific behavior; a non-reasoning model like Llama-3.3-70B would work with 200 tokens, but Kimi is the recommended Telnyx model.
Related Examples
-
ai-language-learning-phone-tutor-python— phone-based language tutor -
ai-content-translator-python— STT + translate + TTS pipeline -
multi-character-narrator-python— multi-voice TTS with emotions
Top comments (0)