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.
- vectordb_bench/backend/cases.py +45 -1
- vectordb_bench/backend/clients/__init__.py +32 -0
- vectordb_bench/backend/clients/aliyun_opensearch/aliyun_opensearch.py +34 -42
- vectordb_bench/backend/clients/aliyun_opensearch/config.py +0 -7
- vectordb_bench/backend/clients/milvus/cli.py +216 -0
- vectordb_bench/backend/clients/oss_opensearch/cli.py +155 -0
- vectordb_bench/backend/clients/oss_opensearch/config.py +157 -0
- vectordb_bench/backend/clients/oss_opensearch/oss_opensearch.py +582 -0
- vectordb_bench/backend/clients/oss_opensearch/run.py +166 -0
- vectordb_bench/backend/clients/s3_vectors/config.py +41 -0
- vectordb_bench/backend/clients/s3_vectors/s3_vectors.py +171 -0
- vectordb_bench/backend/clients/tidb/cli.py +0 -4
- vectordb_bench/backend/clients/tidb/config.py +22 -2
- vectordb_bench/backend/dataset.py +70 -0
- vectordb_bench/backend/filter.py +17 -0
- vectordb_bench/backend/runner/mp_runner.py +4 -0
- vectordb_bench/backend/runner/read_write_runner.py +10 -9
- vectordb_bench/backend/runner/serial_runner.py +23 -7
- vectordb_bench/backend/task_runner.py +5 -4
- vectordb_bench/cli/vectordbbench.py +2 -0
- vectordb_bench/fig/custom_case_run_test.png +0 -0
- vectordb_bench/fig/custom_dataset.png +0 -0
- vectordb_bench/fig/homepage/bar-chart.png +0 -0
- vectordb_bench/fig/homepage/concurrent.png +0 -0
- vectordb_bench/fig/homepage/custom.png +0 -0
- vectordb_bench/fig/homepage/label_filter.png +0 -0
- vectordb_bench/fig/homepage/qp$.png +0 -0
- vectordb_bench/fig/homepage/run_test.png +0 -0
- vectordb_bench/fig/homepage/streaming.png +0 -0
- vectordb_bench/fig/homepage/table.png +0 -0
- vectordb_bench/fig/run_test_select_case.png +0 -0
- vectordb_bench/fig/run_test_select_db.png +0 -0
- vectordb_bench/fig/run_test_submit.png +0 -0
- vectordb_bench/frontend/components/check_results/filters.py +1 -4
- vectordb_bench/frontend/components/check_results/nav.py +2 -1
- vectordb_bench/frontend/components/concurrent/charts.py +5 -0
- vectordb_bench/frontend/components/int_filter/charts.py +60 -0
- vectordb_bench/frontend/components/streaming/data.py +7 -0
- vectordb_bench/frontend/components/welcome/welcomePrams.py +42 -4
- vectordb_bench/frontend/config/dbCaseConfigs.py +60 -13
- vectordb_bench/frontend/config/styles.py +3 -0
- vectordb_bench/frontend/pages/concurrent.py +1 -1
- vectordb_bench/frontend/pages/custom.py +1 -1
- vectordb_bench/frontend/pages/int_filter.py +56 -0
- vectordb_bench/frontend/pages/streaming.py +16 -3
- vectordb_bench/metric.py +7 -0
- vectordb_bench/models.py +36 -4
- vectordb_bench/results/S3Vectors/result_20250722_standard_s3vectors.json +2509 -0
- {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/METADATA +1 -3
- {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/RECORD +54 -32
- {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/WHEEL +0 -0
- {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/entry_points.txt +0 -0
- {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/licenses/LICENSE +0 -0
- {vectordb_bench-1.0.3.dist-info → vectordb_bench-1.0.5.dist-info}/top_level.txt +0 -0
@@ -71,7 +71,6 @@ def main():
|
|
71
71
|
getResults(resultesContainer, "vectordb_bench_streaming")
|
72
72
|
|
73
73
|
# # main
|
74
|
-
# latency_type = st.radio("Latency Type", options=["latency_p99", "latency_avg"])
|
75
74
|
st.markdown("Tests search performance with a **stable** and **fixed** insertion rate.")
|
76
75
|
control_panel = st.columns(3)
|
77
76
|
compared_with_optimized = control_panel[0].toggle(
|
@@ -84,6 +83,15 @@ def main():
|
|
84
83
|
value=False,
|
85
84
|
help="Since vdbbench inserts may be faster than vetordb can process them, the time it actually reaches search_stage may have different delays.",
|
86
85
|
)
|
86
|
+
|
87
|
+
# Latency type selection
|
88
|
+
latency_type = control_panel[2].radio(
|
89
|
+
"Latency Type",
|
90
|
+
options=["latency_p99", "latency_p95"],
|
91
|
+
index=0,
|
92
|
+
help="Choose between P99 (slowest 1%) or P95 (slowest 5%) latency metrics.",
|
93
|
+
)
|
94
|
+
|
87
95
|
accuracy_metric = DisplayedMetric.recall
|
88
96
|
show_ndcg = control_panel[1].toggle(
|
89
97
|
"Show **NDCG** instead of Recall.",
|
@@ -103,6 +111,11 @@ def main():
|
|
103
111
|
else:
|
104
112
|
if need_adjust:
|
105
113
|
accuracy_metric = DisplayedMetric.adjusted_recall
|
114
|
+
|
115
|
+
# Determine which latency metric to display
|
116
|
+
latency_metric = DisplayedMetric.latency_p99 if latency_type == "latency_p99" else DisplayedMetric.latency_p95
|
117
|
+
latency_desc = "serial lantency (p99)" if latency_type == "latency_p99" else "serial lantency (p95)"
|
118
|
+
|
106
119
|
line_chart_displayed_y_metrics: list[tuple[DisplayedMetric, str]] = [
|
107
120
|
(
|
108
121
|
DisplayedMetric.qps,
|
@@ -110,8 +123,8 @@ def main():
|
|
110
123
|
),
|
111
124
|
(accuracy_metric, "calculated in each search_stage."),
|
112
125
|
(
|
113
|
-
|
114
|
-
"
|
126
|
+
latency_metric,
|
127
|
+
f"{latency_desc} of **serial search** tests in each search stage.",
|
115
128
|
),
|
116
129
|
]
|
117
130
|
line_chart_displayed_x_metric = DisplayedMetric.search_stage
|
vectordb_bench/metric.py
CHANGED
@@ -21,11 +21,13 @@ class Metric:
|
|
21
21
|
# for performance cases
|
22
22
|
qps: float = 0.0
|
23
23
|
serial_latency_p99: float = 0.0
|
24
|
+
serial_latency_p95: float = 0.0
|
24
25
|
recall: float = 0.0
|
25
26
|
ndcg: float = 0.0
|
26
27
|
conc_num_list: list[int] = field(default_factory=list)
|
27
28
|
conc_qps_list: list[float] = field(default_factory=list)
|
28
29
|
conc_latency_p99_list: list[float] = field(default_factory=list)
|
30
|
+
conc_latency_p95_list: list[float] = field(default_factory=list)
|
29
31
|
conc_latency_avg_list: list[float] = field(default_factory=list)
|
30
32
|
|
31
33
|
# for streaming cases
|
@@ -36,12 +38,14 @@ class Metric:
|
|
36
38
|
st_recall_list: list[float] = field(default_factory=list)
|
37
39
|
st_ndcg_list: list[float] = field(default_factory=list)
|
38
40
|
st_serial_latency_p99_list: list[float] = field(default_factory=list)
|
41
|
+
st_serial_latency_p95_list: list[float] = field(default_factory=list)
|
39
42
|
st_conc_failed_rate_list: list[float] = field(default_factory=list)
|
40
43
|
|
41
44
|
|
42
45
|
QURIES_PER_DOLLAR_METRIC = "QP$ (Quries per Dollar)"
|
43
46
|
LOAD_DURATION_METRIC = "load_duration"
|
44
47
|
SERIAL_LATENCY_P99_METRIC = "serial_latency_p99"
|
48
|
+
SERIAL_LATENCY_P95_METRIC = "serial_latency_p95"
|
45
49
|
MAX_LOAD_COUNT_METRIC = "max_load_count"
|
46
50
|
QPS_METRIC = "qps"
|
47
51
|
RECALL_METRIC = "recall"
|
@@ -49,6 +53,7 @@ RECALL_METRIC = "recall"
|
|
49
53
|
metric_unit_map = {
|
50
54
|
LOAD_DURATION_METRIC: "s",
|
51
55
|
SERIAL_LATENCY_P99_METRIC: "ms",
|
56
|
+
SERIAL_LATENCY_P95_METRIC: "ms",
|
52
57
|
MAX_LOAD_COUNT_METRIC: "K",
|
53
58
|
QURIES_PER_DOLLAR_METRIC: "K",
|
54
59
|
}
|
@@ -56,6 +61,7 @@ metric_unit_map = {
|
|
56
61
|
lower_is_better_metrics = [
|
57
62
|
LOAD_DURATION_METRIC,
|
58
63
|
SERIAL_LATENCY_P99_METRIC,
|
64
|
+
SERIAL_LATENCY_P95_METRIC,
|
59
65
|
]
|
60
66
|
|
61
67
|
metric_order = [
|
@@ -63,6 +69,7 @@ metric_order = [
|
|
63
69
|
RECALL_METRIC,
|
64
70
|
LOAD_DURATION_METRIC,
|
65
71
|
SERIAL_LATENCY_P99_METRIC,
|
72
|
+
SERIAL_LATENCY_P95_METRIC,
|
66
73
|
MAX_LOAD_COUNT_METRIC,
|
67
74
|
]
|
68
75
|
|
vectordb_bench/models.py
CHANGED
@@ -6,6 +6,9 @@ from typing import Self
|
|
6
6
|
|
7
7
|
import ujson
|
8
8
|
|
9
|
+
from vectordb_bench.backend.cases import type2case
|
10
|
+
from vectordb_bench.backend.dataset import DatasetWithSizeMap
|
11
|
+
|
9
12
|
from . import config
|
10
13
|
from .backend.cases import Case, CaseType
|
11
14
|
from .backend.clients import (
|
@@ -270,6 +273,21 @@ class TestResult(BaseModel):
|
|
270
273
|
b = partial.json(exclude={"db_config": {"password", "api_key"}})
|
271
274
|
f.write(b)
|
272
275
|
|
276
|
+
def get_case_config(case_config: CaseConfig) -> dict[CaseConfig]:
|
277
|
+
if case_config["case_id"] in {6, 7, 8, 9, 12, 13, 14, 15}:
|
278
|
+
case_instance = type2case[CaseType(case_config["case_id"])]()
|
279
|
+
custom_case = case_config["custom_case"]
|
280
|
+
if custom_case is None:
|
281
|
+
custom_case = {}
|
282
|
+
custom_case["filter_rate"] = case_instance.filter_rate
|
283
|
+
for dataset, size_type in DatasetWithSizeMap.items():
|
284
|
+
if case_instance.dataset == size_type:
|
285
|
+
custom_case["dataset_with_size_type"] = dataset
|
286
|
+
break
|
287
|
+
case_config["case_id"] = CaseType.NewIntFilterPerformanceCase
|
288
|
+
case_config["custom_case"] = custom_case
|
289
|
+
return case_config
|
290
|
+
|
273
291
|
@classmethod
|
274
292
|
def read_file(cls, full_path: pathlib.Path, trans_unit: bool = False) -> Self:
|
275
293
|
if not full_path.exists():
|
@@ -280,10 +298,10 @@ class TestResult(BaseModel):
|
|
280
298
|
test_result = ujson.loads(f.read())
|
281
299
|
if "task_label" not in test_result:
|
282
300
|
test_result["task_label"] = test_result["run_id"]
|
283
|
-
|
284
301
|
for case_result in test_result["results"]:
|
285
|
-
task_config = case_result
|
286
|
-
|
302
|
+
task_config = case_result.get("task_config")
|
303
|
+
case_config = task_config.get("case_config")
|
304
|
+
db = DB(task_config.get("db"))
|
287
305
|
|
288
306
|
task_config["db_config"] = db.config_cls(**task_config["db_config"])
|
289
307
|
|
@@ -296,6 +314,7 @@ class TestResult(BaseModel):
|
|
296
314
|
log.exception(f"Couldn't get class for index '{index_value}' ({full_path})")
|
297
315
|
task_config["db_case_config"] = EmptyDBCaseConfig(**raw_case_cfg)
|
298
316
|
|
317
|
+
task_config["case_config"] = cls.get_case_config(case_config=case_config)
|
299
318
|
case_result["task_config"] = task_config
|
300
319
|
|
301
320
|
if trans_unit:
|
@@ -308,6 +327,16 @@ class TestResult(BaseModel):
|
|
308
327
|
case_result["metrics"]["serial_latency_p99"] = (
|
309
328
|
cur_latency * 1000 if cur_latency > 0 else cur_latency
|
310
329
|
)
|
330
|
+
|
331
|
+
# Handle P95 latency for backward compatibility with existing result files
|
332
|
+
if "serial_latency_p95" in case_result["metrics"]:
|
333
|
+
cur_latency_p95 = case_result["metrics"]["serial_latency_p95"]
|
334
|
+
case_result["metrics"]["serial_latency_p95"] = (
|
335
|
+
cur_latency_p95 * 1000 if cur_latency_p95 > 0 else cur_latency_p95
|
336
|
+
)
|
337
|
+
else:
|
338
|
+
# Default to 0 for older result files that don't have P95 data
|
339
|
+
case_result["metrics"]["serial_latency_p95"] = 0.0
|
311
340
|
return TestResult.validate(test_result)
|
312
341
|
|
313
342
|
def display(self, dbs: list[DB] | None = None):
|
@@ -350,6 +379,7 @@ class TestResult(BaseModel):
|
|
350
379
|
max_load_dur,
|
351
380
|
max_qps,
|
352
381
|
15,
|
382
|
+
15,
|
353
383
|
max_recall,
|
354
384
|
14,
|
355
385
|
5,
|
@@ -357,7 +387,7 @@ class TestResult(BaseModel):
|
|
357
387
|
|
358
388
|
DATA_FORMAT = ( # noqa: N806
|
359
389
|
f"%-{max_db}s | %-{max_db_labels}s %-{max_case}s %-{len(self.task_label)}s"
|
360
|
-
f" | %-{max_load_dur}s %-{max_qps}s %-15s %-{max_recall}s %-14s"
|
390
|
+
f" | %-{max_load_dur}s %-{max_qps}s %-15s %-15s %-{max_recall}s %-14s"
|
361
391
|
f" | %-5s"
|
362
392
|
)
|
363
393
|
|
@@ -369,6 +399,7 @@ class TestResult(BaseModel):
|
|
369
399
|
"load_dur",
|
370
400
|
"qps",
|
371
401
|
"latency(p99)",
|
402
|
+
"latency(p95)",
|
372
403
|
"recall",
|
373
404
|
"max_load_count",
|
374
405
|
"label",
|
@@ -391,6 +422,7 @@ class TestResult(BaseModel):
|
|
391
422
|
f.metrics.load_duration,
|
392
423
|
f.metrics.qps,
|
393
424
|
f.metrics.serial_latency_p99,
|
425
|
+
f.metrics.serial_latency_p95,
|
394
426
|
f.metrics.recall,
|
395
427
|
f.metrics.max_load_count,
|
396
428
|
f.label.value,
|