Evaluation¶
evaluator ¶
Standardized evaluation metrics for EA, EL, WSD and WSA.
Evaluator ¶
Computes standard linking metrics from predictions and ground truth.
evaluate
staticmethod
¶
evaluate(
predictions: list[tuple[str, str]],
ground_truth: list[tuple[str, str]],
) -> EvaluationReport
Compute micro precision@1, recall and F1 for unranked predictions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
predictions
|
list[tuple[str, str]]
|
List of |
required |
ground_truth
|
list[tuple[str, str]]
|
List of |
required |
Returns:
| Type | Description |
|---|---|
EvaluationReport
|
A report containing |
Source code in src/linkingtk/eval/evaluator.py
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | |
evaluate_blocking
staticmethod
¶
evaluate_blocking(
candidate_pairs: list[tuple[str, str]],
ground_truth: list[tuple[str, str]],
dataset1_size: int,
dataset2_size: int | None = None,
) -> EvaluationReport
Compute Pair Completeness and Reduction Ratio for a blocking pass.
These metrics assess a BlockingStrategy in isolation, before any linker scores the candidate pairs it produces.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
candidate_pairs
|
list[tuple[str, str]]
|
|
required |
ground_truth
|
list[tuple[str, str]]
|
List of |
required |
dataset1_size
|
int
|
Number of entities in the first dataset. |
required |
dataset2_size
|
int | None
|
Number of entities in the second dataset, or
|
None
|
Returns:
| Type | Description |
|---|---|
EvaluationReport
|
A report containing |
EvaluationReport
|
matches present among the candidate pairs, i.e. blocking recall) |
EvaluationReport
|
and |
EvaluationReport
|
|
EvaluationReport
|
|
Source code in src/linkingtk/eval/evaluator.py
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | |
evaluate_ranked
staticmethod
¶
evaluate_ranked(
ranked_predictions: list[tuple[str, list[str]]],
ground_truth: list[tuple[str, str]],
top_k: list[int],
) -> EvaluationReport
Compute Hits@k and MRR for ranked predictions.
Iterates over ground_truth (not ranked_predictions), so the
denominator is always exactly len(ground_truth) -- the number of
queries actually being scored. This matters for callers (e.g. every
EA-linker benchmark script under examples/) that call
linker.link() over a superset of the evaluated split (train +
val + test entities, since which entities need embeddings is
determined before the split is known): a ground-truth source with no
matching entry in ranked_predictions at all (e.g. blocking found
no candidates for it) counts as a miss, exactly like a source whose
ranked list doesn't contain the correct target -- neither case is
silently excluded, and no non-ground-truth prediction can dilute the
denominator.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ranked_predictions
|
list[tuple[str, list[str]]]
|
List of |
required |
ground_truth
|
list[tuple[str, str]]
|
List of |
required |
top_k
|
list[int]
|
The cut-offs to compute Hits@k for. |
required |
Returns:
| Type | Description |
|---|---|
EvaluationReport
|
A report containing |
EvaluationReport
|
|
Source code in src/linkingtk/eval/evaluator.py
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | |
ranking ¶
Exhaustive, non-blocking ranked evaluation for EA linkers.
rank_exhaustive ¶
rank_exhaustive(
linker: _ScoringLinker,
source_entities: list[Entity],
target_entities: list[Entity],
metric: _Metric = "cosine",
csls_k: int = 0,
) -> list[tuple[str, list[str]]]
Rank every source_entities entity against every target_entities entity.
No blocking/candidate-restriction step at all -- a single dense
similarity matrix, matching OpenEA's own greedy_alignment
methodology (modules/finding/alignment.py, itself a thin wrapper
around modules/finding/similarity.py's sim/csls_sim, ported
here). Intended for benchmark scripts that need numbers directly
comparable to a published target:
BlockingStrategy-restricted
evaluation (the normal, production-scale path via
BaseLinker.link) upper-bounds
the reported metric by blocking's own recall, not purely by the
linker's embedding/ranking quality -- see issue #37. Not intended for
production-scale linking: this always computes a full
len(source_entities) x len(target_entities) similarity matrix.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
linker
|
_ScoringLinker
|
A fitted EA linker exposing |
required |
source_entities
|
list[Entity]
|
Entities to rank from. |
required |
target_entities
|
list[Entity]
|
Entities to rank against. |
required |
metric
|
_Metric
|
Similarity metric -- |
'cosine'
|
csls_k
|
int
|
If |
0
|
Returns:
| Type | Description |
|---|---|
list[tuple[str, list[str]]]
|
|
list[tuple[str, list[str]]]
|
entry per |
list[tuple[str, list[str]]]
|
|
list[tuple[str, list[str]]]
|
|
list[tuple[str, list[str]]]
|
needs the true target's real rank for MRR even when it falls |
list[tuple[str, list[str]]]
|
outside any Hits@k cutoff; truncating here would silently |
list[tuple[str, list[str]]]
|
reintroduce a version of the denominator/miss bug that function's |
list[tuple[str, list[str]]]
|
own docstring documents fixing. |
list[tuple[str, list[str]]]
|
|
Source code in src/linkingtk/eval/ranking.py
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | |
report ¶
Result container returned by linkingtk.eval.evaluator.Evaluator.
EvaluationReport
dataclass
¶
EvaluationReport(metrics: dict[str, float | None])
Holds computed metrics for a single evaluation run.
Attributes:
| Name | Type | Description |
|---|---|---|
metrics |
dict[str, float | None]
|
Mapping of metric name (e.g. |
harness ¶
A small comparison harness for running many linkers/datasets side by side.
Different tasks (EA/EL/WSD/WSA) and tiers (string-similarity, classical ML,
KGE, deep learning, LLM-oriented) need very different fit/link/evaluate
wiring -- ranked vs. unranked evaluation, exhaustive vs. blocking-restricted
ranking, .fit() or not. Rather than have the harness guess at that, each
BenchmarkRun carries a zero-argument
callable that already does exactly what a normal examples/*_benchmark.py
script does, and returns an EvaluationReport.
run_benchmarks only adds timing and,
for runs that make real LLM calls via a
CountingLlmClient, a call count --
see examples/comparative_benchmark.py for real usage.
BenchmarkResult
dataclass
¶
BenchmarkResult(
run: BenchmarkRun,
metrics: dict[str, float | None],
seconds: float,
llm_calls: int | None,
)
The outcome of executing a single BenchmarkRun.
BenchmarkRun
dataclass
¶
BenchmarkRun(
task: str,
tier: str,
linker: str,
dataset: str,
run: Callable[[], EvaluationReport],
client: CountingLlmClient | None = None,
)
One (task, tier, linker, dataset) comparison cell.
Attributes:
| Name | Type | Description |
|---|---|---|
task |
str
|
Display label, e.g. |
tier |
str
|
Display label, e.g. |
linker |
str
|
Display label, e.g. |
dataset |
str
|
Display label, e.g. |
run |
Callable[[], EvaluationReport]
|
Zero-argument callable that fits/links/evaluates and returns an EvaluationReport. Owns all task-specific wiring (blocking, ranked vs. unranked evaluation, training) -- the harness only times it. |
client |
CountingLlmClient | None
|
A CountingLlmClient
used inside |
CountingLlmClient ¶
CountingLlmClient(client: LlmClient)
Bases: LlmClient
Wraps a real LlmClient, counting its calls.
Purely a benchmarking aid -- delegates every call unchanged and doesn't
modify linkingtk.llm.client at all. Attach the instance to a
BenchmarkRun's client field so
run_benchmarks can report an
LLM-call count alongside wall-clock time.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client
|
LlmClient
|
The real client to wrap. |
required |
Source code in src/linkingtk/eval/harness.py
40 41 42 | |
format_table ¶
format_table(results: list[BenchmarkResult]) -> str
Renders results as a plain-text table, grouped by run.task.
Each task gets its own section with its own metric columns (the union
of metric keys across that task's results, in first-seen order), since
different tasks report different metrics (e.g. EA's Hits@k/MRR vs.
EL/WSD's precision@1/recall/f1).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
results
|
list[BenchmarkResult]
|
Results to render, in the order they should appear within each task's section. |
required |
Returns:
| Type | Description |
|---|---|
str
|
The rendered table. |
Source code in src/linkingtk/eval/harness.py
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | |
run_benchmarks ¶
run_benchmarks(
runs: list[BenchmarkRun],
) -> list[BenchmarkResult]
Executes each of runs in order, timing it and collecting its metrics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
runs
|
list[BenchmarkRun]
|
The comparison cells to execute, in order. |
required |
Returns:
| Type | Description |
|---|---|
list[BenchmarkResult]
|
One BenchmarkResult per run. |
Source code in src/linkingtk/eval/harness.py
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |