From b2893945520e2ffa91cdca2e78213f8af73c5cea Mon Sep 17 00:00:00 2001 From: morluto <76467478+morluto@users.noreply.github.com> Date: Tue, 14 Jul 2026 04:41:35 +0000 Subject: [PATCH 1/2] Fix DAPO integer ground-truth normalization --- slime/rollout/rm_hub/math_dapo_utils.py | 20 ++++++++++------- tests/test_rm_math_dapo.py | 29 ++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 11 deletions(-) diff --git a/slime/rollout/rm_hub/math_dapo_utils.py b/slime/rollout/rm_hub/math_dapo_utils.py index 915c3aa480..35f58ab71c 100644 --- a/slime/rollout/rm_hub/math_dapo_utils.py +++ b/slime/rollout/rm_hub/math_dapo_utils.py @@ -15,6 +15,7 @@ import re import signal +from decimal import Decimal, InvalidOperation def last_boxed_only_string(string: str) -> str | None: @@ -63,7 +64,6 @@ def remove_boxed(s: str) -> str: class timeout: - def __init__(self, seconds=1, error_message="Timeout"): self.seconds = seconds self.error_message = error_message @@ -182,9 +182,7 @@ def normalize_final_answer(final_answer: str) -> str: return final_answer.strip() -def is_correct_minerva( - solution_str: str, gt: str, gt_need_extract: bool = False, answer_pattern: str = r"(?i)Answer\s*:\s*([^\n]+)" -) -> tuple[bool, str]: +def is_correct_minerva(solution_str: str, gt: str, gt_need_extract: bool = False, answer_pattern: str = r"(?i)Answer\s*:\s*([^\n]+)") -> tuple[bool, str]: """Check if the solution is correct according to Minerva criteria. Args: @@ -207,7 +205,15 @@ def is_correct_minerva( else: gt = normalize_final_answer(gt) - gt = str(int(float(gt))) # in dapo, all answers are integers + try: + numeric_gt = Decimal(gt) + except InvalidOperation as exc: + raise ValueError(f"DAPO ground-truth label must be an integer, got {gt!r}") from exc + + if not numeric_gt.is_finite() or numeric_gt != numeric_gt.to_integral_value(): + raise ValueError(f"DAPO ground-truth label must be an integer, got {gt!r}") + + gt = str(int(numeric_gt)) return (pred == gt), pred @@ -237,9 +243,7 @@ def is_correct_strict_box(pred: str, gt: str, pause_tokens_index: list[int] | No return 1 if (extracted_pred == gt) else -1, extracted_pred -def verify( - solution_str: str, answer: str, strict_box_verify: bool = False, pause_tokens_index: list[int] | None = None -) -> bool: +def verify(solution_str: str, answer: str, strict_box_verify: bool = False, pause_tokens_index: list[int] | None = None) -> bool: """Verify if the solution is correct. Args: diff --git a/tests/test_rm_math_dapo.py b/tests/test_rm_math_dapo.py index 3a5e9a28b9..9d241b34ce 100644 --- a/tests/test_rm_math_dapo.py +++ b/tests/test_rm_math_dapo.py @@ -153,14 +153,37 @@ def test_is_correct_strict_box_no_box_returns_minus_one(): @pytest.mark.unit def test_is_correct_minerva_matches_int_answer(): - """Minerva path expects gt to coerce via ``int(float(gt))`` (line 210), - so floats / int-strings collapse to canonical int strings before - comparison.""" correct, pred = is_correct_minerva("Long solution. Answer: 42", "42") assert correct is True assert pred == "42" +@pytest.mark.unit +@pytest.mark.parametrize("ground_truth", ["42.0", "4.2e1"]) +def test_is_correct_minerva_accepts_integral_numeric_labels(ground_truth): + correct, pred = is_correct_minerva("Answer: 42", ground_truth) + assert correct is True + assert pred == "42" + + +@pytest.mark.unit +def test_is_correct_minerva_preserves_large_integer_precision(): + ground_truth = "9007199254740993" + correct, pred = is_correct_minerva(f"Answer: {ground_truth}", ground_truth) + assert correct is True + assert pred == ground_truth + + +@pytest.mark.unit +@pytest.mark.parametrize("ground_truth", ["0.5", "1/2", "1+2", "NaN", "Infinity"]) +def test_is_correct_minerva_rejects_non_integer_labels(ground_truth): + with pytest.raises( + ValueError, + match="DAPO ground-truth label must be an integer", + ): + is_correct_minerva("Answer: 0", ground_truth) + + @pytest.mark.unit def test_is_correct_minerva_takes_last_answer_match(): """Multiple ``Answer:`` lines → ``re.findall`` returns the list and From 5e345add05d4302608860da6cd30a4ffd0eda512 Mon Sep 17 00:00:00 2001 From: morluto <76467478+morluto@users.noreply.github.com> Date: Tue, 14 Jul 2026 04:53:40 +0000 Subject: [PATCH 2/2] Apply repository formatting to DAPO scorer --- slime/rollout/rm_hub/math_dapo_utils.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/slime/rollout/rm_hub/math_dapo_utils.py b/slime/rollout/rm_hub/math_dapo_utils.py index 35f58ab71c..1cab28ca0a 100644 --- a/slime/rollout/rm_hub/math_dapo_utils.py +++ b/slime/rollout/rm_hub/math_dapo_utils.py @@ -182,7 +182,9 @@ def normalize_final_answer(final_answer: str) -> str: return final_answer.strip() -def is_correct_minerva(solution_str: str, gt: str, gt_need_extract: bool = False, answer_pattern: str = r"(?i)Answer\s*:\s*([^\n]+)") -> tuple[bool, str]: +def is_correct_minerva( + solution_str: str, gt: str, gt_need_extract: bool = False, answer_pattern: str = r"(?i)Answer\s*:\s*([^\n]+)" +) -> tuple[bool, str]: """Check if the solution is correct according to Minerva criteria. Args: @@ -243,7 +245,9 @@ def is_correct_strict_box(pred: str, gt: str, pause_tokens_index: list[int] | No return 1 if (extracted_pred == gt) else -1, extracted_pred -def verify(solution_str: str, answer: str, strict_box_verify: bool = False, pause_tokens_index: list[int] | None = None) -> bool: +def verify( + solution_str: str, answer: str, strict_box_verify: bool = False, pause_tokens_index: list[int] | None = None +) -> bool: """Verify if the solution is correct. Args: