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,502 @@
|
|
|
1
|
+
"""Dependency-free selector training, abstention calibration, and evaluation.
|
|
2
|
+
|
|
3
|
+
The implementation is intentionally a transparent full-information ridge
|
|
4
|
+
baseline. It consumes discovery-set paired utilities; it never trains on the
|
|
5
|
+
confirmatory or external-test split.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import math
|
|
11
|
+
from collections.abc import Collection, Mapping, Sequence
|
|
12
|
+
from dataclasses import dataclass, field, replace
|
|
13
|
+
from statistics import fmean
|
|
14
|
+
from types import MappingProxyType
|
|
15
|
+
|
|
16
|
+
from agentinputlab.contracts.enums import SemanticFamily
|
|
17
|
+
from agentinputlab.contracts.serialization import content_hash
|
|
18
|
+
from agentinputlab.contracts.state import FrozenAgentState
|
|
19
|
+
|
|
20
|
+
from .base import SelectionDecision, SelectionFeatures, Selector
|
|
21
|
+
|
|
22
|
+
_ACTIONS = (
|
|
23
|
+
SemanticFamily.REFORMULATE,
|
|
24
|
+
SemanticFamily.DECOMPOSE,
|
|
25
|
+
SemanticFamily.ACQUIRE,
|
|
26
|
+
SemanticFamily.CLARIFY,
|
|
27
|
+
SemanticFamily.CURATE,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True, slots=True)
|
|
32
|
+
class SelectorExample:
|
|
33
|
+
example_id: str
|
|
34
|
+
features: SelectionFeatures
|
|
35
|
+
utilities: Mapping[SemanticFamily, float]
|
|
36
|
+
split: str
|
|
37
|
+
costs: Mapping[SemanticFamily, float] = field(default_factory=dict)
|
|
38
|
+
risks: Mapping[SemanticFamily, float] = field(default_factory=dict)
|
|
39
|
+
|
|
40
|
+
def __post_init__(self) -> None:
|
|
41
|
+
if not self.example_id:
|
|
42
|
+
raise ValueError("selector example requires an ID")
|
|
43
|
+
if not isinstance(self.split, str) or not self.split.strip():
|
|
44
|
+
raise ValueError("selector example requires a non-empty split")
|
|
45
|
+
if any(not isinstance(family, SemanticFamily) for family in self.utilities):
|
|
46
|
+
raise ValueError("selector utility keys must be SemanticFamily values")
|
|
47
|
+
if SemanticFamily.NO_OP not in self.utilities:
|
|
48
|
+
raise ValueError("selector utilities require an explicit NO_OP value")
|
|
49
|
+
if any(
|
|
50
|
+
isinstance(value, bool)
|
|
51
|
+
or not isinstance(value, (int, float))
|
|
52
|
+
or not math.isfinite(value)
|
|
53
|
+
for value in self.utilities.values()
|
|
54
|
+
):
|
|
55
|
+
raise ValueError("selector utilities must be finite numbers")
|
|
56
|
+
if any(not isinstance(family, SemanticFamily) for family in self.costs):
|
|
57
|
+
raise ValueError("selector cost keys must be SemanticFamily values")
|
|
58
|
+
if any(
|
|
59
|
+
isinstance(value, bool)
|
|
60
|
+
or not isinstance(value, (int, float))
|
|
61
|
+
or not math.isfinite(value)
|
|
62
|
+
or value < 0
|
|
63
|
+
for value in self.costs.values()
|
|
64
|
+
):
|
|
65
|
+
raise ValueError("selector costs must be finite non-negative numbers")
|
|
66
|
+
if any(not isinstance(family, SemanticFamily) for family in self.risks):
|
|
67
|
+
raise ValueError("selector risk keys must be SemanticFamily values")
|
|
68
|
+
if any(
|
|
69
|
+
isinstance(value, bool)
|
|
70
|
+
or not isinstance(value, (int, float))
|
|
71
|
+
or not math.isfinite(value)
|
|
72
|
+
or not 0 <= value <= 1
|
|
73
|
+
for value in self.risks.values()
|
|
74
|
+
):
|
|
75
|
+
raise ValueError("selector risks must be finite numbers in [0, 1]")
|
|
76
|
+
object.__setattr__(self, "utilities", MappingProxyType(dict(self.utilities)))
|
|
77
|
+
object.__setattr__(self, "costs", MappingProxyType(dict(self.costs)))
|
|
78
|
+
object.__setattr__(self, "risks", MappingProxyType(dict(self.risks)))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@dataclass(frozen=True, slots=True)
|
|
82
|
+
class SelectorSplitProvenance:
|
|
83
|
+
"""Order-invariant identities for one disjoint selector data partition."""
|
|
84
|
+
|
|
85
|
+
id_set_digests: Mapping[str, str]
|
|
86
|
+
split_sizes: Mapping[str, int]
|
|
87
|
+
|
|
88
|
+
def __post_init__(self) -> None:
|
|
89
|
+
digests = dict(self.id_set_digests)
|
|
90
|
+
sizes = dict(self.split_sizes)
|
|
91
|
+
if not digests or set(digests) != set(sizes):
|
|
92
|
+
raise ValueError("selector split provenance requires matching split identities")
|
|
93
|
+
if any(
|
|
94
|
+
not isinstance(split, str)
|
|
95
|
+
or not split.strip()
|
|
96
|
+
or not isinstance(digest, str)
|
|
97
|
+
or len(digest) != 64
|
|
98
|
+
or any(character not in "0123456789abcdef" for character in digest)
|
|
99
|
+
for split, digest in digests.items()
|
|
100
|
+
):
|
|
101
|
+
raise ValueError("selector split provenance requires SHA-256 split digests")
|
|
102
|
+
if any(
|
|
103
|
+
isinstance(size, bool) or not isinstance(size, int) or size < 1
|
|
104
|
+
for size in sizes.values()
|
|
105
|
+
):
|
|
106
|
+
raise ValueError("selector split provenance requires positive split sizes")
|
|
107
|
+
object.__setattr__(self, "id_set_digests", MappingProxyType(digests))
|
|
108
|
+
object.__setattr__(self, "split_sizes", MappingProxyType(sizes))
|
|
109
|
+
|
|
110
|
+
@property
|
|
111
|
+
def provenance_hash(self) -> str:
|
|
112
|
+
return content_hash(
|
|
113
|
+
{
|
|
114
|
+
"id_set_digests": self.id_set_digests,
|
|
115
|
+
"split_sizes": self.split_sizes,
|
|
116
|
+
}
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def validate_selector_split_ids(
|
|
121
|
+
split_examples: Mapping[str, Sequence[SelectorExample]],
|
|
122
|
+
) -> SelectorSplitProvenance:
|
|
123
|
+
"""Reject train/calibration/test ID leakage and bind each split's ID set.
|
|
124
|
+
|
|
125
|
+
The held-out split may use a study-specific name such as
|
|
126
|
+
``confirmatory_test`` or ``external_test``. At least one such split is
|
|
127
|
+
required in addition to ``train`` and ``calibration``.
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
copied = dict(split_examples)
|
|
131
|
+
if "train" not in copied or "calibration" not in copied or len(copied) < 3:
|
|
132
|
+
raise ValueError(
|
|
133
|
+
"selector split validation requires train, calibration, and a held-out test split"
|
|
134
|
+
)
|
|
135
|
+
owner_by_id: dict[str, str] = {}
|
|
136
|
+
digests: dict[str, str] = {}
|
|
137
|
+
sizes: dict[str, int] = {}
|
|
138
|
+
for split in sorted(copied):
|
|
139
|
+
if not isinstance(split, str) or not split.strip():
|
|
140
|
+
raise ValueError("selector split names must be non-empty strings")
|
|
141
|
+
rows = tuple(copied[split])
|
|
142
|
+
if not rows or any(not isinstance(row, SelectorExample) for row in rows):
|
|
143
|
+
raise ValueError(f"selector split {split!r} requires SelectorExample rows")
|
|
144
|
+
if any(row.split != split for row in rows):
|
|
145
|
+
raise ValueError(f"selector split {split!r} contains a mismatched split label")
|
|
146
|
+
ids = [row.example_id for row in rows]
|
|
147
|
+
if len(ids) != len(set(ids)):
|
|
148
|
+
raise ValueError(f"selector split {split!r} requires unique example IDs")
|
|
149
|
+
for example_id in ids:
|
|
150
|
+
previous = owner_by_id.setdefault(example_id, split)
|
|
151
|
+
if previous != split:
|
|
152
|
+
raise ValueError(
|
|
153
|
+
f"selector example ID {example_id!r} overlaps splits {previous!r} and {split!r}"
|
|
154
|
+
)
|
|
155
|
+
digests[split] = _selector_id_set_digest(rows, required_split=split)
|
|
156
|
+
sizes[split] = len(rows)
|
|
157
|
+
return SelectorSplitProvenance(digests, sizes)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@dataclass(frozen=True, slots=True)
|
|
161
|
+
class RidgeUtilitySelector:
|
|
162
|
+
"""Predict per-family utility gains and abstain unless evidence is sufficient."""
|
|
163
|
+
|
|
164
|
+
coefficients: Mapping[SemanticFamily, tuple[float, ...]]
|
|
165
|
+
release_by_family: Mapping[SemanticFamily, str]
|
|
166
|
+
min_gain: float = 0.0
|
|
167
|
+
margin: float = 0.0
|
|
168
|
+
|
|
169
|
+
def __post_init__(self) -> None:
|
|
170
|
+
expected = len(SelectionFeatures().as_vector()) + 1
|
|
171
|
+
if not self.coefficients:
|
|
172
|
+
raise ValueError("selector requires at least one fitted family")
|
|
173
|
+
if any(
|
|
174
|
+
not isinstance(family, SemanticFamily) or family is SemanticFamily.NO_OP
|
|
175
|
+
for family in self.coefficients
|
|
176
|
+
):
|
|
177
|
+
raise ValueError("selector coefficient keys must be intervention families")
|
|
178
|
+
frozen_coefficients = {
|
|
179
|
+
family: tuple(values) for family, values in self.coefficients.items()
|
|
180
|
+
}
|
|
181
|
+
if any(len(values) != expected for values in frozen_coefficients.values()):
|
|
182
|
+
raise ValueError(f"selector coefficient vectors must contain {expected} values")
|
|
183
|
+
if any(
|
|
184
|
+
any(
|
|
185
|
+
isinstance(value, bool)
|
|
186
|
+
or not isinstance(value, (int, float))
|
|
187
|
+
or not math.isfinite(value)
|
|
188
|
+
for value in values
|
|
189
|
+
)
|
|
190
|
+
for values in frozen_coefficients.values()
|
|
191
|
+
):
|
|
192
|
+
raise ValueError("selector coefficients must be finite numbers")
|
|
193
|
+
if (
|
|
194
|
+
isinstance(self.min_gain, bool)
|
|
195
|
+
or not isinstance(self.min_gain, (int, float))
|
|
196
|
+
or not math.isfinite(self.min_gain)
|
|
197
|
+
):
|
|
198
|
+
raise ValueError("selector min_gain must be a finite number")
|
|
199
|
+
if (
|
|
200
|
+
isinstance(self.margin, bool)
|
|
201
|
+
or not isinstance(self.margin, (int, float))
|
|
202
|
+
or not math.isfinite(self.margin)
|
|
203
|
+
or self.margin < 0
|
|
204
|
+
):
|
|
205
|
+
raise ValueError("selector margin must be finite and non-negative")
|
|
206
|
+
release_mapping = dict(self.release_by_family)
|
|
207
|
+
if any(
|
|
208
|
+
not isinstance(family, SemanticFamily)
|
|
209
|
+
or family is SemanticFamily.NO_OP
|
|
210
|
+
or not isinstance(release, str)
|
|
211
|
+
or not release.strip()
|
|
212
|
+
for family, release in release_mapping.items()
|
|
213
|
+
):
|
|
214
|
+
raise ValueError("release mappings require intervention-family keys and IDs")
|
|
215
|
+
missing_release = set(frozen_coefficients) - set(release_mapping)
|
|
216
|
+
if missing_release:
|
|
217
|
+
names = ", ".join(sorted(family.value for family in missing_release))
|
|
218
|
+
raise ValueError(f"missing release mapping for fitted families: {names}")
|
|
219
|
+
object.__setattr__(self, "coefficients", MappingProxyType(frozen_coefficients))
|
|
220
|
+
object.__setattr__(self, "release_by_family", MappingProxyType(release_mapping))
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def model_hash(self) -> str:
|
|
224
|
+
return content_hash(
|
|
225
|
+
{
|
|
226
|
+
"coefficients": {
|
|
227
|
+
family.value: values for family, values in self.coefficients.items()
|
|
228
|
+
},
|
|
229
|
+
"release_by_family": {
|
|
230
|
+
family.value: release for family, release in self.release_by_family.items()
|
|
231
|
+
},
|
|
232
|
+
"min_gain": self.min_gain,
|
|
233
|
+
"margin": self.margin,
|
|
234
|
+
}
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
def predict_gains(self, features: SelectionFeatures) -> dict[SemanticFamily, float]:
|
|
238
|
+
vector = (1.0, *features.as_vector())
|
|
239
|
+
return {
|
|
240
|
+
family: sum(weight * value for weight, value in zip(weights, vector, strict=True))
|
|
241
|
+
for family, weights in self.coefficients.items()
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
def select(
|
|
245
|
+
self,
|
|
246
|
+
state: FrozenAgentState,
|
|
247
|
+
features: SelectionFeatures,
|
|
248
|
+
*,
|
|
249
|
+
eligible_families: Collection[SemanticFamily] | None = None,
|
|
250
|
+
) -> SelectionDecision:
|
|
251
|
+
del state
|
|
252
|
+
gains = self.predict_gains(features)
|
|
253
|
+
eligible = _normalize_eligible_families(eligible_families)
|
|
254
|
+
ordered = sorted(
|
|
255
|
+
((family, gain) for family, gain in gains.items() if family in eligible),
|
|
256
|
+
key=lambda item: (-item[1], item[0].value),
|
|
257
|
+
)
|
|
258
|
+
scores = {item.value: value for item, value in gains.items()}
|
|
259
|
+
scores[SemanticFamily.NO_OP.value] = 0.0
|
|
260
|
+
if not ordered:
|
|
261
|
+
return SelectionDecision(
|
|
262
|
+
family=SemanticFamily.NO_OP,
|
|
263
|
+
release_id="baseline.no_op",
|
|
264
|
+
selection_score=0.0,
|
|
265
|
+
rationale="abstained: no fitted intervention family is eligible",
|
|
266
|
+
scores=scores,
|
|
267
|
+
)
|
|
268
|
+
family, gain = ordered[0]
|
|
269
|
+
runner_up = max(0.0, ordered[1][1] if len(ordered) > 1 else 0.0)
|
|
270
|
+
if gain <= self.min_gain or gain - runner_up <= self.margin:
|
|
271
|
+
return SelectionDecision(
|
|
272
|
+
family=SemanticFamily.NO_OP,
|
|
273
|
+
release_id="baseline.no_op",
|
|
274
|
+
selection_score=0.0,
|
|
275
|
+
rationale="abstained: calibrated gain or margin gate not met",
|
|
276
|
+
scores=scores,
|
|
277
|
+
)
|
|
278
|
+
return SelectionDecision(
|
|
279
|
+
family=family,
|
|
280
|
+
release_id=self.release_by_family[family],
|
|
281
|
+
selection_score=gain,
|
|
282
|
+
rationale=f"selected calibrated predicted-utility winner: {family.value}",
|
|
283
|
+
scores=scores,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
@dataclass(frozen=True, slots=True)
|
|
288
|
+
class PolicyEvaluation:
|
|
289
|
+
count: int
|
|
290
|
+
coverage: float
|
|
291
|
+
mean_policy_value: float
|
|
292
|
+
mean_no_op_value: float
|
|
293
|
+
mean_gain: float
|
|
294
|
+
harm_rate: float
|
|
295
|
+
oracle_regret: float
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
@dataclass(frozen=True, slots=True)
|
|
299
|
+
class CalibrationResult:
|
|
300
|
+
selector: RidgeUtilitySelector
|
|
301
|
+
evaluation: PolicyEvaluation
|
|
302
|
+
candidates_considered: int
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def fit_ridge_selector(
|
|
306
|
+
examples: Sequence[SelectorExample],
|
|
307
|
+
*,
|
|
308
|
+
release_by_family: Mapping[SemanticFamily, str],
|
|
309
|
+
ridge: float = 1e-6,
|
|
310
|
+
) -> RidgeUtilitySelector:
|
|
311
|
+
"""Fit one utility-gain model per family on an explicitly named train split."""
|
|
312
|
+
|
|
313
|
+
rows = tuple(examples)
|
|
314
|
+
if not rows:
|
|
315
|
+
raise ValueError("selector training requires examples")
|
|
316
|
+
if any(example.split != "train" for example in rows):
|
|
317
|
+
raise ValueError("fit_ridge_selector only accepts split='train' examples")
|
|
318
|
+
if not math.isfinite(ridge) or ridge < 0:
|
|
319
|
+
raise ValueError("ridge must be finite and non-negative")
|
|
320
|
+
matrix = [(1.0, *example.features.as_vector()) for example in rows]
|
|
321
|
+
coefficients: dict[SemanticFamily, tuple[float, ...]] = {}
|
|
322
|
+
for family in _ACTIONS:
|
|
323
|
+
if any(family not in example.utilities for example in rows):
|
|
324
|
+
continue
|
|
325
|
+
targets = [
|
|
326
|
+
example.utilities[family] - example.utilities[SemanticFamily.NO_OP] for example in rows
|
|
327
|
+
]
|
|
328
|
+
coefficients[family] = _ridge_solve(matrix, targets, ridge=ridge)
|
|
329
|
+
if not coefficients:
|
|
330
|
+
raise ValueError("no intervention family has complete training utilities")
|
|
331
|
+
missing_release = set(coefficients) - set(release_by_family)
|
|
332
|
+
if missing_release:
|
|
333
|
+
names = ", ".join(sorted(family.value for family in missing_release))
|
|
334
|
+
raise ValueError(f"missing release mapping for fitted families: {names}")
|
|
335
|
+
return RidgeUtilitySelector(coefficients, release_by_family)
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def calibrate_abstention(
|
|
339
|
+
selector: RidgeUtilitySelector,
|
|
340
|
+
examples: Sequence[SelectorExample],
|
|
341
|
+
*,
|
|
342
|
+
gain_grid: Sequence[float],
|
|
343
|
+
margin_grid: Sequence[float],
|
|
344
|
+
max_harm_rate: float,
|
|
345
|
+
) -> CalibrationResult:
|
|
346
|
+
"""Choose gates on calibration data only, maximizing value then coverage."""
|
|
347
|
+
|
|
348
|
+
rows = tuple(examples)
|
|
349
|
+
if not rows or any(example.split != "calibration" for example in rows):
|
|
350
|
+
raise ValueError("abstention calibration requires split='calibration' examples")
|
|
351
|
+
if not 0 <= max_harm_rate <= 1:
|
|
352
|
+
raise ValueError("max_harm_rate must be in [0, 1]")
|
|
353
|
+
if not gain_grid or not margin_grid:
|
|
354
|
+
raise ValueError("abstention calibration grids must be non-empty")
|
|
355
|
+
if any(not math.isfinite(float(value)) for value in gain_grid):
|
|
356
|
+
raise ValueError("gain grid values must be finite")
|
|
357
|
+
if any(not math.isfinite(float(value)) or float(value) < 0 for value in margin_grid):
|
|
358
|
+
raise ValueError("margin grid values must be finite and non-negative")
|
|
359
|
+
candidates: list[tuple[PolicyEvaluation, RidgeUtilitySelector]] = []
|
|
360
|
+
considered = 0
|
|
361
|
+
for gain in gain_grid:
|
|
362
|
+
for margin in margin_grid:
|
|
363
|
+
considered += 1
|
|
364
|
+
candidate = replace(selector, min_gain=float(gain), margin=float(margin))
|
|
365
|
+
evaluation = evaluate_selector(candidate, rows, required_split="calibration")
|
|
366
|
+
if evaluation.harm_rate <= max_harm_rate:
|
|
367
|
+
candidates.append((evaluation, candidate))
|
|
368
|
+
if not candidates:
|
|
369
|
+
raise ValueError("no abstention candidate satisfies the harm constraint")
|
|
370
|
+
evaluation, candidate = max(
|
|
371
|
+
candidates,
|
|
372
|
+
key=lambda item: (
|
|
373
|
+
item[0].mean_policy_value,
|
|
374
|
+
item[0].coverage,
|
|
375
|
+
-item[0].harm_rate,
|
|
376
|
+
-item[1].min_gain,
|
|
377
|
+
-item[1].margin,
|
|
378
|
+
),
|
|
379
|
+
)
|
|
380
|
+
return CalibrationResult(candidate, evaluation, considered)
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
def evaluate_selector(
|
|
384
|
+
selector: Selector,
|
|
385
|
+
examples: Sequence[SelectorExample],
|
|
386
|
+
*,
|
|
387
|
+
required_split: str,
|
|
388
|
+
) -> PolicyEvaluation:
|
|
389
|
+
"""Evaluate a frozen selector on one named, non-training split."""
|
|
390
|
+
|
|
391
|
+
rows = tuple(examples)
|
|
392
|
+
if not rows:
|
|
393
|
+
raise ValueError("selector evaluation requires examples")
|
|
394
|
+
if required_split == "train" or any(example.split != required_split for example in rows):
|
|
395
|
+
raise ValueError("evaluation split must be uniform and must not be train")
|
|
396
|
+
chosen_values: list[float] = []
|
|
397
|
+
no_op_values: list[float] = []
|
|
398
|
+
regrets: list[float] = []
|
|
399
|
+
selected = 0
|
|
400
|
+
harmed = 0
|
|
401
|
+
for example in rows:
|
|
402
|
+
decision = selector.select(
|
|
403
|
+
FrozenAgentState(query=example.example_id),
|
|
404
|
+
example.features,
|
|
405
|
+
eligible_families=tuple(example.utilities),
|
|
406
|
+
)
|
|
407
|
+
family = decision.family
|
|
408
|
+
if family not in example.utilities:
|
|
409
|
+
raise ValueError(
|
|
410
|
+
f"selector chose ineligible family {family.value!r} for {example.example_id!r}"
|
|
411
|
+
)
|
|
412
|
+
chosen = example.utilities[family]
|
|
413
|
+
no_op = example.utilities[SemanticFamily.NO_OP]
|
|
414
|
+
chosen_values.append(chosen)
|
|
415
|
+
no_op_values.append(no_op)
|
|
416
|
+
selected += family is not SemanticFamily.NO_OP
|
|
417
|
+
harmed += chosen < no_op
|
|
418
|
+
regrets.append(max(example.utilities.values()) - chosen)
|
|
419
|
+
return PolicyEvaluation(
|
|
420
|
+
count=len(rows),
|
|
421
|
+
coverage=selected / len(rows),
|
|
422
|
+
mean_policy_value=fmean(chosen_values),
|
|
423
|
+
mean_no_op_value=fmean(no_op_values),
|
|
424
|
+
mean_gain=fmean(
|
|
425
|
+
after - before for before, after in zip(no_op_values, chosen_values, strict=True)
|
|
426
|
+
),
|
|
427
|
+
harm_rate=harmed / len(rows),
|
|
428
|
+
oracle_regret=fmean(regrets),
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
def _selector_id_set_digest(
|
|
433
|
+
examples: Sequence[SelectorExample],
|
|
434
|
+
*,
|
|
435
|
+
required_split: str,
|
|
436
|
+
) -> str:
|
|
437
|
+
rows = tuple(examples)
|
|
438
|
+
if not rows or any(
|
|
439
|
+
not isinstance(row, SelectorExample) or row.split != required_split for row in rows
|
|
440
|
+
):
|
|
441
|
+
raise ValueError(f"selector ID digest requires uniform split={required_split!r} rows")
|
|
442
|
+
ids = [row.example_id for row in rows]
|
|
443
|
+
if len(ids) != len(set(ids)):
|
|
444
|
+
raise ValueError("selector ID digest requires unique example IDs")
|
|
445
|
+
return content_hash(
|
|
446
|
+
{
|
|
447
|
+
"split": required_split,
|
|
448
|
+
"example_ids": sorted(ids),
|
|
449
|
+
}
|
|
450
|
+
)
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
def _ridge_solve(
|
|
454
|
+
matrix: Sequence[tuple[float, ...]],
|
|
455
|
+
targets: Sequence[float],
|
|
456
|
+
*,
|
|
457
|
+
ridge: float,
|
|
458
|
+
) -> tuple[float, ...]:
|
|
459
|
+
width = len(matrix[0])
|
|
460
|
+
gram = [[0.0 for _ in range(width)] for _ in range(width)]
|
|
461
|
+
rhs = [0.0 for _ in range(width)]
|
|
462
|
+
for row, target in zip(matrix, targets, strict=True):
|
|
463
|
+
for left in range(width):
|
|
464
|
+
rhs[left] += row[left] * target
|
|
465
|
+
for right in range(width):
|
|
466
|
+
gram[left][right] += row[left] * row[right]
|
|
467
|
+
for index in range(1, width):
|
|
468
|
+
gram[index][index] += ridge
|
|
469
|
+
gram[0][0] += ridge * 1e-3
|
|
470
|
+
return tuple(_gaussian_elimination(gram, rhs))
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
def _gaussian_elimination(matrix: list[list[float]], rhs: list[float]) -> list[float]:
|
|
474
|
+
size = len(rhs)
|
|
475
|
+
augmented = [[*row, value] for row, value in zip(matrix, rhs, strict=True)]
|
|
476
|
+
for column in range(size):
|
|
477
|
+
pivot = max(range(column, size), key=lambda row: abs(augmented[row][column]))
|
|
478
|
+
if abs(augmented[pivot][column]) < 1e-12:
|
|
479
|
+
raise ValueError("selector design matrix is singular; increase ridge")
|
|
480
|
+
augmented[column], augmented[pivot] = augmented[pivot], augmented[column]
|
|
481
|
+
scale = augmented[column][column]
|
|
482
|
+
augmented[column] = [value / scale for value in augmented[column]]
|
|
483
|
+
for row in range(size):
|
|
484
|
+
if row == column:
|
|
485
|
+
continue
|
|
486
|
+
factor = augmented[row][column]
|
|
487
|
+
augmented[row] = [
|
|
488
|
+
value - factor * pivot_value
|
|
489
|
+
for value, pivot_value in zip(augmented[row], augmented[column], strict=True)
|
|
490
|
+
]
|
|
491
|
+
return [augmented[row][-1] for row in range(size)]
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def _normalize_eligible_families(
|
|
495
|
+
eligible_families: Collection[SemanticFamily] | None,
|
|
496
|
+
) -> frozenset[SemanticFamily]:
|
|
497
|
+
if eligible_families is None:
|
|
498
|
+
return frozenset(_ACTIONS)
|
|
499
|
+
eligible = tuple(eligible_families)
|
|
500
|
+
if any(not isinstance(family, SemanticFamily) for family in eligible):
|
|
501
|
+
raise ValueError("eligible_families must contain SemanticFamily values")
|
|
502
|
+
return frozenset(family for family in eligible if family is not SemanticFamily.NO_OP)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Zero-cost baseline intervention."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
from agentinputlab.contracts.enums import SemanticFamily
|
|
8
|
+
from agentinputlab.contracts.lifecycle import InterventionContext
|
|
9
|
+
from agentinputlab.contracts.patch import InputPatch
|
|
10
|
+
from agentinputlab.contracts.state import FrozenAgentState
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True, slots=True)
|
|
14
|
+
class NoOpIntervention:
|
|
15
|
+
method_id: str = "no_op"
|
|
16
|
+
release_id: str = "baseline.no_op"
|
|
17
|
+
family: SemanticFamily = SemanticFamily.NO_OP
|
|
18
|
+
profile_kind: str = "controlled_adapter"
|
|
19
|
+
|
|
20
|
+
def propose(self, state: FrozenAgentState, context: InterventionContext) -> InputPatch:
|
|
21
|
+
del context
|
|
22
|
+
return InputPatch.no_op(
|
|
23
|
+
state,
|
|
24
|
+
method_id=self.method_id,
|
|
25
|
+
release_id=self.release_id,
|
|
26
|
+
rationale="explicit no-intervention baseline",
|
|
27
|
+
profile_kind=self.profile_kind,
|
|
28
|
+
)
|