We are building a terminal-based conversational language tutor that corrects mistakes in real time and generates personalized exercises. It is for anyone who wants structured speaking or writing practice without the friction of scheduling human sessions. Because the tutor maintains full conversation history, it remembers your weak spots across a long session.
What you'll need
- Python 3.10 or higher
- An Oxlo.ai API key from https://portal.oxlo.ai
- The OpenAI SDK:
pip install openai
Step 1: Connect to Oxlo.ai and test the client
First, instantiate the OpenAI-compatible client pointing at Oxlo.ai. I use llama-3.3-70b here because it handles multilingual instruction and correction reliably. A quick connectivity check confirms your key and endpoint are working.
from openai import OpenAI
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Say hello in Spanish, French, and Japanese."},
],
)
print(response.choices[0].message.content)
Step 2: Define the tutor system prompt
The system prompt is the only manual tuning we need. It sets the tutor persona, restricts response length, and mandates gentle correction with explanations. Store it as a module-level constant so both the chat loop and review functions can reference it.
SYSTEM_PROMPT = """You are a patient, encouraging language tutor. Your student wants to practice a foreign language.
Rules:
1. First, ask which language they want to practice and their proficiency level (A1, A2, B1, etc.).
2. Once you know the language and level, conduct a natural conversation appropriate to that level.
3. When the student makes a grammar, vocabulary, or spelling mistake, correct it gently. Provide the corrected form and a brief explanation.
4. Keep responses concise. Use at most three short paragraphs.
5. If the student asks for an exercise, give them a fill-in-the-blank or translation task.
Always respond in the student's native language (English) except when providing target language examples or corrections."""
Step 3: Build the conversation loop
We need state. A simple list of message dictionaries acts as our conversation memory. The chat_turn function appends the user message, calls Oxlo.ai, and appends the assistant reply. With Oxlo.ai, the context can grow long without cost surprises because pricing is per request, not per token. See https://oxlo.ai/pricing for plan details.
def chat_turn(user_input, messages):
messages.append({"role": "user", "content": user_input})
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=messages,
temperature=0.7,
)
assistant_msg = response.choices[0].message.content
messages.append({"role": "assistant", "content": assistant_msg})
return assistant_msg
Step 4: Add structured review and exercise generation
After several turns, we want extractable data: a list of mistakes and a targeted exercise. I switch to qwen-3-32b for this step because its multilingual reasoning handles grammar analysis accurately. We append a review instruction to the existing history and request JSON mode so the output is machine readable.
import json
def generate_review(messages):
review_instruction = (
"You are a language teacher reviewing the above conversation. "
"Output a JSON object with exactly these keys: "
"'mistakes' (a list of objects, each with 'error' and 'correction'), "
"'exercise' (a fill-in-the-blank sentence using one corrected item), "
"'answer_key' (the completed sentence). "
"If there are no mistakes, set 'mistakes' to an empty list and create a challenge exercise anyway."
)
review_messages = messages + [{"role": "user", "content": review_instruction}]
response = client.chat.completions.create(
model="qwen-3-32b",
messages=review_messages,
response_format={"type": "json_object"},
temperature=0.3,
)
return json.loads(response.choices[0].message.content)
Run it
Wire the pieces together in a small CLI script. The following block simulates a student opening a Spanish A2 session, making a common error, and then requesting a review.
if __name__ == "__main__":
messages = [{"role": "system", "content": SYSTEM_PROMPT}]
# opening turn
print("Student: I want to practice Spanish. I am A2 level.")
print("Tutor:", chat_turn("I want to practice Spanish. I am A2 level.", messages))
print()
# turn with a deliberate mistake
print("Student: Yo tener dos gatos.")
print("Tutor:", chat_turn("Yo tener dos gatos.", messages))
print()
# structured review
print("Generating review...")
review = generate_review(messages)
print(json.dumps(review, indent=2, ensure_ascii=False))
Example output from the tutor and review function looks like this:
Tutor: Great choice. Tell me something about your family or pets to start.
Student: Yo tener dos gatos.
Tutor: Almost. The correct verb form is "Yo tengo dos gatos." In Spanish, "tener" is an irregular verb in the present tense. For "yo," we say "tengo," not "tener." What color are your cats?
Generating review...
{
"mistakes": [
{
"error": "Yo tener dos gatos.",
"correction": "Yo tengo dos gatos."
}
],
"exercise": "Yo ______ (tener) dos gatos y un perro.",
"answer_key": "Yo tengo dos gatos y un perro."
}
Next steps
Store the generated review objects in a local SQLite database so the tutor can reference past mistakes in future sessions. You can also add speech-to-text with Oxlo.ai's Whisper endpoints so students can practice pronunciation out loud and receive transcription feedback.
Top comments (0)