File size: 1,733 Bytes
f0975ca | 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 | """Answer checking for generated traces: math via math-verify, MCQ via boxed letter."""
import re
from math_verify import parse, verify
def last_boxed(text):
"""Return the contents of the last \\boxed{...} (brace-balanced), or None."""
start = text.rfind("\\boxed")
if start < 0:
return None
i = text.find("{", start)
if i < 0:
return None
depth = 0
for j in range(i, len(text)):
if text[j] == "{":
depth += 1
elif text[j] == "}":
depth -= 1
if depth == 0:
return text[i + 1 : j]
return None
def check(content, gold, answer_type):
"""Return (is_correct, extracted_prediction)."""
boxed = last_boxed(content or "")
if answer_type == "mcq":
if boxed is None:
return False, None
m = re.search(r"\b([A-J])\b", re.sub(r"\\text\{([^}]*)\}", r"\1", boxed))
pred = m.group(1) if m else boxed.strip()
return pred == gold.strip(), pred
if boxed is None:
return False, None
plain = re.sub(r"\\text\{([^}]*)\}|\\textbf\{([^}]*)\}", r"\1\2", boxed).strip().lower()
if gold.strip().lower() in ("yes", "no", "true", "false"):
first = re.match(r"[a-z]+", plain)
return bool(first) and first.group(0) == gold.strip().lower(), boxed
try:
gold_p = parse(f"${gold}$")
pred_p = parse(f"$\\boxed{{{boxed}}}$")
ok = verify(gold_p, pred_p)
except Exception:
ok = False
if not ok:
# Plain-text answers (Yes/No, words) that math-verify can't parse.
norm = lambda s: re.sub(r"[\s\\{}$.]|\\text|\\mathrm", "", s).lower()
ok = norm(boxed) == norm(gold)
return bool(ok), boxed
|