From 5c8f7a5397369fc335c3a878434d722c91b99d66 Mon Sep 17 00:00:00 2001 From: Mohamed Shahin Date: Mon, 24 Aug 2026 10:36:10 +0100 Subject: [PATCH] fix: update quantizer keyerror --- test/collection/test_config_update.py | 70 ++++++++++++++++++++++++++ weaviate/collections/classes/config.py | 6 +-- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/test/collection/test_config_update.py b/test/collection/test_config_update.py index 680337291..066d4ecb3 100644 --- a/test/collection/test_config_update.py +++ b/test/collection/test_config_update.py @@ -160,3 +160,73 @@ def test_replication_async_config_reset_all_fields() -> None: ) result = update.merge_with_existing(schema) assert result["asyncConfig"] == {} + + +def _hfresh_schema(rescore_limit: int = 20) -> dict: + """An HFresh schema, which mandates RQ and so carries no pq/bq/sq blocks.""" + return { + "class": "HFreshRQ", + "vectorConfig": { + "boi": { + "vectorizer": {"text2vec-weaviate": {}}, + "vectorIndexType": "hfresh", + "vectorIndexConfig": { + "distance": "cosine", + "maxPostingSizeKB": 1024, + "searchProbe": 8, + "rq": {"enabled": True, "bits": 1, "rescoreLimit": rescore_limit}, + }, + } + }, + } + + +def test_updating_rq_on_hfresh_without_pq_block() -> None: + """An HFresh schema has no pq block, so the quantizer check must not subscript it.""" + schema = _hfresh_schema() + update = _CollectionConfigUpdate( + vector_config=Reconfigure.Vectors.update( + name="boi", + vector_index_config=Reconfigure.VectorIndex.hfresh( + quantizer=Reconfigure.VectorIndex.Quantizer.rq(rescore_limit=500) + ), + ) + ) + + new_schema = update.merge_with_existing(schema) + + assert new_schema["vectorConfig"]["boi"]["vectorIndexConfig"]["rq"]["rescoreLimit"] == 500 + assert new_schema["vectorConfig"]["boi"]["vectorIndexConfig"]["rq"]["enabled"] + + +def test_quantizer_check_tolerates_missing_pq_block() -> None: + """The rq branch of the quantizer check must tolerate a schema with no pq block.""" + schema = _hfresh_schema() + update = _CollectionConfigUpdate( + vector_config=Reconfigure.Vectors.update( + name="boi", + vector_index_config=Reconfigure.VectorIndex.hfresh( + quantizer=Reconfigure.VectorIndex.Quantizer.rq() + ), + ) + ) + + # No KeyError: rq is the quantizer already in use, so the update is allowed through. + update.merge_with_existing(schema) + + +def test_switching_quantizer_still_rejected_when_pq_enabled() -> None: + """The guard itself must be unchanged for schemas that do have a pq block.""" + schema = multi_vector_schema("pq") + update = _CollectionConfigUpdate( + vectorizer_config=[ + Reconfigure.NamedVectors.update( + name="boi", + vector_index_config=Reconfigure.VectorIndex.hnsw( + quantizer=Reconfigure.VectorIndex.Quantizer.rq() + ), + ) + ] + ) + with pytest.raises(WeaviateInvalidInputError): + update.merge_with_existing(schema) diff --git a/weaviate/collections/classes/config.py b/weaviate/collections/classes/config.py index 13298be40..e9effaf15 100644 --- a/weaviate/collections/classes/config.py +++ b/weaviate/collections/classes/config.py @@ -1563,7 +1563,7 @@ def __check_quantizers( or ( isinstance(quantizer, _BQConfigUpdate) and ( - vector_index_config["pq"]["enabled"] + vector_index_config.get("pq", {"enabled": False})["enabled"] or vector_index_config.get("sq", {"enabled": False})["enabled"] or vector_index_config.get("rq", {"enabled": False})["enabled"] ) @@ -1571,7 +1571,7 @@ def __check_quantizers( or ( isinstance(quantizer, _SQConfigUpdate) and ( - vector_index_config["pq"]["enabled"] + vector_index_config.get("pq", {"enabled": False})["enabled"] or vector_index_config.get("bq", {"enabled": False})["enabled"] or vector_index_config.get("rq", {"enabled": False})["enabled"] ) @@ -1579,7 +1579,7 @@ def __check_quantizers( or ( isinstance(quantizer, _RQConfigUpdate) and ( - vector_index_config["pq"]["enabled"] + vector_index_config.get("pq", {"enabled": False})["enabled"] or vector_index_config.get("bq", {"enabled": False})["enabled"] or vector_index_config.get("sq", {"enabled": False})["enabled"] )