Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 41 additions & 19 deletions verl/utils/reward_score/math_verify.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,56 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import multiprocessing
import threading
from concurrent.futures import ProcessPoolExecutor
from concurrent.futures import TimeoutError as FuturesTimeoutError

try:
from math_verify.errors import TimeoutException
from math_verify.grader import verify
from math_verify.parser import ExprExtractionConfig, LatexExtractionConfig, parse
except ImportError:

class TimeoutException(Exception):
pass

print("To use Math-Verify, please install it first by running `pip install math-verify`.")
Comment on lines 21 to 27
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

If math_verify is not installed, TimeoutException will not be defined in the global scope. This will lead to a NameError when compute_score attempts to catch it in the except block at line 58. Since this NameError is then caught by the broad except Exception at line 60, the function will silently return 0.0 without any indication of the missing dependency or the underlying error. Defining a placeholder exception ensures the code remains robust even when the package is missing.

Suggested change
from math_verify.errors import TimeoutException
from math_verify.grader import verify
from math_verify.parser import ExprExtractionConfig, LatexExtractionConfig, parse
except ImportError:
print("To use Math-Verify, please install it first by running `pip install math-verify`.")
from math_verify.errors import TimeoutException
except ImportError:
class TimeoutException(Exception):
pass
print("To use Math-Verify, please install it first by running pip install math-verify.")


_GOLD_TARGETS = (LatexExtractionConfig(),)
_PRED_TARGETS = (ExprExtractionConfig(), LatexExtractionConfig())
_pool = None
_pool_lock = threading.Lock()


def compute_score(model_output: str, ground_truth: str, timeout_score: float = 0) -> float:
ret_score = 0.0
def _get_pool():
global _pool
if _pool is None:
with _pool_lock:
if _pool is None:
_pool = ProcessPoolExecutor(max_workers=4, mp_context=multiprocessing.get_context("spawn"))
return _pool

# Wrap the ground truth in \boxed{} format for verification

def _verify_in_subprocess(ground_truth_boxed: str, model_output: str) -> float:
"""Run math_verify in a subprocess where signal.alarm() works."""
from math_verify.grader import verify
from math_verify.parser import ExprExtractionConfig, LatexExtractionConfig, parse

gold_targets = (LatexExtractionConfig(),)
pred_targets = (ExprExtractionConfig(), LatexExtractionConfig())

extracted_gold = parse(ground_truth_boxed, gold_targets)
extracted_pred = parse(model_output, pred_targets)
if extracted_gold and extracted_pred:
return max(1.0 if any(verify(g, p) for g in extracted_gold) else 0.0 for p in extracted_pred)
return 0.0


def compute_score(model_output: str, ground_truth: str, timeout_score: float = 0, timeout: float = 30.0) -> float:
ret_score = 0.0
ground_truth_boxed = "\\boxed{" + ground_truth + "}"
try:
# Use parsing_timeout=None and timeout_seconds=None to disable
# signal.alarm() which crashes in non-main threads (Ray workers).
extracted_gold = parse(ground_truth_boxed, _GOLD_TARGETS, parsing_timeout=None)
extracted_pred = parse(model_output, _PRED_TARGETS, parsing_timeout=None)
if extracted_gold and extracted_pred:
ret_score = max(
1.0 if any(verify(g, p, timeout_seconds=None) for g in extracted_gold) else 0.0 for p in extracted_pred
)
except TimeoutException:
future = _get_pool().submit(_verify_in_subprocess, ground_truth_boxed, model_output)
ret_score = future.result(timeout=timeout)
except (FuturesTimeoutError, TimeoutException):
ret_score = timeout_score
except Exception:
pass

except Exception as e:
print(f"Error in math_verify compute_score: {e}")
return ret_score
Loading