diff --git a/sacrebleu/metrics/base.py b/sacrebleu/metrics/base.py index 8aa693a..9db6e7c 100644 --- a/sacrebleu/metrics/base.py +++ b/sacrebleu/metrics/base.py @@ -45,6 +45,9 @@ def format( is_json: bool = False, ) -> str: """Returns a pretty representation of the score. + + Includes a computed confidence interval even when its mean is zero. + :param width: Floating point decimal precision width. :param score_only: If `True`, and the format is not `json`, returns a single score string. @@ -61,7 +64,7 @@ def format( sc = f"{self.score:.{width}f}" - if self._mean > 0: + if self._mean >= 0: confidence_mean = f"{self._mean:.{width}f}" confidence_var = f"{self._ci:.{width}f}" confidence_str = f"μ = {confidence_mean} ± {confidence_var}" diff --git a/test/test_metrics_base.py b/test/test_metrics_base.py index 679ec71..631751f 100644 --- a/test/test_metrics_base.py +++ b/test/test_metrics_base.py @@ -1,8 +1,9 @@ +import json from contextlib import nullcontext as does_not_raise import pytest -from sacrebleu.metrics.base import Metric +from sacrebleu.metrics.base import Metric, Score class ConcreteTestMetric(Metric): @@ -353,3 +354,35 @@ def test_check_corpus_score_args(hyps, refs, expected_context): metric = ConcreteTestMetric() with expected_context: metric._check_corpus_score_args(hyps=hyps, refs=refs) + + +@pytest.mark.parametrize("mean", [0.0, 1.0]) +def test_score_format_confidence_interval(mean): + score = Score("TEST", mean) + score.estimate_ci([score] * 40) + confidence = f"\u03bc = {mean:.2f} \u00b1 0.00" + + assert score.format() == f"TEST = {mean:.2f} ({confidence})" + assert score.format(score_only=True) == f"{mean:.2f} ({confidence})" + assert json.loads(score.format(signature="version:test", is_json=True)) == { + "name": "TEST", + "score": mean, + "signature": "version:test", + "version": "test", + "confidence_mean": mean, + "confidence_var": 0.0, + "confidence": confidence, + } + + +def test_score_format_without_confidence_interval(): + score = Score("TEST", 0.0) + + assert score.format() == "TEST = 0.00" + assert score.format(score_only=True) == "0.00" + assert json.loads(score.format(signature="version:test", is_json=True)) == { + "name": "TEST", + "score": 0.0, + "signature": "version:test", + "version": "test", + }