diff --git a/src/rai_s2s/rai_s2s/asr/models/open_wake_word.py b/src/rai_s2s/rai_s2s/asr/models/open_wake_word.py index 21c64b20f..ee87d873a 100644 --- a/src/rai_s2s/rai_s2s/asr/models/open_wake_word.py +++ b/src/rai_s2s/rai_s2s/asr/models/open_wake_word.py @@ -59,6 +59,11 @@ def __init__(self, wake_word_model_path: str, threshold: float = 0.1): """ super(OpenWakeWord, self).__init__() self.model_name = "open_wake_word" + if not isinstance(threshold, (int, float)) or isinstance(threshold, bool): + raise ValueError("threshold must be a number in (0, 1]") + if not (0.0 < float(threshold) <= 1.0) or threshold != threshold: + raise ValueError("threshold must be in (0, 1]") + self.threshold = float(threshold) download_models() self.model = OWWModel( wakeword_models=[ @@ -66,7 +71,6 @@ def __init__(self, wake_word_model_path: str, threshold: float = 0.1): ], inference_framework="onnx", ) - self.threshold = threshold def detect( self, audio_data: NDArray, input_parameters: dict[str, Any] diff --git a/tests/test_open_wake_word_threshold.py b/tests/test_open_wake_word_threshold.py new file mode 100644 index 000000000..aaa93d61f --- /dev/null +++ b/tests/test_open_wake_word_threshold.py @@ -0,0 +1,34 @@ +# Copyright (C) 2026 Robotec.AI +import pytest + +from rai_s2s.asr.models.open_wake_word import OpenWakeWord + + +def test_open_wake_word_rejects_invalid_threshold(monkeypatch): + monkeypatch.setattr( + "rai_s2s.asr.models.open_wake_word.download_models", lambda: None + ) + + class _Boom: + def __init__(self, *a, **k): + raise AssertionError("OWWModel should not load on bad threshold") + + monkeypatch.setattr("rai_s2s.asr.models.open_wake_word.OWWModel", _Boom) + + for bad in (0, -0.1, 1.1, float("nan"), True): + with pytest.raises(ValueError, match="threshold"): + OpenWakeWord(wake_word_model_path="unused.onnx", threshold=bad) + + +def test_open_wake_word_accepts_valid_threshold(monkeypatch): + monkeypatch.setattr( + "rai_s2s.asr.models.open_wake_word.download_models", lambda: None + ) + + class _Ok: + def __init__(self, *a, **k): + pass + + monkeypatch.setattr("rai_s2s.asr.models.open_wake_word.OWWModel", _Ok) + m = OpenWakeWord(wake_word_model_path="unused.onnx", threshold=0.5) + assert m.threshold == 0.5