foley.eval.retrieval#
Tier-1 retrieval metrics + run assembly — pure stdlib, CI-safe, ranx-exact.
The metrics (nDCG@10, Recall@k, Precision@k, mAP@10, MRR@10)
are hand-rolled in stdlib (no ranx/numba) so the nDCG PR gate runs in
foley’s numpy-only CI with zero heavy deps — yet they are **numerically
identical** to ranx/pytrec_eval (guarded by the opt-in
tests/eval/test_metrics_vs_ranx.py oracle). nDCG uses the linear Järvelin
gain Σ grade_i / log2(rank+1) — the definition ranx’s "ndcg@10" and
pytrec_eval’s ndcg_cut_10 actually implement (report 08 §1.1’s
2^grade−1 is a doc bug).
Vocabulary (TREC-style):
qrels —
{query_id: {clip_id: grade}}— the ground-truth relevance grades (0 = wrong, 1 = acceptable, 2 = ideal); the raw grade is the gain, so the metrics are grade-scale-agnostic.run —
{query_id: {clip_id: score}}— the system’s scored results.
build_run() assigns strictly-descending integer scores in the search order,
so a run has no score ties and its ranking reproduces search()’s
(already id-tiebroken) order exactly — the source of cross-platform determinism.
Module Attributes
The metrics reported by |
Functions
|
Average precision (trec_eval |
|
Turn an ordered |
|
Score a |
|
Macro-average of per-query metric values (0.0 for an empty list). |
|
Reciprocal rank of the first relevant doc in the top- |
|
Normalized DCG at |
|
Fraction of the top- |
|
Fraction of ALL relevant docs (grade ≥ |
Classes
|
Per-query + mean Tier-1 metrics over a golden set (JSON-friendly). |
- foley.eval.retrieval.DEFAULT_METRICS = ('ndcg@10', 'recall@10', 'map@10', 'mrr@10')#
The metrics reported by
evaluate_run()(nDCG@10 is the sole PR gate).
- class foley.eval.retrieval.RetrievalReport(per_query=<factory>, mean=<factory>, ranks=<factory>, k=10)[source]#
Bases:
objectPer-query + mean Tier-1 metrics over a golden set (JSON-friendly).
- foley.eval.retrieval.average_precision_at_k(qrels_q, run_q, k=10, *, rel_lvl=1)[source]#
Average precision (trec_eval
map: divide by TOTAL relevant, notmin(R,k)).- Return type:
- foley.eval.retrieval.build_run(candidates)[source]#
Turn an ordered
search()result into a run row with distinct scores.Assigns each candidate a strictly-descending integer score (
len - rank) in the order returned, so the run carries **no score ties** and_ranked_ids()reproduces the search ranking exactly — the determinism the gate relies on. The doc id iscandidate.sound.id.- Parameters:
candidates – An ordered
list[Candidate]fromfoley.index.library.SoundLibrary.search()(best first).- Return type:
- Returns:
{clip_id: score}with distinct descending scores.
- foley.eval.retrieval.evaluate_run(run, qrels, *, k=10, metrics=('ndcg@10', 'recall@10', 'map@10', 'mrr@10'), rel_lvl=1)[source]#
Score a
runagainstqrels, returning aRetrievalReport.Only query ids present in
qrelsare scored (a run row without a ground-truth judgment is ignored).ranksrecords, per query, the 1-based rank of the highest-graded answer (for the failure diff).- Return type:
- foley.eval.retrieval.mean_over_queries(values)[source]#
Macro-average of per-query metric values (0.0 for an empty list).
- Return type:
- foley.eval.retrieval.mrr_at_k(qrels_q, run_q, k=10, *, rel_lvl=1)[source]#
Reciprocal rank of the first relevant doc in the top-
k(0.0 if none).- Return type:
- foley.eval.retrieval.ndcg_at_k(qrels_q, run_q, k=10)[source]#
Normalized DCG at
kwith linear gains (0.0 when no graded answer).- Return type: