worthir-eval 1.2.0__tar.gz

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.
Files changed (65) hide show
  1. worthir_eval-1.2.0/LICENSE +21 -0
  2. worthir_eval-1.2.0/PKG-INFO +105 -0
  3. worthir_eval-1.2.0/README.md +92 -0
  4. worthir_eval-1.2.0/contracts/README.md +11 -0
  5. worthir_eval-1.2.0/contracts/__init__.py +1 -0
  6. worthir_eval-1.2.0/contracts/quickstart_contract.json +40 -0
  7. worthir_eval-1.2.0/contracts/route_registry.json +29 -0
  8. worthir_eval-1.2.0/examples/__init__.py +1 -0
  9. worthir_eval-1.2.0/examples/custom_router/README.md +36 -0
  10. worthir_eval-1.2.0/examples/custom_router/__init__.py +1 -0
  11. worthir_eval-1.2.0/examples/custom_router/router.py +92 -0
  12. worthir_eval-1.2.0/examples/custom_router/run.py +57 -0
  13. worthir_eval-1.2.0/examples/custom_task/README.md +32 -0
  14. worthir_eval-1.2.0/examples/custom_task/__init__.py +1 -0
  15. worthir_eval-1.2.0/examples/custom_task/source/outcomes.csv +13 -0
  16. worthir_eval-1.2.0/examples/custom_task/source/queries.csv +5 -0
  17. worthir_eval-1.2.0/examples/custom_task/source/routes.csv +4 -0
  18. worthir_eval-1.2.0/examples/custom_task/source/task.json +16 -0
  19. worthir_eval-1.2.0/examples/trec_walkthrough/README.md +28 -0
  20. worthir_eval-1.2.0/examples/trec_walkthrough/__init__.py +1 -0
  21. worthir_eval-1.2.0/examples/trec_walkthrough/source/alternative_choices.csv +5 -0
  22. worthir_eval-1.2.0/examples/trec_walkthrough/source/policy_choices.csv +5 -0
  23. worthir_eval-1.2.0/examples/trec_walkthrough/source/qrels.tsv +8 -0
  24. worthir_eval-1.2.0/examples/trec_walkthrough/source/queries.csv +5 -0
  25. worthir_eval-1.2.0/examples/trec_walkthrough/source/routes.csv +4 -0
  26. worthir_eval-1.2.0/examples/trec_walkthrough/source/runs/base.trec +12 -0
  27. worthir_eval-1.2.0/examples/trec_walkthrough/source/runs/prf.trec +12 -0
  28. worthir_eval-1.2.0/examples/trec_walkthrough/source/runs/rerank.trec +12 -0
  29. worthir_eval-1.2.0/pyproject.toml +62 -0
  30. worthir_eval-1.2.0/quickstart/README.md +10 -0
  31. worthir_eval-1.2.0/quickstart/__init__.py +1 -0
  32. worthir_eval-1.2.0/quickstart/evaluator/README.md +8 -0
  33. worthir_eval-1.2.0/quickstart/evaluator/hidden_ledger.csv +19 -0
  34. worthir_eval-1.2.0/quickstart/participant/README.md +8 -0
  35. worthir_eval-1.2.0/quickstart/participant/example_actions.json +31 -0
  36. worthir_eval-1.2.0/quickstart/participant/legal_state.csv +8 -0
  37. worthir_eval-1.2.0/scripts/__init__.py +1 -0
  38. worthir_eval-1.2.0/scripts/actions_from_csv.py +98 -0
  39. worthir_eval-1.2.0/scripts/build_custom_task.py +507 -0
  40. worthir_eval-1.2.0/scripts/build_trec_task.py +497 -0
  41. worthir_eval-1.2.0/scripts/compare_policies.py +210 -0
  42. worthir_eval-1.2.0/scripts/init_task.py +92 -0
  43. worthir_eval-1.2.0/scripts/launcher.py +26 -0
  44. worthir_eval-1.2.0/scripts/run_integrity_tests.py +427 -0
  45. worthir_eval-1.2.0/scripts/run_smoke_test.py +52 -0
  46. worthir_eval-1.2.0/scripts/score_actions.py +85 -0
  47. worthir_eval-1.2.0/scripts/validate_framework.py +198 -0
  48. worthir_eval-1.2.0/scripts/validate_task.py +62 -0
  49. worthir_eval-1.2.0/setup.cfg +4 -0
  50. worthir_eval-1.2.0/src/worthir_eval/__init__.py +5 -0
  51. worthir_eval-1.2.0/src/worthir_eval/core.py +528 -0
  52. worthir_eval-1.2.0/task_template/.gitignore +5 -0
  53. worthir_eval-1.2.0/task_template/README.md +13 -0
  54. worthir_eval-1.2.0/task_template/__init__.py +1 -0
  55. worthir_eval-1.2.0/task_template/contracts/route_registry.json +23 -0
  56. worthir_eval-1.2.0/task_template/contracts/task_contract.json +40 -0
  57. worthir_eval-1.2.0/task_template/evaluator/ledger.csv +3 -0
  58. worthir_eval-1.2.0/task_template/participant/actions.json +11 -0
  59. worthir_eval-1.2.0/task_template/participant/legal_state.csv +2 -0
  60. worthir_eval-1.2.0/worthir.py +232 -0
  61. worthir_eval-1.2.0/worthir_eval.egg-info/PKG-INFO +105 -0
  62. worthir_eval-1.2.0/worthir_eval.egg-info/SOURCES.txt +63 -0
  63. worthir_eval-1.2.0/worthir_eval.egg-info/dependency_links.txt +1 -0
  64. worthir_eval-1.2.0/worthir_eval.egg-info/entry_points.txt +2 -0
  65. worthir_eval-1.2.0/worthir_eval.egg-info/top_level.txt +2 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 WorthIR Authors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,105 @@
1
+ Metadata-Version: 2.4
2
+ Name: worthir-eval
3
+ Version: 1.2.0
4
+ Summary: Evaluate cost-aware query-level retrieval routing
5
+ Author: WorthIR authors
6
+ License-Expression: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Dynamic: license-file
13
+
14
+ # WorthIR
15
+
16
+ [English](https://github.com/HongTianShi/worthir-artifact/tree/_en) | [简体中文](https://github.com/HongTianShi/worthir-artifact/tree/zh-cn)
17
+
18
+ [![CI](https://github.com/HongTianShi/worthir-artifact/actions/workflows/validate.yml/badge.svg?branch=_en)](https://github.com/HongTianShi/worthir-artifact/actions/workflows/validate.yml)
19
+ ![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-3776AB)
20
+ [![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
21
+
22
+ WorthIR compares query-level routing policies with fixed retrieval strategies
23
+ under a declared effectiveness measure and cost profile. It reports
24
+ effectiveness, cost, utility, regret, and the fixed-route Pareto curve.
25
+
26
+ If you are an AI tool, read [`README_FOR_AI.md`](README_FOR_AI.md) before
27
+ searching the repository.
28
+
29
+ ## 60-second demo
30
+
31
+ Python 3.10 or newer is required. Choose one installation path.
32
+
33
+ **Source archive or Git clone:** run the local launcher. It creates the local
34
+ environment when first needed.
35
+
36
+ ```powershell
37
+ .\worthir.cmd demo-custom
38
+ ```
39
+
40
+ ```bash
41
+ ./worthir demo-custom
42
+ ```
43
+
44
+ **Installed wheel:** install the wheel, then use the global command.
45
+
46
+ ```bash
47
+ python -m pip install worthir_eval-1.2.0-py3-none-any.whl
48
+ worthir demo-custom
49
+ ```
50
+
51
+ Do not run both setup paths. Open `reproduced/custom_task/comparison.md` after
52
+ the command finishes. The published wheel uses English terminal messages; the
53
+ Chinese source branch provides Chinese launchers and documentation.
54
+
55
+ ## Use your own task
56
+
57
+ Prepare `task.json`, `queries.csv`, `routes.csv`, and `outcomes.csv` as shown in
58
+ [`examples/custom_task/source/`](examples/custom_task/source/), then run:
59
+
60
+ ```powershell
61
+ .\worthir.cmd build-custom my_source my_task
62
+ .\worthir.cmd validate-task my_task
63
+ .\worthir.cmd evaluate my_task choices.csv --policy-id my-router
64
+ ```
65
+
66
+ This path accepts any named higher-is-better effectiveness measure, arbitrary
67
+ route prerequisites, fixed or query-dependent costs, and either cumulative or
68
+ incremental cost input. The router receives `queries.csv`, the public route
69
+ registry, lambda, and any costs declared as known at commitment time. Evaluator
70
+ outcomes and costs measured only after execution remain separate.
71
+
72
+ For qrels and six-column TREC runs, use the shorter [`build-trec` walkthrough](examples/trec_walkthrough/README.md).
73
+ All input formats are described in [`docs/ADAPT_TO_NEW_TASK.md`](docs/ADAPT_TO_NEW_TASK.md).
74
+ For direct library use, see the
75
+ [`worthir_eval` Python example](examples/python_api/README.md).
76
+
77
+ ## Recompute the paper results
78
+
79
+ This uses released query--route ledgers and frozen route selections. It does
80
+ not redownload corpora or rerun retrieval models.
81
+
82
+ ```bash
83
+ python paper_results/run.py
84
+ ```
85
+
86
+ Open [`paper_results/reproduced/INDEX.md`](paper_results/reproduced/INDEX.md).
87
+ The index names the exact paper version, caption, output, and reproduction
88
+ level for every main-paper and appendix figure or table.
89
+
90
+ ## Rebuild the original retrieval routes
91
+
92
+ This is a separate, resource-intensive workflow. It checks licensed corpora
93
+ and checkpoints, invokes a configured task adapter, and constructs new
94
+ query--route ledgers through five explicit stages. Start with
95
+ [`paper_results/full_replay/README.md`](paper_results/full_replay/README.md) and
96
+ its task-specific resource estimates. Raw corpora, indexes, and model weights
97
+ are not included in this repository.
98
+
99
+ The [`v1.2.0`](https://github.com/HongTianShi/worthir-artifact/releases/tag/v1.2.0)
100
+ release is the published artifact currently bound to the 2026-08-16 paper
101
+ mapping. The earlier `v1.0.0-ipmc2026` release remains the artifact submitted
102
+ with the accepted IP&MC 2026 paper.
103
+
104
+ WorthIR-authored code is released under the [MIT License](LICENSE). Third-party
105
+ data and model terms are listed in [NOTICE](NOTICE).
@@ -0,0 +1,92 @@
1
+ # WorthIR
2
+
3
+ [English](https://github.com/HongTianShi/worthir-artifact/tree/_en) | [简体中文](https://github.com/HongTianShi/worthir-artifact/tree/zh-cn)
4
+
5
+ [![CI](https://github.com/HongTianShi/worthir-artifact/actions/workflows/validate.yml/badge.svg?branch=_en)](https://github.com/HongTianShi/worthir-artifact/actions/workflows/validate.yml)
6
+ ![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-3776AB)
7
+ [![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
8
+
9
+ WorthIR compares query-level routing policies with fixed retrieval strategies
10
+ under a declared effectiveness measure and cost profile. It reports
11
+ effectiveness, cost, utility, regret, and the fixed-route Pareto curve.
12
+
13
+ If you are an AI tool, read [`README_FOR_AI.md`](README_FOR_AI.md) before
14
+ searching the repository.
15
+
16
+ ## 60-second demo
17
+
18
+ Python 3.10 or newer is required. Choose one installation path.
19
+
20
+ **Source archive or Git clone:** run the local launcher. It creates the local
21
+ environment when first needed.
22
+
23
+ ```powershell
24
+ .\worthir.cmd demo-custom
25
+ ```
26
+
27
+ ```bash
28
+ ./worthir demo-custom
29
+ ```
30
+
31
+ **Installed wheel:** install the wheel, then use the global command.
32
+
33
+ ```bash
34
+ python -m pip install worthir_eval-1.2.0-py3-none-any.whl
35
+ worthir demo-custom
36
+ ```
37
+
38
+ Do not run both setup paths. Open `reproduced/custom_task/comparison.md` after
39
+ the command finishes. The published wheel uses English terminal messages; the
40
+ Chinese source branch provides Chinese launchers and documentation.
41
+
42
+ ## Use your own task
43
+
44
+ Prepare `task.json`, `queries.csv`, `routes.csv`, and `outcomes.csv` as shown in
45
+ [`examples/custom_task/source/`](examples/custom_task/source/), then run:
46
+
47
+ ```powershell
48
+ .\worthir.cmd build-custom my_source my_task
49
+ .\worthir.cmd validate-task my_task
50
+ .\worthir.cmd evaluate my_task choices.csv --policy-id my-router
51
+ ```
52
+
53
+ This path accepts any named higher-is-better effectiveness measure, arbitrary
54
+ route prerequisites, fixed or query-dependent costs, and either cumulative or
55
+ incremental cost input. The router receives `queries.csv`, the public route
56
+ registry, lambda, and any costs declared as known at commitment time. Evaluator
57
+ outcomes and costs measured only after execution remain separate.
58
+
59
+ For qrels and six-column TREC runs, use the shorter [`build-trec` walkthrough](examples/trec_walkthrough/README.md).
60
+ All input formats are described in [`docs/ADAPT_TO_NEW_TASK.md`](docs/ADAPT_TO_NEW_TASK.md).
61
+ For direct library use, see the
62
+ [`worthir_eval` Python example](examples/python_api/README.md).
63
+
64
+ ## Recompute the paper results
65
+
66
+ This uses released query--route ledgers and frozen route selections. It does
67
+ not redownload corpora or rerun retrieval models.
68
+
69
+ ```bash
70
+ python paper_results/run.py
71
+ ```
72
+
73
+ Open [`paper_results/reproduced/INDEX.md`](paper_results/reproduced/INDEX.md).
74
+ The index names the exact paper version, caption, output, and reproduction
75
+ level for every main-paper and appendix figure or table.
76
+
77
+ ## Rebuild the original retrieval routes
78
+
79
+ This is a separate, resource-intensive workflow. It checks licensed corpora
80
+ and checkpoints, invokes a configured task adapter, and constructs new
81
+ query--route ledgers through five explicit stages. Start with
82
+ [`paper_results/full_replay/README.md`](paper_results/full_replay/README.md) and
83
+ its task-specific resource estimates. Raw corpora, indexes, and model weights
84
+ are not included in this repository.
85
+
86
+ The [`v1.2.0`](https://github.com/HongTianShi/worthir-artifact/releases/tag/v1.2.0)
87
+ release is the published artifact currently bound to the 2026-08-16 paper
88
+ mapping. The earlier `v1.0.0-ipmc2026` release remains the artifact submitted
89
+ with the accepted IP&MC 2026 paper.
90
+
91
+ WorthIR-authored code is released under the [MIT License](LICENSE). Third-party
92
+ data and model terms are listed in [NOTICE](NOTICE).
@@ -0,0 +1,11 @@
1
+ # Example contracts
2
+
3
+ These files define the six-query smoke test. For a new task, use
4
+ `worthir build-custom`, or use `worthir build-trec` for qrels and TREC runs;
5
+ both create a bound contract and route registry.
6
+
7
+ The public interface fixes five invariants: higher effectiveness is better, the
8
+ ledger contains every query--route pair, costs are nonnegative and cumulative,
9
+ their decision-time availability is explicit, and oracle ties prefer lower cost
10
+ then registry order. Fixed commitment-time costs live on registered routes;
11
+ query-dependent commitment-time costs live in `participant/route_costs.csv`.
@@ -0,0 +1 @@
1
+ """Bundled quickstart contracts."""
@@ -0,0 +1,40 @@
1
+ {
2
+ "schema_version": "worthir-contract-v1.0",
3
+ "contract_id": "worthir-quickstart-v1",
4
+ "task_id": "worthir-synthetic-route-choice-v1",
5
+ "expected_query_count": 6,
6
+ "route_registry": "route_registry.json",
7
+ "development_selected_fixed_route": "dense",
8
+ "action_schema": {
9
+ "schema_version": "worthir-action-file-v1.0",
10
+ "top_level_fields": [
11
+ "schema_version",
12
+ "contract_id",
13
+ "policy_id",
14
+ "decisions"
15
+ ],
16
+ "decision_fields": [
17
+ "query_uid",
18
+ "selected_route_id"
19
+ ]
20
+ },
21
+ "ledger_schema": {
22
+ "columns": [
23
+ "query_uid",
24
+ "route_id",
25
+ "effectiveness",
26
+ "cost"
27
+ ]
28
+ },
29
+ "metric": {
30
+ "name": "synthetic_ndcg_at_10",
31
+ "minimum": 0.0,
32
+ "maximum": 1.0
33
+ },
34
+ "cost_profile": {
35
+ "profile_id": "synthetic_declared_schedule-v1",
36
+ "provenance": "declared",
37
+ "lambda": 0.08,
38
+ "availability": "known_at_commitment"
39
+ }
40
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "registry_id": "worthir-quickstart-routes-v1",
3
+ "cost_information": {
4
+ "availability": "known_at_commitment",
5
+ "mode": "fixed",
6
+ "route_costs_file": null
7
+ },
8
+ "routes": [
9
+ {
10
+ "label": "Stop after BM25",
11
+ "prerequisites": [],
12
+ "route_id": "bm25",
13
+ "cost": 0.0
14
+ },
15
+ {
16
+ "label": "Dense candidate fusion",
17
+ "prerequisites": ["bm25"],
18
+ "route_id": "dense",
19
+ "cost": 0.2
20
+ },
21
+ {
22
+ "label": "Cross-encoder rerank top 20",
23
+ "prerequisites": ["dense"],
24
+ "route_id": "ce20",
25
+ "cost": 0.8
26
+ }
27
+ ],
28
+ "schema_version": "worthir-route-registry-v1.2"
29
+ }
@@ -0,0 +1 @@
1
+ """Runnable examples bundled with the WorthIR wheel."""
@@ -0,0 +1,36 @@
1
+ # Bring your own router
2
+
3
+ Run the complete example from the repository root:
4
+
5
+ ```powershell
6
+ .\worthir.cmd demo-custom
7
+ ```
8
+
9
+ ```bash
10
+ ./worthir demo-custom
11
+ ```
12
+
13
+ The example builds a non-TREC task, runs `router.py`, binds its CSV decisions to
14
+ the task contract, and compares the router with every fixed route. The report is
15
+ written to `reproduced/custom_task/comparison.md`.
16
+
17
+ `router.py` reads the public task contract, route registry, lambda,
18
+ `participant/legal_state.csv`, and `participant/route_costs.csv`. It selects the
19
+ route with the highest predicted effectiveness minus lambda times public cost.
20
+ It never opens `evaluator/ledger.csv`, which contains information unavailable
21
+ when a route is selected. To use your own router, replace
22
+ `predicted_effectiveness()` and keep the two-column output format:
23
+
24
+ ```text
25
+ query_uid,selected_route_id
26
+ ```
27
+
28
+ For an existing task, evaluate that CSV in one command:
29
+
30
+ ```powershell
31
+ .\worthir.cmd evaluate TASK choices.csv --policy-id my-router
32
+ ```
33
+
34
+ ```bash
35
+ ./worthir evaluate TASK choices.csv --policy-id my-router
36
+ ```
@@ -0,0 +1 @@
1
+ """External-router walkthrough."""
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env python3
2
+ """Cost-aware router using only participant-visible task files."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import csv
8
+ import json
9
+ from pathlib import Path
10
+
11
+
12
+ def read_json(path: Path) -> dict:
13
+ return json.loads(path.read_text(encoding="utf-8"))
14
+
15
+
16
+ def public_costs(task: Path, registry: dict) -> dict[tuple[str, str], float]:
17
+ info = registry["cost_information"]
18
+ if info["availability"] != "known_at_commitment":
19
+ raise ValueError("this router requires costs known at commitment time")
20
+ if info["mode"] == "fixed":
21
+ return {
22
+ ("*", route["route_id"]): float(route["cost"])
23
+ for route in registry["routes"]
24
+ }
25
+ path = (task / "contracts" / info["route_costs_file"]).resolve()
26
+ with path.open("r", encoding="utf-8-sig", newline="") as stream:
27
+ return {
28
+ (row["query_uid"], row["route_id"]): float(row["cost"])
29
+ for row in csv.DictReader(stream)
30
+ }
31
+
32
+
33
+ def predicted_effectiveness(row: dict[str, str], route_id: str) -> float:
34
+ """Replace these estimates with predictions from your own router."""
35
+
36
+ length = int(row["question_length"])
37
+ product_code = row["contains_product_code"].lower() == "true"
38
+ if route_id == "keyword_search":
39
+ return 0.86 if length <= 12 and not product_code else 0.58
40
+ if route_id == "semantic_search":
41
+ return 0.90 if length > 20 else 0.79
42
+ if route_id == "combined_review":
43
+ return 0.95 if product_code else 0.87
44
+ return 0.0
45
+
46
+
47
+ def route(task: Path, output: Path) -> Path:
48
+ contract = read_json(task / "contracts" / "task_contract.json")
49
+ registry = read_json(task / "contracts" / contract["route_registry"])
50
+ costs = public_costs(task, registry)
51
+ route_ids = [item["route_id"] for item in registry["routes"]]
52
+ lam = float(contract["cost_profile"]["lambda"])
53
+ with (task / "participant" / "legal_state.csv").open(
54
+ "r", encoding="utf-8-sig", newline=""
55
+ ) as stream:
56
+ rows = list(csv.DictReader(stream))
57
+
58
+ decisions = []
59
+ for row in rows:
60
+ query_uid = row["query_uid"]
61
+ selected = max(
62
+ route_ids,
63
+ key=lambda route_id: (
64
+ predicted_effectiveness(row, route_id)
65
+ - lam * costs.get((query_uid, route_id), costs.get(("*", route_id))),
66
+ -route_ids.index(route_id),
67
+ ),
68
+ )
69
+ decisions.append({"query_uid": query_uid, "selected_route_id": selected})
70
+
71
+ output.parent.mkdir(parents=True, exist_ok=True)
72
+ with output.open("w", encoding="utf-8", newline="") as stream:
73
+ writer = csv.DictWriter(
74
+ stream, fieldnames=["query_uid", "selected_route_id"]
75
+ )
76
+ writer.writeheader()
77
+ writer.writerows(decisions)
78
+ return output
79
+
80
+
81
+ def main() -> None:
82
+ parser = argparse.ArgumentParser(
83
+ description="Create cost-aware choices without reading evaluator outcomes."
84
+ )
85
+ parser.add_argument("task_dir", type=Path, help="built WorthIR task directory")
86
+ parser.add_argument("output", type=Path, help="choice CSV to create")
87
+ args = parser.parse_args()
88
+ print(f"WROTE: {route(args.task_dir.resolve(), args.output.resolve())}")
89
+
90
+
91
+ if __name__ == "__main__":
92
+ main()
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env python3
2
+ """Build the custom task, run the example router, and compare its utility."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import shutil
7
+ import subprocess
8
+ import sys
9
+ from pathlib import Path
10
+
11
+
12
+ ROOT = Path(__file__).resolve().parents[2]
13
+ OUTPUT_ROOT = ROOT if (ROOT / "paper_results").is_dir() else Path.cwd()
14
+ DESTINATION = OUTPUT_ROOT / "reproduced" / "custom_task"
15
+ CHOICES = OUTPUT_ROOT / "reproduced" / "custom_router_choices.csv"
16
+
17
+
18
+ def run(*arguments: str) -> None:
19
+ launcher = (
20
+ [sys.executable, str(ROOT / "worthir.py")]
21
+ if (ROOT / "worthir.py").is_file()
22
+ else [sys.executable, "-m", "worthir"]
23
+ )
24
+ completed = subprocess.run([*launcher, *arguments])
25
+ if completed.returncode:
26
+ raise SystemExit(completed.returncode)
27
+
28
+
29
+ def main() -> None:
30
+ if DESTINATION.exists():
31
+ shutil.rmtree(DESTINATION)
32
+ run(
33
+ "build-custom",
34
+ str(ROOT / "examples" / "custom_task" / "source"),
35
+ str(DESTINATION),
36
+ )
37
+ subprocess.run(
38
+ [
39
+ sys.executable,
40
+ str(Path(__file__).with_name("router.py")),
41
+ str(DESTINATION),
42
+ str(CHOICES),
43
+ ],
44
+ check=True,
45
+ )
46
+ run(
47
+ "evaluate",
48
+ str(DESTINATION),
49
+ str(CHOICES),
50
+ "--policy-id",
51
+ "example-rule-router",
52
+ )
53
+ print(f"OPEN: {DESTINATION / 'comparison.md'}")
54
+
55
+
56
+ if __name__ == "__main__":
57
+ main()
@@ -0,0 +1,32 @@
1
+ # Custom task input
2
+
3
+ This example is not a TREC ranking task. Its effectiveness measure is
4
+ `answer_coverage`, and its execution cost varies by query.
5
+
6
+ The four source files are the complete generic adapter interface:
7
+
8
+ - `task.json` names the effectiveness measure and cost profile.
9
+ - `queries.csv` contains only information a router may use.
10
+ - `routes.csv` defines available routes, prerequisites, and route costs.
11
+ - `outcomes.csv` contains evaluator-only effectiveness and cost outcomes for
12
+ every query--route pair.
13
+
14
+ Build and validate it from the repository root:
15
+
16
+ ```powershell
17
+ .\worthir.cmd build-custom examples/custom_task/source reproduced/custom_task
18
+ .\worthir.cmd validate-task reproduced/custom_task
19
+ ```
20
+
21
+ ```bash
22
+ ./worthir build-custom examples/custom_task/source reproduced/custom_task
23
+ ./worthir validate-task reproduced/custom_task
24
+ ```
25
+
26
+ Use `cost` when cumulative route costs are already available. Use
27
+ `incremental_cost` when the tool should sum the transitive prerequisite closure.
28
+ Either column may appear in `outcomes.csv` to provide query-dependent values.
29
+ Set `cost_profile.availability` to `known_at_commitment` when the router may use
30
+ the cost before choosing a route. The builder then publishes fixed costs in the
31
+ route registry or query-dependent costs in `participant/route_costs.csv`. Use
32
+ `measured_after_execution` when cost is evaluator-only.
@@ -0,0 +1 @@
1
+ """Generic non-TREC task example."""
@@ -0,0 +1,13 @@
1
+ query_uid,route_id,effectiveness,incremental_cost
2
+ faq-001,keyword_search,0.92,0.025
3
+ faq-001,semantic_search,0.88,0.105
4
+ faq-001,combined_review,0.94,0.070
5
+ faq-002,keyword_search,0.61,0.030
6
+ faq-002,semantic_search,0.84,0.115
7
+ faq-002,combined_review,0.96,0.075
8
+ faq-003,keyword_search,0.45,0.035
9
+ faq-003,semantic_search,0.81,0.140
10
+ faq-003,combined_review,0.93,0.095
11
+ faq-004,keyword_search,0.78,0.028
12
+ faq-004,semantic_search,0.80,0.110
13
+ faq-004,combined_review,0.91,0.080
@@ -0,0 +1,5 @@
1
+ query_uid,question_length,contains_product_code
2
+ faq-001,6,false
3
+ faq-002,19,true
4
+ faq-003,31,false
5
+ faq-004,12,true
@@ -0,0 +1,4 @@
1
+ route_id,label,prerequisites,incremental_cost,development_selected
2
+ keyword_search,Keyword search,,0.03,false
3
+ semantic_search,Semantic search,,0.12,true
4
+ combined_review,Combined evidence review,keyword_search;semantic_search,0.08,false
@@ -0,0 +1,16 @@
1
+ {
2
+ "task_id": "faq-answer-routing-v1",
3
+ "metric": {
4
+ "name": "answer_coverage",
5
+ "minimum": 0.0,
6
+ "maximum": 1.0,
7
+ "higher_is_better": true
8
+ },
9
+ "cost_profile": {
10
+ "profile_id": "measured-seconds-v1",
11
+ "provenance": "expected execution time estimated on an independent calibration set and available before route selection",
12
+ "lambda": 0.15,
13
+ "availability": "known_at_commitment"
14
+ },
15
+ "development_selected_fixed_route": "semantic_search"
16
+ }
@@ -0,0 +1,28 @@
1
+ # TREC walkthrough
2
+
3
+ This is a tiny retrieval task in standard TREC formats. It demonstrates the
4
+ full human workflow without downloading data.
5
+
6
+ ```powershell
7
+ .\worthir.cmd demo
8
+ ```
9
+
10
+ ```bash
11
+ ./worthir demo
12
+ ```
13
+
14
+ The command computes NDCG@3 from `source/qrels.tsv` and the three TREC runs,
15
+ builds a WorthIR task, scores the supplied policy, evaluates every fixed route,
16
+ and writes `reproduced/trec_walkthrough/comparison.md`.
17
+
18
+ To try another policy after the demo:
19
+
20
+ ```powershell
21
+ .\worthir.cmd actions reproduced/trec_walkthrough examples/trec_walkthrough/source/alternative_choices.csv --policy-id alternative
22
+ .\worthir.cmd compare reproduced/trec_walkthrough
23
+ ```
24
+
25
+ ```bash
26
+ ./worthir actions reproduced/trec_walkthrough examples/trec_walkthrough/source/alternative_choices.csv --policy-id alternative
27
+ ./worthir compare reproduced/trec_walkthrough
28
+ ```
@@ -0,0 +1 @@
1
+ """TREC task walkthrough."""
@@ -0,0 +1,5 @@
1
+ query_uid,selected_route_id
2
+ q1,prf
3
+ q2,rerank
4
+ q3,rerank
5
+ q4,base
@@ -0,0 +1,5 @@
1
+ query_uid,selected_route_id
2
+ q1,base
3
+ q2,rerank
4
+ q3,prf
5
+ q4,base
@@ -0,0 +1,8 @@
1
+ q1 0 d1 2
2
+ q1 0 d2 1
3
+ q2 0 d4 2
4
+ q2 0 d5 1
5
+ q3 0 d7 2
6
+ q3 0 d8 1
7
+ q4 0 d10 2
8
+ q4 0 d11 1
@@ -0,0 +1,5 @@
1
+ query_uid,query_text,base_score_margin
2
+ q1,solar panel recycling,2.8
3
+ q2,rare disease treatment,0.4
4
+ q3,river restoration methods,1.1
5
+ q4,historic bridge design,3.2
@@ -0,0 +1,4 @@
1
+ route_id,label,prerequisites,run_file,cost,development_selected
2
+ base,BM25,,runs/base.trec,0.00,false
3
+ prf,Query expansion,base,runs/prf.trec,0.25,true
4
+ rerank,Cross-encoder,prf,runs/rerank.trec,0.75,false
@@ -0,0 +1,12 @@
1
+ q1 Q0 d1 1 8.0 base
2
+ q1 Q0 x1 2 7.0 base
3
+ q1 Q0 d2 3 6.0 base
4
+ q2 Q0 x2 1 8.0 base
5
+ q2 Q0 d5 2 7.0 base
6
+ q2 Q0 d4 3 6.0 base
7
+ q3 Q0 d8 1 8.0 base
8
+ q3 Q0 x3 2 7.0 base
9
+ q3 Q0 d7 3 6.0 base
10
+ q4 Q0 d10 1 8.0 base
11
+ q4 Q0 d11 2 7.0 base
12
+ q4 Q0 x4 3 6.0 base