vectordb-bench 0.0.14__py3-none-any.whl → 0.0.16__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.
@@ -4,6 +4,8 @@ import click
4
4
  import os
5
5
  from pydantic import SecretStr
6
6
 
7
+ from vectordb_bench.backend.clients.api import MetricType
8
+
7
9
  from ....cli.cli import (
8
10
  CommonTypedDict,
9
11
  HNSWFlavor1,
@@ -16,6 +18,14 @@ from ....cli.cli import (
16
18
  from vectordb_bench.backend.clients import DB
17
19
 
18
20
 
21
+ def set_default_quantized_fetch_limit(ctx, param, value):
22
+ if ctx.params.get("reranking") and value is None:
23
+ # ef_search is the default value for quantized_fetch_limit as it's bound by ef_search.
24
+ # 100 is default value for quantized_fetch_limit for IVFFlat.
25
+ default_value = ctx.params["ef_search"] if ctx.command.name == "pgvectorhnsw" else 100
26
+ return default_value
27
+ return value
28
+
19
29
  class PgVectorTypedDict(CommonTypedDict):
20
30
  user_name: Annotated[
21
31
  str, click.option("--user-name", type=str, help="Db username", required=True)
@@ -61,11 +71,45 @@ class PgVectorTypedDict(CommonTypedDict):
61
71
  Optional[str],
62
72
  click.option(
63
73
  "--quantization-type",
64
- type=click.Choice(["none", "halfvec"]),
74
+ type=click.Choice(["none", "bit", "halfvec"]),
65
75
  help="quantization type for vectors",
66
76
  required=False,
67
77
  ),
68
78
  ]
79
+ reranking: Annotated[
80
+ Optional[bool],
81
+ click.option(
82
+ "--reranking/--skip-reranking",
83
+ type=bool,
84
+ help="Enable reranking for HNSW search for binary quantization",
85
+ default=False,
86
+ ),
87
+ ]
88
+ reranking_metric: Annotated[
89
+ Optional[str],
90
+ click.option(
91
+ "--reranking-metric",
92
+ type=click.Choice(
93
+ [metric.value for metric in MetricType if metric.value not in ["HAMMING", "JACCARD"]]
94
+ ),
95
+ help="Distance metric for reranking",
96
+ default="COSINE",
97
+ show_default=True,
98
+ ),
99
+ ]
100
+ quantized_fetch_limit: Annotated[
101
+ Optional[int],
102
+ click.option(
103
+ "--quantized-fetch-limit",
104
+ type=int,
105
+ help="Limit of fetching quantized vector ranked by distance for reranking \
106
+ -- bound by ef_search",
107
+ required=False,
108
+ callback=set_default_quantized_fetch_limit,
109
+ )
110
+ ]
111
+
112
+
69
113
 
70
114
  class PgVectorIVFFlatTypedDict(PgVectorTypedDict, IVFFlatTypedDict):
71
115
  ...
@@ -93,6 +137,9 @@ def PgVectorIVFFlat(
93
137
  lists=parameters["lists"],
94
138
  probes=parameters["probes"],
95
139
  quantization_type=parameters["quantization_type"],
140
+ reranking=parameters["reranking"],
141
+ reranking_metric=parameters["reranking_metric"],
142
+ quantized_fetch_limit=parameters["quantized_fetch_limit"],
96
143
  ),
97
144
  **parameters,
98
145
  )
@@ -126,6 +173,9 @@ def PgVectorHNSW(
126
173
  maintenance_work_mem=parameters["maintenance_work_mem"],
127
174
  max_parallel_workers=parameters["max_parallel_workers"],
128
175
  quantization_type=parameters["quantization_type"],
176
+ reranking=parameters["reranking"],
177
+ reranking_metric=parameters["reranking_metric"],
178
+ quantized_fetch_limit=parameters["quantized_fetch_limit"],
129
179
  ),
130
180
  **parameters,
131
181
  )
@@ -65,6 +65,10 @@ class PgVectorIndexConfig(BaseModel, DBCaseConfig):
65
65
  elif self.metric_type == MetricType.IP:
66
66
  return "halfvec_ip_ops"
67
67
  return "halfvec_cosine_ops"
68
+ elif self.quantization_type == "bit":
69
+ if self.metric_type == MetricType.JACCARD:
70
+ return "bit_jaccard_ops"
71
+ return "bit_hamming_ops"
68
72
  else:
69
73
  if self.metric_type == MetricType.L2:
70
74
  return "vector_l2_ops"
@@ -73,11 +77,16 @@ class PgVectorIndexConfig(BaseModel, DBCaseConfig):
73
77
  return "vector_cosine_ops"
74
78
 
75
79
  def parse_metric_fun_op(self) -> LiteralString:
76
- if self.metric_type == MetricType.L2:
77
- return "<->"
78
- elif self.metric_type == MetricType.IP:
79
- return "<#>"
80
- return "<=>"
80
+ if self.quantization_type == "bit":
81
+ if self.metric_type == MetricType.JACCARD:
82
+ return "<%>"
83
+ return "<~>"
84
+ else:
85
+ if self.metric_type == MetricType.L2:
86
+ return "<->"
87
+ elif self.metric_type == MetricType.IP:
88
+ return "<#>"
89
+ return "<=>"
81
90
 
82
91
  def parse_metric_fun_str(self) -> str:
83
92
  if self.metric_type == MetricType.L2:
@@ -85,6 +94,14 @@ class PgVectorIndexConfig(BaseModel, DBCaseConfig):
85
94
  elif self.metric_type == MetricType.IP:
86
95
  return "max_inner_product"
87
96
  return "cosine_distance"
97
+
98
+ def parse_reranking_metric_fun_op(self) -> LiteralString:
99
+ if self.reranking_metric == MetricType.L2:
100
+ return "<->"
101
+ elif self.reranking_metric == MetricType.IP:
102
+ return "<#>"
103
+ return "<=>"
104
+
88
105
 
89
106
  @abstractmethod
90
107
  def index_param(self) -> PgVectorIndexParam:
@@ -151,6 +168,9 @@ class PgVectorIVFFlatConfig(PgVectorIndexConfig):
151
168
  maintenance_work_mem: Optional[str] = None
152
169
  max_parallel_workers: Optional[int] = None
153
170
  quantization_type: Optional[str] = None
171
+ reranking: Optional[bool] = None
172
+ quantized_fetch_limit: Optional[int] = None
173
+ reranking_metric: Optional[str] = None
154
174
 
155
175
  def index_param(self) -> PgVectorIndexParam:
156
176
  index_parameters = {"lists": self.lists}
@@ -170,6 +190,9 @@ class PgVectorIVFFlatConfig(PgVectorIndexConfig):
170
190
  def search_param(self) -> PgVectorSearchParam:
171
191
  return {
172
192
  "metric_fun_op": self.parse_metric_fun_op(),
193
+ "reranking": self.reranking,
194
+ "reranking_metric_fun_op": self.parse_reranking_metric_fun_op(),
195
+ "quantized_fetch_limit": self.quantized_fetch_limit,
173
196
  }
174
197
 
175
198
  def session_param(self) -> PgVectorSessionCommands:
@@ -195,6 +218,9 @@ class PgVectorHNSWConfig(PgVectorIndexConfig):
195
218
  maintenance_work_mem: Optional[str] = None
196
219
  max_parallel_workers: Optional[int] = None
197
220
  quantization_type: Optional[str] = None
221
+ reranking: Optional[bool] = None
222
+ quantized_fetch_limit: Optional[int] = None
223
+ reranking_metric: Optional[str] = None
198
224
 
199
225
  def index_param(self) -> PgVectorIndexParam:
200
226
  index_parameters = {"m": self.m, "ef_construction": self.ef_construction}
@@ -214,6 +240,9 @@ class PgVectorHNSWConfig(PgVectorIndexConfig):
214
240
  def search_param(self) -> PgVectorSearchParam:
215
241
  return {
216
242
  "metric_fun_op": self.parse_metric_fun_op(),
243
+ "reranking": self.reranking,
244
+ "reranking_metric_fun_op": self.parse_reranking_metric_fun_op(),
245
+ "quantized_fetch_limit": self.quantized_fetch_limit,
217
246
  }
218
247
 
219
248
  def session_param(self) -> PgVectorSessionCommands:
@@ -11,7 +11,7 @@ from pgvector.psycopg import register_vector
11
11
  from psycopg import Connection, Cursor, sql
12
12
 
13
13
  from ..api import VectorDB
14
- from .config import PgVectorConfigDict, PgVectorIndexConfig
14
+ from .config import PgVectorConfigDict, PgVectorIndexConfig, PgVectorHNSWConfig
15
15
 
16
16
  log = logging.getLogger(__name__)
17
17
 
@@ -87,6 +87,92 @@ class PgVector(VectorDB):
87
87
  assert cursor is not None, "Cursor is not initialized"
88
88
 
89
89
  return conn, cursor
90
+
91
+ def _generate_search_query(self, filtered: bool=False) -> sql.Composed:
92
+ index_param = self.case_config.index_param()
93
+ reranking = self.case_config.search_param()["reranking"]
94
+ column_name = (
95
+ sql.SQL("binary_quantize({0})").format(sql.Identifier("embedding"))
96
+ if index_param["quantization_type"] == "bit"
97
+ else sql.SQL("embedding")
98
+ )
99
+ search_vector = (
100
+ sql.SQL("binary_quantize({0})").format(sql.Placeholder())
101
+ if index_param["quantization_type"] == "bit"
102
+ else sql.Placeholder()
103
+ )
104
+
105
+ # The following sections assume that the quantization_type value matches the quantization function name
106
+ if index_param["quantization_type"] != None:
107
+ if index_param["quantization_type"] == "bit" and reranking:
108
+ # Embeddings needs to be passed to binary_quantize function if quantization_type is bit
109
+ search_query = sql.Composed(
110
+ [
111
+ sql.SQL(
112
+ """
113
+ SELECT i.id
114
+ FROM (
115
+ SELECT id, embedding {reranking_metric_fun_op} %s::vector AS distance
116
+ FROM public.{table_name} {where_clause}
117
+ ORDER BY {column_name}::{quantization_type}({dim})
118
+ """
119
+ ).format(
120
+ table_name=sql.Identifier(self.table_name),
121
+ column_name=column_name,
122
+ reranking_metric_fun_op=sql.SQL(self.case_config.search_param()["reranking_metric_fun_op"]),
123
+ quantization_type=sql.SQL(index_param["quantization_type"]),
124
+ dim=sql.Literal(self.dim),
125
+ where_clause=sql.SQL("WHERE id >= %s") if filtered else sql.SQL(""),
126
+ ),
127
+ sql.SQL(self.case_config.search_param()["metric_fun_op"]),
128
+ sql.SQL(
129
+ """
130
+ {search_vector}
131
+ LIMIT {quantized_fetch_limit}
132
+ ) i
133
+ ORDER BY i.distance
134
+ LIMIT %s::int
135
+ """
136
+ ).format(
137
+ search_vector=search_vector,
138
+ quantized_fetch_limit=sql.Literal(
139
+ self.case_config.search_param()["quantized_fetch_limit"]
140
+ ),
141
+ ),
142
+ ]
143
+ )
144
+ else:
145
+ search_query = sql.Composed(
146
+ [
147
+ sql.SQL(
148
+ "SELECT id FROM public.{table_name} {where_clause} ORDER BY {column_name}::{quantization_type}({dim}) "
149
+ ).format(
150
+ table_name=sql.Identifier(self.table_name),
151
+ column_name=column_name,
152
+ quantization_type=sql.SQL(index_param["quantization_type"]),
153
+ dim=sql.Literal(self.dim),
154
+ where_clause=sql.SQL("WHERE id >= %s") if filtered else sql.SQL(""),
155
+ ),
156
+ sql.SQL(self.case_config.search_param()["metric_fun_op"]),
157
+ sql.SQL(" {search_vector} LIMIT %s::int").format(search_vector=search_vector),
158
+ ]
159
+ )
160
+ else:
161
+ search_query = sql.Composed(
162
+ [
163
+ sql.SQL(
164
+ "SELECT id FROM public.{table_name} {where_clause} ORDER BY embedding "
165
+ ).format(
166
+ table_name=sql.Identifier(self.table_name),
167
+ where_clause=sql.SQL("WHERE id >= %s") if filtered else sql.SQL(""),
168
+ ),
169
+ sql.SQL(self.case_config.search_param()["metric_fun_op"]),
170
+ sql.SQL(" %s::vector LIMIT %s::int"),
171
+ ]
172
+ )
173
+
174
+ return search_query
175
+
90
176
 
91
177
  @contextmanager
92
178
  def init(self) -> Generator[None, None, None]:
@@ -112,63 +198,8 @@ class PgVector(VectorDB):
112
198
  self.cursor.execute(command)
113
199
  self.conn.commit()
114
200
 
115
- index_param = self.case_config.index_param()
116
- # The following sections assume that the quantization_type value matches the quantization function name
117
- if index_param["quantization_type"] != None:
118
- self._filtered_search = sql.Composed(
119
- [
120
- sql.SQL(
121
- "SELECT id FROM public.{table_name} WHERE id >= %s ORDER BY embedding::{quantization_type}({dim}) "
122
- ).format(
123
- table_name=sql.Identifier(self.table_name),
124
- quantization_type=sql.SQL(index_param["quantization_type"]),
125
- dim=sql.Literal(self.dim),
126
- ),
127
- sql.SQL(self.case_config.search_param()["metric_fun_op"]),
128
- sql.SQL(" %s::{quantization_type}({dim}) LIMIT %s::int").format(
129
- quantization_type=sql.SQL(index_param["quantization_type"]),
130
- dim=sql.Literal(self.dim),
131
- ),
132
- ]
133
- )
134
- else:
135
- self._filtered_search = sql.Composed(
136
- [
137
- sql.SQL(
138
- "SELECT id FROM public.{table_name} WHERE id >= %s ORDER BY embedding "
139
- ).format(table_name=sql.Identifier(self.table_name)),
140
- sql.SQL(self.case_config.search_param()["metric_fun_op"]),
141
- sql.SQL(" %s::vector LIMIT %s::int"),
142
- ]
143
- )
144
-
145
- if index_param["quantization_type"] != None:
146
- self._unfiltered_search = sql.Composed(
147
- [
148
- sql.SQL(
149
- "SELECT id FROM public.{table_name} ORDER BY embedding::{quantization_type}({dim}) "
150
- ).format(
151
- table_name=sql.Identifier(self.table_name),
152
- quantization_type=sql.SQL(index_param["quantization_type"]),
153
- dim=sql.Literal(self.dim),
154
- ),
155
- sql.SQL(self.case_config.search_param()["metric_fun_op"]),
156
- sql.SQL(" %s::{quantization_type}({dim}) LIMIT %s::int").format(
157
- quantization_type=sql.SQL(index_param["quantization_type"]),
158
- dim=sql.Literal(self.dim),
159
- ),
160
- ]
161
- )
162
- else:
163
- self._unfiltered_search = sql.Composed(
164
- [
165
- sql.SQL("SELECT id FROM public.{} ORDER BY embedding ").format(
166
- sql.Identifier(self.table_name)
167
- ),
168
- sql.SQL(self.case_config.search_param()["metric_fun_op"]),
169
- sql.SQL(" %s::vector LIMIT %s::int"),
170
- ]
171
- )
201
+ self._filtered_search = self._generate_search_query(filtered=True)
202
+ self._unfiltered_search = self._generate_search_query()
172
203
 
173
204
  try:
174
205
  yield
@@ -306,12 +337,17 @@ class PgVector(VectorDB):
306
337
  if index_param["quantization_type"] != None:
307
338
  index_create_sql = sql.SQL(
308
339
  """
309
- CREATE INDEX IF NOT EXISTS {index_name} ON public.{table_name}
310
- USING {index_type} ((embedding::{quantization_type}({dim})) {embedding_metric})
340
+ CREATE INDEX IF NOT EXISTS {index_name} ON public.{table_name}
341
+ USING {index_type} (({column_name}::{quantization_type}({dim})) {embedding_metric})
311
342
  """
312
343
  ).format(
313
344
  index_name=sql.Identifier(self._index_name),
314
345
  table_name=sql.Identifier(self.table_name),
346
+ column_name=(
347
+ sql.SQL("binary_quantize({0})").format(sql.Identifier("embedding"))
348
+ if index_param["quantization_type"] == "bit"
349
+ else sql.Identifier("embedding")
350
+ ),
315
351
  index_type=sql.Identifier(index_param["index_type"]),
316
352
  # This assumes that the quantization_type value matches the quantization function name
317
353
  quantization_type=sql.SQL(index_param["quantization_type"]),
@@ -406,15 +442,28 @@ class PgVector(VectorDB):
406
442
  assert self.conn is not None, "Connection is not initialized"
407
443
  assert self.cursor is not None, "Cursor is not initialized"
408
444
 
445
+ index_param = self.case_config.index_param()
446
+ search_param = self.case_config.search_param()
409
447
  q = np.asarray(query)
410
448
  if filters:
411
449
  gt = filters.get("id")
412
- result = self.cursor.execute(
450
+ if index_param["quantization_type"] == "bit" and search_param["reranking"]:
451
+ result = self.cursor.execute(
452
+ self._filtered_search, (q, gt, q, k), prepare=True, binary=True
453
+ )
454
+ else:
455
+ result = self.cursor.execute(
413
456
  self._filtered_search, (gt, q, k), prepare=True, binary=True
414
- )
457
+ )
458
+
415
459
  else:
416
- result = self.cursor.execute(
460
+ if index_param["quantization_type"] == "bit" and search_param["reranking"]:
461
+ result = self.cursor.execute(
462
+ self._unfiltered_search, (q, q, k), prepare=True, binary=True
463
+ )
464
+ else:
465
+ result = self.cursor.execute(
417
466
  self._unfiltered_search, (q, k), prepare=True, binary=True
418
- )
467
+ )
419
468
 
420
469
  return [int(i[0]) for i in result.fetchall()]
@@ -23,7 +23,7 @@ class WeaviateCloud(VectorDB):
23
23
  **kwargs,
24
24
  ):
25
25
  """Initialize wrapper around the weaviate vector database."""
26
- db_config.update("auth_client_secret", weaviate.AuthApiKey(api_key=db_config.get("auth_client_secret")))
26
+ db_config.update({"auth_client_secret": weaviate.AuthApiKey(api_key=db_config.get("auth_client_secret"))})
27
27
  self.db_config = db_config
28
28
  self.case_config = db_case_config
29
29
  self.collection_name = collection_name
vectordb_bench/cli/cli.py CHANGED
@@ -414,7 +414,7 @@ class HNSWBaseRequiredTypedDict(TypedDict):
414
414
 
415
415
  class HNSWFlavor1(HNSWBaseTypedDict):
416
416
  ef_search: Annotated[
417
- Optional[int], click.option("--ef-search", type=int, help="hnsw ef-search")
417
+ Optional[int], click.option("--ef-search", type=int, help="hnsw ef-search", is_eager=True)
418
418
  ]
419
419
 
420
420
 
@@ -479,7 +479,7 @@ def run(
479
479
  concurrency_duration=parameters["concurrency_duration"],
480
480
  num_concurrency=[int(s) for s in parameters["num_concurrency"]],
481
481
  ),
482
- custom_case=parameters.get("custom_case", {}),
482
+ custom_case=get_custom_case_config(parameters),
483
483
  ),
484
484
  stages=parse_task_stages(
485
485
  (
@@ -1,6 +1,7 @@
1
1
  from ..backend.clients.pgvector.cli import PgVectorHNSW
2
2
  from ..backend.clients.pgvecto_rs.cli import PgVectoRSHNSW, PgVectoRSIVFFlat
3
3
  from ..backend.clients.pgvectorscale.cli import PgVectorScaleDiskAnn
4
+ from ..backend.clients.pgdiskann.cli import PgDiskAnn
4
5
  from ..backend.clients.redis.cli import Redis
5
6
  from ..backend.clients.memorydb.cli import MemoryDB
6
7
  from ..backend.clients.test.cli import Test
@@ -22,6 +23,7 @@ cli.add_command(ZillizAutoIndex)
22
23
  cli.add_command(MilvusAutoIndex)
23
24
  cli.add_command(AWSOpenSearch)
24
25
  cli.add_command(PgVectorScaleDiskAnn)
26
+ cli.add_command(PgDiskAnn)
25
27
 
26
28
 
27
29
  if __name__ == "__main__":
@@ -110,6 +110,12 @@ def caseConfigSetting(st, dbToCaseClusterConfigs, uiCaseItem: UICaseItem, active
110
110
  value=config.inputConfig["value"],
111
111
  help=config.inputHelp,
112
112
  )
113
+ elif config.inputType == InputType.Bool:
114
+ caseConfig[config.label] = column.checkbox(
115
+ config.displayLabel if config.displayLabel else config.label.value,
116
+ value=config.inputConfig["value"],
117
+ help=config.inputHelp,
118
+ )
113
119
  k += 1
114
120
  if k == 0:
115
121
  columns[1].write("Auto")
@@ -3,7 +3,7 @@ import typing
3
3
  from pydantic import BaseModel
4
4
  from vectordb_bench.backend.cases import CaseLabel, CaseType
5
5
  from vectordb_bench.backend.clients import DB
6
- from vectordb_bench.backend.clients.api import IndexType
6
+ from vectordb_bench.backend.clients.api import IndexType, MetricType
7
7
  from vectordb_bench.frontend.components.custom.getCustomConfig import get_custom_configs
8
8
 
9
9
  from vectordb_bench.models import CaseConfig, CaseConfigParamType
@@ -149,6 +149,7 @@ class InputType(IntEnum):
149
149
  Number = 20002
150
150
  Option = 20003
151
151
  Float = 20004
152
+ Bool = 20005
152
153
 
153
154
 
154
155
  class CaseConfigInput(BaseModel):
@@ -180,6 +181,16 @@ CaseConfigParamInput_IndexType = CaseConfigInput(
180
181
  },
181
182
  )
182
183
 
184
+ CaseConfigParamInput_IndexType_PgDiskANN = CaseConfigInput(
185
+ label=CaseConfigParamType.IndexType,
186
+ inputHelp="Select Index Type",
187
+ inputType=InputType.Option,
188
+ inputConfig={
189
+ "options": [
190
+ IndexType.DISKANN.value,
191
+ ],
192
+ },
193
+ )
183
194
 
184
195
  CaseConfigParamInput_IndexType_PgVectorScale = CaseConfigInput(
185
196
  label=CaseConfigParamType.IndexType,
@@ -205,6 +216,42 @@ CaseConfigParamInput_storage_layout = CaseConfigInput(
205
216
  },
206
217
  )
207
218
 
219
+ CaseConfigParamInput_max_neighbors = CaseConfigInput(
220
+ label=CaseConfigParamType.max_neighbors,
221
+ inputType=InputType.Number,
222
+ inputConfig={
223
+ "min": 10,
224
+ "max": 300,
225
+ "value": 32,
226
+ },
227
+ isDisplayed=lambda config: config.get(CaseConfigParamType.IndexType, None)
228
+ == IndexType.DISKANN.value,
229
+ )
230
+
231
+ CaseConfigParamInput_l_value_ib = CaseConfigInput(
232
+ label=CaseConfigParamType.l_value_ib,
233
+ inputType=InputType.Number,
234
+ inputConfig={
235
+ "min": 10,
236
+ "max": 300,
237
+ "value": 50,
238
+ },
239
+ isDisplayed=lambda config: config.get(CaseConfigParamType.IndexType, None)
240
+ == IndexType.DISKANN.value,
241
+ )
242
+
243
+ CaseConfigParamInput_l_value_is = CaseConfigInput(
244
+ label=CaseConfigParamType.l_value_is,
245
+ inputType=InputType.Number,
246
+ inputConfig={
247
+ "min": 10,
248
+ "max": 300,
249
+ "value": 40,
250
+ },
251
+ isDisplayed=lambda config: config.get(CaseConfigParamType.IndexType, None)
252
+ == IndexType.DISKANN.value,
253
+ )
254
+
208
255
  CaseConfigParamInput_num_neighbors = CaseConfigInput(
209
256
  label=CaseConfigParamType.num_neighbors,
210
257
  inputType=InputType.Number,
@@ -773,7 +820,7 @@ CaseConfigParamInput_QuantizationType_PgVector = CaseConfigInput(
773
820
  label=CaseConfigParamType.quantizationType,
774
821
  inputType=InputType.Option,
775
822
  inputConfig={
776
- "options": ["none", "halfvec"],
823
+ "options": ["none", "bit", "halfvec"],
777
824
  },
778
825
  isDisplayed=lambda config: config.get(CaseConfigParamType.IndexType, None)
779
826
  in [
@@ -819,6 +866,46 @@ CaseConfigParamInput_ZillizLevel = CaseConfigInput(
819
866
  },
820
867
  )
821
868
 
869
+ CaseConfigParamInput_reranking_PgVector = CaseConfigInput(
870
+ label=CaseConfigParamType.reranking,
871
+ inputType=InputType.Bool,
872
+ displayLabel="Enable Reranking",
873
+ inputHelp="Enable if you want to use reranking while performing \
874
+ similarity search in binary quantization",
875
+ inputConfig={
876
+ "value": False,
877
+ },
878
+ isDisplayed=lambda config: config.get(CaseConfigParamType.quantizationType, None)
879
+ == "bit"
880
+ )
881
+
882
+ CaseConfigParamInput_quantized_fetch_limit_PgVector = CaseConfigInput(
883
+ label=CaseConfigParamType.quantizedFetchLimit,
884
+ displayLabel="Quantized vector fetch limit",
885
+ inputHelp="Limit top-k vectors using the quantized vector comparison --bound by ef_search",
886
+ inputType=InputType.Number,
887
+ inputConfig={
888
+ "min": 20,
889
+ "max": 1000,
890
+ "value": 200,
891
+ },
892
+ isDisplayed=lambda config: config.get(CaseConfigParamType.quantizationType, None)
893
+ == "bit" and config.get(CaseConfigParamType.reranking, False)
894
+ )
895
+
896
+
897
+ CaseConfigParamInput_reranking_metric_PgVector = CaseConfigInput(
898
+ label=CaseConfigParamType.rerankingMetric,
899
+ inputType=InputType.Option,
900
+ inputConfig={
901
+ "options": [
902
+ metric.value for metric in MetricType if metric.value not in ["HAMMING", "JACCARD"]
903
+ ],
904
+ },
905
+ isDisplayed=lambda config: config.get(CaseConfigParamType.quantizationType, None)
906
+ == "bit" and config.get(CaseConfigParamType.reranking, False)
907
+ )
908
+
822
909
  MilvusLoadConfig = [
823
910
  CaseConfigParamInput_IndexType,
824
911
  CaseConfigParamInput_M,
@@ -896,6 +983,9 @@ PgVectorPerformanceConfig = [
896
983
  CaseConfigParamInput_QuantizationType_PgVector,
897
984
  CaseConfigParamInput_maintenance_work_mem_PgVector,
898
985
  CaseConfigParamInput_max_parallel_workers_PgVector,
986
+ CaseConfigParamInput_reranking_PgVector,
987
+ CaseConfigParamInput_reranking_metric_PgVector,
988
+ CaseConfigParamInput_quantized_fetch_limit_PgVector,
899
989
  ]
900
990
 
901
991
  PgVectoRSLoadingConfig = [
@@ -942,6 +1032,19 @@ PgVectorScalePerformanceConfig = [
942
1032
  CaseConfigParamInput_query_search_list_size,
943
1033
  ]
944
1034
 
1035
+ PgDiskANNLoadConfig = [
1036
+ CaseConfigParamInput_IndexType_PgDiskANN,
1037
+ CaseConfigParamInput_max_neighbors,
1038
+ CaseConfigParamInput_l_value_ib,
1039
+ ]
1040
+
1041
+ PgDiskANNPerformanceConfig = [
1042
+ CaseConfigParamInput_IndexType_PgDiskANN,
1043
+ CaseConfigParamInput_max_neighbors,
1044
+ CaseConfigParamInput_l_value_ib,
1045
+ CaseConfigParamInput_l_value_is,
1046
+ ]
1047
+
945
1048
  CASE_CONFIG_MAP = {
946
1049
  DB.Milvus: {
947
1050
  CaseLabel.Load: MilvusLoadConfig,
@@ -974,4 +1077,8 @@ CASE_CONFIG_MAP = {
974
1077
  CaseLabel.Load: PgVectorScaleLoadingConfig,
975
1078
  CaseLabel.Performance: PgVectorScalePerformanceConfig,
976
1079
  },
1080
+ DB.PgDiskANN: {
1081
+ CaseLabel.Load: PgDiskANNLoadConfig,
1082
+ CaseLabel.Performance: PgDiskANNPerformanceConfig,
1083
+ },
977
1084
  }
vectordb_bench/models.py CHANGED
@@ -47,6 +47,9 @@ class CaseConfigParamType(Enum):
47
47
  probes = "probes"
48
48
  quantizationType = "quantization_type"
49
49
  quantizationRatio = "quantization_ratio"
50
+ reranking = "reranking"
51
+ rerankingMetric = "reranking_metric"
52
+ quantizedFetchLimit = "quantized_fetch_limit"
50
53
  m = "m"
51
54
  nbits = "nbits"
52
55
  intermediate_graph_degree = "intermediate_graph_degree"
@@ -64,6 +67,9 @@ class CaseConfigParamType(Enum):
64
67
  max_parallel_workers = "max_parallel_workers"
65
68
  storage_layout = "storage_layout"
66
69
  num_neighbors = "num_neighbors"
70
+ max_neighbors = "max_neighbors"
71
+ l_value_ib = "l_value_ib"
72
+ l_value_is = "l_value_is"
67
73
  search_list_size = "search_list_size"
68
74
  max_alpha = "max_alpha"
69
75
  num_dimensions = "num_dimensions"
@@ -2,6 +2,7 @@ from vectordb_bench import config
2
2
  import ujson
3
3
  import pathlib
4
4
  from vectordb_bench.backend.cases import CaseType
5
+ from vectordb_bench.backend.clients import DB
5
6
  from vectordb_bench.frontend.config.dbPrices import DB_DBLABEL_TO_PRICE
6
7
  from vectordb_bench.interface import benchMarkRunner
7
8
  from vectordb_bench.models import ResultLabel, TestResult
@@ -45,6 +46,8 @@ def main():
45
46
  for d in test_result.results
46
47
  if d.task_config.case_config.case_id != CaseType.CapacityDim128
47
48
  and d.task_config.case_config.case_id != CaseType.CapacityDim960
49
+ if d.task_config.db != DB.ZillizCloud
50
+ or test_result.timestamp >= datetime(2024, 1, 1).timestamp()
48
51
  ]
49
52
 
50
53
  # compute qp$