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>
79 lines
2.2 KiB
Python
79 lines
2.2 KiB
Python
"""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
|