From fa5a6c6ee9427b8002558e19bf0efedf8b3733a8 Mon Sep 17 00:00:00 2001 From: Rodrigo Lopez Date: Tue, 8 Sep 2026 12:39:57 +0200 Subject: [PATCH] Add pathseer filter strategy for HNSW vector index Weaviate core is adding an adaptive filtered-HNSW search strategy named 'pathseer' (weaviate/weaviate#12137) as a third filterStrategy value alongside 'sweeping' and 'acorn'. Expose it in the client via a new VectorFilterStrategy.PATHSEER enum member. Includes a unit test for serialization and an integration test (gated on server >= 1.40.0) covering creation and runtime updates in both directions. --- integration/test_collection_config.py | 36 +++++++++++++++++++ test/collection/test_config.py | 11 ++++++ .../classes/config_vector_index.py | 2 ++ 3 files changed, 49 insertions(+) diff --git a/integration/test_collection_config.py b/integration/test_collection_config.py index 68f1a0691..9a129e697 100644 --- a/integration/test_collection_config.py +++ b/integration/test_collection_config.py @@ -702,6 +702,42 @@ def test_hnsw_with_rq4c(collection_factory: CollectionFactory) -> None: assert config.vector_index_config.quantizer.training_limit == 10000 +def test_hnsw_with_pathseer_filter_strategy(collection_factory: CollectionFactory) -> None: + dummy = collection_factory("dummy") + if dummy._connection._weaviate_version.is_lower_than(1, 40, 0): + pytest.skip( + "pathseer filter strategy is not supported in Weaviate versions lower than 1.40.0" + ) + + collection = collection_factory( + vector_index_config=Configure.VectorIndex.hnsw( + filter_strategy=wvc.config.VectorFilterStrategy.PATHSEER, + ), + ) + + config = collection.config.get() + assert isinstance(config.vector_index_config, _VectorIndexConfigHNSW) + assert config.vector_index_config.filter_strategy == wvc.config.VectorFilterStrategy.PATHSEER + + collection.config.update( + vector_index_config=Reconfigure.VectorIndex.hnsw( + filter_strategy=wvc.config.VectorFilterStrategy.ACORN, + ), + ) + config = collection.config.get() + assert isinstance(config.vector_index_config, _VectorIndexConfigHNSW) + assert config.vector_index_config.filter_strategy == wvc.config.VectorFilterStrategy.ACORN + + collection.config.update( + vector_index_config=Reconfigure.VectorIndex.hnsw( + filter_strategy=wvc.config.VectorFilterStrategy.PATHSEER, + ), + ) + config = collection.config.get() + assert isinstance(config.vector_index_config, _VectorIndexConfigHNSW) + assert config.vector_index_config.filter_strategy == wvc.config.VectorFilterStrategy.PATHSEER + + @pytest.mark.parametrize( "vector_index_config", [ diff --git a/test/collection/test_config.py b/test/collection/test_config.py index 7ff50c847..f8d952aa9 100644 --- a/test/collection/test_config.py +++ b/test/collection/test_config.py @@ -22,6 +22,7 @@ _VectorizerConfigCreate, _ReplicationConfigCreate, ReplicationDeletionStrategy, + VectorFilterStrategy, ) from weaviate.collections.classes.config_named_vectors import _NamedVectorConfigCreate from weaviate.collections.classes.config_vectorizers import ( @@ -1664,6 +1665,16 @@ def test_vector_config_hnsw_rq4c() -> None: assert vi_dict["rq"]["trainingLimit"] == 5012 +def test_vector_config_hnsw_pathseer_filter_strategy() -> None: + vector_index = Configure.VectorIndex.hnsw( + filter_strategy=VectorFilterStrategy.PATHSEER, + ) + + vi_dict = vector_index._to_dict() + + assert vi_dict["filterStrategy"] == "pathseer" + + def test_vector_config_flat_pq() -> None: vector_index = Configure.VectorIndex.flat( distance_metric=VectorDistances.DOT, diff --git a/weaviate/collections/classes/config_vector_index.py b/weaviate/collections/classes/config_vector_index.py index cc9c74994..4e6ea3cc7 100644 --- a/weaviate/collections/classes/config_vector_index.py +++ b/weaviate/collections/classes/config_vector_index.py @@ -22,10 +22,12 @@ class VectorFilterStrategy(str, Enum): Attributes: SWEEPING: Do normal ANN search and skip nodes. ACORN: Multi-hop search to find new candidates matching the filter. + PATHSEER: Adaptive search that decides per query between sweeping and multi-hop candidate discovery. """ SWEEPING = "sweeping" ACORN = "acorn" + PATHSEER = "pathseer" class VectorIndexType(str, Enum):