File size: 5,821 Bytes
ca95ab5 | 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 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | """
Explanation Generation
Generates natural language explanations for errors found
Provides educational context and learning suggestions
"""
from typing import Dict, Any
def generate_explanation(error: Dict[str, Any]) -> str:
"""
Generate human-readable explanation for an error.
Args:
error: Error dictionary with type, found, correct, step_number, etc.
Returns:
Natural language explanation string (2-3 sentences)
"""
error_type = error.get("type", "unknown")
found = error.get("found", "")
correct = error.get("correct", "")
operation = error.get("operation", "")
step_number = error.get("step_number", 0)
# Extract numbers from found and correct
import re
found_nums = re.findall(r'\d+\.?\d*', found)
correct_nums = re.findall(r'\d+\.?\d*', correct)
# Generate explanation based on error type
if error_type == "calculation_error":
explanation = _explain_arithmetic_error(found, correct, operation, found_nums, correct_nums)
elif error_type == "logical_error":
explanation = _explain_logical_error(error, step_number)
elif error_type == "operation_mismatch":
explanation = _explain_operation_mismatch(error, found, correct)
elif error_type == "semantic_error":
explanation = _explain_semantic_error(error, found, correct)
else:
explanation = _explain_generic_error(found, correct)
# Add learning context
learning_tip = _get_learning_tip(error_type, operation)
if learning_tip:
explanation += f" {learning_tip}"
return explanation
def _explain_arithmetic_error(found: str, correct: str, operation: str, found_nums: list, correct_nums: list) -> str:
"""Explain arithmetic calculation errors."""
if not found_nums or not correct_nums:
return f"You wrote '{found}', but the correct answer is '{correct}'."
try:
found_result = float(found_nums[-1]) if found_nums else 0
correct_result = float(correct_nums[-1]) if correct_nums else 0
if len(found_nums) >= 2:
operand1 = float(found_nums[0])
operand2 = float(found_nums[1])
op_names = {
'+': 'add',
'-': 'subtract',
'*': 'multiply',
'/': 'divide'
}
op_name = op_names.get(operation, 'calculate')
explanation = f"You wrote {found_result}, but {operand1} {operation} {operand2} actually equals {correct_result}. "
if operation == '+':
explanation += f"When you add {operand2} to {operand1}, you get {correct_result}, not {found_result}."
elif operation == '-':
explanation += f"When you subtract {operand2} from {operand1}, you count down: {operand1}, {correct_result}. So {operand1} - {operand2} = {correct_result}, not {found_result}."
elif operation == '*':
explanation += f"When you multiply {operand1} by {operand2}, you get {correct_result}, not {found_result}."
elif operation == '/':
explanation += f"When you divide {operand1} by {operand2}, you get {correct_result}, not {found_result}."
else:
explanation += f"The correct calculation gives {correct_result}, not {found_result}."
return explanation
except:
pass
return f"You wrote '{found}', but the correct answer is '{correct}'."
def _explain_logical_error(error: Dict[str, Any], step_number: int) -> str:
"""Explain logical consistency errors."""
description = error.get("description", "There is a logical inconsistency in your reasoning.")
explanation = f"In step {step_number}, {description.lower()} "
explanation += "This contradicts your earlier statements or creates circular reasoning."
return explanation
def _explain_operation_mismatch(error: Dict[str, Any], found: str, correct: str) -> str:
"""Explain operation mismatch errors."""
description = error.get("description", "The operation doesn't match what you described.")
explanation = f"{description} "
explanation += "Make sure the mathematical operation matches what you're trying to do in the problem."
return explanation
def _explain_semantic_error(error: Dict[str, Any], found: str, correct: str) -> str:
"""Explain semantic inconsistency errors."""
description = error.get("description", "The meaning doesn't match the mathematical expression.")
explanation = f"{description} "
explanation += "Review the step to ensure it follows logically from the previous steps."
return explanation
def _explain_generic_error(found: str, correct: str) -> str:
"""Generic error explanation."""
return f"You wrote '{found}', but the correct answer should be '{correct}'. Please review your calculation."
def _get_learning_tip(error_type: str, operation: str) -> str:
"""Get learning tip based on error type."""
tips = {
"calculation_error": "Try double-checking your arithmetic by working through the problem step by step.",
"logical_error": "Make sure each step follows logically from the previous one and doesn't contradict earlier statements.",
"operation_mismatch": "Before writing the math, think about which operation matches what you're trying to do.",
"semantic_error": "Review how this step connects to the overall problem and previous steps."
}
return tips.get(error_type, "Practice similar problems to improve your understanding.")
|