Skip to content

Commit e75a914

Browse files
authored
Merge pull request #2042 from weaviate/empty_default_vector_index
Send empty vector index type on new Weavaite versions
2 parents f26bee0 + d511d31 commit e75a914

7 files changed

Lines changed: 85 additions & 28 deletions

File tree

.github/workflows/main.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ env:
2828
WEAVIATE_134: 1.34.19
2929
WEAVIATE_135: 1.35.18
3030
WEAVIATE_136: 1.36.12
31-
WEAVIATE_137: 1.37.1-4e61e26.amd64
31+
WEAVIATE_137: 1.37.5-e0fe0d5.amd64
3232

3333
jobs:
3434
lint-and-format:

integration/test_collection_config.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,9 +1025,7 @@ def test_config_export_and_recreate_from_dict(collection_factory: CollectionFact
10251025
Property(name="booleans", data_type=DataType.BOOL_ARRAY),
10261026
Property(name="geo", data_type=DataType.GEO_COORDINATES),
10271027
Property(name="phone", data_type=DataType.PHONE_NUMBER),
1028-
Property(
1029-
name="field_index_searchable", data_type=DataType.TEXT, index_searchable=False
1030-
),
1028+
Property(name="field_searchable_off", data_type=DataType.TEXT, index_searchable=False),
10311029
Property(
10321030
name="field_index_range_filters_false",
10331031
data_type=DataType.INT,
@@ -1054,7 +1052,9 @@ def test_config_export_and_recreate_from_dict(collection_factory: CollectionFact
10541052
tokenization=Tokenization.FIELD,
10551053
),
10561054
Property(
1057-
name="nested_searchable", data_type=DataType.TEXT, index_searchable=False
1055+
name="nested_searchable_off",
1056+
data_type=DataType.TEXT,
1057+
index_searchable=False,
10581058
),
10591059
Property(
10601060
name="nested_filterable", data_type=DataType.TEXT, index_filterable=False
@@ -1598,7 +1598,7 @@ def test_replication_config_with_async_config(collection_factory: CollectionFact
15981598
factor=1,
15991599
async_enabled=True,
16001600
async_config=Configure.Replication.async_config(
1601-
max_workers=8,
1601+
propagation_concurrency=4,
16021602
hashtree_height=20,
16031603
),
16041604
),
@@ -1608,8 +1608,12 @@ def test_replication_config_with_async_config(collection_factory: CollectionFact
16081608
assert config.replication_config.async_enabled is True
16091609
assert config.replication_config.async_config is not None
16101610
ac = config.replication_config.async_config
1611-
assert ac.max_workers == 8
1611+
assert ac.propagation_concurrency == 4
16121612
assert ac.hashtree_height == 20
1613+
if collection._connection._weaviate_version.is_at_least(1, 37, 3):
1614+
# Server removed max_workers / alive_nodes_checking_frequency from the schema in 1.37.3
1615+
assert ac.max_workers is None
1616+
assert ac.alive_nodes_checking_frequency is None
16131617

16141618

16151619
def test_replication_config_remove_async_config_by_disabling_async_replication(
@@ -1624,14 +1628,14 @@ def test_replication_config_remove_async_config_by_disabling_async_replication(
16241628
factor=1,
16251629
async_enabled=True,
16261630
async_config=Configure.Replication.async_config(
1627-
max_workers=8,
1631+
propagation_concurrency=4,
16281632
hashtree_height=20,
16291633
),
16301634
),
16311635
)
16321636
config = collection.config.get()
16331637
assert config.replication_config.async_config is not None
1634-
assert config.replication_config.async_config.max_workers == 8
1638+
assert config.replication_config.async_config.propagation_concurrency == 4
16351639

16361640
collection.config.update(
16371641
replication_config=Reconfigure.replication(
@@ -1653,14 +1657,14 @@ def test_replication_config_remove_async_config(collection_factory: CollectionFa
16531657
factor=1,
16541658
async_enabled=True,
16551659
async_config=Configure.Replication.async_config(
1656-
max_workers=8,
1660+
propagation_concurrency=4,
16571661
hashtree_height=20,
16581662
),
16591663
),
16601664
)
16611665
config = collection.config.get()
16621666
assert config.replication_config.async_config is not None
1663-
assert config.replication_config.async_config.max_workers == 8
1667+
assert config.replication_config.async_config.propagation_concurrency == 4
16641668

16651669
collection.config.update(
16661670
replication_config=Reconfigure.replication(
@@ -1685,29 +1689,29 @@ def test_replication_config_unset_single_async_field(
16851689
factor=1,
16861690
async_enabled=True,
16871691
async_config=Configure.Replication.async_config(
1688-
max_workers=8,
1692+
propagation_concurrency=4,
16891693
hashtree_height=20,
16901694
),
16911695
),
16921696
)
16931697
config = collection.config.get()
16941698
ac = config.replication_config.async_config
16951699
assert ac is not None
1696-
assert ac.max_workers == 8
1700+
assert ac.propagation_concurrency == 4
16971701
assert ac.hashtree_height == 20
16981702

1699-
# Update with only max_workers — hashtree_height reverts to server default
1703+
# Update with only propagation_concurrency — hashtree_height reverts to server default
17001704
collection.config.update(
17011705
replication_config=Reconfigure.replication(
17021706
async_config=Reconfigure.Replication.async_config(
1703-
max_workers=8,
1707+
propagation_concurrency=4,
17041708
),
17051709
),
17061710
)
17071711
config = collection.config.get()
17081712
ac = config.replication_config.async_config
17091713
assert ac is not None
1710-
assert ac.max_workers == 8
1714+
assert ac.propagation_concurrency == 4
17111715
assert ac.hashtree_height != 20
17121716

17131717

@@ -1734,16 +1738,16 @@ def test_replication_config_add_async_config_to_existing_collection(
17341738
collection.config.update(
17351739
replication_config=Reconfigure.replication(
17361740
async_config=Reconfigure.Replication.async_config(
1737-
max_workers=8,
17381741
propagation_concurrency=4,
1742+
hashtree_height=20,
17391743
),
17401744
),
17411745
)
17421746
config = collection.config.get()
17431747
assert config.replication_config.async_config is not None
17441748
ac = config.replication_config.async_config
1745-
assert ac.max_workers == 8
17461749
assert ac.propagation_concurrency == 4
1750+
assert ac.hashtree_height == 20
17471751

17481752

17491753
def test_update_property_descriptions(collection_factory: CollectionFactory) -> None:

weaviate/collections/classes/config.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2473,7 +2473,7 @@ def __add_to_module_config(
24732473
else:
24742474
return_dict["moduleConfig"][addition_key] = addition_val
24752475

2476-
def _to_dict(self) -> Dict[str, Any]:
2476+
def _to_dict(self, *, emit_default_vector_index_type: bool = True) -> Dict[str, Any]:
24772477
ret_dict: Dict[str, Any] = {}
24782478

24792479
for cls_field in type(self).model_fields:
@@ -2494,14 +2494,23 @@ def _to_dict(self) -> Dict[str, Any]:
24942494
ret_dict["vectorIndexType"] = val.vector_index_type().value
24952495
ret_dict[cls_field] = val._to_dict()
24962496
elif isinstance(val, _VectorConfigCreate):
2497-
ret_dict["vectorConfig"] = {val.name or "default": val._to_dict()}
2497+
ret_dict["vectorConfig"] = {
2498+
val.name or "default": val._to_dict(
2499+
emit_default_vector_index_type=emit_default_vector_index_type
2500+
)
2501+
}
24982502
elif (
24992503
isinstance(val, list)
25002504
and len(val) > 0
25012505
and all(isinstance(item, _NamedVectorConfigCreate) for item in val)
25022506
):
25032507
val = cast(List[_NamedVectorConfigCreate], val)
2504-
ret_dict["vectorConfig"] = {item.name: item._to_dict() for item in val}
2508+
ret_dict["vectorConfig"] = {
2509+
item.name: item._to_dict(
2510+
emit_default_vector_index_type=emit_default_vector_index_type
2511+
)
2512+
for item in val
2513+
}
25052514
elif (
25062515
isinstance(val, list)
25072516
and len(val) > 0
@@ -2514,11 +2523,17 @@ def _to_dict(self) -> Dict[str, Any]:
25142523
raise WeaviateInvalidInputError(
25152524
"Vector config name must be set when specifying multiple vectors"
25162525
)
2517-
ret_dict["vectorConfig"][item.name] = item._to_dict()
2526+
ret_dict["vectorConfig"][item.name] = item._to_dict(
2527+
emit_default_vector_index_type=emit_default_vector_index_type
2528+
)
25182529
else:
25192530
assert isinstance(val, _ConfigCreateModel)
25202531
ret_dict[cls_field] = val._to_dict()
2521-
if self.vectorIndexConfig is None and "vectorConfig" not in ret_dict:
2532+
if (
2533+
self.vectorIndexConfig is None
2534+
and "vectorConfig" not in ret_dict
2535+
and emit_default_vector_index_type
2536+
):
25222537
ret_dict["vectorIndexType"] = VectorIndexType.HNSW
25232538

25242539
ret_dict["class"] = self.name
@@ -2583,7 +2598,17 @@ def async_config(
25832598
"""Create a configuration object create for async replication settings when creating a collection.
25842599
25852600
This is only available with WeaviateDB `>=v1.36.0`.
2601+
2602+
Note:
2603+
`max_workers` and `alive_nodes_checking_frequency` were removed from the
2604+
Weaviate server schema in v1.37.3. Passing them has no effect against any
2605+
server `>=v1.37.3` (the server silently drops them) and emits a
2606+
``DeprecationWarning``. Both arguments will be removed in a future release.
25862607
"""
2608+
if max_workers is not None:
2609+
_Warnings.async_replication_field_removed_server_side("max_workers")
2610+
if alive_nodes_checking_frequency is not None:
2611+
_Warnings.async_replication_field_removed_server_side("alive_nodes_checking_frequency")
25872612
return _AsyncReplicationConfigCreate(
25882613
maxWorkers=max_workers,
25892614
hashtreeHeight=hashtree_height,
@@ -2624,7 +2649,17 @@ def async_config(
26242649
"""Create a configuration object for async replication settings when updating a collection.
26252650
26262651
This is only available with WeaviateDB `>=v1.36.0`.
2652+
2653+
Note:
2654+
`max_workers` and `alive_nodes_checking_frequency` were removed from the
2655+
Weaviate server schema in v1.37.3. Passing them has no effect against any
2656+
server `>=v1.37.3` (the server silently drops them) and emits a
2657+
``DeprecationWarning``. Both arguments will be removed in a future release.
26272658
"""
2659+
if max_workers is not None:
2660+
_Warnings.async_replication_field_removed_server_side("max_workers")
2661+
if alive_nodes_checking_frequency is not None:
2662+
_Warnings.async_replication_field_removed_server_side("alive_nodes_checking_frequency")
26282663
return _AsyncReplicationConfigUpdate(
26292664
maxWorkers=max_workers,
26302665
hashtreeHeight=hashtree_height,

weaviate/collections/classes/config_named_vectors.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,12 @@ class _NamedVectorConfigCreate(_ConfigCreateModel):
7777
default=None, alias="vector_index_config"
7878
)
7979

80-
def _to_dict(self) -> Dict[str, Any]:
80+
def _to_dict(self, *, emit_default_vector_index_type: bool = True) -> Dict[str, Any]:
8181
ret_dict: Dict[str, Any] = self.__parse_vectorizer()
8282
if self.vectorIndexConfig is not None:
8383
ret_dict["vectorIndexType"] = self.vectorIndexConfig.vector_index_type().value
8484
ret_dict["vectorIndexConfig"] = self.vectorIndexConfig._to_dict()
85-
else:
85+
elif emit_default_vector_index_type:
8686
ret_dict["vectorIndexType"] = self.vectorIndexType.value
8787
return ret_dict
8888

weaviate/collections/classes/config_vectors.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,12 @@ class _VectorConfigCreate(_ConfigCreateModel):
8787
default=None, alias="vector_index_config"
8888
)
8989

90-
def _to_dict(self) -> Dict[str, Any]:
90+
def _to_dict(self, *, emit_default_vector_index_type: bool = True) -> Dict[str, Any]:
9191
ret_dict: Dict[str, Any] = self.__parse_vectorizer()
9292
if self.vectorIndexConfig is not None:
9393
ret_dict["vectorIndexType"] = self.vectorIndexConfig.vector_index_type().value
9494
ret_dict["vectorIndexConfig"] = self.vectorIndexConfig._to_dict()
95-
else:
95+
elif emit_default_vector_index_type:
9696
ret_dict["vectorIndexType"] = self.vectorIndexType.value
9797
return ret_dict
9898

weaviate/collections/collections/executor.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,16 @@ def create(
253253
f"Invalid collection config create parameters: {e}"
254254
) from e
255255

256+
# Servers >= 1.37.5 apply DEFAULT_VECTOR_INDEX_TYPE to named-vector
257+
# configs that omit `vectorIndexType`; older servers reject the empty
258+
# field, so for them we keep emitting the client-side HNSW default.
259+
emit_default_vector_index_type = not self._connection._weaviate_version.is_at_least(
260+
1, 37, 5
261+
)
256262
return self.__create(
257-
config=config._to_dict(),
263+
config=config._to_dict(
264+
emit_default_vector_index_type=emit_default_vector_index_type,
265+
),
258266
data_model_properties=data_model_properties,
259267
data_model_references=data_model_references,
260268
skip_argument_validation=skip_argument_validation,

weaviate/warnings.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,16 @@ def min_occurrences_metric_deprecated() -> None:
251251
stacklevel=1,
252252
)
253253

254+
@staticmethod
255+
def async_replication_field_removed_server_side(argument: str) -> None:
256+
warnings.warn(
257+
message=f"""Dep029: The `{argument}` argument in `Configure.Replication.async_config` / `Reconfigure.Replication.async_config` is deprecated.
258+
It was removed from the Weaviate server schema in v1.37.3 and is silently ignored by newer servers.
259+
The argument has no effect against any server >= 1.37.3 and will be removed in a future release.""",
260+
category=DeprecationWarning,
261+
stacklevel=1,
262+
)
263+
254264
@staticmethod
255265
def datetime_insertion_with_no_specified_timezone(date: datetime) -> None:
256266
warnings.warn(

0 commit comments

Comments
 (0)