DEV Community

shashank ms
shashank ms

Posted on

Leveraging LLMs for Language Learning: A Comprehensive Guide

Project overview

I built a conversational language tutor that corrects grammar in real time, explains mistakes, and tracks vocabulary across turns. It runs on Oxlo.ai, where flat per-request pricing means a long, detailed correction costs the same as a single word, so extended practice sessions stay predictable. This tutorial walks through the exact code I shipped so you can adapt it for any target language.

What you'll need

Step 1: Initialize the Oxlo.ai client

I start by importing the SDK and pointing it at Oxlo.ai's endpoint. Because Oxlo.ai is fully OpenAI SDK compatible, this is the only setup required.

from openai import OpenAI

client = OpenAI(
    base_url="https://api.oxlo.ai/v1",
    api_key="YOUR_OXLO_API_KEY"
)

Step 2: Define the tutor system prompt

The system prompt is the core product decision. I instruct the model to stay in the target language, wrap corrections in parseable tags, and append new vocabulary. I tuned this for Spanish learners at the A2 level, but you can swap the language and proficiency.

SYSTEM_PROMPT = """You are a patient Spanish tutor helping an English speaker at the A2 level.

Rules:
1. Always conduct the main conversation in Spanish.
2. If the student makes a grammar, spelling, or vocabulary error, wrap the corrected version in [correction]...[/correction] tags.
3. Immediately after the correction, add a short English explanation inside [explain]...[/explain] tags.
4. Identify any new or notable vocabulary words the student encountered in this turn. List them at the very end of your response using [vocab]Spanish word - English definition[/vocab] tags, one per line.
5. If the student writes in English, reply in Spanish but provide an English translation of your reply inside [translate]...[/translate] tags.
6. Keep your entire response under 120 words so it is digestible."""

MODEL = "qwen-3-32b"

Step 3: Parse structured tutor responses

To make the tutor useful, I extract the structured pieces so I can display corrections prominently and save vocabulary to a list. I use simple regex rather than a heavy parser.

import re

def parse_tutor_response(text):
    correction = re.search(r'\[correction\](.*?)\[/correction\]', text, re.DOTALL)
    explanation = re.search(r'\[explain\](.*?)\[/explain\]', text, re.DOTALL)
    translation = re.search(r'\[translate\](.*?)\[/translate\]', text, re.DOTALL)
    vocab = re.findall(r'\[vocab\](.*?)\[/vocab\]', text)

    clean = re.sub(r'\[(correction|explain|translate|vocab)\].*?\[/\1\]', '', text, flags=re.DOTALL)
    clean = re.sub(r'\n\s*\n', '\n', clean).strip()

    return {
        "clean_reply": clean,
        "correction": correction.group(1).strip() if correction else None,
        "explanation": explanation.group(1).strip() if explanation else None,
        "translation": translation.group(1).strip() if translation else None,
        "vocab": [v.strip() for v in vocab]
    }

Step 4: Maintain conversation memory

The tutor needs context. I keep a messages list that grows with each turn and is sent to Oxlo.ai on every request. Because Oxlo.ai uses flat per-request pricing, growing this history does not inflate the cost, which makes long practice sessions predictable.

def get_tutor_reply(client, messages):
    response = client.chat.completions.create(
        model=MODEL,
        messages=messages,
        temperature=0.7,
        max_tokens=512
    )
    return response.choices[0].message.content

Step 5: Build the interactive loop

I tie the pieces together in a small CLI loop. It prints the clean reply, surfaces corrections and explanations, and accumulates vocabulary in a session list.

def run_language_tutor():
    messages = [{"role": "system", "content": SYSTEM_PROMPT}]
    session_vocab = set()

    print("Spanish Tutor: Hola. ¿Cómo estás hoy? (type 'exit' to quit)")

    while True:
        user_input = input("You: ").strip()
        if user_input.lower() in ("exit", "quit"):
            break

        messages.append({"role": "user", "content": user_input})
        raw_reply = get_tutor_reply(client, messages)
        parsed = parse_tutor_response(raw_reply)

        print(f"Tutor: {parsed['clean_reply']}")

        if parsed['correction']:
            print(f"  Correction: {parsed['correction']}")
            print(f"  Why: {parsed['explanation']}")
        if parsed['translation']:
            print(f"  Translation: {parsed['translation']}")
        if parsed['vocab']:
            for item in parsed['vocab']:
                if item not in session_vocab:
                    print(f"  New vocab: {item}")
                    session_vocab.add(item)

        messages.append({"role": "assistant", "content": raw_reply})

if __name__ == "__main__":
    run_language_tutor()

Run it

Save the full script as tutor.py, export your key, and run it. Here is a sample session using Oxlo.ai's Qwen 3 32B.

$ export OXLO_API_KEY="sk-oxlo.ai-..."
$ python tutor.py

Spanish Tutor: Hola. ¿Cómo estás hoy? (type 'exit' to quit)
You: Yo tengo hambre, pero no sé donde está el restaurante
Tutor: Hola. Tienes hambre, qué pena. El restaurante está cerca del parque.
  Correction: Yo tengo hambre, pero no sé dónde está el restaurante
  Why: "donde" needs an accent when it means "where" as an interrogative or relative pronoun in a question.
  New vocab: cerca del parque - near the park
You: Gracias. Voy a comer una manzana ahora.
Tutor: De nada. ¡Buen provecho! Disfruta tu manzana.
You: exit

Next steps

To productionize this, wire in Oxlo.ai's audio endpoints. You can pass the tutor's clean reply to the Kokoro text-to-speech model for pronunciation drills, or transcribe the student's spoken responses with Whisper Large v3 before sending them to the chat model. If you are building for a classroom, review the plans at https://oxlo.ai/pricing to find a daily request volume that fits your needs.

Top comments (0)