BuddyMath / math_intent_detector.py
dotandru's picture
Fix: Clean production deployment with sse-starlette
9d29c62
Raw
History Blame Contribute Delete
5.51 kB
# math_intent_detector.py - V4.2 (Intent Lockdown)
# Rigidly classifies user intent before mathematical planning.
import re
import logging
logger = logging.getLogger(__name__)
# Rigid intent categories
INTENT_SIMPLE_LINEAR = "SIMPLE_LINEAR_SOLVE"
INTENT_WORD_PROBLEM_BASIC = "WORD_PROBLEM_BASIC"
INTENT_FUNCTION_ANALYSIS = "FUNCTION_ANALYSIS"
INTENT_SYSTEM_EQUATIONS = "SYSTEM_EQUATIONS"
INTENT_GENERAL = "GENERAL"
# V286.0: New intent categories for 5-unit math coverage
INTENT_VECTORS_3D = "VECTORS_3D"
INTENT_SOLID_GEOMETRY = "SOLID_GEOMETRY"
INTENT_OPTIMIZATION = "OPTIMIZATION"
INTENT_PROBABILITY = "PROBABILITY"
INTENT_TRIGONOMETRY = "TRIGONOMETRY"
INTENT_LOGARITHMS = "LOGARITHMS"
INTENT_LIMITS = "LIMITS"
def detect_intent(text: str, grade_num: int) -> str:
"""
Detects the rigid intent category based on keywords and grade boundaries.
Focuses on 'Simplifying' intent for lower grades.
"""
text_lower = text.lower()
# 1. Simple Linear Solve (Grade 7 focus)
# Check for basic algebra keywords and lack of complex concepts
simple_linear_keywords = ["x=", "驻转讜专", "诪砖讜讜讗讛", "谞注诇诐"]
is_simple_algebra = any(kw in text_lower for kw in simple_linear_keywords)
# Exclusion markers for simple intent
complex_markers = ["谞讙讝专转", "拽讬爪讜谉", "诪注专讻转", "砖谞讬 谞注诇诪讬诐", "x^2", "x虏"]
has_complex_content = any(cm in text_lower for cm in complex_markers)
if grade_num == 7 and is_simple_algebra and not has_complex_content:
print("馃幆 [INTENT] Classified as SIMPLE_LINEAR_SOLVE (Grade 7 Lockdown)")
return INTENT_SIMPLE_LINEAR
# 2. Word Problem Basic
word_problem_keywords = ["讘注讬讛", "诪讬诇讜诇讬转", "拽谞讛", "诪讞讬专", "住讱 讛讻诇"]
if any(kw in text_lower for kw in word_problem_keywords):
print("馃幆 [INTENT] Classified as WORD_PROBLEM_BASIC")
return INTENT_WORD_PROBLEM_BASIC
# 3. System of Equations
if "诪注专讻转" in text_lower or "砖谞讬 谞注诇诪讬诐" in text_lower:
print("馃幆 [INTENT] Classified as SYSTEM_EQUATIONS")
return INTENT_SYSTEM_EQUATIONS
# 4. Function Analysis
function_markers = ["谞讙讝专转", "拽讬爪讜谉", "讞拽讬专讛", "驻讜谞拽爪讬讛", "f(x)"]
if any(fm in text_lower for fm in function_markers):
print("馃幆 [INTENT] Classified as FUNCTION_ANALYSIS")
return INTENT_FUNCTION_ANALYSIS
# V286.0: 5-unit intent categories
# 5. Vectors 3D
if any(kw in text_lower for kw in ["讜拽讟讜专", "讜拽讟讜专讬诐", "诪讻驻诇讛 住拽诇专讬转", "诪讻驻诇讛 讜拽讟讜专讬转"]):
if any(kw in text_lower for kw in ["诪专讞讘", "诪讬砖讜专", "转诇转", "z"]):
print("馃幆 [INTENT] Classified as VECTORS_3D")
return INTENT_VECTORS_3D
# 6. Solid Geometry
if any(kw in text_lower for kw in ["驻讬专诪讬讚讛", "诪谞住专讛", "转讬讘讛", "讞转讱", "讗驻讜转诐", "驻讗讜转"]):
print("馃幆 [INTENT] Classified as SOLID_GEOMETRY")
return INTENT_SOLID_GEOMETRY
# 7. Optimization
if any(kw in text_lower for kw in ["诪拽住讬诪讜诐", "诪讬谞讬诪讜诐", "诪拽住讬诪诇讬", "诪讬谞讬诪诇讬", "注专讱 诪专讘讬", "注专讱 诪讝注专讬", "砖讟讞 讙讚讜诇 讘讬讜转专", "谞驻讞 诪拽住讬诪诇讬"]):
print("馃幆 [INTENT] Classified as OPTIMIZATION")
return INTENT_OPTIMIZATION
# 8. Probability
if any(kw in text_lower for kw in ["讛住转讘专讜转", "拽讜诪讘讬谞讟讜专", "转诪讜专讛", "爪讬专讜祝", "讘讬讬住"]):
print("馃幆 [INTENT] Classified as PROBABILITY")
return INTENT_PROBABILITY
# 9. Trigonometry
if any(kw in text_lower for kw in ["sin", "cos", "tan", "讟专讬讙讜谞讜诪讟专", "住讬谞讜住", "拽讜住讬谞讜住"]):
print("馃幆 [INTENT] Classified as TRIGONOMETRY")
return INTENT_TRIGONOMETRY
# 10. Logarithms
if any(kw in text_lower for kw in ["诇讜讙专讬转诐", "log", "ln", "诪注专讬讻讬"]):
print("馃幆 [INTENT] Classified as LOGARITHMS")
return INTENT_LOGARITHMS
# 11. Limits
if any(kw in text_lower for kw in ["讙讘讜诇", "lim", "砖讜讗祝", "诇讜驻讬讟诇"]):
print("馃幆 [INTENT] Classified as LIMITS")
return INTENT_LIMITS
def _extract_grade_number(text: str) -> int:
import re
# 诪讞诇抓 诪住驻专 诪转讜讱 诪讞专讜谞讛 (诇诪砖诇 "讝壮" 讗讜 "讻讬转讛 7")
match = re.search(r'\d+', text)
if match:
return int(match.group())
# 诪讬驻讜讬 讬讚谞讬 诇诪拽专讬诐 砖诇 讗讜转讬讜转
mapping = {'讝': 7, '讞': 8, '讟': 9, '讬': 10, '讬讗': 11, '讬讘': 12}
for char, num in mapping.items():
if char in text:
return num
return -1
def get_intent_contract(intent: str, grade_num: int) -> dict:
"""
Returns the 'Action Contract' for the given intent.
This contract is used to constrain the LLM/Solver.
"""
if intent == INTENT_SIMPLE_LINEAR and grade_num == 7:
return {
"max_variables": 1,
"allowed_operators": ["ADD", "SUB", "MUL", "DIV"],
"forbidden_strategies": ["DERIVATIVES", "SYSTEM_OF_EQUATIONS", "COMPLEX_SUBSTITUTION"],
"variable_preference": "x",
"narrative_tone": "simple_step_by_step"
}
if intent == INTENT_WORD_PROBLEM_BASIC:
return {
"max_variables": 2 if grade_num > 8 else 1,
"focus": "translation_to_algebra",
"forbidden_strategies": ["CALCULUS"]
}
return {"status": "unconstrained"}