agentinputlab 0.1.0a1__py3-none-any.whl
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.
- agentinputlab/__init__.py +28 -0
- agentinputlab/algorithms/__init__.py +6 -0
- agentinputlab/algorithms/acquire/__init__.py +145 -0
- agentinputlab/algorithms/acquire/adaptive_rag/__init__.py +43 -0
- agentinputlab/algorithms/acquire/adaptive_rag/replay.py +367 -0
- agentinputlab/algorithms/acquire/adaptive_rag/runtime.py +1202 -0
- agentinputlab/algorithms/acquire/adaptive_rag_common_support.py +542 -0
- agentinputlab/algorithms/acquire/hyde.py +296 -0
- agentinputlab/algorithms/acquire/hyde_controlled.py +200 -0
- agentinputlab/algorithms/acquire/hyde_external.py +148 -0
- agentinputlab/algorithms/acquire/ircot.py +28 -0
- agentinputlab/algorithms/acquire/ircot_common_support.py +478 -0
- agentinputlab/algorithms/acquire/ircot_native.py +355 -0
- agentinputlab/algorithms/acquire/ircot_replay.py +327 -0
- agentinputlab/algorithms/acquire/qrag/__init__.py +79 -0
- agentinputlab/algorithms/acquire/qrag/bridge.py +828 -0
- agentinputlab/algorithms/acquire/qrag/common_support.py +891 -0
- agentinputlab/algorithms/acquire/qrag/native_axis.py +71 -0
- agentinputlab/algorithms/acquire/qrag/reader_adapter.py +139 -0
- agentinputlab/algorithms/acquire/r2ag/__init__.py +57 -0
- agentinputlab/algorithms/acquire/r2ag/bridge.py +1312 -0
- agentinputlab/algorithms/acquire/r2ag/common_support.py +1029 -0
- agentinputlab/algorithms/acquire/r2ag/socket_runtime.py +255 -0
- agentinputlab/algorithms/clarify/__init__.py +61 -0
- agentinputlab/algorithms/clarify/_structured.py +64 -0
- agentinputlab/algorithms/clarify/active_task_disambiguation.py +371 -0
- agentinputlab/algorithms/clarify/ask_or_assume/__init__.py +17 -0
- agentinputlab/algorithms/clarify/ask_or_assume/monitor.py +410 -0
- agentinputlab/algorithms/clarify/future_turns.py +379 -0
- agentinputlab/algorithms/clarify/udcs.py +255 -0
- agentinputlab/algorithms/clarify/udcs_deterministic.py +196 -0
- agentinputlab/algorithms/curate/__init__.py +65 -0
- agentinputlab/algorithms/curate/acon/__init__.py +27 -0
- agentinputlab/algorithms/curate/acon/common.py +284 -0
- agentinputlab/algorithms/curate/acon/common_support.py +136 -0
- agentinputlab/algorithms/curate/acon/history_bridge.py +309 -0
- agentinputlab/algorithms/curate/acon/observation_bridge.py +290 -0
- agentinputlab/algorithms/curate/llmlingua/__init__.py +30 -0
- agentinputlab/algorithms/curate/llmlingua/adapters.py +537 -0
- agentinputlab/algorithms/curate/llmlingua/budget.py +48 -0
- agentinputlab/algorithms/curate/llmlingua/controlled.py +175 -0
- agentinputlab/algorithms/curate/llmlingua/multilingual.py +105 -0
- agentinputlab/algorithms/curate/llmlingua/span_map.py +167 -0
- agentinputlab/algorithms/curate/recomp/__init__.py +47 -0
- agentinputlab/algorithms/curate/recomp/external.py +1129 -0
- agentinputlab/algorithms/curate/recomp/selective.py +304 -0
- agentinputlab/algorithms/decompose/__init__.py +107 -0
- agentinputlab/algorithms/decompose/decomp/__init__.py +53 -0
- agentinputlab/algorithms/decompose/decomp/common_support.py +478 -0
- agentinputlab/algorithms/decompose/decomp/planner_component.py +199 -0
- agentinputlab/algorithms/decompose/decomp/worker_bridge.py +416 -0
- agentinputlab/algorithms/decompose/llm_compiler/__init__.py +35 -0
- agentinputlab/algorithms/decompose/llm_compiler/bridge.py +520 -0
- agentinputlab/algorithms/decompose/llm_compiler/common_support.py +504 -0
- agentinputlab/algorithms/decompose/plan_and_budget/__init__.py +43 -0
- agentinputlab/algorithms/decompose/plan_and_budget/cached_soft_budget.py +362 -0
- agentinputlab/algorithms/decompose/plan_and_budget/decomposer_component.py +107 -0
- agentinputlab/algorithms/decompose/plan_and_budget/full.py +205 -0
- agentinputlab/algorithms/decompose/plan_and_budget/hard_cap.py +246 -0
- agentinputlab/algorithms/decompose/plan_and_budget/regenerated_soft_budget.py +448 -0
- agentinputlab/algorithms/decompose/plan_and_solve/__init__.py +33 -0
- agentinputlab/algorithms/decompose/plan_and_solve/plan_component.py +192 -0
- agentinputlab/algorithms/decompose/plan_and_solve/ps_prompt.py +127 -0
- agentinputlab/algorithms/decompose/self_ask/__init__.py +27 -0
- agentinputlab/algorithms/decompose/self_ask/loop.py +362 -0
- agentinputlab/algorithms/decompose/self_ask/planner_component.py +117 -0
- agentinputlab/algorithms/reformulate/__init__.py +85 -0
- agentinputlab/algorithms/reformulate/infocqr/__init__.py +40 -0
- agentinputlab/algorithms/reformulate/infocqr/cache_replay.py +362 -0
- agentinputlab/algorithms/reformulate/infocqr/external.py +675 -0
- agentinputlab/algorithms/reformulate/infocqr/student.py +189 -0
- agentinputlab/algorithms/reformulate/query2doc/__init__.py +42 -0
- agentinputlab/algorithms/reformulate/query2doc/controlled_live.py +190 -0
- agentinputlab/algorithms/reformulate/query2doc/models.py +95 -0
- agentinputlab/algorithms/reformulate/query2doc/official_cached.py +335 -0
- agentinputlab/algorithms/reformulate/query2doc/querygym_bridge.py +223 -0
- agentinputlab/algorithms/reformulate/query2doc/querygym_runtime.py +326 -0
- agentinputlab/algorithms/reformulate/reformer/__init__.py +23 -0
- agentinputlab/algorithms/reformulate/reformer/external.py +417 -0
- agentinputlab/algorithms/reformulate/rrr.py +696 -0
- agentinputlab/annotation/__init__.py +5 -0
- agentinputlab/annotation/independent.py +428 -0
- agentinputlab/annotation/server.py +233 -0
- agentinputlab/annotation/static/app.js +121 -0
- agentinputlab/annotation/static/index.html +60 -0
- agentinputlab/annotation/static/review.css +2 -0
- agentinputlab/annotation/static/review.html +10 -0
- agentinputlab/annotation/static/review.js +11 -0
- agentinputlab/annotation/static/styles.css +55 -0
- agentinputlab/annotation/store.py +444 -0
- agentinputlab/api.py +368 -0
- agentinputlab/artifacts/__init__.py +15 -0
- agentinputlab/artifacts/json_file.py +104 -0
- agentinputlab/artifacts/manifest.py +98 -0
- agentinputlab/artifacts/store.py +157 -0
- agentinputlab/backends/__init__.py +98 -0
- agentinputlab/backends/embedding/__init__.py +25 -0
- agentinputlab/backends/embedding/base.py +145 -0
- agentinputlab/backends/embedding/callable.py +75 -0
- agentinputlab/backends/embedding/replay.py +129 -0
- agentinputlab/backends/llm/__init__.py +31 -0
- agentinputlab/backends/llm/base.py +149 -0
- agentinputlab/backends/llm/callable.py +108 -0
- agentinputlab/backends/llm/decomp_completion.py +88 -0
- agentinputlab/backends/llm/final_content_stop.py +72 -0
- agentinputlab/backends/llm/gpt_oss_final_channel.py +84 -0
- agentinputlab/backends/llm/openai_compatible.py +332 -0
- agentinputlab/backends/llm/transformers.py +171 -0
- agentinputlab/backends/retrieval/__init__.py +35 -0
- agentinputlab/backends/retrieval/base.py +50 -0
- agentinputlab/backends/retrieval/dense.py +777 -0
- agentinputlab/backends/retrieval/memory.py +119 -0
- agentinputlab/backends/retrieval/sqlite_fts.py +155 -0
- agentinputlab/backends/user/__init__.py +15 -0
- agentinputlab/backends/user/base.py +66 -0
- agentinputlab/backends/user/callable.py +54 -0
- agentinputlab/backends/user/replay.py +89 -0
- agentinputlab/backends/vector.py +38 -0
- agentinputlab/benchmarks/__init__.py +246 -0
- agentinputlab/benchmarks/acquisition.py +106 -0
- agentinputlab/benchmarks/ale.py +540 -0
- agentinputlab/benchmarks/appworld_ul.py +669 -0
- agentinputlab/benchmarks/assets.py +226 -0
- agentinputlab/benchmarks/base.py +68 -0
- agentinputlab/benchmarks/beir_archive.py +235 -0
- agentinputlab/benchmarks/beir_sample.py +269 -0
- agentinputlab/benchmarks/bfcl_native.py +245 -0
- agentinputlab/benchmarks/bfcl_v3.py +607 -0
- agentinputlab/benchmarks/cache.py +218 -0
- agentinputlab/benchmarks/clariq.py +203 -0
- agentinputlab/benchmarks/data/registry.json +321 -0
- agentinputlab/benchmarks/data/smoke_assets.json +511 -0
- agentinputlab/benchmarks/data/statebench_v0_8_1_task_ids.json +475 -0
- agentinputlab/benchmarks/data/toolsandbox_165848b_scenario_names.json +1 -0
- agentinputlab/benchmarks/execution.py +1111 -0
- agentinputlab/benchmarks/interactive.py +257 -0
- agentinputlab/benchmarks/ir_query.py +204 -0
- agentinputlab/benchmarks/longbench.py +203 -0
- agentinputlab/benchmarks/paired_replay.py +479 -0
- agentinputlab/benchmarks/preprocess.py +2313 -0
- agentinputlab/benchmarks/production.py +236 -0
- agentinputlab/benchmarks/qa.py +963 -0
- agentinputlab/benchmarks/registry.py +110 -0
- agentinputlab/benchmarks/retrieval.py +459 -0
- agentinputlab/benchmarks/runtime.py +509 -0
- agentinputlab/benchmarks/statebench.py +938 -0
- agentinputlab/benchmarks/tau3.py +725 -0
- agentinputlab/benchmarks/toolsandbox.py +626 -0
- agentinputlab/benchmarks/trec_dl_sample.py +263 -0
- agentinputlab/campaign.py +654 -0
- agentinputlab/campaign_runner.py +953 -0
- agentinputlab/cli/__init__.py +6 -0
- agentinputlab/cli/main.py +933 -0
- agentinputlab/connectors/__init__.py +46 -0
- agentinputlab/connectors/knowledge/__init__.py +4 -0
- agentinputlab/connectors/tools/__init__.py +30 -0
- agentinputlab/connectors/tools/base.py +57 -0
- agentinputlab/connectors/tools/mcp.py +222 -0
- agentinputlab/connectors/tools/memory.py +41 -0
- agentinputlab/connectors/tools/openapi.py +695 -0
- agentinputlab/connectors/tools/schema.py +102 -0
- agentinputlab/contracts/__init__.py +91 -0
- agentinputlab/contracts/availability.py +24 -0
- agentinputlab/contracts/dependency.py +58 -0
- agentinputlab/contracts/enums.py +82 -0
- agentinputlab/contracts/errors.py +63 -0
- agentinputlab/contracts/evidence.py +43 -0
- agentinputlab/contracts/intent.py +110 -0
- agentinputlab/contracts/lifecycle.py +164 -0
- agentinputlab/contracts/patch.py +167 -0
- agentinputlab/contracts/serialization.py +93 -0
- agentinputlab/contracts/state.py +127 -0
- agentinputlab/contracts/trace.py +59 -0
- agentinputlab/contracts/worker.py +42 -0
- agentinputlab/core/__init__.py +7 -0
- agentinputlab/data/__init__.py +32 -0
- agentinputlab/data/checksums.py +9 -0
- agentinputlab/data/downloader.py +235 -0
- agentinputlab/data/http.py +171 -0
- agentinputlab/data/index.py +21 -0
- agentinputlab/data/overlap.py +28 -0
- agentinputlab/data/preprocess.py +32 -0
- agentinputlab/data/storage.py +57 -0
- agentinputlab/data/trec_sample.py +427 -0
- agentinputlab/evaluation/__init__.py +5 -0
- agentinputlab/evaluation/outcomes.py +32 -0
- agentinputlab/experiments/__init__.py +278 -0
- agentinputlab/experiments/analysis.py +981 -0
- agentinputlab/experiments/artifacts.py +687 -0
- agentinputlab/experiments/automatic_measurement.py +678 -0
- agentinputlab/experiments/auxiliary_matrix.py +203 -0
- agentinputlab/experiments/bindings.py +430 -0
- agentinputlab/experiments/blueprints.py +147 -0
- agentinputlab/experiments/builders/__init__.py +45 -0
- agentinputlab/experiments/builders/executable_external_payload.py +423 -0
- agentinputlab/experiments/builders/external_process_arena.py +1018 -0
- agentinputlab/experiments/builders/registry_intervention.py +463 -0
- agentinputlab/experiments/cli.py +158 -0
- agentinputlab/experiments/controls.py +340 -0
- agentinputlab/experiments/driver_guard.py +205 -0
- agentinputlab/experiments/drivers/__init__.py +89 -0
- agentinputlab/experiments/drivers/external_arena.py +2908 -0
- agentinputlab/experiments/drivers/method_process.py +662 -0
- agentinputlab/experiments/drivers/parity_process.py +1484 -0
- agentinputlab/experiments/drivers/static_production.py +1574 -0
- agentinputlab/experiments/executor.py +448 -0
- agentinputlab/experiments/loader.py +605 -0
- agentinputlab/experiments/measurement.py +675 -0
- agentinputlab/experiments/paper_analysis.py +1818 -0
- agentinputlab/experiments/parity_identity.py +605 -0
- agentinputlab/experiments/plan.py +277 -0
- agentinputlab/experiments/production_builders.py +3739 -0
- agentinputlab/experiments/readiness.py +432 -0
- agentinputlab/experiments/schema.py +514 -0
- agentinputlab/experiments/secrets.py +177 -0
- agentinputlab/experiments/stateful_analysis.py +1738 -0
- agentinputlab/experiments/transfer_analysis.py +1316 -0
- agentinputlab/experiments/unseen_analysis.py +1025 -0
- agentinputlab/integrations/__init__.py +1 -0
- agentinputlab/integrations/action_space/__init__.py +1 -0
- agentinputlab/integrations/external_workers/__init__.py +76 -0
- agentinputlab/integrations/external_workers/ace.py +431 -0
- agentinputlab/integrations/external_workers/base.py +181 -0
- agentinputlab/integrations/external_workers/decomp_live.py +249 -0
- agentinputlab/integrations/external_workers/decomp_planner.py +30 -0
- agentinputlab/integrations/external_workers/infocqr_student.py +280 -0
- agentinputlab/integrations/external_workers/ircot.py +576 -0
- agentinputlab/integrations/external_workers/llmcompiler_live.py +360 -0
- agentinputlab/integrations/external_workers/longllmlingua.py +162 -0
- agentinputlab/integrations/external_workers/method.py +314 -0
- agentinputlab/integrations/external_workers/process.py +678 -0
- agentinputlab/integrations/external_workers/supervisor.py +1071 -0
- agentinputlab/integrations/full_architecture/__init__.py +1 -0
- agentinputlab/integrations/full_architecture/hyde.py +212 -0
- agentinputlab/integrations/full_architecture/plan_and_budget.py +188 -0
- agentinputlab/integrations/live_history.py +222 -0
- agentinputlab/integrations/prompt_optimization/__init__.py +1 -0
- agentinputlab/integrations/training/__init__.py +1 -0
- agentinputlab/metrics/__init__.py +50 -0
- agentinputlab/metrics/catalog.py +313 -0
- agentinputlab/metrics/harm.py +95 -0
- agentinputlab/metrics/paired.py +40 -0
- agentinputlab/metrics/qa.py +76 -0
- agentinputlab/metrics/text.py +33 -0
- agentinputlab/metrics/third_party.py +161 -0
- agentinputlab/models/__init__.py +4 -0
- agentinputlab/observability/__init__.py +56 -0
- agentinputlab/observability/budget.py +316 -0
- agentinputlab/observability/instrumentation.py +754 -0
- agentinputlab/observability/models.py +403 -0
- agentinputlab/observability/monitor.py +380 -0
- agentinputlab/optimizers/__init__.py +1 -0
- agentinputlab/optimizers/clarify/__init__.py +12 -0
- agentinputlab/optimizers/context/__init__.py +22 -0
- agentinputlab/optimizers/decompose/__init__.py +64 -0
- agentinputlab/optimizers/evidence/__init__.py +22 -0
- agentinputlab/optimizers/rewrite/__init__.py +30 -0
- agentinputlab/parity/__init__.py +5 -0
- agentinputlab/parity/base.py +206 -0
- agentinputlab/production_campaign.py +763 -0
- agentinputlab/py.typed +1 -0
- agentinputlab/recipes/__init__.py +333 -0
- agentinputlab/recipes/ace.py +418 -0
- agentinputlab/recipes/ace_bfcl.py +273 -0
- agentinputlab/recipes/ace_common_support.py +169 -0
- agentinputlab/recipes/ace_native_plan.py +322 -0
- agentinputlab/recipes/ace_online.py +711 -0
- agentinputlab/recipes/ace_retrieval.py +330 -0
- agentinputlab/recipes/ace_statebench.py +382 -0
- agentinputlab/recipes/ace_tau.py +463 -0
- agentinputlab/recipes/ace_toolsandbox.py +432 -0
- agentinputlab/recipes/acon_guideline.py +22 -0
- agentinputlab/recipes/adaptive_rag.py +822 -0
- agentinputlab/recipes/llmlingua2_inference.py +146 -0
- agentinputlab/recipes/llmlingua2_training.py +796 -0
- agentinputlab/recipes/mce.py +1486 -0
- agentinputlab/recipes/mce_final.py +335 -0
- agentinputlab/recipes/mce_text_fit.py +499 -0
- agentinputlab/recipes/mce_text_only.py +298 -0
- agentinputlab/recipes/qrag.py +729 -0
- agentinputlab/recipes/qrag_inference.py +364 -0
- agentinputlab/recipes/r2ag_features.py +236 -0
- agentinputlab/recipes/r2ag_inference.py +503 -0
- agentinputlab/recipes/r2ag_training.py +948 -0
- agentinputlab/recipes/recomp_abstractive.py +592 -0
- agentinputlab/recipes/recomp_extractive.py +525 -0
- agentinputlab/recipes/reformer.py +17 -0
- agentinputlab/recipes/rqrag.py +1516 -0
- agentinputlab/recipes/rqrag_common_support.py +193 -0
- agentinputlab/recipes/rqrag_completion.py +147 -0
- agentinputlab/recipes/skillopt.py +462 -0
- agentinputlab/recipes/skillopt_common_support.py +154 -0
- agentinputlab/recipes/skillopt_environment.py +165 -0
- agentinputlab/recipes/skillopt_environment_cli.py +5 -0
- agentinputlab/recipes/skillopt_retrieval.py +188 -0
- agentinputlab/recipes/smartsearch.py +897 -0
- agentinputlab/recipes/smartsearch_curriculum.py +283 -0
- agentinputlab/recipes/smartsearch_grpo_contracts.py +58 -0
- agentinputlab/recipes/smartsearch_grpo_data.py +314 -0
- agentinputlab/recipes/smartsearch_grpo_meter.py +324 -0
- agentinputlab/recipes/smartsearch_grpo_prefix.py +144 -0
- agentinputlab/recipes/smartsearch_grpo_rollout.py +119 -0
- agentinputlab/recipes/smartsearch_grpo_tools.py +364 -0
- agentinputlab/recipes/smartsearch_grpo_training.py +305 -0
- agentinputlab/recipes/smartsearch_grpo_transport.py +248 -0
- agentinputlab/recipes/smartsearch_grpo_worker.py +364 -0
- agentinputlab/recipes/smartsearch_inference.py +524 -0
- agentinputlab/recipes/smartsearch_native_data.py +172 -0
- agentinputlab/recipes/smartsearch_policy.py +616 -0
- agentinputlab/recipes/smartsearch_policy_worker.py +9 -0
- agentinputlab/recipes/smartsearch_sampling.py +232 -0
- agentinputlab/recipes/smartsearch_teacher.py +203 -0
- agentinputlab/recipes/smartsearch_training.py +265 -0
- agentinputlab/registry/__init__.py +46 -0
- agentinputlab/registry/beta.py +727 -0
- agentinputlab/registry/data/algorithms.json +1959 -0
- agentinputlab/registry/data/auxiliary_method_profiles.json +34 -0
- agentinputlab/registry/loader.py +100 -0
- agentinputlab/registry/result_manifest.py +184 -0
- agentinputlab/registry/runtime.py +195 -0
- agentinputlab/registry/schema.py +449 -0
- agentinputlab/runner/__init__.py +30 -0
- agentinputlab/runner/balance.py +248 -0
- agentinputlab/runner/cache.py +135 -0
- agentinputlab/runner/composite.py +130 -0
- agentinputlab/runner/engine.py +285 -0
- agentinputlab/runner/runtime_guard.py +268 -0
- agentinputlab/runner/worker.py +80 -0
- agentinputlab/runtime_bootstrap.py +288 -0
- agentinputlab/selectors/__init__.py +196 -0
- agentinputlab/selectors/advanced.py +1514 -0
- agentinputlab/selectors/artifacts.py +1087 -0
- agentinputlab/selectors/base.py +112 -0
- agentinputlab/selectors/campaigns.py +1893 -0
- agentinputlab/selectors/catalog.py +86 -0
- agentinputlab/selectors/discovery.py +1860 -0
- agentinputlab/selectors/evaluation.py +1348 -0
- agentinputlab/selectors/features.py +383 -0
- agentinputlab/selectors/learned.py +502 -0
- agentinputlab/selectors/no_op.py +28 -0
- agentinputlab/selectors/outcome_table.py +475 -0
- agentinputlab/selectors/producer.py +853 -0
- agentinputlab/selectors/rules.py +109 -0
- agentinputlab/selectors/runtime.py +420 -0
- agentinputlab/studies/__init__.py +16 -0
- agentinputlab/studies/design.py +165 -0
- agentinputlab/studies/paired.py +322 -0
- agentinputlab/studio/__init__.py +6 -0
- agentinputlab/studio/campaigns.py +819 -0
- agentinputlab/studio/engine.py +1408 -0
- agentinputlab/studio/model_backends.py +425 -0
- agentinputlab/studio/prepared.py +410 -0
- agentinputlab/studio/server.py +613 -0
- agentinputlab/studio/static/app.js +397 -0
- agentinputlab/studio/static/campaigns.html +175 -0
- agentinputlab/studio/static/campaigns.js +426 -0
- agentinputlab/studio/static/index.html +192 -0
- agentinputlab/studio/static/result.html +103 -0
- agentinputlab/studio/static/result.js +273 -0
- agentinputlab/studio/static/styles.css +467 -0
- agentinputlab-0.1.0a1.data/data/share/agentinputlab/CITATION.cff +22 -0
- agentinputlab-0.1.0a1.dist-info/METADATA +392 -0
- agentinputlab-0.1.0a1.dist-info/RECORD +469 -0
- agentinputlab-0.1.0a1.dist-info/WHEEL +5 -0
- agentinputlab-0.1.0a1.dist-info/entry_points.txt +6 -0
- agentinputlab-0.1.0a1.dist-info/licenses/LICENSE +21 -0
- agentinputlab-0.1.0a1.dist-info/licenses/NOTICE +31 -0
- agentinputlab-0.1.0a1.dist-info/licenses/THIRD_PARTY_NOTICES.md +94 -0
- agentinputlab-0.1.0a1.dist-info/top_level.txt +2 -0
- workers/README.md +94 -0
- workers/ace/README.md +261 -0
- workers/ace/__init__.py +1 -0
- workers/ace/compatibility_manifest.json +39 -0
- workers/ace/driver.py +1682 -0
- workers/acon/README.md +215 -0
- workers/acon/__init__.py +5 -0
- workers/acon/compatibility_manifest.json +93 -0
- workers/acon/driver.py +1859 -0
- workers/acon/fitted.py +395 -0
- workers/acon/guideline.py +470 -0
- workers/acon/guideline_source_manifest.json +20 -0
- workers/adaptive_rag/README.md +96 -0
- workers/adaptive_rag/__init__.py +15 -0
- workers/adaptive_rag/compatibility_manifest.json +61 -0
- workers/adaptive_rag/driver.py +1470 -0
- workers/adaptive_rag/fixture_runtime.py +163 -0
- workers/adaptive_rag/runtime.py +252 -0
- workers/ask_or_assume/README.md +124 -0
- workers/ask_or_assume/__init__.py +1 -0
- workers/ask_or_assume/compatibility_manifest.json +36 -0
- workers/ask_or_assume/driver.py +1227 -0
- workers/decomp/README.md +133 -0
- workers/decomp/UPSTREAM_LICENSE.Apache-2.0.txt +201 -0
- workers/decomp/__init__.py +5 -0
- workers/decomp/compatibility_manifest.json +205 -0
- workers/decomp/driver.py +1015 -0
- workers/decomp/live.py +137 -0
- workers/decomp/runtime.py +231 -0
- workers/infocqr/README.md +106 -0
- workers/infocqr/__init__.py +1 -0
- workers/infocqr/compatibility_manifest.json +84 -0
- workers/infocqr/driver.py +1766 -0
- workers/ircot/README.md +167 -0
- workers/ircot/__init__.py +7 -0
- workers/ircot/compatibility_manifest.json +121 -0
- workers/ircot/controlled.py +457 -0
- workers/ircot/driver.py +1373 -0
- workers/ircot/fixture_bindings.json +39 -0
- workers/ircot/fixture_config.json +48 -0
- workers/ircot/fixture_prompt.txt +2 -0
- workers/ircot/native_qa.py +398 -0
- workers/ircot/qa_compatibility_manifest.json +57 -0
- workers/ircot/runtime.py +97 -0
- workers/llmcompiler/README.md +160 -0
- workers/llmcompiler/__init__.py +1 -0
- workers/llmcompiler/compatibility_manifest.json +45 -0
- workers/llmcompiler/driver.py +1514 -0
- workers/llmcompiler/export_prompts.py +74 -0
- workers/llmcompiler/live.py +174 -0
- workers/llmcompiler/patch_manifest.json +147 -0
- workers/mce/README.md +198 -0
- workers/mce/__init__.py +29 -0
- workers/mce/compatibility_manifest.json +115 -0
- workers/mce/driver.py +2585 -0
- workers/mce/final_eval.py +173 -0
- workers/official_arenas/README.md +25 -0
- workers/official_arenas/__init__.py +1 -0
- workers/official_arenas/capture_records.py +110 -0
- workers/official_arenas/driver.py +619 -0
- workers/official_arenas/protocol.py +334 -0
- workers/official_arenas/providers/__init__.py +1 -0
- workers/official_arenas/providers/_live_history.py +228 -0
- workers/official_arenas/providers/_message_compat.py +77 -0
- workers/official_arenas/providers/appworld_ul.py +196 -0
- workers/official_arenas/providers/fixture.py +112 -0
- workers/official_arenas/providers/statebench.py +960 -0
- workers/official_arenas/providers/tau3.py +1672 -0
- workers/official_arenas/providers/tau_retail.py +586 -0
- workers/official_arenas/providers/toolsandbox.py +1321 -0
- workers/official_arenas/providers/tooltalk.py +699 -0
- workers/official_arenas/retail_capture.py +188 -0
- workers/official_arenas/retail_driver.py +275 -0
- workers/qrag/README.md +172 -0
- workers/qrag/__init__.py +1 -0
- workers/qrag/compatibility_manifest.json +64 -0
- workers/qrag/driver.py +673 -0
- workers/r2ag/README.md +154 -0
- workers/r2ag/__init__.py +5 -0
- workers/r2ag/compatibility_manifest.json +55 -0
- workers/r2ag/driver.py +1287 -0
- workers/r2ag/feature_schema.json +8 -0
- workers/r2ag/runtime.py +589 -0
- workers/recomp/README.md +120 -0
- workers/recomp/__init__.py +1 -0
- workers/recomp/compatibility_manifest.json +43 -0
- workers/recomp/driver.py +1653 -0
- workers/reformer/README.md +125 -0
- workers/reformer/__init__.py +1 -0
- workers/reformer/compatibility_manifest.json +68 -0
- workers/reformer/driver.py +1459 -0
- workers/reformer/induction.py +457 -0
- workers/rrr/README.md +126 -0
- workers/rrr/__init__.py +1 -0
- workers/rrr/compatibility_manifest.json +57 -0
- workers/rrr/driver.py +1133 -0
- workers/smartsearch/README.md +331 -0
- workers/smartsearch/__init__.py +1 -0
- workers/smartsearch/compatibility_manifest.json +41 -0
- workers/smartsearch/driver.py +1643 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""Packaged benchmark inventory."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from collections.abc import Mapping
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from importlib import resources
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from agentinputlab.contracts.enums import SemanticFamily
|
|
12
|
+
from agentinputlab.contracts.errors import RegistryError
|
|
13
|
+
|
|
14
|
+
EXPECTED_BENCHMARK_CELL_COUNT = 31
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True, slots=True)
|
|
18
|
+
class BenchmarkCell:
|
|
19
|
+
cell_id: str
|
|
20
|
+
suite: str
|
|
21
|
+
task: str
|
|
22
|
+
size: str
|
|
23
|
+
families: tuple[SemanticFamily, ...]
|
|
24
|
+
source_revision: str
|
|
25
|
+
metrics: tuple[str, ...]
|
|
26
|
+
eligibility_gate: str = ""
|
|
27
|
+
family_support: str = "cell_declared"
|
|
28
|
+
adapter_metrics: tuple[str, ...] = ()
|
|
29
|
+
paired_metrics: tuple[str, ...] = ()
|
|
30
|
+
study_metrics: tuple[str, ...] = ()
|
|
31
|
+
|
|
32
|
+
def __post_init__(self) -> None:
|
|
33
|
+
if self.family_support not in {"cell_declared", "checkpoint_conditional"}:
|
|
34
|
+
raise ValueError("benchmark family_support has an unsupported value")
|
|
35
|
+
if not self.metrics or len(self.metrics) != len(set(self.metrics)):
|
|
36
|
+
raise ValueError("benchmark metrics must be non-empty and unique")
|
|
37
|
+
adapter = tuple(self.adapter_metrics)
|
|
38
|
+
paired = tuple(self.paired_metrics)
|
|
39
|
+
study = tuple(self.study_metrics)
|
|
40
|
+
if not adapter and not paired and not study:
|
|
41
|
+
adapter = tuple(self.metrics)
|
|
42
|
+
layered = (*adapter, *paired, *study)
|
|
43
|
+
if len(layered) != len(set(layered)) or set(layered) != set(self.metrics):
|
|
44
|
+
raise ValueError("benchmark metric layers must partition metrics exactly")
|
|
45
|
+
object.__setattr__(self, "adapter_metrics", adapter)
|
|
46
|
+
object.__setattr__(self, "paired_metrics", paired)
|
|
47
|
+
object.__setattr__(self, "study_metrics", study)
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def from_mapping(cls, value: Mapping[str, Any]) -> BenchmarkCell:
|
|
51
|
+
try:
|
|
52
|
+
return cls(
|
|
53
|
+
cell_id=str(value["cell_id"]),
|
|
54
|
+
suite=str(value["suite"]),
|
|
55
|
+
task=str(value["task"]),
|
|
56
|
+
size=str(value["size"]),
|
|
57
|
+
families=tuple(SemanticFamily(item) for item in value["families"]),
|
|
58
|
+
source_revision=str(value["source_revision"]),
|
|
59
|
+
metrics=tuple(str(item) for item in value["metrics"]),
|
|
60
|
+
eligibility_gate=str(value.get("eligibility_gate", "")),
|
|
61
|
+
family_support=str(value.get("family_support", "cell_declared")),
|
|
62
|
+
adapter_metrics=tuple(str(item) for item in value.get("adapter_metrics", ())),
|
|
63
|
+
paired_metrics=tuple(str(item) for item in value.get("paired_metrics", ())),
|
|
64
|
+
study_metrics=tuple(str(item) for item in value.get("study_metrics", ())),
|
|
65
|
+
)
|
|
66
|
+
except (KeyError, TypeError, ValueError) as exc:
|
|
67
|
+
raise RegistryError(f"invalid benchmark cell: {value!r}") from exc
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class BenchmarkRegistry:
|
|
71
|
+
def __init__(self, cells: tuple[BenchmarkCell, ...]) -> None:
|
|
72
|
+
if len(cells) != EXPECTED_BENCHMARK_CELL_COUNT:
|
|
73
|
+
raise RegistryError(
|
|
74
|
+
"benchmark registry requires "
|
|
75
|
+
f"{EXPECTED_BENCHMARK_CELL_COUNT} cells, got {len(cells)}"
|
|
76
|
+
)
|
|
77
|
+
if len({cell.cell_id for cell in cells}) != len(cells):
|
|
78
|
+
raise RegistryError("benchmark cell IDs must be unique")
|
|
79
|
+
self._cells = cells
|
|
80
|
+
self._by_id = {cell.cell_id: cell for cell in cells}
|
|
81
|
+
|
|
82
|
+
@classmethod
|
|
83
|
+
def default(cls) -> BenchmarkRegistry:
|
|
84
|
+
resource = resources.files("agentinputlab.benchmarks").joinpath("data", "registry.json")
|
|
85
|
+
payload = json.loads(resource.read_text(encoding="utf-8"))
|
|
86
|
+
if (
|
|
87
|
+
payload.get("schema_version") != 1
|
|
88
|
+
or payload.get("cell_count") != EXPECTED_BENCHMARK_CELL_COUNT
|
|
89
|
+
):
|
|
90
|
+
raise RegistryError("unsupported benchmark registry snapshot")
|
|
91
|
+
return cls(tuple(BenchmarkCell.from_mapping(item) for item in payload["cells"]))
|
|
92
|
+
|
|
93
|
+
def get(self, cell_id: str) -> BenchmarkCell:
|
|
94
|
+
try:
|
|
95
|
+
return self._by_id[cell_id]
|
|
96
|
+
except KeyError as exc:
|
|
97
|
+
raise RegistryError(f"unknown benchmark cell: {cell_id}") from exc
|
|
98
|
+
|
|
99
|
+
def list(
|
|
100
|
+
self,
|
|
101
|
+
*,
|
|
102
|
+
family: SemanticFamily | str | None = None,
|
|
103
|
+
) -> tuple[BenchmarkCell, ...]:
|
|
104
|
+
selected = SemanticFamily(family) if isinstance(family, str) else family
|
|
105
|
+
if selected is None:
|
|
106
|
+
return self._cells
|
|
107
|
+
return tuple(cell for cell in self._cells if selected in cell.families)
|
|
108
|
+
|
|
109
|
+
def __len__(self) -> int:
|
|
110
|
+
return len(self._cells)
|
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
"""Prepared retrieval benchmark adapter with evaluator-only qrels.
|
|
2
|
+
|
|
3
|
+
The adapter consumes the checksum-verified normalized representation produced
|
|
4
|
+
by :mod:`agentinputlab.benchmarks.preprocess`. Prediction callbacks see only
|
|
5
|
+
the query-side state; qrels remain attached to ``BenchmarkExample`` and cross
|
|
6
|
+
the boundary only inside :meth:`score`.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
import math
|
|
13
|
+
from collections.abc import Mapping, Sequence
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from types import MappingProxyType
|
|
17
|
+
from typing import Any
|
|
18
|
+
|
|
19
|
+
from agentinputlab.contracts.errors import ArtifactError, ValidationError
|
|
20
|
+
from agentinputlab.contracts.serialization import canonical_json, freeze_mapping
|
|
21
|
+
from agentinputlab.metrics import retrieval_aggregates
|
|
22
|
+
|
|
23
|
+
from .base import BenchmarkExample
|
|
24
|
+
from .preprocess import PreparedBenchmark
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True, slots=True)
|
|
28
|
+
class _NamedRetrievalProfile:
|
|
29
|
+
query_asset_id: str
|
|
30
|
+
query_processor: str
|
|
31
|
+
split: str
|
|
32
|
+
corpus_asset_id: str | None = None
|
|
33
|
+
corpus_processor: str | None = None
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
_NAMED_RETRIEVAL_PROFILES = {
|
|
37
|
+
"beir.arguana": _NamedRetrievalProfile(
|
|
38
|
+
query_asset_id="beir.arguana.official",
|
|
39
|
+
query_processor="beir_zip_v1",
|
|
40
|
+
split="test",
|
|
41
|
+
),
|
|
42
|
+
"bright.earth_science": _NamedRetrievalProfile(
|
|
43
|
+
query_asset_id="bright.earth_science.examples",
|
|
44
|
+
query_processor="bright_examples_parquet_v1",
|
|
45
|
+
split="test",
|
|
46
|
+
corpus_asset_id="bright.earth_science.corpus",
|
|
47
|
+
corpus_processor="bright_corpus_parquet_v1",
|
|
48
|
+
),
|
|
49
|
+
"bright.economics": _NamedRetrievalProfile(
|
|
50
|
+
query_asset_id="bright.economics.examples",
|
|
51
|
+
query_processor="bright_examples_parquet_v1",
|
|
52
|
+
split="test",
|
|
53
|
+
corpus_asset_id="bright.economics.corpus",
|
|
54
|
+
corpus_processor="bright_corpus_parquet_v1",
|
|
55
|
+
),
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass(frozen=True, slots=True)
|
|
60
|
+
class RetrievalPrediction:
|
|
61
|
+
"""One ranked retrieval run represented by document scores."""
|
|
62
|
+
|
|
63
|
+
scores: Mapping[str, float]
|
|
64
|
+
|
|
65
|
+
def __post_init__(self) -> None:
|
|
66
|
+
converted: dict[str, float] = {}
|
|
67
|
+
for document_id, score in self.scores.items():
|
|
68
|
+
if not isinstance(document_id, str) or not document_id.strip():
|
|
69
|
+
raise ValidationError("retrieval document IDs must be non-empty strings")
|
|
70
|
+
if isinstance(score, bool) or not isinstance(score, (int, float)):
|
|
71
|
+
raise ValidationError("retrieval scores must be numeric")
|
|
72
|
+
numeric = float(score)
|
|
73
|
+
if not math.isfinite(numeric):
|
|
74
|
+
raise ValidationError("retrieval scores must be finite")
|
|
75
|
+
converted[document_id] = numeric
|
|
76
|
+
object.__setattr__(self, "scores", MappingProxyType(converted))
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def from_ranked_ids(cls, document_ids: Sequence[str]) -> RetrievalPrediction:
|
|
80
|
+
if isinstance(document_ids, str):
|
|
81
|
+
raise ValidationError("ranked document IDs must be a sequence, not one string")
|
|
82
|
+
ids = tuple(document_ids)
|
|
83
|
+
if len(ids) != len(set(ids)):
|
|
84
|
+
raise ValidationError("ranked retrieval predictions must not contain duplicates")
|
|
85
|
+
size = len(ids)
|
|
86
|
+
return cls({document_id: float(size - rank) for rank, document_id in enumerate(ids)})
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class PreparedRetrievalBenchmarkAdapter:
|
|
90
|
+
"""Production adapter for a verified, normalized retrieval benchmark."""
|
|
91
|
+
|
|
92
|
+
pairing_mode = "stateless_score_twice"
|
|
93
|
+
|
|
94
|
+
def __init__(
|
|
95
|
+
self,
|
|
96
|
+
prepared: PreparedBenchmark,
|
|
97
|
+
*,
|
|
98
|
+
benchmark_id: str,
|
|
99
|
+
split: str = "test",
|
|
100
|
+
corpus_prepared: PreparedBenchmark | None = None,
|
|
101
|
+
) -> None:
|
|
102
|
+
if not isinstance(prepared, PreparedBenchmark):
|
|
103
|
+
raise TypeError("prepared must be a PreparedBenchmark")
|
|
104
|
+
_validated_identity(benchmark_id, label="benchmark_id")
|
|
105
|
+
_validated_identity(split, label="split")
|
|
106
|
+
if corpus_prepared is not None and not isinstance(corpus_prepared, PreparedBenchmark):
|
|
107
|
+
raise TypeError("corpus_prepared must be a PreparedBenchmark")
|
|
108
|
+
named_profile = _NAMED_RETRIEVAL_PROFILES.get(benchmark_id)
|
|
109
|
+
if named_profile is None:
|
|
110
|
+
_validate_prepared_identity(
|
|
111
|
+
prepared,
|
|
112
|
+
benchmark_id=benchmark_id,
|
|
113
|
+
split=split,
|
|
114
|
+
label="prepared retrieval query/gold",
|
|
115
|
+
require_complete=prepared.processor == "bright_examples_parquet_v1",
|
|
116
|
+
)
|
|
117
|
+
if corpus_prepared is not None:
|
|
118
|
+
_validate_prepared_identity(
|
|
119
|
+
corpus_prepared,
|
|
120
|
+
benchmark_id=benchmark_id,
|
|
121
|
+
split=split,
|
|
122
|
+
label="prepared retrieval corpus",
|
|
123
|
+
require_complete=True,
|
|
124
|
+
)
|
|
125
|
+
else:
|
|
126
|
+
_validate_named_prepared_identity(
|
|
127
|
+
prepared,
|
|
128
|
+
benchmark_id=benchmark_id,
|
|
129
|
+
split=split,
|
|
130
|
+
expected_asset_id=named_profile.query_asset_id,
|
|
131
|
+
expected_processor=named_profile.query_processor,
|
|
132
|
+
expected_split=named_profile.split,
|
|
133
|
+
label="prepared retrieval query/gold",
|
|
134
|
+
)
|
|
135
|
+
if named_profile.corpus_asset_id is None:
|
|
136
|
+
if corpus_prepared is not None:
|
|
137
|
+
raise ArtifactError(
|
|
138
|
+
f"named retrieval profile {benchmark_id!r} does not accept "
|
|
139
|
+
"a separate corpus"
|
|
140
|
+
)
|
|
141
|
+
else:
|
|
142
|
+
if corpus_prepared is None:
|
|
143
|
+
raise ArtifactError(
|
|
144
|
+
f"named retrieval profile {benchmark_id!r} requires its locked corpus"
|
|
145
|
+
)
|
|
146
|
+
_validate_named_prepared_identity(
|
|
147
|
+
corpus_prepared,
|
|
148
|
+
benchmark_id=benchmark_id,
|
|
149
|
+
split=split,
|
|
150
|
+
expected_asset_id=named_profile.corpus_asset_id,
|
|
151
|
+
expected_processor=named_profile.corpus_processor,
|
|
152
|
+
expected_split=named_profile.split,
|
|
153
|
+
label="prepared retrieval corpus",
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
input_rows = _records_by_id(prepared.inputs_path, label="prepared retrieval inputs")
|
|
157
|
+
gold_rows = _records_by_id(prepared.gold_path, label="prepared retrieval gold")
|
|
158
|
+
if set(input_rows) != set(gold_rows):
|
|
159
|
+
raise ArtifactError("prepared retrieval input and gold IDs do not match")
|
|
160
|
+
effective_corpus = corpus_prepared or prepared
|
|
161
|
+
corpus_path = effective_corpus.corpus_path
|
|
162
|
+
if corpus_path is None:
|
|
163
|
+
raise ArtifactError("prepared retrieval benchmark requires a corpus")
|
|
164
|
+
|
|
165
|
+
examples: list[BenchmarkExample] = []
|
|
166
|
+
for example_id in sorted(input_rows):
|
|
167
|
+
visible = input_rows[example_id]
|
|
168
|
+
evaluator = gold_rows[example_id]
|
|
169
|
+
query = _required_text(visible, "query", label="prepared retrieval input")
|
|
170
|
+
instruction = _required_text(
|
|
171
|
+
visible,
|
|
172
|
+
"instruction",
|
|
173
|
+
label="prepared retrieval input",
|
|
174
|
+
)
|
|
175
|
+
metadata = _visible_metadata(
|
|
176
|
+
visible.get("visible_metadata", {}),
|
|
177
|
+
benchmark_id=benchmark_id,
|
|
178
|
+
split=split,
|
|
179
|
+
require_source_split=(
|
|
180
|
+
prepared.processor == "bright_examples_parquet_v1"
|
|
181
|
+
or (named_profile is not None and named_profile.corpus_asset_id is not None)
|
|
182
|
+
),
|
|
183
|
+
)
|
|
184
|
+
relevance = evaluator.get("relevance")
|
|
185
|
+
if not isinstance(relevance, Mapping) or not relevance:
|
|
186
|
+
raise ArtifactError("prepared retrieval gold requires non-empty relevance labels")
|
|
187
|
+
normalized_relevance: dict[str, int] = {}
|
|
188
|
+
for document_id, value in relevance.items():
|
|
189
|
+
if not isinstance(document_id, str) or not document_id:
|
|
190
|
+
raise ArtifactError("prepared retrieval qrel IDs must be non-empty strings")
|
|
191
|
+
if isinstance(value, bool) or not isinstance(value, int) or value < 0:
|
|
192
|
+
raise ArtifactError("prepared retrieval qrels must be non-negative integers")
|
|
193
|
+
normalized_relevance[document_id] = value
|
|
194
|
+
if not any(value > 0 for value in normalized_relevance.values()):
|
|
195
|
+
raise ArtifactError("prepared retrieval example requires a positive qrel")
|
|
196
|
+
|
|
197
|
+
evaluator_metadata: Mapping[str, Any] | None = None
|
|
198
|
+
excluded_document_ids: tuple[str, ...] = ()
|
|
199
|
+
if "evaluator_metadata" in evaluator:
|
|
200
|
+
raw_evaluator_metadata = evaluator["evaluator_metadata"]
|
|
201
|
+
if not isinstance(raw_evaluator_metadata, Mapping):
|
|
202
|
+
raise ArtifactError("prepared retrieval evaluator_metadata must be an object")
|
|
203
|
+
excluded_document_ids = _excluded_document_ids(raw_evaluator_metadata)
|
|
204
|
+
if set(excluded_document_ids) & set(normalized_relevance):
|
|
205
|
+
raise ArtifactError(
|
|
206
|
+
"prepared retrieval excluded document IDs overlap relevance labels"
|
|
207
|
+
)
|
|
208
|
+
evaluator_metadata = _frozen_canonical_mapping(
|
|
209
|
+
raw_evaluator_metadata,
|
|
210
|
+
label="prepared retrieval evaluator_metadata",
|
|
211
|
+
)
|
|
212
|
+
evaluator_gold: dict[str, Any] = {"relevance": normalized_relevance}
|
|
213
|
+
if evaluator_metadata is not None:
|
|
214
|
+
evaluator_gold["evaluator_metadata"] = evaluator_metadata
|
|
215
|
+
examples.append(
|
|
216
|
+
BenchmarkExample(
|
|
217
|
+
example_id=example_id,
|
|
218
|
+
query=query,
|
|
219
|
+
instruction=instruction,
|
|
220
|
+
visible_metadata=metadata,
|
|
221
|
+
evaluator_gold=_frozen_canonical_mapping(
|
|
222
|
+
evaluator_gold,
|
|
223
|
+
label="prepared retrieval evaluator gold",
|
|
224
|
+
),
|
|
225
|
+
)
|
|
226
|
+
)
|
|
227
|
+
self.benchmark_id = benchmark_id
|
|
228
|
+
self.split = split
|
|
229
|
+
self.prepared = prepared
|
|
230
|
+
self.query_prepared = prepared
|
|
231
|
+
self.corpus_prepared = effective_corpus
|
|
232
|
+
self.corpus_path = corpus_path
|
|
233
|
+
self._ignore_identical_ids = prepared.processor == "beir_zip_v1"
|
|
234
|
+
self._examples = tuple(examples)
|
|
235
|
+
self._examples_by_id = {example.example_id: example for example in examples}
|
|
236
|
+
|
|
237
|
+
def examples(self, split: str) -> tuple[BenchmarkExample, ...]:
|
|
238
|
+
if split != self.split:
|
|
239
|
+
raise ValidationError(
|
|
240
|
+
f"prepared retrieval adapter exposes split {self.split!r}, not {split!r}"
|
|
241
|
+
)
|
|
242
|
+
return self._examples
|
|
243
|
+
|
|
244
|
+
def example(self, split: str, example_id: str) -> BenchmarkExample:
|
|
245
|
+
"""Resolve one verified unit without rescanning the full split."""
|
|
246
|
+
|
|
247
|
+
if split != self.split:
|
|
248
|
+
raise ValidationError(
|
|
249
|
+
f"prepared retrieval adapter exposes split {self.split!r}, not {split!r}"
|
|
250
|
+
)
|
|
251
|
+
if not isinstance(example_id, str) or not example_id.strip():
|
|
252
|
+
raise ValidationError("prepared retrieval example_id must be non-empty")
|
|
253
|
+
try:
|
|
254
|
+
return self._examples_by_id[example_id]
|
|
255
|
+
except KeyError as exc:
|
|
256
|
+
raise ValidationError(
|
|
257
|
+
f"prepared retrieval split does not contain example {example_id!r}"
|
|
258
|
+
) from exc
|
|
259
|
+
|
|
260
|
+
def fingerprint(self) -> Mapping[str, Any]:
|
|
261
|
+
"""Portable prepared-source identities without exposing qrel contents.
|
|
262
|
+
|
|
263
|
+
Hashes were verified while loading the immutable prepared cache. Do not
|
|
264
|
+
rescan a potentially large corpus each time a caller binds a runtime.
|
|
265
|
+
Evaluation dependencies are resolved only by ``score``, not this method.
|
|
266
|
+
"""
|
|
267
|
+
def prepared(value: PreparedBenchmark) -> dict[str, Any]:
|
|
268
|
+
return dict(
|
|
269
|
+
asset_id=value.asset_id,
|
|
270
|
+
processor=value.processor,
|
|
271
|
+
processor_revision=value.processor_revision,
|
|
272
|
+
source_sha256=value.source_sha256,
|
|
273
|
+
source_revision=value.source_revision,
|
|
274
|
+
cell_id=value.cell_id,
|
|
275
|
+
split=value.split,
|
|
276
|
+
counts=dict(value.counts),
|
|
277
|
+
file_sha256=dict(value.file_sha256),
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
return dict(
|
|
281
|
+
benchmark_id=self.benchmark_id,
|
|
282
|
+
split=self.split,
|
|
283
|
+
query_preparation=prepared(self.query_prepared),
|
|
284
|
+
corpus_preparation=prepared(self.corpus_prepared),
|
|
285
|
+
test_queries=len(self._examples),
|
|
286
|
+
scorer="ir_measures:nDCG@10,R@100",
|
|
287
|
+
ignore_identical_ids=self._ignore_identical_ids,
|
|
288
|
+
excluded_documents_policy="evaluator_metadata.excluded_document_ids_except_N/A",
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
def score(
|
|
292
|
+
self,
|
|
293
|
+
example: BenchmarkExample,
|
|
294
|
+
prediction: RetrievalPrediction | Mapping[str, float] | Sequence[str],
|
|
295
|
+
) -> Mapping[str, float]:
|
|
296
|
+
if not isinstance(example, BenchmarkExample):
|
|
297
|
+
raise TypeError("example must be a BenchmarkExample")
|
|
298
|
+
if self._examples_by_id.get(example.example_id) is not example:
|
|
299
|
+
raise ValidationError(
|
|
300
|
+
"benchmark example does not belong to this prepared retrieval adapter"
|
|
301
|
+
)
|
|
302
|
+
if isinstance(prediction, RetrievalPrediction):
|
|
303
|
+
normalized = prediction
|
|
304
|
+
elif isinstance(prediction, Mapping):
|
|
305
|
+
normalized = RetrievalPrediction(prediction)
|
|
306
|
+
else:
|
|
307
|
+
normalized = RetrievalPrediction.from_ranked_ids(prediction)
|
|
308
|
+
relevance = example.evaluator_gold.get("relevance")
|
|
309
|
+
if not isinstance(relevance, Mapping):
|
|
310
|
+
raise ArtifactError("benchmark example does not contain retrieval qrels")
|
|
311
|
+
evaluator_metadata = example.evaluator_gold.get("evaluator_metadata", {})
|
|
312
|
+
if not isinstance(evaluator_metadata, Mapping): # pragma: no cover - construction invariant
|
|
313
|
+
raise ArtifactError("benchmark example evaluator metadata is invalid")
|
|
314
|
+
raw_excluded = evaluator_metadata.get("excluded_document_ids", ())
|
|
315
|
+
if not isinstance(raw_excluded, tuple): # pragma: no cover - construction invariant
|
|
316
|
+
raise ArtifactError("benchmark example excluded document IDs are invalid")
|
|
317
|
+
excluded = frozenset(item for item in raw_excluded if item != "N/A")
|
|
318
|
+
# BRIGHT's official get_scores removes excluded documents before
|
|
319
|
+
# truncation/evaluation. Apply the same boundary here so callers may
|
|
320
|
+
# submit raw retriever scores without accidentally changing ranks.
|
|
321
|
+
# BEIR's default evaluator also removes query/document pairs with an
|
|
322
|
+
# identical ID; this is material for ArguAna, whose corpus reuses most
|
|
323
|
+
# query IDs. Keep this profile-specific rather than applying it to
|
|
324
|
+
# unrelated retrieval suites.
|
|
325
|
+
evaluation_scores = {
|
|
326
|
+
document_id: score
|
|
327
|
+
for document_id, score in normalized.scores.items()
|
|
328
|
+
if document_id not in excluded
|
|
329
|
+
and not (self._ignore_identical_ids and document_id == example.example_id)
|
|
330
|
+
}
|
|
331
|
+
return retrieval_aggregates(
|
|
332
|
+
{example.example_id: relevance},
|
|
333
|
+
{example.example_id: evaluation_scores},
|
|
334
|
+
measures={
|
|
335
|
+
"ndcg_at_10": "nDCG@10",
|
|
336
|
+
"recall": "R@100",
|
|
337
|
+
},
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
def _records_by_id(path: Path, *, label: str) -> dict[str, dict[str, Any]]:
|
|
342
|
+
records: dict[str, dict[str, Any]] = {}
|
|
343
|
+
try:
|
|
344
|
+
with path.open(encoding="utf-8") as handle:
|
|
345
|
+
for line_number, raw in enumerate(handle, start=1):
|
|
346
|
+
if not raw.strip():
|
|
347
|
+
raise ArtifactError(f"{label} contains a blank line at {line_number}")
|
|
348
|
+
value = json.loads(raw)
|
|
349
|
+
if not isinstance(value, dict):
|
|
350
|
+
raise ArtifactError(f"{label} row {line_number} must be an object")
|
|
351
|
+
row_id = _required_text(value, "id", label=label)
|
|
352
|
+
if row_id in records:
|
|
353
|
+
raise ArtifactError(f"{label} contains duplicate ID {row_id!r}")
|
|
354
|
+
records[row_id] = value
|
|
355
|
+
except (OSError, UnicodeError, json.JSONDecodeError) as exc:
|
|
356
|
+
raise ArtifactError(f"{label} is not valid UTF-8 JSONL") from exc
|
|
357
|
+
if not records:
|
|
358
|
+
raise ArtifactError(f"{label} contains no records")
|
|
359
|
+
return records
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def _required_text(record: Mapping[str, Any], key: str, *, label: str) -> str:
|
|
363
|
+
value = record.get(key)
|
|
364
|
+
if not isinstance(value, str) or not value.strip():
|
|
365
|
+
raise ArtifactError(f"{label} field {key!r} must be a non-empty string")
|
|
366
|
+
return value
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def _validated_identity(value: str, *, label: str) -> None:
|
|
370
|
+
if not isinstance(value, str) or not value.strip():
|
|
371
|
+
raise ValidationError(f"{label} must be non-empty")
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def _validate_prepared_identity(
|
|
375
|
+
prepared: PreparedBenchmark,
|
|
376
|
+
*,
|
|
377
|
+
benchmark_id: str,
|
|
378
|
+
split: str,
|
|
379
|
+
label: str,
|
|
380
|
+
require_complete: bool,
|
|
381
|
+
) -> None:
|
|
382
|
+
if require_complete and not prepared.cell_id:
|
|
383
|
+
raise ArtifactError(f"{label} requires an explicit cell_id")
|
|
384
|
+
if require_complete and not prepared.split:
|
|
385
|
+
raise ArtifactError(f"{label} requires an explicit split")
|
|
386
|
+
if prepared.cell_id and prepared.cell_id != benchmark_id:
|
|
387
|
+
raise ArtifactError(f"{label} cell_id does not match adapter benchmark_id")
|
|
388
|
+
if prepared.split and prepared.split != split:
|
|
389
|
+
raise ArtifactError(f"{label} split does not match adapter split")
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def _validate_named_prepared_identity(
|
|
393
|
+
prepared: PreparedBenchmark,
|
|
394
|
+
*,
|
|
395
|
+
benchmark_id: str,
|
|
396
|
+
split: str,
|
|
397
|
+
expected_asset_id: str,
|
|
398
|
+
expected_processor: str | None,
|
|
399
|
+
expected_split: str,
|
|
400
|
+
label: str,
|
|
401
|
+
) -> None:
|
|
402
|
+
if split != expected_split:
|
|
403
|
+
raise ArtifactError(
|
|
404
|
+
f"named retrieval profile {benchmark_id!r} requires adapter split {expected_split!r}"
|
|
405
|
+
)
|
|
406
|
+
expected_fields = {
|
|
407
|
+
"asset_id": expected_asset_id,
|
|
408
|
+
"processor": expected_processor,
|
|
409
|
+
"cell_id": benchmark_id,
|
|
410
|
+
"split": expected_split,
|
|
411
|
+
}
|
|
412
|
+
for field, expected_value in expected_fields.items():
|
|
413
|
+
if getattr(prepared, field) != expected_value:
|
|
414
|
+
raise ArtifactError(f"{label} {field} does not match named profile {benchmark_id!r}")
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def _visible_metadata(
|
|
418
|
+
value: Any,
|
|
419
|
+
*,
|
|
420
|
+
benchmark_id: str,
|
|
421
|
+
split: str,
|
|
422
|
+
require_source_split: bool,
|
|
423
|
+
) -> Mapping[str, Any]:
|
|
424
|
+
if not isinstance(value, Mapping):
|
|
425
|
+
raise ArtifactError("prepared retrieval visible_metadata must be an object")
|
|
426
|
+
if value.get("benchmark_cell") != benchmark_id:
|
|
427
|
+
raise ArtifactError("prepared retrieval benchmark_cell does not match adapter benchmark_id")
|
|
428
|
+
source_split = value.get("source_split")
|
|
429
|
+
if require_source_split and source_split is None:
|
|
430
|
+
raise ArtifactError("prepared retrieval visible_metadata requires source_split")
|
|
431
|
+
if source_split is not None and source_split != split:
|
|
432
|
+
raise ArtifactError("prepared retrieval source_split does not match adapter split")
|
|
433
|
+
return _frozen_canonical_mapping(value, label="prepared retrieval visible_metadata")
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
def _excluded_document_ids(evaluator_metadata: Mapping[str, Any]) -> tuple[str, ...]:
|
|
437
|
+
value = evaluator_metadata.get("excluded_document_ids", [])
|
|
438
|
+
if not isinstance(value, list):
|
|
439
|
+
raise ArtifactError("prepared retrieval excluded_document_ids must be a JSON array")
|
|
440
|
+
if not all(isinstance(item, str) and item.strip() for item in value):
|
|
441
|
+
raise ArtifactError(
|
|
442
|
+
"prepared retrieval excluded_document_ids must contain non-empty strings"
|
|
443
|
+
)
|
|
444
|
+
normalized = tuple(item for item in value if item != "N/A")
|
|
445
|
+
if len(normalized) != len(set(normalized)):
|
|
446
|
+
raise ArtifactError("prepared retrieval excluded_document_ids must not contain duplicates")
|
|
447
|
+
return normalized
|
|
448
|
+
|
|
449
|
+
|
|
450
|
+
def _frozen_canonical_mapping(value: Mapping[str, Any], *, label: str) -> Mapping[str, Any]:
|
|
451
|
+
try:
|
|
452
|
+
frozen = freeze_mapping(value)
|
|
453
|
+
canonical_json(frozen)
|
|
454
|
+
except (TypeError, ValueError) as exc:
|
|
455
|
+
raise ArtifactError(f"{label} is not canonical: {exc}") from exc
|
|
456
|
+
return frozen
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
__all__ = ["PreparedRetrievalBenchmarkAdapter", "RetrievalPrediction"]
|