Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ir/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,9 @@ def search(corpus, query, **kwargs):
if isinstance(corpus, str):
corpus = open_corpus(corpus)
return _search(corpus, query, **kwargs)


# The evaluation harness is reachable as ``ir.eval`` (its ``ef`` imports are
# lazy, so this does not weigh down ``import ir``). Kept out of ``__all__`` so a
# star-import does not shadow the ``eval`` builtin.
from . import eval # noqa: E402,F401 (submodule attribute: ir.eval)
32 changes: 31 additions & 1 deletion ir/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
ir info packages # config + stats for a corpus
ir register notes files --root ~/notes --pattern '.*\\.md$'
ir rm notes # unregister (keeps built data)
ir eval skills skills_eval.jsonl --mode hybrid # score retrieval on a case file
"""

from __future__ import annotations
Expand Down Expand Up @@ -83,4 +84,33 @@ def rm(name):
return f"unregistered {name!r}"


COMMANDS = [ls, register, build, search, info, rm]
def eval(name, cases, *, mode="hybrid", k=10):
"""Score a built corpus's retrieval against a DiscoveryCase JSONL file.

cases: path to a JSONL file of cases (see :mod:`ir.eval`); each line is a
``{"query": ..., "gold": [artifact_id, ...]}`` record (empty ``gold`` = an
abstention case). Prints recall@k / NDCG@k / MRR / MAP plus the failure-mode
taxonomy. mode: dense | lexical | hybrid.
"""
from .eval import evaluate_discovery, load_cases, validate_cases

corpus = open_corpus(name)
if len(corpus) == 0:
return f"corpus {name!r} is empty; build it first: ir build {name}"
case_list = load_cases(cases)
if not case_list:
return f"no cases found in {cases!r}"
drift = validate_cases(corpus, case_list)
report = evaluate_discovery(
corpus, case_list, mode=mode, primary_k=k, k_values=tuple(sorted({1, 5, k}))
)
out = str(report)
if drift:
out += (
f"\n WARNING: {len(drift)} case(s) reference gold ids absent from "
f"corpus {name!r} (stale fixture?); their misses are not real."
)
return out


COMMANDS = [ls, register, build, search, info, rm, eval]
Loading
Loading