retrieval-evaluator 0.1.0__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.
- retrieval_evaluator/__init__.py +142 -0
- retrieval_evaluator/cli.py +743 -0
- retrieval_evaluator/config.py +248 -0
- retrieval_evaluator/dashboard/__init__.py +0 -0
- retrieval_evaluator/dashboard/app.py +152 -0
- retrieval_evaluator/dashboard/data.py +107 -0
- retrieval_evaluator/dashboard/inspector.py +309 -0
- retrieval_evaluator/dashboard/metrics.py +60 -0
- retrieval_evaluator/dashboard/results.py +178 -0
- retrieval_evaluator/data/EXAMPLE/corpus.jsonl +31 -0
- retrieval_evaluator/data/EXAMPLE/meta.json +8 -0
- retrieval_evaluator/data/EXAMPLE/qrels.tsv +12 -0
- retrieval_evaluator/data/EXAMPLE/queries.jsonl +12 -0
- retrieval_evaluator/database/numpy_index.py +75 -0
- retrieval_evaluator/database/vector_index.py +46 -0
- retrieval_evaluator/database/weaviate_db.py +263 -0
- retrieval_evaluator/dataset/beir.py +461 -0
- retrieval_evaluator/dataset/chunk_sources.py +397 -0
- retrieval_evaluator/dataset/dataset_builder.py +190 -0
- retrieval_evaluator/dataset/document_selection.py +119 -0
- retrieval_evaluator/dataset/importer.py +230 -0
- retrieval_evaluator/dataset/query_generation.py +355 -0
- retrieval_evaluator/dataset/source_validation.py +85 -0
- retrieval_evaluator/evaluation/__init__.py +0 -0
- retrieval_evaluator/evaluation/chunk_merging.py +69 -0
- retrieval_evaluator/evaluation/embedder.py +450 -0
- retrieval_evaluator/evaluation/embedders_evaluation.py +345 -0
- retrieval_evaluator/evaluation/metrics.py +111 -0
- retrieval_evaluator/evaluation/run_id.py +50 -0
- retrieval_evaluator/py.typed +0 -0
- retrieval_evaluator/templates.py +92 -0
- retrieval_evaluator/utils/cache.py +17 -0
- retrieval_evaluator/utils/constants.py +19 -0
- retrieval_evaluator/utils/device.py +24 -0
- retrieval_evaluator/utils/json_io.py +45 -0
- retrieval_evaluator/utils/logger.py +33 -0
- retrieval_evaluator/utils/paths.py +14 -0
- retrieval_evaluator/utils/retry.py +151 -0
- retrieval_evaluator-0.1.0.dist-info/METADATA +419 -0
- retrieval_evaluator-0.1.0.dist-info/RECORD +44 -0
- retrieval_evaluator-0.1.0.dist-info/WHEEL +5 -0
- retrieval_evaluator-0.1.0.dist-info/entry_points.txt +2 -0
- retrieval_evaluator-0.1.0.dist-info/licenses/LICENSE +21 -0
- retrieval_evaluator-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import tempfile
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Literal, Sequence
|
|
6
|
+
|
|
7
|
+
import pandas as pd
|
|
8
|
+
|
|
9
|
+
from retrieval_evaluator.utils.paths import safe_child_path
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def evaluate(
|
|
13
|
+
dataset_dir: str | Path | None = None,
|
|
14
|
+
embedder_configs: dict[str, dict] | None = None,
|
|
15
|
+
collections: list[str] | None = None,
|
|
16
|
+
alphas: Sequence[float] = (1.0,),
|
|
17
|
+
k_values: Sequence[int] = (1, 3, 5, 10),
|
|
18
|
+
batch_size: int | Literal["auto"] = 64,
|
|
19
|
+
artifacts_dir: str | Path | None = None,
|
|
20
|
+
qrels_split: str = "test",
|
|
21
|
+
index_backend: str | None = None,
|
|
22
|
+
) -> pd.DataFrame:
|
|
23
|
+
"""
|
|
24
|
+
Evaluate one or more embedder configs on a BEIR-format dataset directory.
|
|
25
|
+
|
|
26
|
+
Returns a DataFrame with one row per (embedder, collection, alpha) combination.
|
|
27
|
+
Columns include: embedder, collection, alpha, R@1, R@3, R@5, R@10, MRR@10, ...
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
dataset_dir: Path to a directory of BEIR-format collection subdirectories.
|
|
31
|
+
Defaults to the configured evaluation_dataset_dir.
|
|
32
|
+
embedder_configs: Dict of {name: config_dict}. Required.
|
|
33
|
+
collections: Which subdirectories to evaluate. Defaults to all subdirectories in dataset_dir.
|
|
34
|
+
alphas: Hybrid search alpha values (1.0 = pure semantic, 0.0 = pure BM25).
|
|
35
|
+
k_values: Retrieval cut-offs for metric computation.
|
|
36
|
+
batch_size: Encoding batch size for HuggingFace models.
|
|
37
|
+
artifacts_dir: Directory to write per-run artifacts (rankings, corpus meta, qrels).
|
|
38
|
+
When provided, artifacts are preserved after the call. To inspect
|
|
39
|
+
them in the dashboard, also save the returned DataFrame with
|
|
40
|
+
results.to_csv("results.csv", index=False), then launch
|
|
41
|
+
`retrieval-evaluator dashboard --results-file results.csv
|
|
42
|
+
--artifacts-dir <artifacts_dir> --dataset-dir <dataset_dir>`.
|
|
43
|
+
When omitted, artifacts are written to a temporary directory and
|
|
44
|
+
discarded. The API does not persist a results CSV automatically.
|
|
45
|
+
qrels_split: BEIR qrels split to load from qrels/{split}.tsv when a root qrels.tsv
|
|
46
|
+
is not present.
|
|
47
|
+
index_backend: Retrieval backend ("numpy" or "weaviate"). Defaults to config.
|
|
48
|
+
"""
|
|
49
|
+
from retrieval_evaluator.config import get_evaluation_dataset_dir
|
|
50
|
+
from retrieval_evaluator.evaluation.embedders_evaluation import evaluate_embedders
|
|
51
|
+
|
|
52
|
+
if embedder_configs is None:
|
|
53
|
+
raise ValueError("embedder_configs must be provided — pass a dict of {name: config_dict}")
|
|
54
|
+
|
|
55
|
+
dataset_dir = get_evaluation_dataset_dir(dataset_dir)
|
|
56
|
+
|
|
57
|
+
if collections is None:
|
|
58
|
+
collections = sorted(p.name for p in dataset_dir.iterdir() if p.is_dir())
|
|
59
|
+
|
|
60
|
+
with tempfile.TemporaryDirectory() as tmp:
|
|
61
|
+
results_file = Path(tmp) / "results.csv"
|
|
62
|
+
effective_artifacts_dir = (
|
|
63
|
+
Path(artifacts_dir) if artifacts_dir is not None else Path(tmp) / "artifacts"
|
|
64
|
+
)
|
|
65
|
+
if artifacts_dir is not None:
|
|
66
|
+
effective_artifacts_dir.mkdir(parents=True, exist_ok=True)
|
|
67
|
+
|
|
68
|
+
evaluate_embedders(
|
|
69
|
+
collections=collections,
|
|
70
|
+
embedder_configs=embedder_configs,
|
|
71
|
+
alphas=alphas,
|
|
72
|
+
batch_size=batch_size,
|
|
73
|
+
k_values=k_values,
|
|
74
|
+
dataset_dir=dataset_dir,
|
|
75
|
+
results_file=results_file,
|
|
76
|
+
artifacts_output_dir=effective_artifacts_dir,
|
|
77
|
+
qrels_split=qrels_split,
|
|
78
|
+
index_backend=index_backend,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
if results_file.exists():
|
|
82
|
+
return pd.read_csv(results_file)
|
|
83
|
+
|
|
84
|
+
return pd.DataFrame()
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def build_dataset(
|
|
88
|
+
collection_name: str,
|
|
89
|
+
chunks: list[dict],
|
|
90
|
+
output_dir: str | Path = "eval_data",
|
|
91
|
+
field_mapping: dict[str, str] | None = None,
|
|
92
|
+
llm_model: str | None = None,
|
|
93
|
+
n_docs: int = 30,
|
|
94
|
+
) -> Path:
|
|
95
|
+
"""
|
|
96
|
+
Generate a BEIR-format evaluation dataset from an in-memory chunk list.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
collection_name: Name for the output subdirectory.
|
|
100
|
+
chunks: List of dicts. Must contain at least the fields named in field_mapping.
|
|
101
|
+
output_dir: Root directory to write {collection_name}/ into.
|
|
102
|
+
field_mapping: Maps canonical names (id, text, doc_id) to your chunk's field names.
|
|
103
|
+
Defaults to {"id": "id", "text": "content", "doc_id": "document_id"}.
|
|
104
|
+
llm_model: LangChain model string for query generation (e.g. "openai:gpt-4o").
|
|
105
|
+
Defaults to the configured llm.model.
|
|
106
|
+
n_docs: Number of diverse documents to sample per language.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
Path to the written dataset directory.
|
|
110
|
+
"""
|
|
111
|
+
import copy
|
|
112
|
+
|
|
113
|
+
from retrieval_evaluator.config import get_config
|
|
114
|
+
from retrieval_evaluator.dataset.chunk_sources import InMemoryChunkSource
|
|
115
|
+
from retrieval_evaluator.dataset.dataset_builder import build_eval_sets
|
|
116
|
+
|
|
117
|
+
if not isinstance(chunks, list) or not chunks:
|
|
118
|
+
raise ValueError("chunks must be a non-empty list of dictionaries")
|
|
119
|
+
if any(not isinstance(chunk, dict) for chunk in chunks):
|
|
120
|
+
raise ValueError("chunks must contain only dictionaries")
|
|
121
|
+
if n_docs <= 0:
|
|
122
|
+
raise ValueError("n_docs must be positive")
|
|
123
|
+
|
|
124
|
+
cfg = get_config()
|
|
125
|
+
collection_path = safe_child_path(output_dir, collection_name, label="collection_name")
|
|
126
|
+
dataset_cfg = copy.deepcopy(cfg["retrieval_evaluation"]["dataset"])
|
|
127
|
+
settings = copy.deepcopy(cfg["settings"])
|
|
128
|
+
settings["evaluation_dataset_dir"] = str(output_dir)
|
|
129
|
+
dataset_cfg["n_docs_per_language"] = n_docs
|
|
130
|
+
|
|
131
|
+
default_mapping = {"id": "id", "text": "content", "doc_id": "document_id"}
|
|
132
|
+
effective_mapping = {**default_mapping, **(field_mapping or {})}
|
|
133
|
+
dataset_cfg["field_mapping"] = {**dataset_cfg["field_mapping"], **effective_mapping}
|
|
134
|
+
|
|
135
|
+
build_eval_sets(
|
|
136
|
+
collections=[collection_name],
|
|
137
|
+
chunk_source=InMemoryChunkSource(chunks),
|
|
138
|
+
dataset_cfg=dataset_cfg,
|
|
139
|
+
settings=settings,
|
|
140
|
+
llm_model=llm_model or cfg["llm"]["model"],
|
|
141
|
+
)
|
|
142
|
+
return collection_path
|