Documentation
¶
Overview ¶
Package eval provides an offline retrieval-quality harness: it runs a golden dataset (query → expected relevant sources) through a Retriever and reports the standard ranking metrics — Recall@k, Mean Reciprocal Rank (MRR) and nDCG@k — so that changes to the retrieval stack (fusion, reranking, grounding) can be validated objectively rather than by feel.
The metric functions are pure and dependency-free (this file), so they run in the short unit suite. The end-to-end evaluation of a real Codex against a dataset lives in the integration tests, gated behind an env var like the other Ollama-backed tests.
Index ¶
- Variables
- func AnswerExactMatch(pred string, golds []string) float64
- func AnswerF1(pred string, golds []string) float64
- func FirstRelevantRank(retrieved, relevant []string) int
- func NDCGAtK(retrieved, relevant []string, k int) float64
- func NormalizeAnswer(s string) string
- func PrecisionAtK(retrieved, relevant []string, k int) float64
- func RecallAtK(retrieved, relevant []string, k int) float64
- func ReciprocalRank(retrieved, relevant []string) float64
- func Subsample(corpus *Corpus, dataset *Dataset, maxQueries, maxDocs int) (*Corpus, *Dataset)
- type Corpus
- type Dataset
- type Document
- type Query
- type QueryReport
- type Report
- type Retriever
- type RetrieverFunc
Constants ¶
This section is empty.
Variables ¶
var DefaultKs = []int{1, 3, 5, 10}
DefaultKs are the cut-offs reported by default (Recall@1/3/5/10, nDCG@1/3/5/10).
Functions ¶
func AnswerExactMatch ¶
AnswerExactMatch is 1.0 when the prediction, after normalisation, equals any of the gold answers, else 0.0. With no gold answers it returns 0.
func AnswerF1 ¶
AnswerF1 is the maximum SQuAD token-overlap F1 between the prediction and any gold answer: with p = |common|/|pred| and r = |common|/|gold| over the multiset of normalised tokens, F1 = 2pr/(p+r). It credits partial answers that a strict Exact Match misses. Two empty (after normalisation) strings count as a perfect match — matching the SQuAD convention for yes/no and no-answer cases — while an empty prediction against a non-empty gold (or vice-versa) scores 0.
func FirstRelevantRank ¶
FirstRelevantRank returns the 1-indexed rank of the first relevant document in the retrieved list, or -1 when none of them is relevant.
func NDCGAtK ¶
NDCGAtK is the normalised Discounted Cumulative Gain at cut-off k for binary relevance: DCG@k / IDCG@k, where each relevant document contributes a gain of 1 discounted by log2(position+1). It rewards placing relevant documents higher and, unlike Recall@k, is sensitive to their exact rank. It returns 0 when there are no relevant documents.
func NormalizeAnswer ¶
NormalizeAnswer applies the canonical SQuAD answer normalisation before comparison: lower-case, drop punctuation, drop the articles a/an/the, and collapse runs of whitespace. This makes "The Eiffel Tower." and "eiffel tower" compare equal, so EM/F1 measure answer content rather than surface formatting.
func PrecisionAtK ¶
PrecisionAtK is the fraction of the top-k retrieved results that are relevant: |relevant ∩ top-k| / k'. It is the counterpart of Recall@k on the precision axis — where recall asks "did we find the gold documents", precision asks "of what we returned, how much is gold". It matters for pipelines that deliberately return a small, high-purity evidence set (e.g. grounded iterative retrieval), whose value recall@k understates. The denominator k' is min(k, len(retrieved)), so a run that returns fewer than k results is not penalised for the empty slots. It returns 0 when nothing was retrieved or there are no relevant documents.
func RecallAtK ¶
RecallAtK is the fraction of the relevant documents that appear within the top-k retrieved results: |relevant ∩ top-k| / |relevant|. With a single relevant document it degrades to the binary "is the target in the top-k" measure. It returns 0 when there are no relevant documents (nothing to find) and clamps k to a non-negative value.
func ReciprocalRank ¶
ReciprocalRank is 1/rank of the first relevant document, or 0 when none of the relevant documents was retrieved. It is the per-query term averaged into the Mean Reciprocal Rank.
func Subsample ¶
Subsample builds a smaller, self-consistent corpus + query set for cheap evaluation on a machine that cannot embed a full BEIR corpus: it keeps the first maxQueries queries, ALL of their relevant documents (so every kept query stays answerable), then fills the corpus with further documents as distractors up to maxDocs. Unlike Corpus.Truncate (which keeps the first N documents and would drop the scattered gold documents of a BEIR dataset), it is gold-aware. A non-positive bound disables that limit; gold documents are always included even if they exceed maxDocs. Selection order is deterministic.
Types ¶
type Corpus ¶
Corpus is the set of documents an evaluation indexes before scoring queries.
func LoadCorpus ¶
LoadCorpus reads a JSON corpus from the given file path.
func ReadCorpus ¶
ReadCorpus decodes a JSON corpus from r.
func (*Corpus) Merge ¶
Merge appends the documents of others into c, de-duplicating by Source (the first occurrence wins). It is used to combine per-language corpora into a single index.
type Dataset ¶
Dataset is a named collection of golden queries.
func LoadDataset ¶
LoadDataset reads a JSON dataset from the given file path.
func LoadDatasetFS ¶
LoadDatasetFS reads a JSON dataset from a file system (e.g. an embed.FS), so fixtures can be embedded into a binary or test.
func ReadDataset ¶
ReadDataset decodes a JSON dataset from r.
func (*Dataset) KeepAnswerable ¶
KeepAnswerable returns a copy of the dataset keeping only the queries whose every relevant source is present in the given set — i.e. questions that are actually answerable against the (possibly truncated) corpus. Queries with no relevant sources are dropped.
type Document ¶
type Document struct {
Source string `json:"source"`
Title string `json:"title,omitempty"`
Content string `json:"content"`
Lang string `json:"lang,omitempty"`
}
Document is one indexable unit of an evaluation corpus: the passage/document that queries are expected to retrieve. Source is the identifier that a Query's RelevantSources refer to (and that a Retriever returns), so the two must agree.
type Query ¶
type Query struct {
// ID is a stable identifier for the query, used to label per-query results
// and to segment metrics. Optional but recommended.
ID string `json:"id,omitempty"`
// Query is the search string submitted to the retriever.
Query string `json:"query"`
// Lang is the ISO language code of the query (e.g. "fr", "en", "es"), used
// to segment metrics by language.
Lang string `json:"lang,omitempty"`
// RelevantSources lists the source identifiers expected in the results.
RelevantSources []string `json:"relevant_sources"`
// Answers lists the acceptable gold answer strings for the query, used only by
// the optional generation (reader) evaluation to score answer EM/F1. Empty for
// pure retrieval datasets; a query may have several equally-correct answers
// (SQuAD) or a single one (HotpotQA).
Answers []string `json:"answers,omitempty"`
// Tags optionally categorise the query (intent, complexity, domain) for
// segmented reporting.
Tags []string `json:"tags,omitempty"`
}
Query is one golden evaluation case: a natural-language query and the set of document source identifiers that are considered relevant answers to it. The identifiers must match whatever the Retriever returns (for a Codex-backed retriever, the document Source URL as a string).
type QueryReport ¶
type QueryReport struct {
QueryID string
Query string
Lang string
Tags []string
// TargetRank is the 1-indexed rank of the first relevant document, or -1 if
// none was retrieved.
TargetRank int
ReciprocalRank float64
RecallAtK map[int]float64
NDCGAtK map[int]float64
PrecisionAtK map[int]float64
}
QueryReport holds the metrics computed for a single query.
type Report ¶
type Report struct {
Dataset string
NumQueries int
Ks []int
// MRR is the mean reciprocal rank across all queries.
MRR float64
// RecallAtK, NDCGAtK and PrecisionAtK are the dataset-averaged metrics per
// cut-off.
RecallAtK map[int]float64
NDCGAtK map[int]float64
PrecisionAtK map[int]float64
PerQuery []QueryReport
}
Report aggregates the metrics over a whole dataset run.
func Evaluate ¶
Evaluate runs every query in the dataset through the retriever and returns the aggregated report. It fetches the largest requested cut-off worth of results per query. ks defaults to DefaultKs when empty. A retriever error aborts the run (a query with no results is not an error — it simply scores 0).
func (*Report) BySegment ¶
func (r *Report) BySegment(key func(QueryReport) string) map[string]*Report
BySegment partitions the report's queries by the given key function and re-aggregates each partition into its own sub-report. Segments with an empty key are grouped under "" and can be ignored by the caller. It is the basis for query-type analysis (by language, intent, complexity, ...).
type Retriever ¶
Retriever is the minimal contract the harness evaluates: given a query and a cut-off k, return up to k document source identifiers ranked best-first. It is deliberately decoupled from *Codex so the harness can score any retrieval implementation (a Codex, a single index, a baseline BM25, a mock).
func FromSearchResults ¶
func FromSearchResults(search func(ctx context.Context, query string, k int) ([]*index.SearchResult, error)) Retriever
FromSearchResults adapts a search function returning ranked index.SearchResult (such as Codex.Search) into a Retriever, using each result's Source as the identifier. Results with a nil Source are skipped.
type RetrieverFunc ¶
RetrieverFunc adapts a function to the Retriever interface.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package beir loads datasets in the BEIR format (the de-facto information retrieval benchmark) into an amoxtli evaluation corpus + query set.
|
Package beir loads datasets in the BEIR format (the de-facto information retrieval benchmark) into an amoxtli evaluation corpus + query set. |
|
Package hfqa loads Hugging Face extractive-QA datasets in the SQuAD JSON format into an amoxtli evaluation corpus + query set.
|
Package hfqa loads Hugging Face extractive-QA datasets in the SQuAD JSON format into an amoxtli evaluation corpus + query set. |