From 1f5ae1fc16ff7e908440c0459613d2d39c7d5cad Mon Sep 17 00:00:00 2001 From: Deepanshu Pal <40927968+DeepanshuPal@users.noreply.github.com> Date: Wed, 7 Oct 2026 14:25:35 +0530 Subject: [PATCH 1/4] fix: avoid NumericDiff overflow in Python --- py/autoevals/number.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/py/autoevals/number.py b/py/autoevals/number.py index 408e8bc9..39739024 100644 --- a/py/autoevals/number.py +++ b/py/autoevals/number.py @@ -47,7 +47,10 @@ def _run_eval_sync(self, output, expected=None, **kwargs): if expected == 0 and output == 0: score = 1 else: - score = 1 - abs(expected - output) / (abs(expected) + abs(output)) + # Scale first so finite inputs cannot overflow the difference or sum. + scale = max(abs(expected), abs(output)) + expected_scaled, output_scaled = expected / scale, output / scale + score = 1 - abs(expected_scaled - output_scaled) / (abs(expected_scaled) + abs(output_scaled)) return Score(name=self._name(), score=score) From cff140a5e8f398a410400b346e76a95f314a140a Mon Sep 17 00:00:00 2001 From: Deepanshu Pal <40927968+DeepanshuPal@users.noreply.github.com> Date: Wed, 7 Oct 2026 14:25:52 +0530 Subject: [PATCH 2/4] fix: avoid NumericDiff overflow in TypeScript --- js/number.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/js/number.ts b/js/number.ts index 1034ea83..5e2fa527 100644 --- a/js/number.ts +++ b/js/number.ts @@ -11,11 +11,16 @@ export const NumericDiff: ScorerWithPartial = makePartial( throw new Error("NumericDiff requires an expected value"); } + // Scale first so finite inputs cannot overflow the difference or sum. + const scale = Math.max(Math.abs(expected), Math.abs(output)); + const expectedScaled = scale === 0 ? 0 : expected / scale; + const outputScaled = scale === 0 ? 0 : output / scale; const score = - output === 0 && expected === 0 + scale === 0 ? 1 : 1 - - Math.abs(expected - output) / (Math.abs(expected) + Math.abs(output)); + Math.abs(expectedScaled - outputScaled) / + (Math.abs(expectedScaled) + Math.abs(outputScaled)); return { name: "NumericDiff", From 1e7a98b3677d62b7f4dbbcf1a036981301c1165c Mon Sep 17 00:00:00 2001 From: Deepanshu Pal <40927968+DeepanshuPal@users.noreply.github.com> Date: Wed, 7 Oct 2026 14:26:05 +0530 Subject: [PATCH 3/4] test: cover NumericDiff finite extremes in TypeScript --- js/number.test.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 js/number.test.ts diff --git a/js/number.test.ts b/js/number.test.ts new file mode 100644 index 00000000..907b29e1 --- /dev/null +++ b/js/number.test.ts @@ -0,0 +1,19 @@ +import { describe, expect, test } from "vitest"; +import { NumericDiff } from "./number"; + +describe("NumericDiff finite extremes", () => { + test.each([ + [Number.MAX_VALUE, Number.MAX_VALUE, 1], + [Number.MAX_VALUE, Number.MAX_VALUE / 2, 2 / 3], + [Number.MAX_VALUE, -Number.MAX_VALUE, 0], + [-Number.MAX_VALUE, -Number.MAX_VALUE / 2, 2 / 3], + [1e-320, 1e-320 / 2, 2 / 3], + [0, 0, 1], + [0, Number.MAX_VALUE, 0], + [10, 5, 2 / 3], + ])("output %s and expected %s", async (output, expected, score) => { + const result = await NumericDiff({ output, expected }); + expect(Number.isFinite(result.score)).toBe(true); + expect(result.score).toBeCloseTo(score, 12); + }); +}); From 53b81fbf7cbcff44d6bddaef061b45b9bff2794c Mon Sep 17 00:00:00 2001 From: Deepanshu Pal <40927968+DeepanshuPal@users.noreply.github.com> Date: Wed, 7 Oct 2026 14:26:21 +0530 Subject: [PATCH 4/4] test: cover NumericDiff finite extremes in Python --- py/autoevals/test_number.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 py/autoevals/test_number.py diff --git a/py/autoevals/test_number.py b/py/autoevals/test_number.py new file mode 100644 index 00000000..f48711cf --- /dev/null +++ b/py/autoevals/test_number.py @@ -0,0 +1,25 @@ +import math +import sys + +import pytest + +from autoevals.number import NumericDiff + + +@pytest.mark.parametrize( + "output,expected,score", + [ + (sys.float_info.max, sys.float_info.max, 1), + (sys.float_info.max, sys.float_info.max / 2, 2 / 3), + (sys.float_info.max, -sys.float_info.max, 0), + (-sys.float_info.max, -sys.float_info.max / 2, 2 / 3), + (1e-320, 1e-320 / 2, 2 / 3), + (0, 0, 1), + (0, sys.float_info.max, 0), + (10, 5, 2 / 3), + ], +) +def test_numeric_diff_finite_extremes(output, expected, score): + result = NumericDiff()(output, expected).score + assert math.isfinite(result) + assert result == pytest.approx(score)