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:
78
python/persian-tutor/modules/essay.py
Normal file
78
python/persian-tutor/modules/essay.py
Normal file
@@ -0,0 +1,78 @@
|
||||
"""Essay writing and AI marking."""
|
||||
|
||||
import db
|
||||
from ai import ask
|
||||
|
||||
MARKING_SYSTEM_PROMPT = """You are an expert Persian (Farsi) language teacher marking a GCSE-level essay.
|
||||
You write in English but can read and correct Persian text.
|
||||
Always provide constructive, encouraging feedback suitable for a language learner."""
|
||||
|
||||
MARKING_PROMPT_TEMPLATE = """Please mark this Persian essay written by a GCSE student.
|
||||
|
||||
Theme: {theme}
|
||||
|
||||
Student's essay:
|
||||
{essay_text}
|
||||
|
||||
Please provide your response in this exact format:
|
||||
|
||||
**Grade:** [Give a grade from 1-9 matching GCSE grading, or a descriptive level like A2/B1]
|
||||
|
||||
**Summary:** [1-2 sentence overview of the essay quality]
|
||||
|
||||
**Corrections:**
|
||||
[List specific errors with corrections. For each error, show the original text and the corrected version in Persian, with an English explanation]
|
||||
|
||||
**Improved version:**
|
||||
[Rewrite the essay in corrected Persian]
|
||||
|
||||
**Tips for improvement:**
|
||||
[3-5 specific, actionable tips for the student]"""
|
||||
|
||||
|
||||
GCSE_THEMES = [
|
||||
"Identity and culture",
|
||||
"Local area and environment",
|
||||
"School and work",
|
||||
"Travel and tourism",
|
||||
"International and global dimension",
|
||||
]
|
||||
|
||||
|
||||
def mark_essay(essay_text, theme="General"):
|
||||
"""Send essay to AI for marking. Returns structured feedback."""
|
||||
if not essay_text or not essay_text.strip():
|
||||
return "Please write an essay first."
|
||||
|
||||
prompt = MARKING_PROMPT_TEMPLATE.format(
|
||||
theme=theme,
|
||||
essay_text=essay_text.strip(),
|
||||
)
|
||||
|
||||
feedback = ask(prompt, system=MARKING_SYSTEM_PROMPT, quality="smart")
|
||||
|
||||
# Extract grade from feedback (best-effort)
|
||||
grade = ""
|
||||
for line in feedback.split("\n"):
|
||||
if line.strip().startswith("**Grade:**"):
|
||||
grade = line.replace("**Grade:**", "").strip()
|
||||
break
|
||||
|
||||
# Save to database
|
||||
db.save_essay(essay_text.strip(), grade, feedback, theme)
|
||||
|
||||
return feedback
|
||||
|
||||
|
||||
def get_essay_history(limit=10):
|
||||
"""Return recent essays for the history view."""
|
||||
essays = db.get_recent_essays(limit)
|
||||
result = []
|
||||
for e in essays:
|
||||
result.append({
|
||||
"Date": e["timestamp"],
|
||||
"Theme": e["theme"] or "General",
|
||||
"Grade": e["grade"] or "-",
|
||||
"Preview": (e["essay_text"] or "")[:50] + "...",
|
||||
})
|
||||
return result
|
||||
Reference in New Issue
Block a user