Add persian-tutor: Gradio-based GCSE Persian language learning app

Vocabulary study with FSRS spaced repetition, AI tutoring (Ollama/Claude),
essay marking, idioms browser, Anki export, and dashboard. 918 vocabulary
entries across 39 categories. 41 tests passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
local
2026-02-08 01:57:44 +00:00
parent 104da381fb
commit 2e8c2c11d0
22 changed files with 10664 additions and 0 deletions

View File

@@ -0,0 +1,65 @@
"""Conversational Persian lessons by GCSE theme."""
import time
import db
from ai import chat_ollama
TUTOR_SYSTEM_PROMPT = """You are a friendly Persian (Farsi) language tutor teaching English-speaking GCSE students.
Rules:
- Use a mix of English and Persian. Start mostly in English, gradually introducing more Persian.
- When you write Persian, also provide the Finglish transliteration in parentheses.
- Keep responses concise (2-4 sentences per turn).
- Ask the student to practice: translate phrases, answer questions in Persian, or fill in blanks.
- Correct mistakes gently and explain why.
- Stay on the current theme/topic.
- Use Iranian Persian (Farsi), not Dari or Tajik.
- Adapt to the student's level based on their responses."""
THEME_PROMPTS = {
"Identity and culture": "Let's practice talking about family, personality, daily routines, and Persian celebrations like Nowruz!",
"Local area and environment": "Let's practice talking about your home, neighbourhood, shopping, and the environment!",
"School and work": "Let's practice talking about school subjects, school life, jobs, and future plans!",
"Travel and tourism": "Let's practice talking about transport, directions, holidays, hotels, and restaurants!",
"International and global dimension": "Let's practice talking about health, global issues, technology, and social media!",
"Free conversation": "Let's have a free conversation in Persian! I'll help you along the way.",
}
def start_lesson(theme):
"""Generate the opening message for a new lesson.
Returns:
(assistant_message, messages_list)
"""
intro = THEME_PROMPTS.get(theme, THEME_PROMPTS["Free conversation"])
system = TUTOR_SYSTEM_PROMPT + f"\n\nCurrent topic: {theme}. {intro}"
messages = [{"role": "user", "content": f"I'd like to practice Persian. Today's theme is: {theme}"}]
response = chat_ollama(messages, system=system)
messages.append({"role": "assistant", "content": response})
return response, messages, system
def process_response(user_input, messages, system=None):
"""Add user input to conversation, get AI response.
Returns:
(assistant_response, updated_messages)
"""
if not user_input or not user_input.strip():
return "", messages
messages.append({"role": "user", "content": user_input.strip()})
response = chat_ollama(messages, system=system)
messages.append({"role": "assistant", "content": response})
return response, messages
def save_session(theme, messages, start_time):
"""Save the current tutor session to the database."""
duration = int(time.time() - start_time)
db.save_tutor_session(theme, messages, duration)