| |
| 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: |
| |
| expressions = [] |
| |
| |
| 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: |
| |
| vars_count = len(expr.free_symbols) |
| if vars_count > 1: |
| score += vars_count |
| |
| |
| ops_count = expr.count_ops() |
| score += ops_count // 3 |
| |
| |
| if expr.has(sp.sin, sp.cos, sp.tan, sp.log, sp.exp): |
| score += 3 |
| |
| |
| 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: |
| |
| 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 = [] |
| |
| |
| constraints.append("讗转讛 诪讜专讛 驻专讟讬 诇诪转诪讟讬拽讛.") |
| |
| |
| 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 |
|
|