vectordb-bench 1.0.3__py3-none-any.whl → 1.0.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. vectordb_bench/backend/cases.py +45 -1
  2. vectordb_bench/backend/clients/__init__.py +32 -0
  3. vectordb_bench/backend/clients/aliyun_opensearch/aliyun_opensearch.py +34 -42
  4. vectordb_bench/backend/clients/aliyun_opensearch/config.py +0 -7
  5. vectordb_bench/backend/clients/milvus/cli.py +216 -0
  6. vectordb_bench/backend/clients/oss_opensearch/cli.py +155 -0
  7. vectordb_bench/backend/clients/oss_opensearch/config.py +157 -0
  8. vectordb_bench/backend/clients/oss_opensearch/oss_opensearch.py +582 -0
  9. vectordb_bench/backend/clients/oss_opensearch/run.py +166 -0
  10. vectordb_bench/backend/clients/s3_vectors/config.py +41 -0
  11. vectordb_bench/backend/clients/s3_vectors/s3_vectors.py +171 -0
  12. vectordb_bench/backend/clients/tidb/cli.py +0 -4
  13. vectordb_bench/backend/clients/tidb/config.py +22 -2
  14. vectordb_bench/backend/dataset.py +70 -0
  15. vectordb_bench/backend/filter.py +17 -0
  16. vectordb_bench/backend/runner/mp_runner.py +4 -0
  17. vectordb_bench/backend/runner/read_write_runner.py +10 -9
  18. vectordb_bench/backend/runner/serial_runner.py +23 -7
  19. vectordb_bench/backend/task_runner.py +5 -4
  20. vectordb_bench/cli/vectordbbench.py +2 -0
  21. vectordb_bench/fig/custom_case_run_test.png +0 -0
  22. vectordb_bench/fig/custom_dataset.png +0 -0
  23. vectordb_bench/fig/homepage/bar-chart.png +0 -0
  24. vectordb_bench/fig/homepage/concurrent.png +0 -0
  25. vectordb_bench/fig/homepage/custom.png +0 -0
  26. vectordb_bench/fig/homepage/label_filter.png +0 -0
  27. vectordb_bench/fig/homepage/qp$.png +0 -0
  28. vectordb_bench/fig/homepage/run_test.png +0 -0
  29. vectordb_bench/fig/homepage/streaming.png +0 -0
  30. vectordb_bench/fig/homepage/table.png +0 -0
  31. vectordb_bench/fig/run_test_select_case.png +0 -0
  32. vectordb_bench/fig/run_test_select_db.png +0 -0
  33. vectordb_bench/fig/run_test_submit.png +0 -0
  34. vectordb_bench/frontend/components/check_results/filters.py +1 -4
  35. vectordb_bench/frontend/components/check_results/nav.py +2 -1
  36. vectordb_bench/frontend/components/concurrent/charts.py +5 -0
  37. vectordb_bench/frontend/components/int_filter/charts.py +60 -0
  38. vectordb_bench/frontend/components/streaming/data.py +7 -0
  39. vectordb_bench/frontend/components/welcome/welcomePrams.py +42 -4
  40. vectordb_bench/frontend/config/dbCaseConfigs.py +60 -13
  41. vectordb_bench/frontend/config/styles.py +3 -0
  42. vectordb_bench/frontend/pages/concurrent.py +1 -1
  43. vectordb_bench/frontend/pages/custom.py +1 -1
  44. vectordb_bench/frontend/pages/int_filter.py +56 -0
  45. vectordb_bench/frontend/pages/streaming.py +16 -3
  46. vectordb_bench/metric.py +7 -0
  47. vectordb_bench/models.py +36 -4
  48. vectordb_bench/results/S3Vectors/result_20250722_standard_s3vectors.json +2509 -0
  49. {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/METADATA +1 -3
  50. {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/RECORD +54 -32
  51. {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/WHEEL +0 -0
  52. {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/entry_points.txt +0 -0
  53. {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/licenses/LICENSE +0 -0
  54. {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/top_level.txt +0 -0
@@ -4,7 +4,7 @@ from enum import Enum, auto
4
4
 
5
5
  from vectordb_bench import config
6
6
  from vectordb_bench.backend.clients.api import MetricType
7
- from vectordb_bench.backend.filter import Filter, FilterOp, IntFilter, LabelFilter, NonFilter, non_filter
7
+ from vectordb_bench.backend.filter import Filter, FilterOp, IntFilter, LabelFilter, NewIntFilter, NonFilter, non_filter
8
8
  from vectordb_bench.base import BaseModel
9
9
  from vectordb_bench.frontend.components.custom.getCustomConfig import CustomDatasetConfig
10
10
 
@@ -54,6 +54,8 @@ class CaseType(Enum):
54
54
 
55
55
  LabelFilterPerformanceCase = 300
56
56
 
57
+ NewIntFilterPerformanceCase = 400
58
+
57
59
  def case_cls(self, custom_configs: dict | None = None) -> type["Case"]:
58
60
  if custom_configs is None:
59
61
  return type2case.get(self)()
@@ -130,6 +132,7 @@ class PerformanceCase(Case):
130
132
  filter_rate: float | None = None
131
133
  load_timeout: float | int = config.LOAD_TIMEOUT_DEFAULT
132
134
  optimize_timeout: float | int | None = config.OPTIMIZE_TIMEOUT_DEFAULT
135
+ int_value: float | None = None
133
136
 
134
137
 
135
138
  class CapacityDim960(CapacityCase):
@@ -471,6 +474,46 @@ class StreamingPerformanceCase(Case):
471
474
  )
472
475
 
473
476
 
477
+ class NewIntFilterPerformanceCase(PerformanceCase):
478
+ case_id: CaseType = CaseType.NewIntFilterPerformanceCase
479
+ dataset_with_size_type: DatasetWithSizeType
480
+ filter_rate: float
481
+
482
+ def __init__(
483
+ self,
484
+ dataset_with_size_type: DatasetWithSizeType | str,
485
+ filter_rate: float,
486
+ int_value: float | None = 0,
487
+ **kwargs,
488
+ ):
489
+ if not isinstance(dataset_with_size_type, DatasetWithSizeType):
490
+ dataset_with_size_type = DatasetWithSizeType(dataset_with_size_type)
491
+ name = f"Int-Filter-{filter_rate*100:.1f}% - {dataset_with_size_type.value}"
492
+ description = f"Int-Filter-{filter_rate*100:.1f}% Performance Test ({dataset_with_size_type.value})"
493
+ dataset = dataset_with_size_type.get_manager()
494
+ load_timeout = dataset_with_size_type.get_load_timeout()
495
+ optimize_timeout = dataset_with_size_type.get_optimize_timeout()
496
+ filters = IntFilter(filter_rate=filter_rate, int_value=int_value)
497
+ filter_rate = filters.filter_rate
498
+ super().__init__(
499
+ name=name,
500
+ description=description,
501
+ dataset=dataset,
502
+ load_timeout=load_timeout,
503
+ optimize_timeout=optimize_timeout,
504
+ filter_rate=filter_rate,
505
+ int_value=int_value,
506
+ dataset_with_size_type=dataset_with_size_type,
507
+ **kwargs,
508
+ )
509
+
510
+ @property
511
+ def filters(self) -> Filter:
512
+ int_field = self.dataset.data.train_id_field
513
+ int_value = int(self.dataset.data.size * self.filter_rate)
514
+ return NewIntFilter(filter_rate=self.filter_rate, int_field=int_field, int_value=int_value)
515
+
516
+
474
517
  class LabelFilterPerformanceCase(PerformanceCase):
475
518
  case_id: CaseType = CaseType.LabelFilterPerformanceCase
476
519
  dataset_with_size_type: DatasetWithSizeType
@@ -529,5 +572,6 @@ type2case = {
529
572
  CaseType.Performance1536D50K: Performance1536D50K,
530
573
  CaseType.PerformanceCustomDataset: PerformanceCustomDataset,
531
574
  CaseType.StreamingPerformanceCase: StreamingPerformanceCase,
575
+ CaseType.NewIntFilterPerformanceCase: NewIntFilterPerformanceCase,
532
576
  CaseType.LabelFilterPerformanceCase: LabelFilterPerformanceCase,
533
577
  }
@@ -38,6 +38,7 @@ class DB(Enum):
38
38
  MemoryDB = "MemoryDB"
39
39
  Chroma = "Chroma"
40
40
  AWSOpenSearch = "OpenSearch"
41
+ OSSOpenSearch = "OSSOpenSearch"
41
42
  AliyunElasticsearch = "AliyunElasticsearch"
42
43
  MariaDB = "MariaDB"
43
44
  Test = "test"
@@ -48,6 +49,7 @@ class DB(Enum):
48
49
  Vespa = "Vespa"
49
50
  LanceDB = "LanceDB"
50
51
  OceanBase = "OceanBase"
52
+ S3Vectors = "S3Vectors"
51
53
 
52
54
  @property
53
55
  def init_cls(self) -> type[VectorDB]: # noqa: PLR0911, PLR0912, C901, PLR0915
@@ -127,6 +129,11 @@ class DB(Enum):
127
129
 
128
130
  return AWSOpenSearch
129
131
 
132
+ if self == DB.OSSOpenSearch:
133
+ from .oss_opensearch.oss_opensearch import OSSOpenSearch
134
+
135
+ return OSSOpenSearch
136
+
130
137
  if self == DB.Clickhouse:
131
138
  from .clickhouse.clickhouse import Clickhouse
132
139
 
@@ -182,6 +189,11 @@ class DB(Enum):
182
189
 
183
190
  return LanceDB
184
191
 
192
+ if self == DB.S3Vectors:
193
+ from .s3_vectors.s3_vectors import S3Vectors
194
+
195
+ return S3Vectors
196
+
185
197
  msg = f"Unknown DB: {self.name}"
186
198
  raise ValueError(msg)
187
199
 
@@ -263,6 +275,11 @@ class DB(Enum):
263
275
 
264
276
  return AWSOpenSearchConfig
265
277
 
278
+ if self == DB.OSSOpenSearch:
279
+ from .oss_opensearch.config import OSSOpenSearchConfig
280
+
281
+ return OSSOpenSearchConfig
282
+
266
283
  if self == DB.Clickhouse:
267
284
  from .clickhouse.config import ClickhouseConfig
268
285
 
@@ -318,6 +335,11 @@ class DB(Enum):
318
335
 
319
336
  return LanceDBConfig
320
337
 
338
+ if self == DB.S3Vectors:
339
+ from .s3_vectors.config import S3VectorsConfig
340
+
341
+ return S3VectorsConfig
342
+
321
343
  msg = f"Unknown DB: {self.name}"
322
344
  raise ValueError(msg)
323
345
 
@@ -370,6 +392,11 @@ class DB(Enum):
370
392
 
371
393
  return AWSOpenSearchIndexConfig
372
394
 
395
+ if self == DB.OSSOpenSearch:
396
+ from .oss_opensearch.config import OSSOpenSearchIndexConfig
397
+
398
+ return OSSOpenSearchIndexConfig
399
+
373
400
  if self == DB.Clickhouse:
374
401
  from .clickhouse.config import ClickhouseHNSWConfig
375
402
 
@@ -430,6 +457,11 @@ class DB(Enum):
430
457
 
431
458
  return _lancedb_case_config.get(index_type)
432
459
 
460
+ if self == DB.S3Vectors:
461
+ from .s3_vectors.config import S3VectorsIndexConfig
462
+
463
+ return S3VectorsIndexConfig
464
+
433
465
  # DB.Pinecone, DB.Chroma, DB.Redis
434
466
  return EmptyDBCaseConfig
435
467
 
@@ -3,11 +3,9 @@ import logging
3
3
  import time
4
4
  from contextlib import contextmanager
5
5
 
6
- from alibabacloud_ha3engine_vector import client, models
6
+ from alibabacloud_ha3engine_vector import models
7
+ from alibabacloud_ha3engine_vector.client import Client
7
8
  from alibabacloud_ha3engine_vector.models import QueryRequest
8
- from alibabacloud_searchengine20211025 import models as searchengine_models
9
- from alibabacloud_searchengine20211025.client import Client as searchengineClient
10
- from alibabacloud_tea_openapi import models as open_api_models
11
9
 
12
10
  from ..api import MetricType, VectorDB
13
11
  from .config import AliyunOpenSearchIndexConfig
@@ -28,18 +26,25 @@ class AliyunOpenSearch(VectorDB):
28
26
  drop_old: bool = False,
29
27
  **kwargs,
30
28
  ):
31
- self.control_client = None
32
29
  self.dim = dim
33
30
  self.db_config = db_config
34
31
  self.case_config = db_case_config
35
32
  self.collection_name = collection_name
36
33
  self.instance_id = db_config["host"].split(".")[0].replace("http://", "").replace("https://", "")
34
+ self.config = models.Config(
35
+ endpoint=self.db_config["host"],
36
+ protocol="http",
37
+ access_user_name=self.db_config["user"],
38
+ access_pass_word=self.db_config["password"],
39
+ )
37
40
 
38
41
  self._primary_field = "id"
39
42
  self._scalar_field = "int_id"
40
43
  self._vector_field = "vector"
41
44
  self._index_name = "vector_idx"
42
45
 
46
+ client = Client(self.config)
47
+
43
48
  self.batch_size = int(
44
49
  min(
45
50
  ALIYUN_OPENSEARCH_MAX_SIZE_PER_BATCH / (dim * 25),
@@ -48,22 +53,16 @@ class AliyunOpenSearch(VectorDB):
48
53
  )
49
54
 
50
55
  log.info(f"Aliyun_OpenSearch client config: {self.db_config}")
51
- control_config = open_api_models.Config(
52
- access_key_id=self.db_config["ak"],
53
- access_key_secret=self.db_config["sk"],
54
- endpoint=self.db_config["control_host"],
55
- )
56
- self.control_client = searchengineClient(control_config)
57
56
 
58
57
  if drop_old:
59
58
  log.info(f"aliyun_OpenSearch client drop old index: {self.collection_name}")
60
- if self._index_exists(self.control_client):
61
- self._modify_index(self.control_client)
59
+ if self._index_exists(client):
60
+ self._modify_index(client)
62
61
  else:
63
- self._create_index(self.control_client)
62
+ self._create_index(client)
64
63
 
65
- def _create_index(self, client: searchengineClient):
66
- create_table_request = searchengine_models.CreateTableRequest()
64
+ def _create_index(self, client: Client):
65
+ create_table_request = models.CreateTableRequest()
67
66
  create_table_request.name = self.collection_name
68
67
  create_table_request.primary_key = self._primary_field
69
68
  create_table_request.partition_count = 1
@@ -72,14 +71,14 @@ class AliyunOpenSearch(VectorDB):
72
71
  self._vector_field: "MULTI_FLOAT",
73
72
  self._scalar_field: "INT64",
74
73
  }
75
- vector_index = searchengine_models.ModifyTableRequestVectorIndex()
74
+ vector_index = models.ModifyTableRequestVectorIndex()
76
75
  vector_index.index_name = self._index_name
77
76
  vector_index.dimension = self.dim
78
77
  vector_index.distance_type = self.case_config.distance_type()
79
78
  vector_index.vector_field = self._vector_field
80
79
  vector_index.vector_index_type = "HNSW"
81
80
 
82
- advance_params = searchengine_models.ModifyTableRequestVectorIndexAdvanceParams()
81
+ advance_params = models.ModifyTableRequestVectorIndexAdvanceParams()
83
82
  str_max_neighbor_count = f'"proxima.hnsw.builder.max_neighbor_count":{self.case_config.M}'
84
83
  str_efc = f'"proxima.hnsw.builder.efconstruction":{self.case_config.ef_construction}'
85
84
  str_enable_adsampling = '"proxima.hnsw.builder.enable_adsampling":true'
@@ -95,7 +94,7 @@ class AliyunOpenSearch(VectorDB):
95
94
  str_thread_count,
96
95
  ],
97
96
  )
98
- advance_params.build_index_params = params
97
+ advance_params.build_index_params = "{" + params + "}"
99
98
  advance_params.search_index_params = (
100
99
  '{"proxima.hnsw.searcher.ef":400,"proxima.hnsw.searcher.dynamic_termination.prob_threshold":0.7}'
101
100
  )
@@ -103,7 +102,7 @@ class AliyunOpenSearch(VectorDB):
103
102
  create_table_request.vector_index = [vector_index]
104
103
 
105
104
  try:
106
- response = client.create_table(self.instance_id, create_table_request)
105
+ response = client.create_table(create_table_request)
107
106
  log.info(f"create table success: {response.body}")
108
107
  except Exception as error:
109
108
  log.info(error.message)
@@ -115,20 +114,20 @@ class AliyunOpenSearch(VectorDB):
115
114
  self._active_index(client)
116
115
 
117
116
  # check if index create success
118
- def _active_index(self, client: searchengineClient) -> None:
117
+ def _active_index(self, client: Client) -> None:
119
118
  retry_times = 0
120
119
  while True:
121
120
  time.sleep(10)
122
121
  log.info(f"begin to {retry_times} times get table")
123
122
  retry_times += 1
124
- response = client.get_table(self.instance_id, self.collection_name)
123
+ response = client.get_table(self.collection_name)
125
124
  if response.body.result.status == "IN_USE":
126
125
  log.info(f"{self.collection_name} table begin to use.")
127
126
  return
128
127
 
129
- def _index_exists(self, client: searchengineClient) -> bool:
128
+ def _index_exists(self, client: Client) -> bool:
130
129
  try:
131
- client.get_table(self.instance_id, self.collection_name)
130
+ client.get_table(self.collection_name)
132
131
  except Exception as err:
133
132
  log.warning(f"get table from searchengine error, err={err}")
134
133
  return False
@@ -136,7 +135,7 @@ class AliyunOpenSearch(VectorDB):
136
135
  return True
137
136
 
138
137
  # check if index build success, Insert the embeddings to the vector database after index build success
139
- def _index_build_success(self, client: searchengineClient) -> None:
138
+ def _index_build_success(self, client: Client) -> None:
140
139
  log.info("begin to check if table build success.")
141
140
  time.sleep(50)
142
141
 
@@ -145,10 +144,10 @@ class AliyunOpenSearch(VectorDB):
145
144
  time.sleep(10)
146
145
  log.info(f"begin to {retry_times} times get table fsm")
147
146
  retry_times += 1
148
- request = searchengine_models.ListTasksRequest()
149
- request.start = (int(time.time()) - 3600) * 1000
150
- request.end = int(time.time()) * 1000
151
- response = client.list_tasks(self.instance_id, request)
147
+ request = models.ListTasksRequest()
148
+ request.start = int(time.time()) - 3600
149
+ request.end = int(time.time())
150
+ response = client.list_tasks(request)
152
151
  fsms = response.body.result
153
152
  cur_fsm = None
154
153
  for fsm in fsms:
@@ -164,11 +163,11 @@ class AliyunOpenSearch(VectorDB):
164
163
  if cur_fsm["status"] == "success":
165
164
  return
166
165
 
167
- def _modify_index(self, client: searchengineClient) -> None:
166
+ def _modify_index(self, client: Client) -> None:
168
167
  # check if index create success
169
168
  self._active_index(client)
170
169
 
171
- modify_table_request = searchengine_models.ModifyTableRequest()
170
+ modify_table_request = models.ModifyTableRequest()
172
171
  modify_table_request.partition_count = 1
173
172
  modify_table_request.primary_key = self._primary_field
174
173
  modify_table_request.field_schema = {
@@ -176,13 +175,13 @@ class AliyunOpenSearch(VectorDB):
176
175
  self._vector_field: "MULTI_FLOAT",
177
176
  self._scalar_field: "INT64",
178
177
  }
179
- vector_index = searchengine_models.ModifyTableRequestVectorIndex()
178
+ vector_index = models.ModifyTableRequestVectorIndex()
180
179
  vector_index.index_name = self._index_name
181
180
  vector_index.dimension = self.dim
182
181
  vector_index.distance_type = self.case_config.distance_type()
183
182
  vector_index.vector_field = self._vector_field
184
183
  vector_index.vector_index_type = "HNSW"
185
- advance_params = searchengine_models.ModifyTableRequestVectorIndexAdvanceParams()
184
+ advance_params = models.ModifyTableRequestVectorIndexAdvanceParams()
186
185
 
187
186
  str_max_neighbor_count = f'"proxima.hnsw.builder.max_neighbor_count":{self.case_config.M}'
188
187
  str_efc = f'"proxima.hnsw.builder.efconstruction":{self.case_config.ef_construction}'
@@ -199,7 +198,7 @@ class AliyunOpenSearch(VectorDB):
199
198
  str_thread_count,
200
199
  ],
201
200
  )
202
- advance_params.build_index_params = params
201
+ advance_params.build_index_params = "{" + params + "}"
203
202
  advance_params.search_index_params = (
204
203
  '{"proxima.hnsw.searcher.ef":400,"proxima.hnsw.searcher.dynamic_termination.prob_threshold":0.7}'
205
204
  )
@@ -209,7 +208,6 @@ class AliyunOpenSearch(VectorDB):
209
208
 
210
209
  try:
211
210
  response = client.modify_table(
212
- self.instance_id,
213
211
  self.collection_name,
214
212
  modify_table_request,
215
213
  )
@@ -240,14 +238,8 @@ class AliyunOpenSearch(VectorDB):
240
238
  @contextmanager
241
239
  def init(self) -> None:
242
240
  """connect to aliyun opensearch"""
243
- config = models.Config(
244
- endpoint=self.db_config["host"],
245
- protocol="http",
246
- access_user_name=self.db_config["user"],
247
- access_pass_word=self.db_config["password"],
248
- )
249
241
 
250
- self.client = client.Client(config)
242
+ self.client = Client(self.config)
251
243
 
252
244
  yield
253
245
  self.client = None
@@ -12,18 +12,11 @@ class AliyunOpenSearchConfig(DBConfig, BaseModel):
12
12
  user: str = ""
13
13
  password: SecretStr = ""
14
14
 
15
- ak: str = ""
16
- sk: SecretStr = ""
17
- control_host: str = "searchengine.cn-hangzhou.aliyuncs.com"
18
-
19
15
  def to_dict(self) -> dict:
20
16
  return {
21
17
  "host": self.host,
22
18
  "user": self.user,
23
19
  "password": self.password.get_secret_value(),
24
- "ak": self.ak,
25
- "sk": self.sk.get_secret_value(),
26
- "control_host": self.control_host,
27
20
  }
28
21
 
29
22
 
@@ -109,6 +109,157 @@ def MilvusHNSW(**parameters: Unpack[MilvusHNSWTypedDict]):
109
109
  )
110
110
 
111
111
 
112
+ class MilvusRefineTypedDict(TypedDict):
113
+ refine: Annotated[
114
+ bool,
115
+ click.option(
116
+ "--refine",
117
+ type=bool,
118
+ required=True,
119
+ help="Whether refined data is reserved during index building.",
120
+ ),
121
+ ]
122
+ refine_type: Annotated[
123
+ str | None,
124
+ click.option(
125
+ "--refine-type",
126
+ type=click.Choice(["SQ6", "SQ8", "BF16", "FP16", "FP32"], case_sensitive=False),
127
+ help="The data type of the refine index to use. Supported values: SQ6,SQ8,BF16,FP16,FP32",
128
+ required=True,
129
+ ),
130
+ ]
131
+ refine_k: Annotated[
132
+ float,
133
+ click.option(
134
+ "--refine-k",
135
+ type=float,
136
+ help="The magnification factor of refine compared to k.",
137
+ required=True,
138
+ ),
139
+ ]
140
+
141
+
142
+ class MilvusHNSWPQTypedDict(CommonTypedDict, MilvusTypedDict, MilvusHNSWTypedDict, MilvusRefineTypedDict):
143
+ nbits: Annotated[
144
+ int,
145
+ click.option(
146
+ "--nbits",
147
+ type=int,
148
+ required=True,
149
+ ),
150
+ ]
151
+
152
+
153
+ @cli.command()
154
+ @click_parameter_decorators_from_typed_dict(MilvusHNSWPQTypedDict)
155
+ def MilvusHNSWPQ(**parameters: Unpack[MilvusHNSWPQTypedDict]):
156
+ from .config import HNSWPQConfig, MilvusConfig
157
+
158
+ run(
159
+ db=DBTYPE,
160
+ db_config=MilvusConfig(
161
+ db_label=parameters["db_label"],
162
+ uri=SecretStr(parameters["uri"]),
163
+ user=parameters["user_name"],
164
+ password=SecretStr(parameters["password"]) if parameters["password"] else None,
165
+ num_shards=int(parameters["num_shards"]),
166
+ ),
167
+ db_case_config=HNSWPQConfig(
168
+ M=parameters["m"],
169
+ efConstruction=parameters["ef_construction"],
170
+ ef=parameters["ef_search"],
171
+ nbits=parameters["nbits"],
172
+ refine=parameters["refine"],
173
+ refine_type=parameters["refine_type"],
174
+ refine_k=parameters["refine_k"],
175
+ ),
176
+ **parameters,
177
+ )
178
+
179
+
180
+ class MilvusHNSWPRQTypedDict(
181
+ CommonTypedDict,
182
+ MilvusTypedDict,
183
+ MilvusHNSWPQTypedDict,
184
+ ):
185
+ nrq: Annotated[
186
+ int,
187
+ click.option(
188
+ "--nrq",
189
+ type=int,
190
+ help="The number of residual subquantizers.",
191
+ required=True,
192
+ ),
193
+ ]
194
+
195
+
196
+ @cli.command()
197
+ @click_parameter_decorators_from_typed_dict(MilvusHNSWPRQTypedDict)
198
+ def MilvusHNSWPRQ(**parameters: Unpack[MilvusHNSWPRQTypedDict]):
199
+ from .config import HNSWPRQConfig, MilvusConfig
200
+
201
+ run(
202
+ db=DBTYPE,
203
+ db_config=MilvusConfig(
204
+ db_label=parameters["db_label"],
205
+ uri=SecretStr(parameters["uri"]),
206
+ user=parameters["user_name"],
207
+ password=SecretStr(parameters["password"]) if parameters["password"] else None,
208
+ num_shards=int(parameters["num_shards"]),
209
+ ),
210
+ db_case_config=HNSWPRQConfig(
211
+ M=parameters["m"],
212
+ efConstruction=parameters["ef_construction"],
213
+ ef=parameters["ef_search"],
214
+ nbits=parameters["nbits"],
215
+ refine=parameters["refine"],
216
+ refine_type=parameters["refine_type"],
217
+ refine_k=parameters["refine_k"],
218
+ nrq=parameters["nrq"],
219
+ ),
220
+ **parameters,
221
+ )
222
+
223
+
224
+ class MilvusHNSWSQTypedDict(CommonTypedDict, MilvusTypedDict, MilvusHNSWTypedDict, MilvusRefineTypedDict):
225
+ sq_type: Annotated[
226
+ str | None,
227
+ click.option(
228
+ "--sq-type",
229
+ type=click.Choice(["SQ6", "SQ8", "BF16", "FP16", "FP32"], case_sensitive=False),
230
+ help="Scalar quantizer type. Supported values: SQ6,SQ8,BF16,FP16,FP32",
231
+ required=True,
232
+ ),
233
+ ]
234
+
235
+
236
+ @cli.command()
237
+ @click_parameter_decorators_from_typed_dict(MilvusHNSWSQTypedDict)
238
+ def MilvusHNSWSQ(**parameters: Unpack[MilvusHNSWSQTypedDict]):
239
+ from .config import HNSWSQConfig, MilvusConfig
240
+
241
+ run(
242
+ db=DBTYPE,
243
+ db_config=MilvusConfig(
244
+ db_label=parameters["db_label"],
245
+ uri=SecretStr(parameters["uri"]),
246
+ user=parameters["user_name"],
247
+ password=SecretStr(parameters["password"]) if parameters["password"] else None,
248
+ num_shards=int(parameters["num_shards"]),
249
+ ),
250
+ db_case_config=HNSWSQConfig(
251
+ M=parameters["m"],
252
+ efConstruction=parameters["ef_construction"],
253
+ ef=parameters["ef_search"],
254
+ sq_type=parameters["sq_type"],
255
+ refine=parameters["refine"],
256
+ refine_type=parameters["refine_type"],
257
+ refine_k=parameters["refine_k"],
258
+ ),
259
+ **parameters,
260
+ )
261
+
262
+
112
263
  class MilvusIVFFlatTypedDict(CommonTypedDict, MilvusTypedDict, IVFFlatTypedDictN): ...
113
264
 
114
265
 
@@ -156,6 +307,71 @@ def MilvusIVFSQ8(**parameters: Unpack[MilvusIVFFlatTypedDict]):
156
307
  )
157
308
 
158
309
 
310
+ class MilvusIVFRABITQTypedDict(CommonTypedDict, MilvusTypedDict, MilvusIVFFlatTypedDict):
311
+ rbq_bits_query: Annotated[
312
+ int,
313
+ click.option(
314
+ "--rbq-bits-query",
315
+ type=int,
316
+ help="The magnification factor of refine compared to k.",
317
+ required=True,
318
+ ),
319
+ ]
320
+ refine: Annotated[
321
+ bool,
322
+ click.option(
323
+ "--refine",
324
+ type=bool,
325
+ required=True,
326
+ help="Whether refined data is reserved during index building.",
327
+ ),
328
+ ]
329
+ refine_type: Annotated[
330
+ str | None,
331
+ click.option(
332
+ "--refine-type",
333
+ type=click.Choice(["SQ6", "SQ8", "BF16", "FP16", "FP32"], case_sensitive=False),
334
+ help="The data type of the refine index to use. Supported values: SQ6,SQ8,BF16,FP16,FP32",
335
+ required=True,
336
+ ),
337
+ ]
338
+ refine_k: Annotated[
339
+ float,
340
+ click.option(
341
+ "--refine-k",
342
+ type=float,
343
+ help="The magnification factor of refine compared to k.",
344
+ required=True,
345
+ ),
346
+ ]
347
+
348
+
349
+ @cli.command()
350
+ @click_parameter_decorators_from_typed_dict(MilvusIVFRABITQTypedDict)
351
+ def MilvusIVFRabitQ(**parameters: Unpack[MilvusIVFRABITQTypedDict]):
352
+ from .config import IVFRABITQConfig, MilvusConfig
353
+
354
+ run(
355
+ db=DBTYPE,
356
+ db_config=MilvusConfig(
357
+ db_label=parameters["db_label"],
358
+ uri=SecretStr(parameters["uri"]),
359
+ user=parameters["user_name"],
360
+ password=SecretStr(parameters["password"]) if parameters["password"] else None,
361
+ num_shards=int(parameters["num_shards"]),
362
+ ),
363
+ db_case_config=IVFRABITQConfig(
364
+ nlist=parameters["nlist"],
365
+ nprobe=parameters["nprobe"],
366
+ rbq_bits_query=parameters["rbq_bits_query"],
367
+ refine=parameters["refine"],
368
+ refine_type=parameters["refine_type"],
369
+ refine_k=parameters["refine_k"],
370
+ ),
371
+ **parameters,
372
+ )
373
+
374
+
159
375
  class MilvusDISKANNTypedDict(CommonTypedDict, MilvusTypedDict):
160
376
  search_list: Annotated[str, click.option("--search-list", type=int, required=True)]
161
377