File size: 2,810 Bytes
950121e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
"""tutor/model_loader.py โ€” generates child-facing feedback (templates + optional LLM)."""
from __future__ import annotations
import os, random
from typing import Optional

_CORRECT = {
    "en":  ["Amazing work! ๐ŸŽ‰ You got it!","Superstar! โญ That's exactly right!",
             "Brilliant! ๐ŸŒŸ You're on fire!","Perfect! Keep it up! ๐Ÿš€","You nailed it! ๐ŸŽŠ"],
    "fr":  ["Bravo ! ๐ŸŽ‰ C'est exactement รงa !","Super ! โญ Tu es fantastique !",
             "Excellent ! ๐ŸŒŸ Continue comme รงa !","Parfait ! ๐Ÿฅณ Tu es une รฉtoile !"],
    "kin": ["Byiza cyane! ๐ŸŽ‰ Wabitsinze!","Ntangaza! โญ Uravuga ukuri!",
             "Komeza! ๐ŸŒŸ Uri inzobere!","Superbe! ๐Ÿฅณ Urashoboye!"],
    "sw":  ["Vizuri sana! ๐ŸŽ‰ Umeshinda!","Hongera! โญ Jibu sahihi!",
             "Endelea hivyo! ๐ŸŒŸ Umefaulu!","Bora sana! ๐Ÿฅณ Ushindi!"],
}
_WRONG = {
    "en":  ["Almost! Give it another try ๐Ÿ’ช","Not quite โ€” you can do it! ๐ŸŒˆ",
             "Good try! Think again ๐Ÿค”","Keep going โ€” try once more! ๐Ÿ’ซ"],
    "fr":  ["Presque ! Essaie encore ๐Ÿ’ช","Pas tout ร  fait โ€” tu peux le faire ! ๐ŸŒˆ",
             "Bon essai ! Rรฉflรฉchis encore ๐Ÿค”"],
    "kin": ["Hafi! Gerageza nanone ๐Ÿ’ช","Ntabwo ari byo โ€” gerageza! ๐ŸŒˆ","Gerageza nanone! ๐Ÿค”"],
    "sw":  ["Karibu! Jaribu tena ๐Ÿ’ช","Si sahihi โ€” unaweza! ๐ŸŒˆ","Jaribu tena! ๐Ÿค”"],
}

_sdk_checked = False
_sdk_ok      = False

def _check_sdk():
    global _sdk_checked, _sdk_ok
    if _sdk_checked:
        return _sdk_ok
    _sdk_checked = True
    try:
        import anthropic  # type: ignore  # noqa
        _sdk_ok = bool(os.environ.get("ANTHROPIC_API_KEY"))
    except ImportError:
        pass
    return _sdk_ok

def _llm_feedback(is_correct, answer, lang, child_text) -> Optional[str]:
    if not _check_sdk():
        return None
    try:
        import anthropic  # type: ignore
        client = anthropic.Anthropic()
        outcome = "correct" if is_correct else "incorrect"
        msg = client.messages.create(
            model="claude-haiku-4-5-20251001", max_tokens=60,
            messages=[{"role":"user","content":
                f"You are a warm math tutor for a child aged 5-9. "
                f"Child answered '{child_text}', correct answer is {answer}, "
                f"their answer was {outcome}. Reply in language '{lang}' "
                f"with ONE short encouraging sentence (max 12 words)."}])
        return msg.content[0].text.strip()
    except Exception:
        return None

def generate_feedback(is_correct: bool, answer: int,
                      lang: str = "en", child_text: str = "") -> str:
    llm = _llm_feedback(is_correct, answer, lang, child_text)
    if llm:
        return llm
    bank = _CORRECT if is_correct else _WRONG
    return random.choice(bank.get(lang, bank["en"]))