DEV Community

anusha
anusha

Posted on

I Built a Language Tutor That Listens and Scores Your Pronunciation

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:

  1. TTS speaks — an Ultra voice (Camila for Spanish, Valerie for French) plays a flashcard phrase. Audio autoplays.
  2. You repeat — click Record, speak the phrase, click Stop.
  3. STT transcribes — Whisper transcribes your speech.
  4. 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!"}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)