vectordb-bench 1.0.5__py3-none-any.whl → 1.0.8__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.
- vectordb_bench/__init__.py +1 -0
- vectordb_bench/backend/clients/__init__.py +15 -0
- vectordb_bench/backend/clients/api.py +2 -0
- vectordb_bench/backend/clients/aws_opensearch/aws_opensearch.py +104 -40
- vectordb_bench/backend/clients/aws_opensearch/cli.py +52 -15
- vectordb_bench/backend/clients/aws_opensearch/config.py +27 -7
- vectordb_bench/backend/clients/hologres/cli.py +50 -0
- vectordb_bench/backend/clients/hologres/config.py +120 -0
- vectordb_bench/backend/clients/hologres/hologres.py +385 -0
- vectordb_bench/backend/clients/lancedb/lancedb.py +1 -0
- vectordb_bench/backend/clients/milvus/cli.py +25 -0
- vectordb_bench/backend/clients/milvus/config.py +2 -1
- vectordb_bench/backend/clients/milvus/milvus.py +1 -1
- vectordb_bench/backend/clients/oceanbase/cli.py +1 -0
- vectordb_bench/backend/clients/oceanbase/config.py +3 -1
- vectordb_bench/backend/clients/oceanbase/oceanbase.py +20 -4
- vectordb_bench/backend/clients/pgdiskann/cli.py +45 -0
- vectordb_bench/backend/clients/pgdiskann/config.py +16 -0
- vectordb_bench/backend/clients/pgdiskann/pgdiskann.py +94 -26
- vectordb_bench/backend/clients/zilliz_cloud/cli.py +14 -1
- vectordb_bench/backend/clients/zilliz_cloud/config.py +4 -1
- vectordb_bench/backend/runner/rate_runner.py +23 -11
- vectordb_bench/cli/cli.py +59 -1
- vectordb_bench/cli/vectordbbench.py +2 -0
- vectordb_bench/frontend/config/dbCaseConfigs.py +82 -3
- vectordb_bench/frontend/config/styles.py +1 -0
- vectordb_bench/interface.py +5 -1
- vectordb_bench/models.py +4 -0
- vectordb_bench/results/getLeaderboardDataV2.py +23 -2
- vectordb_bench/results/leaderboard_v2.json +200 -0
- vectordb_bench/results/leaderboard_v2_streaming.json +128 -0
- {vectordb_bench-1.0.5.dist-info → vectordb_bench-1.0.8.dist-info}/METADATA +40 -8
- {vectordb_bench-1.0.5.dist-info → vectordb_bench-1.0.8.dist-info}/RECORD +37 -33
- {vectordb_bench-1.0.5.dist-info → vectordb_bench-1.0.8.dist-info}/WHEEL +0 -0
- {vectordb_bench-1.0.5.dist-info → vectordb_bench-1.0.8.dist-info}/entry_points.txt +0 -0
- {vectordb_bench-1.0.5.dist-info → vectordb_bench-1.0.8.dist-info}/licenses/LICENSE +0 -0
- {vectordb_bench-1.0.5.dist-info → vectordb_bench-1.0.8.dist-info}/top_level.txt +0 -0
@@ -5,6 +5,7 @@ import click
|
|
5
5
|
from pydantic import SecretStr
|
6
6
|
|
7
7
|
from vectordb_bench.backend.clients import DB
|
8
|
+
from vectordb_bench.backend.clients.api import MetricType
|
8
9
|
|
9
10
|
from ....cli.cli import (
|
10
11
|
CommonTypedDict,
|
@@ -48,6 +49,15 @@ class PgDiskAnnTypedDict(CommonTypedDict):
|
|
48
49
|
help="PgDiskAnn l_value_ib",
|
49
50
|
),
|
50
51
|
]
|
52
|
+
pq_param_num_chunks: Annotated[
|
53
|
+
int,
|
54
|
+
click.option(
|
55
|
+
"--pq-param-num-chunks",
|
56
|
+
type=int,
|
57
|
+
help="PgDiskAnn pq_param_num_chunks",
|
58
|
+
required=False,
|
59
|
+
),
|
60
|
+
]
|
51
61
|
l_value_is: Annotated[
|
52
62
|
float,
|
53
63
|
click.option(
|
@@ -56,6 +66,37 @@ class PgDiskAnnTypedDict(CommonTypedDict):
|
|
56
66
|
help="PgDiskAnn l_value_is",
|
57
67
|
),
|
58
68
|
]
|
69
|
+
reranking: Annotated[
|
70
|
+
bool | None,
|
71
|
+
click.option(
|
72
|
+
"--reranking/--skip-reranking",
|
73
|
+
type=bool,
|
74
|
+
help="Enable reranking for PQ search",
|
75
|
+
default=False,
|
76
|
+
),
|
77
|
+
]
|
78
|
+
reranking_metric: Annotated[
|
79
|
+
str | None,
|
80
|
+
click.option(
|
81
|
+
"--reranking-metric",
|
82
|
+
type=click.Choice(
|
83
|
+
[metric.value for metric in MetricType if metric.value not in ["HAMMING", "JACCARD", "DP"]],
|
84
|
+
),
|
85
|
+
help="Distance metric for reranking",
|
86
|
+
default="COSINE",
|
87
|
+
show_default=True,
|
88
|
+
required=False,
|
89
|
+
),
|
90
|
+
]
|
91
|
+
quantized_fetch_limit: Annotated[
|
92
|
+
int | None,
|
93
|
+
click.option(
|
94
|
+
"--quantized-fetch-limit",
|
95
|
+
type=int,
|
96
|
+
help="Limit of inner query in case of reranking",
|
97
|
+
required=False,
|
98
|
+
),
|
99
|
+
]
|
59
100
|
maintenance_work_mem: Annotated[
|
60
101
|
str | None,
|
61
102
|
click.option(
|
@@ -98,7 +139,11 @@ def PgDiskAnn(
|
|
98
139
|
db_case_config=PgDiskANNImplConfig(
|
99
140
|
max_neighbors=parameters["max_neighbors"],
|
100
141
|
l_value_ib=parameters["l_value_ib"],
|
142
|
+
pq_param_num_chunks=parameters["pq_param_num_chunks"],
|
101
143
|
l_value_is=parameters["l_value_is"],
|
144
|
+
reranking=parameters["reranking"],
|
145
|
+
reranking_metric=parameters["reranking_metric"],
|
146
|
+
quantized_fetch_limit=parameters["quantized_fetch_limit"],
|
102
147
|
max_parallel_workers=parameters["max_parallel_workers"],
|
103
148
|
maintenance_work_mem=parameters["maintenance_work_mem"],
|
104
149
|
),
|
@@ -60,6 +60,13 @@ class PgDiskANNIndexConfig(BaseModel, DBCaseConfig):
|
|
60
60
|
return "<#>"
|
61
61
|
return "<=>"
|
62
62
|
|
63
|
+
def parse_reranking_metric_fun_op(self) -> LiteralString:
|
64
|
+
if self.reranking_metric == MetricType.L2:
|
65
|
+
return "<->"
|
66
|
+
if self.reranking_metric == MetricType.IP:
|
67
|
+
return "<#>"
|
68
|
+
return "<=>"
|
69
|
+
|
63
70
|
def parse_metric_fun_str(self) -> str:
|
64
71
|
if self.metric_type == MetricType.L2:
|
65
72
|
return "l2_distance"
|
@@ -115,7 +122,11 @@ class PgDiskANNImplConfig(PgDiskANNIndexConfig):
|
|
115
122
|
index: IndexType = IndexType.DISKANN
|
116
123
|
max_neighbors: int | None
|
117
124
|
l_value_ib: int | None
|
125
|
+
pq_param_num_chunks: int | None
|
118
126
|
l_value_is: float | None
|
127
|
+
reranking: bool | None = None
|
128
|
+
reranking_metric: str | None = None
|
129
|
+
quantized_fetch_limit: int | None = None
|
119
130
|
maintenance_work_mem: str | None = None
|
120
131
|
max_parallel_workers: int | None = None
|
121
132
|
|
@@ -126,6 +137,8 @@ class PgDiskANNImplConfig(PgDiskANNIndexConfig):
|
|
126
137
|
"options": {
|
127
138
|
"max_neighbors": self.max_neighbors,
|
128
139
|
"l_value_ib": self.l_value_ib,
|
140
|
+
"pq_param_num_chunks": self.pq_param_num_chunks,
|
141
|
+
"product_quantized": str(self.reranking),
|
129
142
|
},
|
130
143
|
"maintenance_work_mem": self.maintenance_work_mem,
|
131
144
|
"max_parallel_workers": self.max_parallel_workers,
|
@@ -135,6 +148,9 @@ class PgDiskANNImplConfig(PgDiskANNIndexConfig):
|
|
135
148
|
return {
|
136
149
|
"metric": self.parse_metric(),
|
137
150
|
"metric_fun_op": self.parse_metric_fun_op(),
|
151
|
+
"reranking": self.reranking,
|
152
|
+
"reranking_metric_fun_op": self.parse_reranking_metric_fun_op(),
|
153
|
+
"quantized_fetch_limit": self.quantized_fetch_limit,
|
138
154
|
}
|
139
155
|
|
140
156
|
def session_param(self) -> dict:
|
@@ -90,38 +90,83 @@ class PgDiskANN(VectorDB):
|
|
90
90
|
def init(self) -> Generator[None, None, None]:
|
91
91
|
self.conn, self.cursor = self._create_connection(**self.db_config)
|
92
92
|
|
93
|
-
# index configuration may have commands defined that we should set during each client session
|
94
93
|
session_options: dict[str, Any] = self.case_config.session_param()
|
95
94
|
|
96
95
|
if len(session_options) > 0:
|
97
96
|
for setting_name, setting_val in session_options.items():
|
98
|
-
command = sql.SQL("SET {setting_name}
|
99
|
-
setting_name=sql.Identifier(setting_name),
|
100
|
-
setting_val=sql.Identifier(str(setting_val)),
|
97
|
+
command = sql.SQL("SET {setting_name} = {setting_val};").format(
|
98
|
+
setting_name=sql.Identifier(setting_name), setting_val=sql.Literal(setting_val)
|
101
99
|
)
|
102
100
|
log.debug(command.as_string(self.cursor))
|
103
101
|
self.cursor.execute(command)
|
104
102
|
self.conn.commit()
|
105
103
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
104
|
+
search_params = self.case_config.search_param()
|
105
|
+
|
106
|
+
if search_params.get("reranking"):
|
107
|
+
# Reranking-enabled queries
|
108
|
+
self._filtered_search = sql.SQL(
|
109
|
+
"""
|
110
|
+
SELECT i.id
|
111
|
+
FROM (
|
112
|
+
SELECT id, embedding
|
113
|
+
FROM public.{table_name}
|
114
|
+
WHERE id >= %s
|
115
|
+
ORDER BY embedding {metric_fun_op} %s::vector
|
116
|
+
LIMIT {quantized_fetch_limit}::int
|
117
|
+
) i
|
118
|
+
ORDER BY i.embedding {reranking_metric_fun_op} %s::vector
|
119
|
+
LIMIT %s::int
|
120
|
+
"""
|
121
|
+
).format(
|
122
|
+
table_name=sql.Identifier(self.table_name),
|
123
|
+
metric_fun_op=sql.SQL(search_params["metric_fun_op"]),
|
124
|
+
reranking_metric_fun_op=sql.SQL(search_params["reranking_metric_fun_op"]),
|
125
|
+
quantized_fetch_limit=sql.Literal(search_params["quantized_fetch_limit"]),
|
126
|
+
)
|
115
127
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
128
|
+
self._unfiltered_search = sql.SQL(
|
129
|
+
"""
|
130
|
+
SELECT i.id
|
131
|
+
FROM (
|
132
|
+
SELECT id, embedding
|
133
|
+
FROM public.{table_name}
|
134
|
+
ORDER BY embedding {metric_fun_op} %s::vector
|
135
|
+
LIMIT {quantized_fetch_limit}::int
|
136
|
+
) i
|
137
|
+
ORDER BY i.embedding {reranking_metric_fun_op} %s::vector
|
138
|
+
LIMIT %s::int
|
139
|
+
"""
|
140
|
+
).format(
|
141
|
+
table_name=sql.Identifier(self.table_name),
|
142
|
+
metric_fun_op=sql.SQL(search_params["metric_fun_op"]),
|
143
|
+
reranking_metric_fun_op=sql.SQL(search_params["reranking_metric_fun_op"]),
|
144
|
+
quantized_fetch_limit=sql.Literal(search_params["quantized_fetch_limit"]),
|
145
|
+
)
|
146
|
+
|
147
|
+
else:
|
148
|
+
self._filtered_search = sql.Composed(
|
149
|
+
[
|
150
|
+
sql.SQL(
|
151
|
+
"SELECT id FROM public.{table_name} WHERE id >= %s ORDER BY embedding ",
|
152
|
+
).format(table_name=sql.Identifier(self.table_name)),
|
153
|
+
sql.SQL(search_params["metric_fun_op"]),
|
154
|
+
sql.SQL(" %s::vector LIMIT %s::int"),
|
155
|
+
]
|
156
|
+
)
|
157
|
+
|
158
|
+
self._unfiltered_search = sql.Composed(
|
159
|
+
[
|
160
|
+
sql.SQL("SELECT id FROM public.{table_name} ORDER BY embedding ").format(
|
161
|
+
table_name=sql.Identifier(self.table_name)
|
162
|
+
),
|
163
|
+
sql.SQL(search_params["metric_fun_op"]),
|
164
|
+
sql.SQL(" %s::vector LIMIT %s::int"),
|
165
|
+
]
|
166
|
+
)
|
167
|
+
|
168
|
+
log.debug(f"Unfiltered search query={self._unfiltered_search.as_string(self.conn)}")
|
169
|
+
log.debug(f"Filtered search query={self._filtered_search.as_string(self.conn)}")
|
125
170
|
|
126
171
|
try:
|
127
172
|
yield
|
@@ -234,7 +279,7 @@ class PgDiskANN(VectorDB):
|
|
234
279
|
options.append(
|
235
280
|
sql.SQL("{option_name} = {val}").format(
|
236
281
|
option_name=sql.Identifier(option_name),
|
237
|
-
val=sql.
|
282
|
+
val=sql.Literal(option_val),
|
238
283
|
),
|
239
284
|
)
|
240
285
|
|
@@ -314,16 +359,39 @@ class PgDiskANN(VectorDB):
|
|
314
359
|
assert self.conn is not None, "Connection is not initialized"
|
315
360
|
assert self.cursor is not None, "Cursor is not initialized"
|
316
361
|
|
362
|
+
search_params = self.case_config.search_param()
|
363
|
+
is_reranking = search_params.get("reranking", False)
|
364
|
+
|
317
365
|
q = np.asarray(query)
|
318
366
|
if filters:
|
319
367
|
gt = filters.get("id")
|
368
|
+
if is_reranking:
|
369
|
+
result = self.cursor.execute(
|
370
|
+
self._filtered_search,
|
371
|
+
(gt, q, q, k),
|
372
|
+
prepare=True,
|
373
|
+
binary=True,
|
374
|
+
)
|
375
|
+
else:
|
376
|
+
result = self.cursor.execute(
|
377
|
+
self._filtered_search,
|
378
|
+
(gt, q, k),
|
379
|
+
prepare=True,
|
380
|
+
binary=True,
|
381
|
+
)
|
382
|
+
elif is_reranking:
|
320
383
|
result = self.cursor.execute(
|
321
|
-
self.
|
322
|
-
(
|
384
|
+
self._unfiltered_search,
|
385
|
+
(q, q, k),
|
323
386
|
prepare=True,
|
324
387
|
binary=True,
|
325
388
|
)
|
326
389
|
else:
|
327
|
-
result = self.cursor.execute(
|
390
|
+
result = self.cursor.execute(
|
391
|
+
self._unfiltered_search,
|
392
|
+
(q, k),
|
393
|
+
prepare=True,
|
394
|
+
binary=True,
|
395
|
+
)
|
328
396
|
|
329
397
|
return [int(i[0]) for i in result.fetchall()]
|
@@ -36,6 +36,17 @@ class ZillizTypedDict(CommonTypedDict):
|
|
36
36
|
str,
|
37
37
|
click.option("--level", type=str, help="Zilliz index level", required=False),
|
38
38
|
]
|
39
|
+
num_shards: Annotated[
|
40
|
+
int,
|
41
|
+
click.option(
|
42
|
+
"--num-shards",
|
43
|
+
type=int,
|
44
|
+
help="Number of shards",
|
45
|
+
required=False,
|
46
|
+
default=1,
|
47
|
+
show_default=True,
|
48
|
+
),
|
49
|
+
]
|
39
50
|
|
40
51
|
|
41
52
|
@cli.command()
|
@@ -50,9 +61,11 @@ def ZillizAutoIndex(**parameters: Unpack[ZillizTypedDict]):
|
|
50
61
|
uri=SecretStr(parameters["uri"]),
|
51
62
|
user=parameters["user_name"],
|
52
63
|
password=SecretStr(parameters["password"]),
|
64
|
+
num_shards=parameters["num_shards"],
|
53
65
|
),
|
54
66
|
db_case_config=AutoIndexConfig(
|
55
|
-
|
67
|
+
level=int(parameters["level"]) if parameters["level"] else 1,
|
68
|
+
num_shards=parameters["num_shards"],
|
56
69
|
),
|
57
70
|
**parameters,
|
58
71
|
)
|
@@ -8,24 +8,27 @@ class ZillizCloudConfig(DBConfig):
|
|
8
8
|
uri: SecretStr
|
9
9
|
user: str
|
10
10
|
password: SecretStr
|
11
|
+
num_shards: int = 1
|
11
12
|
|
12
13
|
def to_dict(self) -> dict:
|
13
14
|
return {
|
14
15
|
"uri": self.uri.get_secret_value(),
|
15
16
|
"user": self.user,
|
16
17
|
"password": self.password.get_secret_value(),
|
18
|
+
"num_shards": self.num_shards,
|
17
19
|
}
|
18
20
|
|
19
21
|
|
20
22
|
class AutoIndexConfig(MilvusIndexConfig, DBCaseConfig):
|
21
23
|
index: IndexType = IndexType.AUTOINDEX
|
22
24
|
level: int = 1
|
25
|
+
num_shards: int = 1
|
23
26
|
|
24
27
|
def index_param(self) -> dict:
|
25
28
|
return {
|
26
29
|
"metric_type": self.parse_metric(),
|
27
30
|
"index_type": self.index.value,
|
28
|
-
"params": {},
|
31
|
+
"params": {"shardsNum": self.num_shards},
|
29
32
|
}
|
30
33
|
|
31
34
|
def search_param(self) -> dict:
|
@@ -3,9 +3,11 @@ import logging
|
|
3
3
|
import multiprocessing as mp
|
4
4
|
import time
|
5
5
|
from concurrent.futures import ThreadPoolExecutor
|
6
|
+
from copy import deepcopy
|
6
7
|
|
7
8
|
from vectordb_bench import config
|
8
9
|
from vectordb_bench.backend.clients import api
|
10
|
+
from vectordb_bench.backend.clients.pgvector.pgvector import PgVector
|
9
11
|
from vectordb_bench.backend.dataset import DataSetIterator
|
10
12
|
from vectordb_bench.backend.utils import time_it
|
11
13
|
|
@@ -33,17 +35,27 @@ class RatedMultiThreadingInsertRunner:
|
|
33
35
|
self.executing_futures = []
|
34
36
|
self.sig_idx = 0
|
35
37
|
|
36
|
-
def send_insert_task(self, db: api.VectorDB, emb: list[list[float]], metadata: list[str]
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
38
|
+
def send_insert_task(self, db: api.VectorDB, emb: list[list[float]], metadata: list[str]):
|
39
|
+
def _insert_embeddings(db: api.VectorDB, emb: list[list[float]], metadata: list[str], retry_idx: int = 0):
|
40
|
+
_, error = db.insert_embeddings(emb, metadata)
|
41
|
+
if error is not None:
|
42
|
+
log.warning(f"Insert Failed, try_idx={retry_idx}, Exception: {error}")
|
43
|
+
retry_idx += 1
|
44
|
+
if retry_idx <= config.MAX_INSERT_RETRY:
|
45
|
+
time.sleep(retry_idx)
|
46
|
+
_insert_embeddings(db, emb=emb, metadata=metadata, retry_idx=retry_idx)
|
47
|
+
else:
|
48
|
+
msg = f"Insert failed and retried more than {config.MAX_INSERT_RETRY} times"
|
49
|
+
raise RuntimeError(msg) from None
|
50
|
+
|
51
|
+
if isinstance(db, PgVector):
|
52
|
+
# pgvector is not thread-safe for concurrent insert,
|
53
|
+
# so we need to copy the db object, make sure each thread has its own connection
|
54
|
+
db_copy = deepcopy(db)
|
55
|
+
with db_copy.init():
|
56
|
+
_insert_embeddings(db_copy, emb, metadata, retry_idx=0)
|
57
|
+
else:
|
58
|
+
_insert_embeddings(db, emb, metadata, retry_idx=0)
|
47
59
|
|
48
60
|
@time_it
|
49
61
|
def run_with_rate(self, q: mp.Queue):
|
vectordb_bench/cli/cli.py
CHANGED
@@ -183,6 +183,11 @@ def get_custom_case_config(parameters: dict) -> dict:
|
|
183
183
|
"with_gt": parameters["custom_dataset_with_gt"],
|
184
184
|
},
|
185
185
|
}
|
186
|
+
elif parameters["case_type"] == "NewIntFilterPerformanceCase" :
|
187
|
+
custom_case_config = {
|
188
|
+
"dataset_with_size_type" : parameters["dataset_with_size_type"],
|
189
|
+
"filter_rate": parameters["filter_rate"],
|
190
|
+
}
|
186
191
|
return custom_case_config
|
187
192
|
|
188
193
|
|
@@ -416,7 +421,24 @@ class CommonTypedDict(TypedDict):
|
|
416
421
|
),
|
417
422
|
]
|
418
423
|
task_label: Annotated[str, click.option("--task-label", help="Task label")]
|
419
|
-
|
424
|
+
dataset_with_size_type: Annotated[
|
425
|
+
str,
|
426
|
+
click.option(
|
427
|
+
"--dataset-with-size-type",
|
428
|
+
help="Dataset with size type for NewIntFilterPerformanceCase, you can use Medium Cohere (768dim, 1M)|Large Cohere (768dim, 10M)|Medium Bioasq (1024dim, 1M)|Large Bioasq (1024dim, 10M)|Large OpenAI (1536dim, 5M)|Medium OpenAI (1536dim, 500K)",
|
429
|
+
default="Medium Cohere (768dim, 1M)",
|
430
|
+
show_default=True,
|
431
|
+
)
|
432
|
+
]
|
433
|
+
filter_rate: Annotated[
|
434
|
+
float,
|
435
|
+
click.option(
|
436
|
+
"--filter-rate",
|
437
|
+
help="Filter rate for NewIntFilterPerformanceCase",
|
438
|
+
default=0.01,
|
439
|
+
show_default=True,
|
440
|
+
)
|
441
|
+
]
|
420
442
|
|
421
443
|
class HNSWBaseTypedDict(TypedDict):
|
422
444
|
m: Annotated[int | None, click.option("--m", type=int, help="hnsw m")]
|
@@ -471,6 +493,33 @@ class HNSWFlavor4(HNSWBaseRequiredTypedDict):
|
|
471
493
|
]
|
472
494
|
|
473
495
|
|
496
|
+
class HNSWFlavor5(HNSWBaseRequiredTypedDict):
|
497
|
+
ef_search: Annotated[
|
498
|
+
int | None,
|
499
|
+
click.option("--ef-search", type=int, help="hnsw ef-search", required=True),
|
500
|
+
]
|
501
|
+
index_type: Annotated[
|
502
|
+
str | None,
|
503
|
+
click.option(
|
504
|
+
"--index-type",
|
505
|
+
type=click.Choice(["HGraph"], case_sensitive=True),
|
506
|
+
help="Type of index to use. Supported values: HGraph",
|
507
|
+
required=True,
|
508
|
+
),
|
509
|
+
]
|
510
|
+
use_reorder: Annotated[
|
511
|
+
bool,
|
512
|
+
click.option(
|
513
|
+
"--use-reorder/--no-use-reorder",
|
514
|
+
is_flag=True,
|
515
|
+
type=bool,
|
516
|
+
help="use reorder index",
|
517
|
+
default=True,
|
518
|
+
show_default=True,
|
519
|
+
),
|
520
|
+
]
|
521
|
+
|
522
|
+
|
474
523
|
class IVFFlatTypedDict(TypedDict):
|
475
524
|
lists: Annotated[int | None, click.option("--lists", type=int, help="ivfflat lists")]
|
476
525
|
probes: Annotated[int | None, click.option("--probes", type=int, help="ivfflat probes")]
|
@@ -501,6 +550,15 @@ class OceanBaseIVFTypedDict(TypedDict):
|
|
501
550
|
int | None,
|
502
551
|
click.option("--nlist", "nlist", type=int, help="Number of cluster centers", required=True),
|
503
552
|
]
|
553
|
+
nbits: Annotated[
|
554
|
+
int | None,
|
555
|
+
click.option(
|
556
|
+
"--nbits",
|
557
|
+
"nbits",
|
558
|
+
type=int,
|
559
|
+
help="Number of bits used to encode the index of a sub-vector's centroid in the compressed representation",
|
560
|
+
),
|
561
|
+
]
|
504
562
|
sample_per_nlist: Annotated[
|
505
563
|
int | None,
|
506
564
|
click.option(
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from ..backend.clients.alloydb.cli import AlloyDBScaNN
|
2
2
|
from ..backend.clients.aws_opensearch.cli import AWSOpenSearch
|
3
3
|
from ..backend.clients.clickhouse.cli import Clickhouse
|
4
|
+
from ..backend.clients.hologres.cli import HologresHGraph
|
4
5
|
from ..backend.clients.lancedb.cli import LanceDB
|
5
6
|
from ..backend.clients.mariadb.cli import MariaDBHNSW
|
6
7
|
from ..backend.clients.memorydb.cli import MemoryDB
|
@@ -43,6 +44,7 @@ cli.add_command(TiDB)
|
|
43
44
|
cli.add_command(Clickhouse)
|
44
45
|
cli.add_command(Vespa)
|
45
46
|
cli.add_command(LanceDB)
|
47
|
+
cli.add_command(HologresHGraph)
|
46
48
|
cli.add_command(QdrantCloud)
|
47
49
|
cli.add_command(QdrantLocal)
|
48
50
|
cli.add_command(BatchCli)
|
@@ -423,8 +423,58 @@ CaseConfigParamInput_storage_layout = CaseConfigInput(
|
|
423
423
|
},
|
424
424
|
)
|
425
425
|
|
426
|
-
|
426
|
+
CaseConfigParamInput_reranking_PgDiskANN = CaseConfigInput(
|
427
|
+
label=CaseConfigParamType.reranking,
|
428
|
+
inputType=InputType.Bool,
|
429
|
+
displayLabel="Enable Reranking",
|
430
|
+
inputHelp="Enable if you want to use reranking while performing \
|
431
|
+
similarity search with PQ",
|
432
|
+
inputConfig={
|
433
|
+
"value": False,
|
434
|
+
},
|
435
|
+
)
|
436
|
+
|
437
|
+
CaseConfigParamInput_quantized_fetch_limit_PgDiskANN = CaseConfigInput(
|
438
|
+
label=CaseConfigParamType.quantized_fetch_limit,
|
439
|
+
displayLabel="Quantized Fetch Limit",
|
440
|
+
inputHelp="Limit top-k vectors using the quantized vector comparison",
|
441
|
+
inputType=InputType.Number,
|
442
|
+
inputConfig={
|
443
|
+
"min": 20,
|
444
|
+
"max": 1000,
|
445
|
+
"value": 200,
|
446
|
+
},
|
447
|
+
isDisplayed=lambda config: config.get(CaseConfigParamType.reranking, False),
|
448
|
+
)
|
449
|
+
|
450
|
+
CaseConfigParamInput_pq_param_num_chunks_PgDiskANN = CaseConfigInput(
|
451
|
+
label=CaseConfigParamType.pq_param_num_chunks,
|
452
|
+
displayLabel="pq_param_num_chunks",
|
453
|
+
inputHelp="Number of chunks for product quantization (Defaults to 0). 0 means it is determined automatically, based on embedding dimensions.",
|
454
|
+
inputType=InputType.Number,
|
455
|
+
inputConfig={
|
456
|
+
"min": 0,
|
457
|
+
"max": 1028,
|
458
|
+
"value": 0,
|
459
|
+
},
|
460
|
+
isDisplayed=lambda config: config.get(CaseConfigParamType.reranking, False),
|
461
|
+
)
|
462
|
+
|
463
|
+
|
464
|
+
CaseConfigParamInput_reranking_metric_PgDiskANN = CaseConfigInput(
|
465
|
+
label=CaseConfigParamType.reranking_metric,
|
466
|
+
displayLabel="Reranking Metric",
|
467
|
+
inputType=InputType.Option,
|
468
|
+
inputConfig={
|
469
|
+
"options": [metric.value for metric in MetricType if metric.value not in ["HAMMING", "JACCARD", "DP"]],
|
470
|
+
},
|
471
|
+
isDisplayed=lambda config: config.get(CaseConfigParamType.reranking, False),
|
472
|
+
)
|
473
|
+
|
474
|
+
|
475
|
+
CaseConfigParamInput_max_neighbors_PgDiskANN = CaseConfigInput(
|
427
476
|
label=CaseConfigParamType.max_neighbors,
|
477
|
+
displayLabel="max_neighbors",
|
428
478
|
inputType=InputType.Number,
|
429
479
|
inputConfig={
|
430
480
|
"min": 10,
|
@@ -456,6 +506,29 @@ CaseConfigParamInput_l_value_is = CaseConfigInput(
|
|
456
506
|
isDisplayed=lambda config: config.get(CaseConfigParamType.IndexType, None) == IndexType.DISKANN.value,
|
457
507
|
)
|
458
508
|
|
509
|
+
CaseConfigParamInput_maintenance_work_mem_PgDiskANN = CaseConfigInput(
|
510
|
+
label=CaseConfigParamType.maintenance_work_mem,
|
511
|
+
inputHelp="Memory to use during index builds. Not to exceed the available free memory."
|
512
|
+
"Specify in gigabytes. e.g. 8GB",
|
513
|
+
inputType=InputType.Text,
|
514
|
+
inputConfig={
|
515
|
+
"value": "8GB",
|
516
|
+
},
|
517
|
+
)
|
518
|
+
|
519
|
+
CaseConfigParamInput_max_parallel_workers_PgDiskANN = CaseConfigInput(
|
520
|
+
label=CaseConfigParamType.max_parallel_workers,
|
521
|
+
displayLabel="Max parallel workers",
|
522
|
+
inputHelp="Recommended value: (cpu cores - 1). This will set the parameters: max_parallel_maintenance_workers,"
|
523
|
+
" max_parallel_workers & table(parallel_workers)",
|
524
|
+
inputType=InputType.Number,
|
525
|
+
inputConfig={
|
526
|
+
"min": 0,
|
527
|
+
"max": 1024,
|
528
|
+
"value": 16,
|
529
|
+
},
|
530
|
+
)
|
531
|
+
|
459
532
|
CaseConfigParamInput_num_neighbors = CaseConfigInput(
|
460
533
|
label=CaseConfigParamType.num_neighbors,
|
461
534
|
inputType=InputType.Number,
|
@@ -1796,15 +1869,21 @@ PgVectorScalePerformanceConfig = [
|
|
1796
1869
|
|
1797
1870
|
PgDiskANNLoadConfig = [
|
1798
1871
|
CaseConfigParamInput_IndexType_PgDiskANN,
|
1799
|
-
|
1872
|
+
CaseConfigParamInput_max_neighbors_PgDiskANN,
|
1800
1873
|
CaseConfigParamInput_l_value_ib,
|
1801
1874
|
]
|
1802
1875
|
|
1803
1876
|
PgDiskANNPerformanceConfig = [
|
1804
1877
|
CaseConfigParamInput_IndexType_PgDiskANN,
|
1805
|
-
|
1878
|
+
CaseConfigParamInput_reranking_PgDiskANN,
|
1879
|
+
CaseConfigParamInput_max_neighbors_PgDiskANN,
|
1806
1880
|
CaseConfigParamInput_l_value_ib,
|
1807
1881
|
CaseConfigParamInput_l_value_is,
|
1882
|
+
CaseConfigParamInput_maintenance_work_mem_PgDiskANN,
|
1883
|
+
CaseConfigParamInput_max_parallel_workers_PgDiskANN,
|
1884
|
+
CaseConfigParamInput_pq_param_num_chunks_PgDiskANN,
|
1885
|
+
CaseConfigParamInput_quantized_fetch_limit_PgDiskANN,
|
1886
|
+
CaseConfigParamInput_reranking_metric_PgDiskANN,
|
1808
1887
|
]
|
1809
1888
|
|
1810
1889
|
|
@@ -67,6 +67,7 @@ DB_TO_ICON = {
|
|
67
67
|
DB.LanceDB: "data:image/png;base64,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",
|
68
68
|
DB.OceanBase: "data:image/png;base64,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",
|
69
69
|
DB.S3Vectors: "https://assets.zilliz.com/s3_vectors_daf370b4e5.png",
|
70
|
+
DB.Hologres: "https://img.alicdn.com/imgextra/i3/O1CN01d9qrry1i6lTNa2BRa_!!6000000004364-2-tps-218-200.png",
|
70
71
|
}
|
71
72
|
|
72
73
|
# RedisCloud color: #0D6EFD
|
vectordb_bench/interface.py
CHANGED
@@ -43,7 +43,11 @@ class BenchMarkRunner:
|
|
43
43
|
self.running_task: TaskRunner | None = None
|
44
44
|
self.latest_error: str | None = None
|
45
45
|
self.drop_old: bool = True
|
46
|
-
|
46
|
+
# set default data source by ENV
|
47
|
+
if config.DATASET_SOURCE.upper() == "ALIYUNOSS":
|
48
|
+
self.dataset_source: DatasetSource = DatasetSource.AliyunOSS
|
49
|
+
else:
|
50
|
+
self.dataset_source: DatasetSource = DatasetSource.S3
|
47
51
|
|
48
52
|
def set_drop_old(self, drop_old: bool):
|
49
53
|
self.drop_old = drop_old
|
vectordb_bench/models.py
CHANGED
@@ -86,6 +86,9 @@ class CaseConfigParamType(Enum):
|
|
86
86
|
storage_layout = "storage_layout"
|
87
87
|
num_neighbors = "num_neighbors"
|
88
88
|
max_neighbors = "max_neighbors"
|
89
|
+
quantized_fetch_limit = "quantized_fetch_limit"
|
90
|
+
pq_param_num_chunks = "pq_param_num_chunks"
|
91
|
+
reranking_metric = "reranking_metric"
|
89
92
|
l_value_ib = "l_value_ib"
|
90
93
|
l_value_is = "l_value_is"
|
91
94
|
search_list_size = "search_list_size"
|
@@ -124,6 +127,7 @@ class CaseConfigParamType(Enum):
|
|
124
127
|
use_routing = "use_routing"
|
125
128
|
|
126
129
|
dataset_with_size_type = "dataset_with_size_type"
|
130
|
+
filter_rate = "filter_rate"
|
127
131
|
insert_rate = "insert_rate"
|
128
132
|
search_stages = "search_stages"
|
129
133
|
concurrencies = "concurrencies"
|