File size: 4,207 Bytes
9d29c62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# domain/curriculum_classifier.py
import sympy as sp
import logging

logger = logging.getLogger(__name__)

class CurriculumClassifier:
    """
    V6.1 Hybrid Architecture - Phase 1: Router Layer
    Evaluates math complexity and injects grade-specific pedagogical prompts.
    """
    
    @staticmethod
    def estimate_complexity(math_string: str) -> int:
        """
        Calculates a complexity score (1-10) based on AST features.
        """
        score = 1
        try:
            # Parse multiple equations if necessary
            expressions = []
            
            # Helper to quickly strip common LaTeX that crashes sympify
            import re
            cleaned_str = re.sub(r'\\[a-zA-Z]+', '', str(math_string))
            cleaned_str = cleaned_str.replace('{', '(').replace('}', ')').replace('$', '')
            
            for part in cleaned_str.split(','):
                expressions.append(sp.sympify(part.replace('=', '-'), evaluate=False))
                
            for expr in expressions:
                # Number of variables
                vars_count = len(expr.free_symbols)
                if vars_count > 1:
                    score += vars_count
                
                # Number of operations / tree depth mapping (approx)
                ops_count = expr.count_ops()
                score += ops_count // 3
                
                # Advanced functions (Trigonometry, Logarithms)
                if expr.has(sp.sin, sp.cos, sp.tan, sp.log, sp.exp):
                    score += 3
                    
                # High degree polynomials
                if expr.is_polynomial():
                    degrees = sp.degree_list(expr)
                    max_deg = max(degrees) if degrees else 0
                    if max_deg > 2:
                        score += 2
                        
        except Exception as e:
            # Fallback heuristic if SymPy parse fails entirely
            raw_len = len(str(math_string))
            fallback_score = 3 + (raw_len // 15)
            logger.warning(f"Complexity estimation failed, falling back to len heuristic ({fallback_score}): {e}")
            score = fallback_score

            
        final_score = min(max(int(score), 1), 10)
        logger.info(f"[ROUTER] Intended Math Complexity Score: {final_score}/10")
        return final_score

    @staticmethod
    def get_prompt_specialization(grade: str, intent_category: str) -> str:
        """
        Returns pedagogical prompt constraints based on the student's grade.
        """
        grade_num = 0
        import re
        match = re.search(r'\d+', str(grade))
        if match:
            grade_num = int(match.group())
            
        constraints = []
        
        # Base setup
        constraints.append("讗转讛 诪讜专讛 驻专讟讬 诇诪转诪讟讬拽讛.")
        
        # Grade specific logic
        if grade_num <= 7:
            constraints.append("讛住讘专 讘诪讜谞讞讬诐 驻砖讜讟讬诐 诪讗讜讚. 讗诇 转砖转诪砖 讘诪讬诇讬诐 讻诪讜 '谞讘讜讚讚' 讗讜 '谞驻砖讟', 讗诇讗 '谞砖讗讬专 讗转 讛谞注诇诐 诇讘讚' 讗讜 '谞讞砖讘 讗转 讛诪住驻专讬诐'.")
        elif grade_num <= 9:
            constraints.append("讛砖转诪砖 讘诪讜谞讞讬 讗诇讙讘专讛 转拽谞讬讬诐 讻诪讜 '讛注讘专转 讗讙驻讬诐', '讻讬谞讜住 讗讬讘专讬诐 讚讜诪讬诐', 讜'讘讬讚讜讚 诪砖转谞讛'. 砖诪讜专 注诇 砖驻讛 诪注讜讚讚转.")
        elif grade_num <= 12:
            constraints.append("讛谞讞 讻讬 讛转诇诪讬讚 诪讻讬专 诪讜砖讙讬 讬住讜讚 讘讗诇讙讘专讛. 讛转诪拽讚 讘讛讬讙讬讜谉 讛注诪讜拽 砖诇 讛转专讙讬诇 讜讘讞讜拽讬诐 讛诪转诪讟讬讬诐 (诇诪砖诇 讞讜拽讬 讞讝拽讜转, 讝讛讜讬讜转). 讛讬讬讛 专砖诪讬 讜诪讚讜讬拽.")
            if "TRIGONOMETRY" in intent_category.upper():
                constraints.append("讘诪砖讜讜讗讜转 讟专讬讙讜谞讜诪讟专讬讜转, 讛讘讛专 转诪讬讚 讗转 砖讬拽讜诇讬 讛诪讞讝讜专讬讜转 讗讜 诪注讙诇 讛讬讞讬讚讛.")
        else:
            constraints.append("讛住讘专 讘讘讛讬专讜转 讜讘爪讜专讛 讬砖讬专讛.")
            
        specialization = " ".join(constraints)
        logger.info(f"[ROUTER] Prompt specialization applied for Grade {grade} ({intent_category})")
        return specialization