From c9e796da158cff65f1f111f1ae26f921e0f9b31b Mon Sep 17 00:00:00 2001 From: Pothan Date: Sat, 26 Sep 2026 03:15:15 -0500 Subject: [PATCH 1/9] Fix MUVERA encoding for empty documents --- fastembed/postprocess/muvera.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fastembed/postprocess/muvera.py b/fastembed/postprocess/muvera.py index 3c6476795..e41e29c38 100644 --- a/fastembed/postprocess/muvera.py +++ b/fastembed/postprocess/muvera.py @@ -283,6 +283,11 @@ def process( vectors.shape[1] == self.dim ), f"Expected vectors of shape (n, {self.dim}), got {vectors.shape}" + # An empty document has no cluster to fill from; match the zero encoding + # already produced for an empty query. + if len(vectors) == 0: + return np.zeros(self.embedding_size) + # Store results from each random projection output_vectors = [] From 6758e3da72ca1608898a187d503588ee697e5b50 Mon Sep 17 00:00:00 2001 From: Pothan Date: Sat, 26 Sep 2026 03:16:49 -0500 Subject: [PATCH 2/9] Test MUVERA empty multivector encodings --- tests/test_postprocess.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_postprocess.py b/tests/test_postprocess.py index 82576f115..313b911cd 100644 --- a/tests/test_postprocess.py +++ b/tests/test_postprocess.py @@ -36,3 +36,13 @@ def test_single_input(): fde_query = muvera.process_query(multivector) assert fde_query.shape[0] == muvera.embedding_size assert np.allclose(fde_query[np.nonzero(fde_query)][:3], CANONICAL_QUERY_VALUES) + + +def test_empty_multivector_encodings(): + muvera = Muvera(dim=4, k_sim=2, dim_proj=2, r_reps=3) + empty = np.empty((0, 4)) + + for encode in (muvera.process_document, muvera.process_query): + encoded = encode(empty) + assert encoded.shape == (muvera.embedding_size,) + assert np.count_nonzero(encoded) == 0 From 67b7f4a175fd6874e7c952b09a02f9949089753f Mon Sep 17 00:00:00 2001 From: George Panchuk Date: Sat, 26 Sep 2026 21:20:53 +0700 Subject: [PATCH 3/9] fix: raise on empty vectors in muvera --- fastembed/postprocess/muvera.py | 11 ++++++++--- tests/test_postprocess.py | 10 ---------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/fastembed/postprocess/muvera.py b/fastembed/postprocess/muvera.py index e41e29c38..806cd4adb 100644 --- a/fastembed/postprocess/muvera.py +++ b/fastembed/postprocess/muvera.py @@ -228,6 +228,9 @@ def process_document(self, vectors: NumpyArray) -> NumpyArray: Returns: NumpyArray: Fixed dimensional encodings of shape (r_reps * b * dim_proj,) + + Raises: + ValueError: If the document multivector is empty """ return self.process(vectors, fill_empty_clusters=True, normalize_by_count=True) @@ -243,6 +246,9 @@ def process_query(self, vectors: NumpyArray) -> NumpyArray: Returns: NumpyArray: Fixed dimensional encoding of shape (r_reps * b * dim_proj,) + + Raises: + ValueError: If the query multivector is empty """ return self.process(vectors, fill_empty_clusters=False, normalize_by_count=False) @@ -278,15 +284,14 @@ def process( Raises: AssertionError: If input vectors don't have expected dimensionality + ValueError: If the input multivector is empty """ assert ( vectors.shape[1] == self.dim ), f"Expected vectors of shape (n, {self.dim}), got {vectors.shape}" - # An empty document has no cluster to fill from; match the zero encoding - # already produced for an empty query. if len(vectors) == 0: - return np.zeros(self.embedding_size) + raise ValueError("Cannot encode an empty multivector") # Store results from each random projection output_vectors = [] diff --git a/tests/test_postprocess.py b/tests/test_postprocess.py index 313b911cd..82576f115 100644 --- a/tests/test_postprocess.py +++ b/tests/test_postprocess.py @@ -36,13 +36,3 @@ def test_single_input(): fde_query = muvera.process_query(multivector) assert fde_query.shape[0] == muvera.embedding_size assert np.allclose(fde_query[np.nonzero(fde_query)][:3], CANONICAL_QUERY_VALUES) - - -def test_empty_multivector_encodings(): - muvera = Muvera(dim=4, k_sim=2, dim_proj=2, r_reps=3) - empty = np.empty((0, 4)) - - for encode in (muvera.process_document, muvera.process_query): - encoded = encode(empty) - assert encoded.shape == (muvera.embedding_size,) - assert np.count_nonzero(encoded) == 0 From fa6f1a3d5b9a03769992a735ca46f848c11d52c2 Mon Sep 17 00:00:00 2001 From: Pothan Date: Sat, 26 Sep 2026 09:43:44 -0500 Subject: [PATCH 4/9] Test ValueError for empty MUVERA inputs --- tests/test_postprocess.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_postprocess.py b/tests/test_postprocess.py index 82576f115..695a9f4ef 100644 --- a/tests/test_postprocess.py +++ b/tests/test_postprocess.py @@ -1,4 +1,5 @@ import numpy as np +import pytest from fastembed import LateInteractionTextEmbedding from fastembed.postprocess import Muvera @@ -36,3 +37,12 @@ def test_single_input(): fde_query = muvera.process_query(multivector) assert fde_query.shape[0] == muvera.embedding_size assert np.allclose(fde_query[np.nonzero(fde_query)][:3], CANONICAL_QUERY_VALUES) + + +@pytest.mark.parametrize("method", ["process_document", "process_query"]) +def test_empty_multivectors_raise_value_error(method): + muvera = Muvera(dim=4, k_sim=2, dim_proj=2, r_reps=3) + empty = np.empty((0, 4)) + + with pytest.raises(ValueError, match="Cannot encode an empty multivector"): + getattr(muvera, method)(empty) From 0c8fc4a5553f44a9bc6175a4f8b9cadc587d6443 Mon Sep 17 00:00:00 2001 From: George Date: Sat, 26 Sep 2026 22:41:57 +0700 Subject: [PATCH 5/9] replace getattr with explicit calls in tests Updated error messages for empty inputs in tests. --- tests/test_postprocess.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_postprocess.py b/tests/test_postprocess.py index 695a9f4ef..33543a0cd 100644 --- a/tests/test_postprocess.py +++ b/tests/test_postprocess.py @@ -44,5 +44,9 @@ def test_empty_multivectors_raise_value_error(method): muvera = Muvera(dim=4, k_sim=2, dim_proj=2, r_reps=3) empty = np.empty((0, 4)) - with pytest.raises(ValueError, match="Cannot encode an empty multivector"): - getattr(muvera, method)(empty) + with pytest.raises(ValueError, match="Cannot encode an empty document"): + muvera.process_document(empty) + + with pytest.raises(ValueError, match="Cannot encode an empty query"): + muvera.process_query(empty) + From 38767d71ac4c854e25df04975552bf201424b9e0 Mon Sep 17 00:00:00 2001 From: George Date: Sat, 26 Sep 2026 22:44:38 +0700 Subject: [PATCH 6/9] remove redundant fixture --- tests/test_postprocess.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_postprocess.py b/tests/test_postprocess.py index 33543a0cd..73fc4146b 100644 --- a/tests/test_postprocess.py +++ b/tests/test_postprocess.py @@ -39,8 +39,7 @@ def test_single_input(): assert np.allclose(fde_query[np.nonzero(fde_query)][:3], CANONICAL_QUERY_VALUES) -@pytest.mark.parametrize("method", ["process_document", "process_query"]) -def test_empty_multivectors_raise_value_error(method): +def test_empty_multivectors_raise_value_error(): muvera = Muvera(dim=4, k_sim=2, dim_proj=2, r_reps=3) empty = np.empty((0, 4)) From c7e3ae5025c69736a32fe95ce18043fe04fe332f Mon Sep 17 00:00:00 2001 From: George Date: Sat, 26 Sep 2026 22:45:00 +0700 Subject: [PATCH 7/9] remove unused import --- tests/test_postprocess.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_postprocess.py b/tests/test_postprocess.py index 73fc4146b..4b95d3095 100644 --- a/tests/test_postprocess.py +++ b/tests/test_postprocess.py @@ -1,5 +1,4 @@ import numpy as np -import pytest from fastembed import LateInteractionTextEmbedding from fastembed.postprocess import Muvera From d4f493cf45c5b242cca357609967e618f10b05e3 Mon Sep 17 00:00:00 2001 From: George Date: Sat, 26 Sep 2026 23:01:41 +0700 Subject: [PATCH 8/9] pytest import is actually required --- tests/test_postprocess.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_postprocess.py b/tests/test_postprocess.py index 4b95d3095..73fc4146b 100644 --- a/tests/test_postprocess.py +++ b/tests/test_postprocess.py @@ -1,4 +1,5 @@ import numpy as np +import pytest from fastembed import LateInteractionTextEmbedding from fastembed.postprocess import Muvera From 5c1e5db90a189644630cfb1de057eddd5f014f03 Mon Sep 17 00:00:00 2001 From: George Date: Sat, 26 Sep 2026 23:03:02 +0700 Subject: [PATCH 9/9] fix exception match message --- tests/test_postprocess.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_postprocess.py b/tests/test_postprocess.py index 73fc4146b..3dc80d411 100644 --- a/tests/test_postprocess.py +++ b/tests/test_postprocess.py @@ -43,9 +43,9 @@ def test_empty_multivectors_raise_value_error(): muvera = Muvera(dim=4, k_sim=2, dim_proj=2, r_reps=3) empty = np.empty((0, 4)) - with pytest.raises(ValueError, match="Cannot encode an empty document"): + with pytest.raises(ValueError, match="Cannot encode an empty multivector"): muvera.process_document(empty) - with pytest.raises(ValueError, match="Cannot encode an empty query"): + with pytest.raises(ValueError, match="Cannot encode an empty multivector"): muvera.process_query(empty)