Spaces:
Running
Running
| """Tutor engine: builds system prompts with STRICT language isolation.""" | |
| from backend.language_config import LANGUAGES, LEVELS, CURRICULUM, get_vocabulary | |
| from backend.teacher_profiles import TEACHERS | |
| def build_system_prompt(target_lang, instruction_lang, level, topic_id, teacher_id): | |
| """Build the system prompt with strict language isolation rules.""" | |
| target = LANGUAGES.get(target_lang, {}) | |
| instruction = LANGUAGES.get(instruction_lang, {}) | |
| level_cfg = LEVELS.get(level, {}) | |
| teacher = TEACHERS.get(teacher_id, {}) | |
| target_name = target.get("name", target_lang) | |
| instruction_name = instruction.get("name", instruction_lang) | |
| target_script = target.get("script", "") | |
| target_native = target.get("native_name", "") | |
| topics = CURRICULUM.get(level, []) | |
| topic_info = next((t for t in topics if t["id"] == topic_id), {}) | |
| topic_title = topic_info.get("title", topic_id) | |
| vocab = get_vocabulary(target_lang, topic_id) | |
| vocab_block = "" | |
| if vocab: | |
| vocab_lines = [f" - {v['word']} ({v['transliteration']}) = {v['meaning']}" | |
| for v in vocab[:10]] | |
| vocab_block = "Key vocabulary for this lesson:\n" + "\n".join(vocab_lines) | |
| is_immersion = target_lang == instruction_lang | |
| # --- STRICT LANGUAGE ISOLATION (MOST CRITICAL RULES) --- | |
| if is_immersion: | |
| lang_rules = f""" | |
| === ABSOLUTE LANGUAGE RULES (HIGHEST PRIORITY — NEVER VIOLATE) === | |
| You are in IMMERSION MODE. The student is learning {target_name} using {target_name} itself. | |
| 1. EVERY SINGLE WORD you write MUST be in {target_name} ({target_script} script). | |
| 2. DO NOT use ANY other language. Not a single word of English or any other language. | |
| 3. Explanations, grammar notes, encouragement — ALL in {target_name}. | |
| 4. If the student writes in another language, respond ONLY in {target_name} and gently guide them back. | |
| === END LANGUAGE RULES === | |
| """ | |
| else: | |
| lang_rules = f""" | |
| === ABSOLUTE LANGUAGE RULES (HIGHEST PRIORITY — NEVER VIOLATE) === | |
| The student is learning {target_name} and already knows {instruction_name}. | |
| 1. ALL your explanations, instructions, grammar notes, encouragement, and conversation MUST be in {instruction_name}. | |
| 2. Teach {target_name} words/phrases using {target_script} script. | |
| 3. NEVER use English unless the instruction language IS English. | |
| 4. NEVER use any language other than {target_name} (for teaching) and {instruction_name} (for explaining). | |
| 5. When presenting vocabulary, use this format: | |
| [{target_name} word in {target_script}] ([transliteration]) — [{instruction_name} meaning] | |
| 6. Even small words like "means", "is called", "for example" MUST be in {instruction_name}. | |
| 7. If the student writes in {instruction_name}, respond in {instruction_name} while teaching {target_name} content. | |
| 8. If the student attempts {target_name}, praise them in {instruction_name} and provide corrections in {instruction_name}. | |
| === END LANGUAGE RULES === | |
| """ | |
| # Teacher personality | |
| teacher_traits = teacher.get("system_prompt_traits", "You are a helpful language teacher.") | |
| greeting_style = teacher.get("greeting_style", "friendly") | |
| # Honorifics | |
| honorifics_note = "" | |
| if target.get("has_honorifics"): | |
| honorifics_note = f"\n{target_name} has formal/informal address. At {level} level, teach the polite/formal forms primarily." | |
| prompt = f"""{lang_rules} | |
| {teacher_traits} | |
| You are teaching {target_name} ({target_native}) to a {level_cfg.get('name', level)} student. | |
| Topic: {topic_title} | |
| {honorifics_note} | |
| Teaching guidelines for {level} level: | |
| - Vocabulary limit: ~{level_cfg.get('vocab_limit', 500)} words | |
| - Grammar: {level_cfg.get('grammar_complexity', 'simple')} | |
| - Corrections: {level_cfg.get('correction_style', 'gentle')} | |
| - Response length: {level_cfg.get('response_length', '3-6 sentences')} | |
| {vocab_block} | |
| Format rules: | |
| - When introducing a new {target_name} word, always write it in {target_script} script first, then transliteration in parentheses. | |
| - Use short, clear sentences. | |
| - After teaching 2-3 new words, give a quick practice exercise. | |
| - When sharing cultural context, wrap it in [CULTURAL NOTE: your note here] format. | |
| - For mini-dialogues, use [DIALOGUE] and [/DIALOGUE] markers. | |
| - For sentence builder exercises, use [SENTENCE_BUILDER: word1 | word2 | word3 | ...] format with the correct order. | |
| Remember: The language rules above are ABSOLUTE. Never break them under any circumstances. | |
| """ | |
| return prompt.strip() | |
| def build_greeting_prompt(target_lang, instruction_lang, level, topic_id, teacher_id): | |
| """Build the first greeting message prompt.""" | |
| target = LANGUAGES.get(target_lang, {}) | |
| instruction = LANGUAGES.get(instruction_lang, {}) | |
| teacher = TEACHERS.get(teacher_id, {}) | |
| target_name = target.get("name", target_lang) | |
| instruction_name = instruction.get("name", instruction_lang) | |
| greeting_style = teacher.get("greeting_style", "friendly") | |
| topics = CURRICULUM.get(level, []) | |
| topic_info = next((t for t in topics if t["id"] == topic_id), {}) | |
| topic_title = topic_info.get("title", topic_id) | |
| is_immersion = target_lang == instruction_lang | |
| if is_immersion: | |
| return ( | |
| f"Greet the student in {target_name} only. Be {greeting_style}. " | |
| f"Introduce yourself as {teacher.get('name', 'Teacher')} and say you'll be teaching " | |
| f"'{topic_title}' today. Start with a warm greeting in {target_name} and " | |
| f"introduce 1-2 basic words from the topic. Keep it short and encouraging. " | |
| f"Remember: EVERYTHING must be in {target_name}." | |
| ) | |
| else: | |
| return ( | |
| f"Greet the student in {instruction_name}. Be {greeting_style}. " | |
| f"Introduce yourself as {teacher.get('name', 'Teacher')} and say you'll be teaching " | |
| f"{target_name} today, specifically '{topic_title}'. " | |
| f"Say a common greeting in {target_name} with its {instruction_name} meaning. " | |
| f"Keep it short and welcoming. Remember: explain everything in {instruction_name}, " | |
| f"teach words in {target_name}." | |
| ) | |
| def evaluate_pronunciation(user_text, expected_text): | |
| """Simple pronunciation scoring by comparing transcribed text to expected.""" | |
| if not user_text or not expected_text: | |
| return {"score": 0, "feedback": "No text to compare"} | |
| user_words = user_text.lower().strip().split() | |
| expected_words = expected_text.lower().strip().split() | |
| if not expected_words: | |
| return {"score": 0, "feedback": "No expected text"} | |
| matches = 0 | |
| for uw in user_words: | |
| if uw in expected_words: | |
| matches += 1 | |
| score = min(100, int((matches / len(expected_words)) * 100)) | |
| if score >= 90: | |
| feedback = "Excellent pronunciation!" | |
| elif score >= 70: | |
| feedback = "Good attempt! A few sounds need practice." | |
| elif score >= 50: | |
| feedback = "Decent try! Keep practicing the tricky sounds." | |
| else: | |
| feedback = "Let's practice this phrase more. Listen carefully and try again." | |
| return {"score": score, "feedback": feedback, "expected": expected_text, "heard": user_text} | |