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,1316 @@
|
|
|
1
|
+
"""Fail-closed analysis for the frozen held-out-model transfer block.
|
|
2
|
+
|
|
3
|
+
This module deliberately accepts only the generated robustness protocol:
|
|
4
|
+
200 STATE-Bench groups, six rank-1 representative arms, four frozen transfer
|
|
5
|
+
models, and one continuation seed. A checksum-complete run is necessary but not
|
|
6
|
+
sufficient. The scientific boundary also rechecks the persisted prerequisite
|
|
7
|
+
binding receipt, driver arm/source identity, and per-cell dependency and
|
|
8
|
+
atomic-replay receipts before reading outcomes.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import json
|
|
14
|
+
import math
|
|
15
|
+
import random
|
|
16
|
+
from collections import defaultdict
|
|
17
|
+
from collections.abc import Mapping, Sequence
|
|
18
|
+
from dataclasses import dataclass
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from statistics import fmean
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
from agentinputlab.benchmarks import (
|
|
24
|
+
ATOMIC_EXTERNAL_PAIR_CONTRACT,
|
|
25
|
+
AtomicReplayArmReceipt,
|
|
26
|
+
AtomicReplayReceipt,
|
|
27
|
+
)
|
|
28
|
+
from agentinputlab.contracts.enums import ProfileKind, SemanticFamily
|
|
29
|
+
from agentinputlab.contracts.errors import ArtifactError, ValidationError
|
|
30
|
+
from agentinputlab.contracts.serialization import canonical_json, content_hash, to_jsonable
|
|
31
|
+
from agentinputlab.metrics.paired import summarize_pairs
|
|
32
|
+
|
|
33
|
+
from .analysis import (
|
|
34
|
+
_arm_metrics,
|
|
35
|
+
_cluster_bootstrap_interval,
|
|
36
|
+
_cluster_id,
|
|
37
|
+
_load_manifest,
|
|
38
|
+
_primary_families,
|
|
39
|
+
_required_record_text,
|
|
40
|
+
_validate_resample_arguments,
|
|
41
|
+
load_verified_cell_results,
|
|
42
|
+
)
|
|
43
|
+
from .bindings import FrozenBindingEntry, FrozenBindingReceipt
|
|
44
|
+
from .paper_analysis import (
|
|
45
|
+
_COMMON_SUPPORT_KIND,
|
|
46
|
+
_load_and_validate_paper_run,
|
|
47
|
+
)
|
|
48
|
+
from .schema import ExperimentManifest, ExperimentStage, PrerequisiteKind
|
|
49
|
+
|
|
50
|
+
HELDOUT_MODEL_TRANSFER_PROTOCOL = "paper-heldout-model-transfer-v1"
|
|
51
|
+
|
|
52
|
+
_CENSUS_PROTOCOL = "agentinputlab.experiment_census.v1"
|
|
53
|
+
_CAMPAIGN_KIND = "heldout_model_transfer"
|
|
54
|
+
_STUDY_ID = "robustness.heldout_model_transfer"
|
|
55
|
+
_BENCHMARK_ID = "state_bench.common_support"
|
|
56
|
+
_TRANSFER_SPLIT = "heldout_model_transfer"
|
|
57
|
+
_TRANSFER_MODEL_SLOTS = (
|
|
58
|
+
"qwen3_4b",
|
|
59
|
+
"deepseek_r1_distill_qwen_7b",
|
|
60
|
+
"claude_sonnet_4_6",
|
|
61
|
+
"deepseek_v4_flash",
|
|
62
|
+
)
|
|
63
|
+
_PRIMARY_MODEL_SLOTS = ("anchor_a", "anchor_b")
|
|
64
|
+
_SEED = 17
|
|
65
|
+
_STATEBENCH_REVISION = "4efcbf2d4fe60df04878859b692d9391f3d5b33a"
|
|
66
|
+
_EXTERNAL_DRIVER = "agentinputlab.experiments.drivers.external_arena:factory"
|
|
67
|
+
_EXTERNAL_DRIVER_IMPLEMENTATION = "agentinputlab.external_arena.atomic_multi_arm"
|
|
68
|
+
_GUARD_ID = "agentinputlab.frozen_binding_driver_guard"
|
|
69
|
+
_CORE_FAMILIES = _primary_families()
|
|
70
|
+
_DEPENDENCY_SLOTS = frozenset(
|
|
71
|
+
{
|
|
72
|
+
"agent_model",
|
|
73
|
+
"official_runtime",
|
|
74
|
+
"corpus",
|
|
75
|
+
"preprocessing",
|
|
76
|
+
"index",
|
|
77
|
+
"embedder",
|
|
78
|
+
"retriever",
|
|
79
|
+
"reranker",
|
|
80
|
+
"reader",
|
|
81
|
+
"scorer",
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
_HELDOUT_PREREQUISITES = {
|
|
85
|
+
"AILAB_STATEBENCH_CHECKOUT",
|
|
86
|
+
"AILAB_REPRESENTATIVE_MANIFEST",
|
|
87
|
+
"AILAB_EXTERNAL_ARENA_DRIVER_CONFIG",
|
|
88
|
+
"AILAB_MODEL_CONFIG",
|
|
89
|
+
"AILAB_RETRIEVER_CONFIG",
|
|
90
|
+
"AILAB_HELDOUT_MODEL_FREEZE_RECEIPT",
|
|
91
|
+
}
|
|
92
|
+
_PRIMARY_PREREQUISITES = {
|
|
93
|
+
"AILAB_TAU3_CHECKOUT",
|
|
94
|
+
"AILAB_STATEBENCH_CHECKOUT",
|
|
95
|
+
"AILAB_TOOLSANDBOX_CHECKOUT",
|
|
96
|
+
"AILAB_TOOLSANDBOX_GATE_RECEIPT",
|
|
97
|
+
"AILAB_COMMON_SUPPORT_FREEZE_RECEIPT",
|
|
98
|
+
"AILAB_EXTERNAL_ARENA_DRIVER_CONFIG",
|
|
99
|
+
"AILAB_MODEL_CONFIG",
|
|
100
|
+
"AILAB_RETRIEVER_CONFIG",
|
|
101
|
+
"AILAB_REPRESENTATIVE_MANIFEST",
|
|
102
|
+
}
|
|
103
|
+
_PRIMARY_TARGET_COUNTS = {
|
|
104
|
+
"tau3.banking_knowledge:common_support_lockbox": 97,
|
|
105
|
+
"state_bench.common_support:common_support_lockbox": 300,
|
|
106
|
+
"toolsandbox.common_support:common_support_lockbox": 129,
|
|
107
|
+
}
|
|
108
|
+
_PRIMARY_SOURCE_REVISIONS = {
|
|
109
|
+
"tau3.banking_knowledge": "cf71a8070269883e38a365ffa85f78f46844c1f4",
|
|
110
|
+
"state_bench.common_support": _STATEBENCH_REVISION,
|
|
111
|
+
"toolsandbox.common_support": "165848b9a78cead7ca7fe7c89c688b58e6501219",
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@dataclass(frozen=True, slots=True)
|
|
116
|
+
class _VerifiedTransferRun:
|
|
117
|
+
root: Path
|
|
118
|
+
manifest: ExperimentManifest
|
|
119
|
+
records: tuple[Mapping[str, Any], ...]
|
|
120
|
+
clusters: frozenset[str]
|
|
121
|
+
representative_hash: str
|
|
122
|
+
baseline_arm_id: str
|
|
123
|
+
arms_by_family: Mapping[SemanticFamily, str]
|
|
124
|
+
binding_receipt: Mapping[str, Any]
|
|
125
|
+
runtime_receipts: Mapping[str, Any]
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def validate_heldout_model_transfer_run(run_dir: str | Path) -> Mapping[str, Any]:
|
|
129
|
+
"""Validate the exact frozen transfer run without computing outcome effects."""
|
|
130
|
+
|
|
131
|
+
run = _load_and_validate_heldout_run(run_dir)
|
|
132
|
+
return {
|
|
133
|
+
"analysis_protocol": HELDOUT_MODEL_TRANSFER_PROTOCOL,
|
|
134
|
+
"study_id": run.manifest.study_id,
|
|
135
|
+
"manifest_hash": run.manifest.manifest_hash,
|
|
136
|
+
"campaign_kind": _CAMPAIGN_KIND,
|
|
137
|
+
"verified_complete_run": True,
|
|
138
|
+
"independent_groups": 200,
|
|
139
|
+
"verified_plan_cells": 800,
|
|
140
|
+
"verified_agent_episodes": 4_800,
|
|
141
|
+
"model_slots": list(_TRANSFER_MODEL_SLOTS),
|
|
142
|
+
"representative_binding": dict(run.binding_receipt["representative_binding"]),
|
|
143
|
+
"runtime_receipts": dict(run.runtime_receipts),
|
|
144
|
+
"experiments_executed_by_analysis": False,
|
|
145
|
+
"paper_claim_authorized": False,
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def analyze_heldout_model_transfer(
|
|
150
|
+
run_dir: str | Path,
|
|
151
|
+
*,
|
|
152
|
+
metric: str,
|
|
153
|
+
primary_common_support_run_dir: str | Path | None = None,
|
|
154
|
+
algorithm_failure_value: float | None = None,
|
|
155
|
+
bootstrap_samples: int = 2_000,
|
|
156
|
+
random_seed: int = 2027,
|
|
157
|
+
) -> Mapping[str, Any]:
|
|
158
|
+
"""Estimate each rank-1 family representative versus matched NO_OP.
|
|
159
|
+
|
|
160
|
+
When a primary common-support run is supplied, the additional boundary is
|
|
161
|
+
a matched difference-in-differences on the 200 underlying STATE-Bench
|
|
162
|
+
units. It is not a pooled common-population effect.
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
_validate_analysis_arguments(
|
|
166
|
+
metric=metric,
|
|
167
|
+
algorithm_failure_value=algorithm_failure_value,
|
|
168
|
+
bootstrap_samples=bootstrap_samples,
|
|
169
|
+
random_seed=random_seed,
|
|
170
|
+
)
|
|
171
|
+
transfer = _load_and_validate_heldout_run(run_dir)
|
|
172
|
+
transfer_rows = _collapsed_family_rows(
|
|
173
|
+
transfer.records,
|
|
174
|
+
manifest=transfer.manifest,
|
|
175
|
+
baseline_arm_id=transfer.baseline_arm_id,
|
|
176
|
+
arms_by_family=transfer.arms_by_family,
|
|
177
|
+
metric=metric,
|
|
178
|
+
algorithm_failure_value=algorithm_failure_value,
|
|
179
|
+
)
|
|
180
|
+
if len(transfer_rows) != 200:
|
|
181
|
+
raise ArtifactError("heldout-model transfer analysis requires exactly 200 clusters")
|
|
182
|
+
|
|
183
|
+
rng = random.Random(random_seed)
|
|
184
|
+
family_summaries = _family_summaries(
|
|
185
|
+
transfer_rows,
|
|
186
|
+
arms_by_family=transfer.arms_by_family,
|
|
187
|
+
manifest=transfer.manifest,
|
|
188
|
+
bootstrap_samples=bootstrap_samples,
|
|
189
|
+
rng=rng,
|
|
190
|
+
)
|
|
191
|
+
model_summaries = {
|
|
192
|
+
model_slot: _family_summaries(
|
|
193
|
+
_collapsed_family_rows(
|
|
194
|
+
tuple(
|
|
195
|
+
record
|
|
196
|
+
for record in transfer.records
|
|
197
|
+
if record["cell"]["model_slot"] == model_slot
|
|
198
|
+
),
|
|
199
|
+
manifest=transfer.manifest,
|
|
200
|
+
baseline_arm_id=transfer.baseline_arm_id,
|
|
201
|
+
arms_by_family=transfer.arms_by_family,
|
|
202
|
+
metric=metric,
|
|
203
|
+
algorithm_failure_value=algorithm_failure_value,
|
|
204
|
+
),
|
|
205
|
+
arms_by_family=transfer.arms_by_family,
|
|
206
|
+
manifest=transfer.manifest,
|
|
207
|
+
bootstrap_samples=bootstrap_samples,
|
|
208
|
+
rng=rng,
|
|
209
|
+
)
|
|
210
|
+
for model_slot in _TRANSFER_MODEL_SLOTS
|
|
211
|
+
}
|
|
212
|
+
comparison: Mapping[str, Any] | None = None
|
|
213
|
+
if primary_common_support_run_dir is not None:
|
|
214
|
+
primary = _load_and_validate_primary_run(primary_common_support_run_dir)
|
|
215
|
+
if primary.root == transfer.root:
|
|
216
|
+
raise ArtifactError("transfer and primary comparison require different run directories")
|
|
217
|
+
_require_same_representatives(transfer, primary)
|
|
218
|
+
primary_rows = _collapsed_family_rows(
|
|
219
|
+
primary.records,
|
|
220
|
+
manifest=primary.manifest,
|
|
221
|
+
baseline_arm_id=primary.baseline_arm_id,
|
|
222
|
+
arms_by_family=primary.arms_by_family,
|
|
223
|
+
metric=metric,
|
|
224
|
+
algorithm_failure_value=algorithm_failure_value,
|
|
225
|
+
)
|
|
226
|
+
comparison = _transfer_primary_boundary(
|
|
227
|
+
transfer_rows,
|
|
228
|
+
primary_rows,
|
|
229
|
+
transfer=transfer,
|
|
230
|
+
primary=primary,
|
|
231
|
+
bootstrap_samples=bootstrap_samples,
|
|
232
|
+
rng=rng,
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
result: dict[str, Any] = {
|
|
236
|
+
"schema_version": 1,
|
|
237
|
+
"analysis": "heldout_model_transfer_family_vs_no_op",
|
|
238
|
+
"analysis_protocol": HELDOUT_MODEL_TRANSFER_PROTOCOL,
|
|
239
|
+
"metric": metric,
|
|
240
|
+
"run_count": 1 + int(primary_common_support_run_dir is not None),
|
|
241
|
+
"study_id": transfer.manifest.study_id,
|
|
242
|
+
"manifest_hash": transfer.manifest.manifest_hash,
|
|
243
|
+
"verified_complete_run": True,
|
|
244
|
+
"independent_groups": 200,
|
|
245
|
+
"verified_plan_cells": 800,
|
|
246
|
+
"verified_agent_episodes": 4_800,
|
|
247
|
+
"arm_layout": "NO_OP + one frozen rank-1 representative per core family",
|
|
248
|
+
"model_slots": list(_TRANSFER_MODEL_SLOTS),
|
|
249
|
+
"seed": _SEED,
|
|
250
|
+
"cluster_definition": "benchmark_id/split/unit_id",
|
|
251
|
+
"family_summaries": family_summaries,
|
|
252
|
+
"family_summaries_by_model": model_summaries,
|
|
253
|
+
"representative_binding": dict(transfer.binding_receipt["representative_binding"]),
|
|
254
|
+
"runtime_receipts": dict(transfer.runtime_receipts),
|
|
255
|
+
"primary_common_support_boundary": comparison,
|
|
256
|
+
"bootstrap_samples": bootstrap_samples,
|
|
257
|
+
"random_seed": random_seed,
|
|
258
|
+
"algorithm_failure_value": algorithm_failure_value,
|
|
259
|
+
"scope_note": (
|
|
260
|
+
"Transfer estimates are matched family-versus-NO_OP effects on the "
|
|
261
|
+
"prespecified 200-group four-model block. The aggregate gives every model "
|
|
262
|
+
"equal weight. Any optional primary comparison "
|
|
263
|
+
"is a matched transfer-minus-primary interaction boundary, not a pooled "
|
|
264
|
+
"effect or evidence that the populations are exchangeable."
|
|
265
|
+
),
|
|
266
|
+
"experiments_executed_by_analysis": False,
|
|
267
|
+
"paper_claim_authorized": False,
|
|
268
|
+
}
|
|
269
|
+
return result
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def _load_and_validate_heldout_run(run_dir: str | Path) -> _VerifiedTransferRun:
|
|
273
|
+
root = Path(run_dir).expanduser().resolve()
|
|
274
|
+
manifest = _load_manifest(root)
|
|
275
|
+
records = load_verified_cell_results(root)
|
|
276
|
+
baseline, arms_by_family, representative_hash = _heldout_manifest_contract(manifest)
|
|
277
|
+
clusters = _validate_exact_grid(
|
|
278
|
+
records,
|
|
279
|
+
manifest=manifest,
|
|
280
|
+
expected_groups=200,
|
|
281
|
+
expected_cells=800,
|
|
282
|
+
expected_episodes=4_800,
|
|
283
|
+
)
|
|
284
|
+
binding_receipt, operator = _validate_persisted_run_identity(root, manifest)
|
|
285
|
+
_validate_operator_identity(operator, manifest)
|
|
286
|
+
runtime_receipts = _validate_external_runtime_receipts(records, manifest)
|
|
287
|
+
return _VerifiedTransferRun(
|
|
288
|
+
root=root,
|
|
289
|
+
manifest=manifest,
|
|
290
|
+
records=records,
|
|
291
|
+
clusters=clusters,
|
|
292
|
+
representative_hash=representative_hash,
|
|
293
|
+
baseline_arm_id=baseline,
|
|
294
|
+
arms_by_family=arms_by_family,
|
|
295
|
+
binding_receipt=binding_receipt,
|
|
296
|
+
runtime_receipts=runtime_receipts,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def _load_and_validate_primary_run(run_dir: str | Path) -> _VerifiedTransferRun:
|
|
301
|
+
root = Path(run_dir).expanduser().resolve()
|
|
302
|
+
paper_run = _load_and_validate_paper_run(root, expected_kind=_COMMON_SUPPORT_KIND)
|
|
303
|
+
_primary_common_support_contract(paper_run.manifest)
|
|
304
|
+
baseline, arms_by_family, representative_hash = _rank_one_arm_contract(paper_run.manifest)
|
|
305
|
+
_validate_primary_grid(paper_run.records, manifest=paper_run.manifest)
|
|
306
|
+
binding_receipt, operator = _validate_persisted_run_identity(root, paper_run.manifest)
|
|
307
|
+
_validate_operator_identity(operator, paper_run.manifest)
|
|
308
|
+
runtime_receipts = _validate_external_runtime_receipts(
|
|
309
|
+
paper_run.records,
|
|
310
|
+
paper_run.manifest,
|
|
311
|
+
)
|
|
312
|
+
return _VerifiedTransferRun(
|
|
313
|
+
root=root,
|
|
314
|
+
manifest=paper_run.manifest,
|
|
315
|
+
records=paper_run.records,
|
|
316
|
+
clusters=paper_run.cluster_ids,
|
|
317
|
+
representative_hash=representative_hash,
|
|
318
|
+
baseline_arm_id=baseline,
|
|
319
|
+
arms_by_family=arms_by_family,
|
|
320
|
+
binding_receipt=binding_receipt,
|
|
321
|
+
runtime_receipts=runtime_receipts,
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def _heldout_manifest_contract(
|
|
326
|
+
manifest: ExperimentManifest,
|
|
327
|
+
) -> tuple[str, Mapping[SemanticFamily, str], str]:
|
|
328
|
+
if (
|
|
329
|
+
manifest.study_id != _STUDY_ID
|
|
330
|
+
or manifest.stage is not ExperimentStage.TRANSFER
|
|
331
|
+
or manifest.estimand_profile_kind is not ProfileKind.CONTROLLED_ADAPTER
|
|
332
|
+
or manifest.driver_entrypoint != _EXTERNAL_DRIVER
|
|
333
|
+
or manifest.model_slots != _TRANSFER_MODEL_SLOTS
|
|
334
|
+
or manifest.seeds != (_SEED,)
|
|
335
|
+
):
|
|
336
|
+
raise ArtifactError(
|
|
337
|
+
"heldout-model transfer manifest differs from the frozen study/stage/model/seed"
|
|
338
|
+
)
|
|
339
|
+
if len(manifest.benchmarks) != 1:
|
|
340
|
+
raise ArtifactError("heldout-model transfer requires exactly one benchmark target")
|
|
341
|
+
target = manifest.benchmarks[0]
|
|
342
|
+
if (
|
|
343
|
+
target.cell_id != _BENCHMARK_ID
|
|
344
|
+
or target.split != _TRANSFER_SPLIT
|
|
345
|
+
or target.external is not True
|
|
346
|
+
or target.source_revision != _STATEBENCH_REVISION
|
|
347
|
+
or target.unit_inventory_env != "AILAB_HELDOUT_MODEL_UNITS"
|
|
348
|
+
or target.unit_inventory_sha256_env != "AILAB_HELDOUT_MODEL_UNITS_SHA256"
|
|
349
|
+
or target.arm_ids
|
|
350
|
+
):
|
|
351
|
+
raise ArtifactError("heldout-model transfer benchmark/source identity is invalid")
|
|
352
|
+
metadata = manifest.metadata
|
|
353
|
+
if (
|
|
354
|
+
metadata.get("model_used_for_tuning") is not False
|
|
355
|
+
or metadata.get("group_relation") != "prespecified_subset_of_common_support_lockbox"
|
|
356
|
+
or metadata.get("requires_atomic_external_replay") is not True
|
|
357
|
+
or metadata.get("confirmatory_claimed_before_execution") is not False
|
|
358
|
+
):
|
|
359
|
+
raise ArtifactError("heldout-model transfer freeze metadata is invalid")
|
|
360
|
+
|
|
361
|
+
census = metadata.get("experiment_census")
|
|
362
|
+
expected_census = {
|
|
363
|
+
"protocol": _CENSUS_PROTOCOL,
|
|
364
|
+
"campaign_kind": _CAMPAIGN_KIND,
|
|
365
|
+
"independent_group_unit": "benchmark_cell:unit_id",
|
|
366
|
+
"independent_group_target": 200,
|
|
367
|
+
"target_group_counts": {
|
|
368
|
+
f"{_BENCHMARK_ID}:{_TRANSFER_SPLIT}": 200,
|
|
369
|
+
},
|
|
370
|
+
"expected_arm_ids": [
|
|
371
|
+
"no_op",
|
|
372
|
+
*(f"{family.value}_representative" for family in _CORE_FAMILIES),
|
|
373
|
+
],
|
|
374
|
+
"expected_model_slots": list(_TRANSFER_MODEL_SLOTS),
|
|
375
|
+
"expected_seeds": [_SEED],
|
|
376
|
+
"expected_plan_cells": 800,
|
|
377
|
+
"expected_agent_episodes": 4_800,
|
|
378
|
+
"episode_formula": ("sum(target_groups * target_arms * models * continuation_seeds)"),
|
|
379
|
+
"seed_semantics": "one_primary_continuation_seed_per_group_model_arm",
|
|
380
|
+
}
|
|
381
|
+
if not isinstance(census, Mapping) or canonical_json(census) != canonical_json(expected_census):
|
|
382
|
+
raise ArtifactError("heldout-model transfer census must be exactly 200x6x4x1=4800")
|
|
383
|
+
prerequisite_names = {item.name for item in manifest.prerequisites}
|
|
384
|
+
if prerequisite_names != _HELDOUT_PREREQUISITES:
|
|
385
|
+
raise ArtifactError("heldout-model transfer prerequisite inventory is invalid")
|
|
386
|
+
return _rank_one_arm_contract(manifest)
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
def _primary_common_support_contract(manifest: ExperimentManifest) -> None:
|
|
390
|
+
if (
|
|
391
|
+
manifest.study_id != "primary.common_support"
|
|
392
|
+
or manifest.stage is not ExperimentStage.CONFIRMATORY
|
|
393
|
+
or manifest.estimand_profile_kind is not ProfileKind.CONTROLLED_ADAPTER
|
|
394
|
+
or manifest.driver_entrypoint != _EXTERNAL_DRIVER
|
|
395
|
+
or manifest.model_slots != _PRIMARY_MODEL_SLOTS
|
|
396
|
+
or manifest.seeds != (_SEED,)
|
|
397
|
+
):
|
|
398
|
+
raise ArtifactError("primary comparison is not the frozen paper common-support run")
|
|
399
|
+
targets = {f"{target.cell_id}:{target.split}": target for target in manifest.benchmarks}
|
|
400
|
+
if set(targets) != set(_PRIMARY_TARGET_COUNTS):
|
|
401
|
+
raise ArtifactError("primary common-support benchmark inventory is invalid")
|
|
402
|
+
for key, target in targets.items():
|
|
403
|
+
if (
|
|
404
|
+
target.external is not True
|
|
405
|
+
or target.source_revision != _PRIMARY_SOURCE_REVISIONS[target.cell_id]
|
|
406
|
+
or target.unit_inventory_env is None
|
|
407
|
+
or target.unit_inventory_sha256_env is None
|
|
408
|
+
or target.arm_ids
|
|
409
|
+
):
|
|
410
|
+
raise ArtifactError(f"primary common-support source identity is invalid for {key}")
|
|
411
|
+
census = manifest.metadata.get("experiment_census")
|
|
412
|
+
if (
|
|
413
|
+
not isinstance(census, Mapping)
|
|
414
|
+
or census.get("protocol") != _CENSUS_PROTOCOL
|
|
415
|
+
or census.get("campaign_kind") != _COMMON_SUPPORT_KIND
|
|
416
|
+
or census.get("independent_group_target") != 526
|
|
417
|
+
or census.get("target_group_counts") != _PRIMARY_TARGET_COUNTS
|
|
418
|
+
or tuple(census.get("expected_model_slots", ())) != _PRIMARY_MODEL_SLOTS
|
|
419
|
+
or tuple(census.get("expected_seeds", ())) != (_SEED,)
|
|
420
|
+
or census.get("expected_plan_cells") != 1_052
|
|
421
|
+
or census.get("expected_agent_episodes") != 6_312
|
|
422
|
+
):
|
|
423
|
+
raise ArtifactError("primary comparison differs from the strict paper census")
|
|
424
|
+
if {item.name for item in manifest.prerequisites} != _PRIMARY_PREREQUISITES:
|
|
425
|
+
raise ArtifactError("primary common-support prerequisite inventory is invalid")
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
def _rank_one_arm_contract(
|
|
429
|
+
manifest: ExperimentManifest,
|
|
430
|
+
) -> tuple[str, Mapping[SemanticFamily, str], str]:
|
|
431
|
+
expected_families = (SemanticFamily.NO_OP, *_CORE_FAMILIES)
|
|
432
|
+
if (
|
|
433
|
+
len(manifest.arms) != 6
|
|
434
|
+
or tuple(arm.family for arm in manifest.arms) != expected_families
|
|
435
|
+
or any(arm.profile_kind is not ProfileKind.CONTROLLED_ADAPTER for arm in manifest.arms)
|
|
436
|
+
):
|
|
437
|
+
raise ArtifactError(
|
|
438
|
+
"transfer/common-support arm roster requires NO_OP plus five core families"
|
|
439
|
+
)
|
|
440
|
+
baseline = manifest.arms[0]
|
|
441
|
+
if (
|
|
442
|
+
baseline.arm_id != "no_op"
|
|
443
|
+
or baseline.release_id != "baseline.no_op"
|
|
444
|
+
or baseline.parameters.get("role") != "paired_baseline"
|
|
445
|
+
):
|
|
446
|
+
raise ArtifactError("transfer/common-support NO_OP arm identity is invalid")
|
|
447
|
+
representative_hash = manifest.metadata.get("representative_manifest_hash")
|
|
448
|
+
if not _is_sha256(representative_hash):
|
|
449
|
+
raise ArtifactError("run lacks a valid representative manifest hash")
|
|
450
|
+
arms_by_family: dict[SemanticFamily, str] = {}
|
|
451
|
+
releases: set[str] = set()
|
|
452
|
+
for arm, family in zip(manifest.arms[1:], _CORE_FAMILIES, strict=True):
|
|
453
|
+
if (
|
|
454
|
+
arm.arm_id != f"{family.value}_representative"
|
|
455
|
+
or arm.family is not family
|
|
456
|
+
or arm.release_id == "baseline.no_op"
|
|
457
|
+
or arm.parameters.get("representative_rank") != 1
|
|
458
|
+
or arm.parameters.get("representative_manifest_hash") != representative_hash
|
|
459
|
+
):
|
|
460
|
+
raise ArtifactError(f"{family.value} arm differs from its frozen rank-1 representative")
|
|
461
|
+
if arm.release_id in releases:
|
|
462
|
+
raise ArtifactError("rank-1 representative release identities are not unique")
|
|
463
|
+
releases.add(arm.release_id)
|
|
464
|
+
arms_by_family[family] = arm.arm_id
|
|
465
|
+
census = manifest.metadata.get("experiment_census")
|
|
466
|
+
if not isinstance(census, Mapping) or tuple(census.get("expected_arm_ids", ())) != tuple(
|
|
467
|
+
arm.arm_id for arm in manifest.arms
|
|
468
|
+
):
|
|
469
|
+
raise ArtifactError("census arm identities differ from the representative roster")
|
|
470
|
+
return baseline.arm_id, arms_by_family, representative_hash
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
def _validate_exact_grid(
|
|
474
|
+
records: Sequence[Mapping[str, Any]],
|
|
475
|
+
*,
|
|
476
|
+
manifest: ExperimentManifest,
|
|
477
|
+
expected_groups: int,
|
|
478
|
+
expected_cells: int,
|
|
479
|
+
expected_episodes: int,
|
|
480
|
+
) -> frozenset[str]:
|
|
481
|
+
if len(records) != expected_cells:
|
|
482
|
+
raise ArtifactError(
|
|
483
|
+
f"heldout-model transfer has {len(records)} verified cells, expected {expected_cells}"
|
|
484
|
+
)
|
|
485
|
+
expected_arms = tuple(arm.arm_id for arm in manifest.arms)
|
|
486
|
+
clusters: set[str] = set()
|
|
487
|
+
replicates_by_group: dict[tuple[str, str], set[tuple[str, int]]] = defaultdict(set)
|
|
488
|
+
episodes = 0
|
|
489
|
+
for record in records:
|
|
490
|
+
cell = record.get("cell")
|
|
491
|
+
if not isinstance(cell, Mapping):
|
|
492
|
+
raise ArtifactError("heldout-model transfer record lacks an experiment cell")
|
|
493
|
+
if (
|
|
494
|
+
_required_record_text(cell, "benchmark_id", label="experiment cell") != _BENCHMARK_ID
|
|
495
|
+
or _required_record_text(cell, "split", label="experiment cell") != _TRANSFER_SPLIT
|
|
496
|
+
or _required_record_text(cell, "model_slot", label="experiment cell")
|
|
497
|
+
not in _TRANSFER_MODEL_SLOTS
|
|
498
|
+
or cell.get("seed") != _SEED
|
|
499
|
+
or tuple(cell.get("arm_ids", ())) != expected_arms
|
|
500
|
+
):
|
|
501
|
+
raise ArtifactError(
|
|
502
|
+
"heldout-model transfer cell differs from its benchmark/model/seed/arm grid"
|
|
503
|
+
)
|
|
504
|
+
model_slot = _required_record_text(cell, "model_slot", label="experiment cell")
|
|
505
|
+
cluster = f"{_cluster_id(cell)}::{model_slot}::{_SEED}"
|
|
506
|
+
if cluster in clusters:
|
|
507
|
+
raise ArtifactError("heldout-model transfer duplicates a group/model replicate")
|
|
508
|
+
clusters.add(cluster)
|
|
509
|
+
group = (
|
|
510
|
+
_required_record_text(cell, "benchmark_id", label="experiment cell"),
|
|
511
|
+
_required_record_text(cell, "unit_id", label="experiment cell"),
|
|
512
|
+
)
|
|
513
|
+
replicate = (
|
|
514
|
+
_required_record_text(cell, "model_slot", label="experiment cell"),
|
|
515
|
+
int(cell["seed"]),
|
|
516
|
+
)
|
|
517
|
+
if replicate in replicates_by_group[group]:
|
|
518
|
+
raise ArtifactError("heldout-model transfer duplicates a group/model replicate")
|
|
519
|
+
replicates_by_group[group].add(replicate)
|
|
520
|
+
episodes += len(expected_arms)
|
|
521
|
+
expected_replicates = {(model_slot, _SEED) for model_slot in _TRANSFER_MODEL_SLOTS}
|
|
522
|
+
if (
|
|
523
|
+
len(replicates_by_group) != expected_groups
|
|
524
|
+
or any(replicates != expected_replicates for replicates in replicates_by_group.values())
|
|
525
|
+
or episodes != expected_episodes
|
|
526
|
+
):
|
|
527
|
+
raise ArtifactError(
|
|
528
|
+
"heldout-model transfer must contain 200 groups, four model replicates, "
|
|
529
|
+
"and 4800 arm episodes"
|
|
530
|
+
)
|
|
531
|
+
return frozenset(clusters)
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
def _validate_primary_grid(
|
|
535
|
+
records: Sequence[Mapping[str, Any]],
|
|
536
|
+
*,
|
|
537
|
+
manifest: ExperimentManifest,
|
|
538
|
+
) -> None:
|
|
539
|
+
if len(records) != 1_052:
|
|
540
|
+
raise ArtifactError("primary common-support comparison requires exactly 1052 cells")
|
|
541
|
+
expected_arms = tuple(arm.arm_id for arm in manifest.arms)
|
|
542
|
+
groups_by_target: dict[str, dict[str, set[tuple[str, int]]]] = defaultdict(
|
|
543
|
+
lambda: defaultdict(set)
|
|
544
|
+
)
|
|
545
|
+
for record in records:
|
|
546
|
+
cell = record.get("cell")
|
|
547
|
+
if not isinstance(cell, Mapping):
|
|
548
|
+
raise ArtifactError("primary common-support record lacks an experiment cell")
|
|
549
|
+
benchmark = _required_record_text(
|
|
550
|
+
cell,
|
|
551
|
+
"benchmark_id",
|
|
552
|
+
label="experiment cell",
|
|
553
|
+
)
|
|
554
|
+
split = _required_record_text(cell, "split", label="experiment cell")
|
|
555
|
+
unit_id = _required_record_text(cell, "unit_id", label="experiment cell")
|
|
556
|
+
model_slot = _required_record_text(
|
|
557
|
+
cell,
|
|
558
|
+
"model_slot",
|
|
559
|
+
label="experiment cell",
|
|
560
|
+
)
|
|
561
|
+
seed = cell.get("seed")
|
|
562
|
+
key = f"{benchmark}:{split}"
|
|
563
|
+
if (
|
|
564
|
+
key not in _PRIMARY_TARGET_COUNTS
|
|
565
|
+
or model_slot not in _PRIMARY_MODEL_SLOTS
|
|
566
|
+
or seed != _SEED
|
|
567
|
+
or tuple(cell.get("arm_ids", ())) != expected_arms
|
|
568
|
+
):
|
|
569
|
+
raise ArtifactError(
|
|
570
|
+
"primary common-support cell differs from its target/model/seed/arm grid"
|
|
571
|
+
)
|
|
572
|
+
replicate = (model_slot, int(seed))
|
|
573
|
+
if replicate in groups_by_target[key][unit_id]:
|
|
574
|
+
raise ArtifactError("primary common-support duplicates a group replicate")
|
|
575
|
+
groups_by_target[key][unit_id].add(replicate)
|
|
576
|
+
expected_replicates = {(model_slot, _SEED) for model_slot in _PRIMARY_MODEL_SLOTS}
|
|
577
|
+
if set(groups_by_target) != set(_PRIMARY_TARGET_COUNTS):
|
|
578
|
+
raise ArtifactError("primary common-support records omit a frozen target")
|
|
579
|
+
for key, expected_groups in _PRIMARY_TARGET_COUNTS.items():
|
|
580
|
+
groups = groups_by_target[key]
|
|
581
|
+
if len(groups) != expected_groups or any(
|
|
582
|
+
replicates != expected_replicates for replicates in groups.values()
|
|
583
|
+
):
|
|
584
|
+
raise ArtifactError(f"primary common-support record census is invalid for {key}")
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
def _validate_persisted_run_identity(
|
|
588
|
+
root: Path,
|
|
589
|
+
manifest: ExperimentManifest,
|
|
590
|
+
) -> tuple[Mapping[str, Any], Mapping[str, Any]]:
|
|
591
|
+
identity = _load_run_identity(root)
|
|
592
|
+
fingerprint = identity.get("driver_fingerprint")
|
|
593
|
+
if (
|
|
594
|
+
not isinstance(fingerprint, Mapping)
|
|
595
|
+
or set(fingerprint)
|
|
596
|
+
!= {
|
|
597
|
+
"schema_version",
|
|
598
|
+
"guard",
|
|
599
|
+
"operator_driver_fingerprint",
|
|
600
|
+
"frozen_binding_receipt",
|
|
601
|
+
"frozen_binding_receipt_hash",
|
|
602
|
+
"parity_contract",
|
|
603
|
+
}
|
|
604
|
+
or fingerprint.get("schema_version") != 1
|
|
605
|
+
or fingerprint.get("guard") != _GUARD_ID
|
|
606
|
+
or fingerprint.get("parity_contract") != {}
|
|
607
|
+
):
|
|
608
|
+
raise ArtifactError("run lacks the frozen binding driver-guard identity")
|
|
609
|
+
raw_receipt = fingerprint.get("frozen_binding_receipt")
|
|
610
|
+
receipt = _parse_binding_receipt(raw_receipt)
|
|
611
|
+
if (
|
|
612
|
+
receipt.manifest_hash != manifest.manifest_hash
|
|
613
|
+
or fingerprint.get("frozen_binding_receipt_hash") != receipt.receipt_hash
|
|
614
|
+
):
|
|
615
|
+
raise ArtifactError("frozen binding receipt belongs to another manifest")
|
|
616
|
+
declared = {(item.kind.value, item.name) for item in manifest.prerequisites}
|
|
617
|
+
observed = {(item.kind, item.name) for item in receipt.bindings}
|
|
618
|
+
if observed != declared:
|
|
619
|
+
raise ArtifactError("frozen binding receipt differs from the manifest prerequisites")
|
|
620
|
+
binding_by_name = {item.name: item for item in receipt.bindings}
|
|
621
|
+
for prerequisite in manifest.prerequisites:
|
|
622
|
+
if prerequisite.kind is not PrerequisiteKind.FILE_ENV:
|
|
623
|
+
continue
|
|
624
|
+
entry = binding_by_name[prerequisite.name]
|
|
625
|
+
_file_binding_sha(entry, label=prerequisite.name)
|
|
626
|
+
if entry.identity.get("checksum_environment") != prerequisite.sha256_env:
|
|
627
|
+
raise ArtifactError(
|
|
628
|
+
f"{prerequisite.name} binding differs from its checksum prerequisite"
|
|
629
|
+
)
|
|
630
|
+
representative = binding_by_name.get("AILAB_REPRESENTATIVE_MANIFEST")
|
|
631
|
+
if representative is None or representative.kind != PrerequisiteKind.FILE_ENV.value:
|
|
632
|
+
raise ArtifactError("run lacks the frozen representative file binding")
|
|
633
|
+
representative_file_sha = _file_binding_sha(
|
|
634
|
+
representative,
|
|
635
|
+
label="representative manifest",
|
|
636
|
+
)
|
|
637
|
+
freeze_name = (
|
|
638
|
+
"AILAB_HELDOUT_MODEL_FREEZE_RECEIPT"
|
|
639
|
+
if manifest.stage is ExperimentStage.TRANSFER
|
|
640
|
+
else "AILAB_COMMON_SUPPORT_FREEZE_RECEIPT"
|
|
641
|
+
)
|
|
642
|
+
freeze = binding_by_name.get(freeze_name)
|
|
643
|
+
if freeze is None:
|
|
644
|
+
raise ArtifactError(f"run lacks required source/freeze receipt {freeze_name}")
|
|
645
|
+
freeze_file_sha = _file_binding_sha(freeze, label=freeze_name)
|
|
646
|
+
driver_config = binding_by_name.get("AILAB_EXTERNAL_ARENA_DRIVER_CONFIG")
|
|
647
|
+
if driver_config is None:
|
|
648
|
+
raise ArtifactError("run lacks the frozen external driver configuration")
|
|
649
|
+
driver_config_sha = _file_binding_sha(
|
|
650
|
+
driver_config,
|
|
651
|
+
label="external driver configuration",
|
|
652
|
+
)
|
|
653
|
+
_validate_checkout_bindings(binding_by_name, manifest)
|
|
654
|
+
operator = fingerprint.get("operator_driver_fingerprint")
|
|
655
|
+
if not isinstance(operator, Mapping):
|
|
656
|
+
raise ArtifactError("run lacks an operator driver fingerprint")
|
|
657
|
+
if operator.get("config_sha256") != driver_config_sha:
|
|
658
|
+
raise ArtifactError(
|
|
659
|
+
"operator driver identity differs from its frozen configuration binding"
|
|
660
|
+
)
|
|
661
|
+
return (
|
|
662
|
+
{
|
|
663
|
+
"frozen_binding_receipt_hash": receipt.receipt_hash,
|
|
664
|
+
"representative_binding": {
|
|
665
|
+
"representative_manifest_hash": manifest.metadata.get(
|
|
666
|
+
"representative_manifest_hash"
|
|
667
|
+
),
|
|
668
|
+
"representative_file_sha256": representative_file_sha,
|
|
669
|
+
"frozen_binding_receipt_hash": receipt.receipt_hash,
|
|
670
|
+
"external_driver_config_sha256": driver_config_sha,
|
|
671
|
+
"source_freeze_receipt_name": freeze_name,
|
|
672
|
+
"source_freeze_receipt_sha256": freeze_file_sha,
|
|
673
|
+
"binding_verified": True,
|
|
674
|
+
},
|
|
675
|
+
},
|
|
676
|
+
operator,
|
|
677
|
+
)
|
|
678
|
+
|
|
679
|
+
|
|
680
|
+
def _parse_binding_receipt(value: Any) -> FrozenBindingReceipt:
|
|
681
|
+
if (
|
|
682
|
+
not isinstance(value, Mapping)
|
|
683
|
+
or set(value)
|
|
684
|
+
!= {
|
|
685
|
+
"schema_version",
|
|
686
|
+
"manifest_hash",
|
|
687
|
+
"bindings",
|
|
688
|
+
"receipt_hash",
|
|
689
|
+
}
|
|
690
|
+
or not isinstance(value.get("bindings"), Sequence)
|
|
691
|
+
or isinstance(value.get("bindings"), str | bytes)
|
|
692
|
+
):
|
|
693
|
+
raise ArtifactError("frozen binding receipt schema is invalid")
|
|
694
|
+
entries: list[FrozenBindingEntry] = []
|
|
695
|
+
try:
|
|
696
|
+
for raw in value["bindings"]:
|
|
697
|
+
if not isinstance(raw, Mapping) or set(raw) != {
|
|
698
|
+
"schema_version",
|
|
699
|
+
"name",
|
|
700
|
+
"kind",
|
|
701
|
+
"identity",
|
|
702
|
+
"binding_hash",
|
|
703
|
+
}:
|
|
704
|
+
raise ArtifactError("frozen binding entry schema is invalid")
|
|
705
|
+
entry = FrozenBindingEntry(
|
|
706
|
+
schema_version=raw["schema_version"],
|
|
707
|
+
name=raw["name"],
|
|
708
|
+
kind=raw["kind"],
|
|
709
|
+
identity=raw["identity"],
|
|
710
|
+
)
|
|
711
|
+
if canonical_json(raw) != canonical_json(entry.to_dict()):
|
|
712
|
+
raise ArtifactError("frozen binding entry hash differs from its content")
|
|
713
|
+
entries.append(entry)
|
|
714
|
+
receipt = FrozenBindingReceipt(
|
|
715
|
+
schema_version=value["schema_version"],
|
|
716
|
+
manifest_hash=value["manifest_hash"],
|
|
717
|
+
bindings=tuple(entries),
|
|
718
|
+
)
|
|
719
|
+
except (TypeError, ValueError, ValidationError) as exc:
|
|
720
|
+
raise ArtifactError("frozen binding receipt is malformed") from exc
|
|
721
|
+
if canonical_json(value) != canonical_json(receipt.to_dict()):
|
|
722
|
+
raise ArtifactError("frozen binding receipt hash differs from its content")
|
|
723
|
+
return receipt
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
def _file_binding_sha(entry: FrozenBindingEntry, *, label: str) -> str:
|
|
727
|
+
identity = entry.identity
|
|
728
|
+
digest = identity.get("content_sha256")
|
|
729
|
+
if identity.get("identity_mode") != "file_sha256" or not _is_sha256(digest):
|
|
730
|
+
raise ArtifactError(f"{label} binding lacks a file SHA-256 receipt")
|
|
731
|
+
return str(digest)
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
def _validate_checkout_bindings(
|
|
735
|
+
bindings: Mapping[str, FrozenBindingEntry],
|
|
736
|
+
manifest: ExperimentManifest,
|
|
737
|
+
) -> None:
|
|
738
|
+
expected = manifest.metadata.get("checkout_expected_revisions")
|
|
739
|
+
if not isinstance(expected, Mapping):
|
|
740
|
+
raise ArtifactError("manifest checkout source locks are invalid")
|
|
741
|
+
for name, revision in expected.items():
|
|
742
|
+
entry = bindings.get(str(name))
|
|
743
|
+
identity = entry.identity if entry is not None else None
|
|
744
|
+
if (
|
|
745
|
+
entry is None
|
|
746
|
+
or entry.kind != PrerequisiteKind.DIRECTORY_ENV.value
|
|
747
|
+
or not isinstance(identity, Mapping)
|
|
748
|
+
or identity.get("identity_mode") != "clean_git_checkout"
|
|
749
|
+
or identity.get("git_head") != revision
|
|
750
|
+
or identity.get("expected_revision") != revision
|
|
751
|
+
or identity.get("git_clean") is not True
|
|
752
|
+
):
|
|
753
|
+
raise ArtifactError(f"source checkout receipt is invalid for {name}")
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
def _validate_operator_identity(
|
|
757
|
+
operator: Mapping[str, Any],
|
|
758
|
+
manifest: ExperimentManifest,
|
|
759
|
+
) -> None:
|
|
760
|
+
if (
|
|
761
|
+
operator.get("implementation_id") != _EXTERNAL_DRIVER_IMPLEMENTATION
|
|
762
|
+
or operator.get("schema_version") != 3
|
|
763
|
+
or operator.get("baseline_arm_id") != "no_op"
|
|
764
|
+
or not _is_sha256(operator.get("driver_revision_sha256"))
|
|
765
|
+
or not _is_sha256(operator.get("config_sha256"))
|
|
766
|
+
):
|
|
767
|
+
raise ArtifactError("run operator is not the frozen atomic external-arena driver")
|
|
768
|
+
raw_arms = operator.get("arms")
|
|
769
|
+
if not isinstance(raw_arms, Mapping) or set(raw_arms) != {arm.arm_id for arm in manifest.arms}:
|
|
770
|
+
raise ArtifactError("operator arm identities differ from the manifest")
|
|
771
|
+
for arm in manifest.arms:
|
|
772
|
+
identity = raw_arms.get(arm.arm_id)
|
|
773
|
+
if (
|
|
774
|
+
not isinstance(identity, Mapping)
|
|
775
|
+
or identity.get("release_id") != arm.release_id
|
|
776
|
+
or identity.get("family") != arm.family.value
|
|
777
|
+
or identity.get("profile_kind") != arm.profile_kind.value
|
|
778
|
+
or identity.get("arm_kind") != arm.arm_kind.value
|
|
779
|
+
):
|
|
780
|
+
raise ArtifactError(f"operator arm identity is mixed or invalid for {arm.arm_id}")
|
|
781
|
+
raw_targets = operator.get("benchmark_targets")
|
|
782
|
+
expected_targets = {
|
|
783
|
+
f"{target.cell_id}:{target.split}": target for target in manifest.benchmarks
|
|
784
|
+
}
|
|
785
|
+
if not isinstance(raw_targets, Mapping) or set(raw_targets) != set(expected_targets):
|
|
786
|
+
raise ArtifactError("operator source targets differ from the manifest")
|
|
787
|
+
for key, target in expected_targets.items():
|
|
788
|
+
identity = raw_targets.get(key)
|
|
789
|
+
if (
|
|
790
|
+
not isinstance(identity, Mapping)
|
|
791
|
+
or identity.get("benchmark_id") != target.cell_id
|
|
792
|
+
or identity.get("split") != target.split
|
|
793
|
+
or identity.get("source_revision") != target.source_revision
|
|
794
|
+
):
|
|
795
|
+
raise ArtifactError(f"operator source identity is invalid for {key}")
|
|
796
|
+
policy_bindings = operator.get("resolved_policy_bindings")
|
|
797
|
+
if not isinstance(policy_bindings, Mapping) or policy_bindings:
|
|
798
|
+
raise ArtifactError("rank-1 release run unexpectedly contains policy bindings")
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
def _validate_external_runtime_receipts(
|
|
802
|
+
records: Sequence[Mapping[str, Any]],
|
|
803
|
+
manifest: ExperimentManifest,
|
|
804
|
+
) -> Mapping[str, Any]:
|
|
805
|
+
expected_arms = tuple(arm.arm_id for arm in manifest.arms)
|
|
806
|
+
baseline = expected_arms[0]
|
|
807
|
+
treatment_arms = expected_arms[1:]
|
|
808
|
+
targets = {(target.cell_id, target.split): target for target in manifest.benchmarks}
|
|
809
|
+
dependency_by_stratum: dict[tuple[str, str], Mapping[str, str]] = {}
|
|
810
|
+
source_revisions: dict[str, str] = {}
|
|
811
|
+
atomic_pair_count = 0
|
|
812
|
+
checkpoint_count = 0
|
|
813
|
+
for record in records:
|
|
814
|
+
cell = record.get("cell")
|
|
815
|
+
result = record.get("result")
|
|
816
|
+
payload = result.get("payload") if isinstance(result, Mapping) else None
|
|
817
|
+
if not isinstance(cell, Mapping) or not isinstance(payload, Mapping):
|
|
818
|
+
raise ArtifactError("external result lacks a cell payload")
|
|
819
|
+
benchmark = _required_record_text(cell, "benchmark_id", label="experiment cell")
|
|
820
|
+
split = _required_record_text(cell, "split", label="experiment cell")
|
|
821
|
+
unit_id = _required_record_text(cell, "unit_id", label="experiment cell")
|
|
822
|
+
model_slot = _required_record_text(cell, "model_slot", label="experiment cell")
|
|
823
|
+
target = targets.get((benchmark, split))
|
|
824
|
+
if target is None:
|
|
825
|
+
raise ArtifactError("external result references another benchmark source")
|
|
826
|
+
if (
|
|
827
|
+
payload.get("benchmark_id") != benchmark
|
|
828
|
+
or payload.get("split") != split
|
|
829
|
+
or payload.get("unit_id") != unit_id
|
|
830
|
+
or payload.get("model_slot") != model_slot
|
|
831
|
+
or payload.get("seed") != cell.get("seed")
|
|
832
|
+
or payload.get("baseline_arm_id") != baseline
|
|
833
|
+
or tuple(payload.get("planned_arm_ids", ())) != expected_arms
|
|
834
|
+
or payload.get("target_source_revision") != target.source_revision
|
|
835
|
+
or payload.get("atomic_replay_contract") != ATOMIC_EXTERNAL_PAIR_CONTRACT
|
|
836
|
+
):
|
|
837
|
+
raise ArtifactError("external result identity differs from its frozen cell/source")
|
|
838
|
+
dependencies = _dependency_receipt(payload)
|
|
839
|
+
stratum = (benchmark, model_slot)
|
|
840
|
+
previous = dependency_by_stratum.get(stratum)
|
|
841
|
+
if previous is None:
|
|
842
|
+
dependency_by_stratum[stratum] = dependencies
|
|
843
|
+
elif previous != dependencies:
|
|
844
|
+
raise ArtifactError(
|
|
845
|
+
"runtime dependency identity drifts across groups in one model/source stratum"
|
|
846
|
+
)
|
|
847
|
+
checkpoint = _checkpoint_source_receipt(
|
|
848
|
+
payload,
|
|
849
|
+
source_revision=str(target.source_revision),
|
|
850
|
+
)
|
|
851
|
+
checkpoint_count += 1
|
|
852
|
+
atomic_pair_count += _validate_atomic_pair_receipts(
|
|
853
|
+
payload,
|
|
854
|
+
benchmark=benchmark,
|
|
855
|
+
seed=int(cell["seed"]),
|
|
856
|
+
source_revision=str(target.source_revision),
|
|
857
|
+
baseline_arm_id=baseline,
|
|
858
|
+
treatment_arm_ids=treatment_arms,
|
|
859
|
+
dependencies=dependencies,
|
|
860
|
+
checkpoint=checkpoint,
|
|
861
|
+
)
|
|
862
|
+
source_revisions[benchmark] = str(target.source_revision)
|
|
863
|
+
return {
|
|
864
|
+
"checkpoint_source_receipts": checkpoint_count,
|
|
865
|
+
"atomic_pair_receipts": atomic_pair_count,
|
|
866
|
+
"dependency_receipt_strata": {
|
|
867
|
+
f"{benchmark}::{model}": dict(dependencies)
|
|
868
|
+
for (benchmark, model), dependencies in sorted(dependency_by_stratum.items())
|
|
869
|
+
},
|
|
870
|
+
"source_revisions": dict(sorted(source_revisions.items())),
|
|
871
|
+
"dependency_and_source_receipts_verified": True,
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
def _dependency_receipt(payload: Mapping[str, Any]) -> Mapping[str, str]:
|
|
876
|
+
raw = payload.get("observed_dependency_hashes")
|
|
877
|
+
if not isinstance(raw, Mapping) or set(raw) != _DEPENDENCY_SLOTS:
|
|
878
|
+
raise ArtifactError("external result lacks the exact shared dependency receipt slots")
|
|
879
|
+
parsed: dict[str, str] = {}
|
|
880
|
+
for slot, digest in raw.items():
|
|
881
|
+
if not isinstance(slot, str) or not _is_sha256(digest):
|
|
882
|
+
raise ArtifactError("external dependency receipts must be SHA-256 mappings")
|
|
883
|
+
parsed[slot] = str(digest)
|
|
884
|
+
not_applicable = payload.get("not_applicable_dependency_slots")
|
|
885
|
+
if (
|
|
886
|
+
not isinstance(not_applicable, Sequence)
|
|
887
|
+
or isinstance(not_applicable, str | bytes)
|
|
888
|
+
or len(not_applicable) != len(set(not_applicable))
|
|
889
|
+
or any(slot not in _DEPENDENCY_SLOTS for slot in not_applicable)
|
|
890
|
+
):
|
|
891
|
+
raise ArtifactError("not-applicable dependency receipt is malformed")
|
|
892
|
+
expected_not_applicable = tuple(
|
|
893
|
+
sorted(
|
|
894
|
+
slot
|
|
895
|
+
for slot, digest in parsed.items()
|
|
896
|
+
if digest
|
|
897
|
+
== content_hash(
|
|
898
|
+
{
|
|
899
|
+
"agentinputlab_dependency": "not_applicable",
|
|
900
|
+
"schema_version": 1,
|
|
901
|
+
"slot": slot,
|
|
902
|
+
}
|
|
903
|
+
)
|
|
904
|
+
)
|
|
905
|
+
)
|
|
906
|
+
if tuple(not_applicable) != expected_not_applicable:
|
|
907
|
+
raise ArtifactError("not-applicable dependency receipt differs from observed hashes")
|
|
908
|
+
return parsed
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
def _checkpoint_source_receipt(
|
|
912
|
+
payload: Mapping[str, Any],
|
|
913
|
+
*,
|
|
914
|
+
source_revision: str,
|
|
915
|
+
) -> Mapping[str, Any]:
|
|
916
|
+
checkpoint = payload.get("checkpoint_identity")
|
|
917
|
+
required = {
|
|
918
|
+
"identity_sha256",
|
|
919
|
+
"group_sha256",
|
|
920
|
+
"visible_state_sha256",
|
|
921
|
+
"origin_state_sha256",
|
|
922
|
+
"replay_identity_sha256",
|
|
923
|
+
"source_revision",
|
|
924
|
+
}
|
|
925
|
+
if not isinstance(checkpoint, Mapping) or set(checkpoint) != required:
|
|
926
|
+
raise ArtifactError("external result lacks a checkpoint source receipt")
|
|
927
|
+
if checkpoint.get("source_revision") != source_revision or any(
|
|
928
|
+
not _is_sha256(checkpoint.get(key)) for key in required if key != "source_revision"
|
|
929
|
+
):
|
|
930
|
+
raise ArtifactError("checkpoint source receipt is malformed or source-mixed")
|
|
931
|
+
return checkpoint
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
def _validate_atomic_pair_receipts(
|
|
935
|
+
payload: Mapping[str, Any],
|
|
936
|
+
*,
|
|
937
|
+
benchmark: str,
|
|
938
|
+
seed: int,
|
|
939
|
+
source_revision: str,
|
|
940
|
+
baseline_arm_id: str,
|
|
941
|
+
treatment_arm_ids: Sequence[str],
|
|
942
|
+
dependencies: Mapping[str, str],
|
|
943
|
+
checkpoint: Mapping[str, Any],
|
|
944
|
+
) -> int:
|
|
945
|
+
raw_pairs = payload.get("atomic_pairs")
|
|
946
|
+
if (
|
|
947
|
+
not isinstance(raw_pairs, Sequence)
|
|
948
|
+
or isinstance(raw_pairs, str | bytes)
|
|
949
|
+
or len(raw_pairs) != len(treatment_arm_ids)
|
|
950
|
+
):
|
|
951
|
+
raise ArtifactError("external result lacks the complete atomic replay receipts")
|
|
952
|
+
baseline_consistency = payload.get("baseline_consistency_sha256")
|
|
953
|
+
if not _is_sha256(baseline_consistency):
|
|
954
|
+
raise ArtifactError("external result lacks the NO_OP consistency receipt")
|
|
955
|
+
observed_treatments: set[str] = set()
|
|
956
|
+
checkpoint_ids: set[str] = set()
|
|
957
|
+
for raw_pair in raw_pairs:
|
|
958
|
+
if not isinstance(raw_pair, Mapping):
|
|
959
|
+
raise ArtifactError("atomic replay receipt row must be an object")
|
|
960
|
+
treatment_id = raw_pair.get("treatment_arm_id")
|
|
961
|
+
if (
|
|
962
|
+
treatment_id not in treatment_arm_ids
|
|
963
|
+
or treatment_id in observed_treatments
|
|
964
|
+
or not _is_sha256(raw_pair.get("request_sha256"))
|
|
965
|
+
or raw_pair.get("baseline_consistency_sha256") != baseline_consistency
|
|
966
|
+
):
|
|
967
|
+
raise ArtifactError("atomic replay receipt arm/request identity is invalid")
|
|
968
|
+
observed_treatments.add(str(treatment_id))
|
|
969
|
+
raw_receipt = raw_pair.get("receipt")
|
|
970
|
+
receipt = _parse_atomic_receipt(raw_receipt)
|
|
971
|
+
if (
|
|
972
|
+
receipt.benchmark_id != benchmark
|
|
973
|
+
or receipt.source_revision != source_revision
|
|
974
|
+
or receipt.seed != seed
|
|
975
|
+
or receipt.locked_dependency_hashes != dependencies
|
|
976
|
+
or receipt.origin_state_hash != checkpoint["origin_state_sha256"]
|
|
977
|
+
or receipt.replay_identity != checkpoint["replay_identity_sha256"]
|
|
978
|
+
or raw_pair.get("receipt_sha256") != content_hash(receipt)
|
|
979
|
+
):
|
|
980
|
+
raise ArtifactError("atomic replay source/dependency receipt is mixed")
|
|
981
|
+
arm_roles = {(arm.role, arm.arm_id) for arm in receipt.arms}
|
|
982
|
+
if arm_roles != {
|
|
983
|
+
("baseline", baseline_arm_id),
|
|
984
|
+
("treatment", treatment_id),
|
|
985
|
+
}:
|
|
986
|
+
raise ArtifactError("atomic replay receipt covers another arm pair")
|
|
987
|
+
checkpoint_ids.add(receipt.checkpoint_id)
|
|
988
|
+
resource_hashes = raw_pair.get("resource_receipt_sha256s")
|
|
989
|
+
if (
|
|
990
|
+
not isinstance(resource_hashes, Sequence)
|
|
991
|
+
or isinstance(resource_hashes, str | bytes)
|
|
992
|
+
or any(not _is_sha256(value) for value in resource_hashes)
|
|
993
|
+
):
|
|
994
|
+
raise ArtifactError("atomic replay resource-receipt hashes are invalid")
|
|
995
|
+
if observed_treatments != set(treatment_arm_ids) or len(checkpoint_ids) != 1:
|
|
996
|
+
raise ArtifactError("atomic replay receipts do not form one complete checkpoint block")
|
|
997
|
+
return len(raw_pairs)
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
def _parse_atomic_receipt(value: Any) -> AtomicReplayReceipt:
|
|
1001
|
+
if not isinstance(value, Mapping):
|
|
1002
|
+
raise ArtifactError("atomic replay receipt is missing")
|
|
1003
|
+
raw_arms = value.get("arms")
|
|
1004
|
+
if not isinstance(raw_arms, Sequence) or isinstance(raw_arms, str | bytes):
|
|
1005
|
+
raise ArtifactError("atomic replay receipt lacks arm receipts")
|
|
1006
|
+
try:
|
|
1007
|
+
arms = tuple(
|
|
1008
|
+
AtomicReplayArmReceipt(
|
|
1009
|
+
role=raw["role"],
|
|
1010
|
+
arm_id=raw["arm_id"],
|
|
1011
|
+
origin_state_hash=raw["origin_state_hash"],
|
|
1012
|
+
replay_identity=raw["replay_identity"],
|
|
1013
|
+
seed=raw["seed"],
|
|
1014
|
+
locked_dependency_hashes=raw["locked_dependency_hashes"],
|
|
1015
|
+
runtime_instance_id=raw["runtime_instance_id"],
|
|
1016
|
+
completed=raw["completed"],
|
|
1017
|
+
)
|
|
1018
|
+
for raw in raw_arms
|
|
1019
|
+
if isinstance(raw, Mapping)
|
|
1020
|
+
)
|
|
1021
|
+
if len(arms) != len(raw_arms):
|
|
1022
|
+
raise ArtifactError("atomic replay arm receipt is malformed")
|
|
1023
|
+
receipt = AtomicReplayReceipt(
|
|
1024
|
+
benchmark_id=value["benchmark_id"],
|
|
1025
|
+
checkpoint_id=value["checkpoint_id"],
|
|
1026
|
+
source_revision=value["source_revision"],
|
|
1027
|
+
bridge_id=value["bridge_id"],
|
|
1028
|
+
bridge_revision=value["bridge_revision"],
|
|
1029
|
+
scorer_id=value["scorer_id"],
|
|
1030
|
+
scorer_revision=value["scorer_revision"],
|
|
1031
|
+
origin_state_hash=value["origin_state_hash"],
|
|
1032
|
+
replay_identity=value["replay_identity"],
|
|
1033
|
+
seed=value["seed"],
|
|
1034
|
+
locked_dependency_hashes=value["locked_dependency_hashes"],
|
|
1035
|
+
arms=arms,
|
|
1036
|
+
)
|
|
1037
|
+
except (KeyError, TypeError, ValueError, ValidationError) as exc:
|
|
1038
|
+
raise ArtifactError("atomic replay receipt is malformed") from exc
|
|
1039
|
+
if canonical_json(value) != canonical_json(to_jsonable(receipt)):
|
|
1040
|
+
raise ArtifactError("atomic replay receipt schema contains missing or extra fields")
|
|
1041
|
+
return receipt
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
def _collapsed_family_rows(
|
|
1045
|
+
records: Sequence[Mapping[str, Any]],
|
|
1046
|
+
*,
|
|
1047
|
+
manifest: ExperimentManifest,
|
|
1048
|
+
baseline_arm_id: str,
|
|
1049
|
+
arms_by_family: Mapping[SemanticFamily, str],
|
|
1050
|
+
metric: str,
|
|
1051
|
+
algorithm_failure_value: float | None,
|
|
1052
|
+
) -> Mapping[tuple[str, str], Mapping[str, Any]]:
|
|
1053
|
+
grouped: dict[tuple[str, str], list[Mapping[str, Any]]] = defaultdict(list)
|
|
1054
|
+
for record in records:
|
|
1055
|
+
cell = record["cell"]
|
|
1056
|
+
values = _arm_metrics(
|
|
1057
|
+
record,
|
|
1058
|
+
metric=metric,
|
|
1059
|
+
algorithm_failure_value=algorithm_failure_value,
|
|
1060
|
+
)
|
|
1061
|
+
if values is None: # pragma: no cover - verified all-succeeded invariant
|
|
1062
|
+
raise ArtifactError("transfer record is not a completed cell")
|
|
1063
|
+
benchmark = _required_record_text(cell, "benchmark_id", label="experiment cell")
|
|
1064
|
+
unit_id = _required_record_text(cell, "unit_id", label="experiment cell")
|
|
1065
|
+
grouped[(benchmark, unit_id)].append(
|
|
1066
|
+
{
|
|
1067
|
+
"cluster_id": _cluster_id(cell),
|
|
1068
|
+
"model_slot": _required_record_text(
|
|
1069
|
+
cell,
|
|
1070
|
+
"model_slot",
|
|
1071
|
+
label="experiment cell",
|
|
1072
|
+
),
|
|
1073
|
+
"baseline": values[baseline_arm_id],
|
|
1074
|
+
**{family.value: values[arm_id] for family, arm_id in arms_by_family.items()},
|
|
1075
|
+
}
|
|
1076
|
+
)
|
|
1077
|
+
collapsed: dict[tuple[str, str], Mapping[str, Any]] = {}
|
|
1078
|
+
for key, rows in sorted(grouped.items()):
|
|
1079
|
+
model_slots = tuple(sorted(str(row["model_slot"]) for row in rows))
|
|
1080
|
+
if len(model_slots) != len(set(model_slots)):
|
|
1081
|
+
raise ArtifactError("family analysis duplicates a model replicate within a group")
|
|
1082
|
+
collapsed[key] = {
|
|
1083
|
+
"underlying_group": f"{key[0]}::{key[1]}",
|
|
1084
|
+
"cluster_ids": tuple(str(row["cluster_id"]) for row in rows),
|
|
1085
|
+
"model_slots": model_slots,
|
|
1086
|
+
"baseline": fmean(float(row["baseline"]) for row in rows),
|
|
1087
|
+
**{
|
|
1088
|
+
family.value: fmean(float(row[family.value]) for row in rows)
|
|
1089
|
+
for family in _CORE_FAMILIES
|
|
1090
|
+
},
|
|
1091
|
+
}
|
|
1092
|
+
return collapsed
|
|
1093
|
+
|
|
1094
|
+
|
|
1095
|
+
def _family_summaries(
|
|
1096
|
+
rows: Mapping[tuple[str, str], Mapping[str, Any]],
|
|
1097
|
+
*,
|
|
1098
|
+
arms_by_family: Mapping[SemanticFamily, str],
|
|
1099
|
+
manifest: ExperimentManifest,
|
|
1100
|
+
bootstrap_samples: int,
|
|
1101
|
+
rng: random.Random,
|
|
1102
|
+
) -> Mapping[str, Any]:
|
|
1103
|
+
release_by_arm = {arm.arm_id: arm.release_id for arm in manifest.arms}
|
|
1104
|
+
summaries: dict[str, Any] = {}
|
|
1105
|
+
for family in _CORE_FAMILIES:
|
|
1106
|
+
arm_id = arms_by_family[family]
|
|
1107
|
+
baseline = tuple(float(row["baseline"]) for row in rows.values())
|
|
1108
|
+
treatment = tuple(float(row[family.value]) for row in rows.values())
|
|
1109
|
+
paired = summarize_pairs(baseline, treatment)
|
|
1110
|
+
effects = tuple(after - before for before, after in zip(baseline, treatment, strict=True))
|
|
1111
|
+
summaries[family.value] = {
|
|
1112
|
+
"arm_id": arm_id,
|
|
1113
|
+
"release_id": release_by_arm[arm_id],
|
|
1114
|
+
"cluster_count": len(effects),
|
|
1115
|
+
"no_op_mean": fmean(baseline),
|
|
1116
|
+
"family_mean": fmean(treatment),
|
|
1117
|
+
"mean_effect_vs_no_op": paired.mean_effect,
|
|
1118
|
+
"cluster_bootstrap_95ci": list(
|
|
1119
|
+
_cluster_bootstrap_interval(
|
|
1120
|
+
effects,
|
|
1121
|
+
samples=bootstrap_samples,
|
|
1122
|
+
rng=rng,
|
|
1123
|
+
)
|
|
1124
|
+
),
|
|
1125
|
+
"win_rate_vs_no_op": paired.win_rate,
|
|
1126
|
+
"tie_rate_vs_no_op": paired.tie_rate,
|
|
1127
|
+
"harm_rate_vs_no_op": paired.harm_rate,
|
|
1128
|
+
}
|
|
1129
|
+
return summaries
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
def _require_same_representatives(
|
|
1133
|
+
transfer: _VerifiedTransferRun,
|
|
1134
|
+
primary: _VerifiedTransferRun,
|
|
1135
|
+
) -> None:
|
|
1136
|
+
if transfer.representative_hash != primary.representative_hash:
|
|
1137
|
+
raise ArtifactError("transfer and primary runs bind different representative manifests")
|
|
1138
|
+
transfer_file = transfer.binding_receipt["representative_binding"].get(
|
|
1139
|
+
"representative_file_sha256"
|
|
1140
|
+
)
|
|
1141
|
+
primary_file = primary.binding_receipt["representative_binding"].get(
|
|
1142
|
+
"representative_file_sha256"
|
|
1143
|
+
)
|
|
1144
|
+
if transfer_file != primary_file:
|
|
1145
|
+
raise ArtifactError("transfer and primary runs bind different representative files")
|
|
1146
|
+
transfer_releases = {arm.family: arm.release_id for arm in transfer.manifest.arms[1:]}
|
|
1147
|
+
primary_releases = {arm.family: arm.release_id for arm in primary.manifest.arms[1:]}
|
|
1148
|
+
if transfer_releases != primary_releases:
|
|
1149
|
+
raise ArtifactError("transfer and primary runs use different rank-1 releases")
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
def _transfer_primary_boundary(
|
|
1153
|
+
transfer_rows: Mapping[tuple[str, str], Mapping[str, Any]],
|
|
1154
|
+
primary_rows: Mapping[tuple[str, str], Mapping[str, Any]],
|
|
1155
|
+
*,
|
|
1156
|
+
transfer: _VerifiedTransferRun,
|
|
1157
|
+
primary: _VerifiedTransferRun,
|
|
1158
|
+
bootstrap_samples: int,
|
|
1159
|
+
rng: random.Random,
|
|
1160
|
+
) -> Mapping[str, Any]:
|
|
1161
|
+
transfer_keys = set(transfer_rows)
|
|
1162
|
+
if (
|
|
1163
|
+
len(transfer_keys) != 200
|
|
1164
|
+
or any(key[0] != _BENCHMARK_ID for key in transfer_keys)
|
|
1165
|
+
or not transfer_keys.issubset(primary_rows)
|
|
1166
|
+
):
|
|
1167
|
+
raise ArtifactError(
|
|
1168
|
+
"heldout-model units are not an exact 200-group subset of primary "
|
|
1169
|
+
"STATE-Bench common support"
|
|
1170
|
+
)
|
|
1171
|
+
dependency_boundary = _validate_dependency_interaction_boundary(
|
|
1172
|
+
transfer.runtime_receipts,
|
|
1173
|
+
primary.runtime_receipts,
|
|
1174
|
+
)
|
|
1175
|
+
summaries: dict[str, Any] = {}
|
|
1176
|
+
for family in _CORE_FAMILIES:
|
|
1177
|
+
transfer_effects: list[float] = []
|
|
1178
|
+
primary_effects: list[float] = []
|
|
1179
|
+
interaction: list[float] = []
|
|
1180
|
+
for key in sorted(transfer_keys):
|
|
1181
|
+
transfer_row = transfer_rows[key]
|
|
1182
|
+
primary_row = primary_rows[key]
|
|
1183
|
+
transfer_effect = float(transfer_row[family.value]) - float(transfer_row["baseline"])
|
|
1184
|
+
primary_effect = float(primary_row[family.value]) - float(primary_row["baseline"])
|
|
1185
|
+
transfer_effects.append(transfer_effect)
|
|
1186
|
+
primary_effects.append(primary_effect)
|
|
1187
|
+
interaction.append(transfer_effect - primary_effect)
|
|
1188
|
+
summaries[family.value] = {
|
|
1189
|
+
"matched_group_count": len(interaction),
|
|
1190
|
+
"heldout_model_effect_vs_no_op": fmean(transfer_effects),
|
|
1191
|
+
"primary_anchor_mean_effect_vs_no_op": fmean(primary_effects),
|
|
1192
|
+
"transfer_minus_primary_effect": fmean(interaction),
|
|
1193
|
+
"matched_cluster_bootstrap_95ci": list(
|
|
1194
|
+
_cluster_bootstrap_interval(
|
|
1195
|
+
interaction,
|
|
1196
|
+
samples=bootstrap_samples,
|
|
1197
|
+
rng=rng,
|
|
1198
|
+
)
|
|
1199
|
+
),
|
|
1200
|
+
}
|
|
1201
|
+
return {
|
|
1202
|
+
"comparison_kind": "matched_transfer_minus_primary_interaction_boundary",
|
|
1203
|
+
"primary_study_id": primary.manifest.study_id,
|
|
1204
|
+
"primary_manifest_hash": primary.manifest.manifest_hash,
|
|
1205
|
+
"matched_underlying_groups": 200,
|
|
1206
|
+
"primary_effect_replicate_handling": (
|
|
1207
|
+
"equal-weight mean over anchor_a and anchor_b within each underlying group"
|
|
1208
|
+
),
|
|
1209
|
+
"dependency_boundary": dependency_boundary,
|
|
1210
|
+
"families": summaries,
|
|
1211
|
+
"scope_note": (
|
|
1212
|
+
"Difference-in-differences on the same 200 STATE-Bench unit IDs. "
|
|
1213
|
+
"This boundary is not a pooled population effect and does not assert "
|
|
1214
|
+
"exchangeability with the remaining primary common-support groups."
|
|
1215
|
+
),
|
|
1216
|
+
"paper_claim_authorized": False,
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
def _validate_dependency_interaction_boundary(
|
|
1221
|
+
transfer_receipts: Mapping[str, Any],
|
|
1222
|
+
primary_receipts: Mapping[str, Any],
|
|
1223
|
+
) -> Mapping[str, Any]:
|
|
1224
|
+
transfer_strata = transfer_receipts.get("dependency_receipt_strata")
|
|
1225
|
+
primary_strata = primary_receipts.get("dependency_receipt_strata")
|
|
1226
|
+
transfer_keys = tuple(f"{_BENCHMARK_ID}::{model_slot}" for model_slot in _TRANSFER_MODEL_SLOTS)
|
|
1227
|
+
primary_keys = tuple(f"{_BENCHMARK_ID}::{model_slot}" for model_slot in _PRIMARY_MODEL_SLOTS)
|
|
1228
|
+
if (
|
|
1229
|
+
not isinstance(transfer_strata, Mapping)
|
|
1230
|
+
or not isinstance(primary_strata, Mapping)
|
|
1231
|
+
or any(key not in transfer_strata for key in transfer_keys)
|
|
1232
|
+
or any(key not in primary_strata for key in primary_keys)
|
|
1233
|
+
):
|
|
1234
|
+
raise ArtifactError("model-transfer dependency strata are incomplete")
|
|
1235
|
+
by_model = {
|
|
1236
|
+
**{
|
|
1237
|
+
model_slot: transfer_strata[f"{_BENCHMARK_ID}::{model_slot}"]
|
|
1238
|
+
for model_slot in _TRANSFER_MODEL_SLOTS
|
|
1239
|
+
},
|
|
1240
|
+
**{
|
|
1241
|
+
model_slot: primary_strata[f"{_BENCHMARK_ID}::{model_slot}"]
|
|
1242
|
+
for model_slot in _PRIMARY_MODEL_SLOTS
|
|
1243
|
+
},
|
|
1244
|
+
}
|
|
1245
|
+
if any(
|
|
1246
|
+
not isinstance(dependencies, Mapping) or set(dependencies) != _DEPENDENCY_SLOTS
|
|
1247
|
+
for dependencies in by_model.values()
|
|
1248
|
+
):
|
|
1249
|
+
raise ArtifactError("model-transfer dependency boundary has invalid slots")
|
|
1250
|
+
nuisance_slots = _DEPENDENCY_SLOTS - {"agent_model"}
|
|
1251
|
+
for slot in nuisance_slots:
|
|
1252
|
+
if len({dependencies[slot] for dependencies in by_model.values()}) != 1:
|
|
1253
|
+
raise ArtifactError(f"model-transfer nuisance dependency {slot!r} differs across runs")
|
|
1254
|
+
model_hashes = {
|
|
1255
|
+
model_slot: str(dependencies["agent_model"])
|
|
1256
|
+
for model_slot, dependencies in by_model.items()
|
|
1257
|
+
}
|
|
1258
|
+
if len(set(model_hashes.values())) != len(_TRANSFER_MODEL_SLOTS) + len(_PRIMARY_MODEL_SLOTS):
|
|
1259
|
+
raise ArtifactError(
|
|
1260
|
+
"transfer and primary model slots do not resolve to six distinct identities"
|
|
1261
|
+
)
|
|
1262
|
+
return {
|
|
1263
|
+
"varied_dependency_slot": "agent_model",
|
|
1264
|
+
"model_identity_hashes": model_hashes,
|
|
1265
|
+
"shared_nuisance_dependency_slots": sorted(nuisance_slots),
|
|
1266
|
+
"source_revision": _STATEBENCH_REVISION,
|
|
1267
|
+
"boundary_verified": True,
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
|
|
1271
|
+
def _validate_analysis_arguments(
|
|
1272
|
+
*,
|
|
1273
|
+
metric: str,
|
|
1274
|
+
algorithm_failure_value: float | None,
|
|
1275
|
+
bootstrap_samples: int,
|
|
1276
|
+
random_seed: int,
|
|
1277
|
+
) -> None:
|
|
1278
|
+
if not isinstance(metric, str) or not metric.strip():
|
|
1279
|
+
raise ValidationError("analysis metric must be non-empty")
|
|
1280
|
+
if algorithm_failure_value is not None and (
|
|
1281
|
+
isinstance(algorithm_failure_value, bool)
|
|
1282
|
+
or not isinstance(algorithm_failure_value, (int, float))
|
|
1283
|
+
or not math.isfinite(float(algorithm_failure_value))
|
|
1284
|
+
):
|
|
1285
|
+
raise ValidationError("algorithm_failure_value must be finite when provided")
|
|
1286
|
+
_validate_resample_arguments(
|
|
1287
|
+
bootstrap_samples=bootstrap_samples,
|
|
1288
|
+
permutation_samples=1,
|
|
1289
|
+
random_seed=random_seed,
|
|
1290
|
+
)
|
|
1291
|
+
|
|
1292
|
+
|
|
1293
|
+
def _load_run_identity(root: Path) -> Mapping[str, Any]:
|
|
1294
|
+
path = root / "run_identity.json"
|
|
1295
|
+
try:
|
|
1296
|
+
value = json.loads(path.read_text(encoding="utf-8"))
|
|
1297
|
+
except (OSError, UnicodeError, json.JSONDecodeError) as exc:
|
|
1298
|
+
raise ArtifactError("run identity is missing or invalid") from exc
|
|
1299
|
+
if not isinstance(value, Mapping):
|
|
1300
|
+
raise ArtifactError("run identity must be a JSON object")
|
|
1301
|
+
return value
|
|
1302
|
+
|
|
1303
|
+
|
|
1304
|
+
def _is_sha256(value: Any) -> bool:
|
|
1305
|
+
return (
|
|
1306
|
+
isinstance(value, str)
|
|
1307
|
+
and len(value) == 64
|
|
1308
|
+
and all(character in "0123456789abcdef" for character in value)
|
|
1309
|
+
)
|
|
1310
|
+
|
|
1311
|
+
|
|
1312
|
+
__all__ = [
|
|
1313
|
+
"HELDOUT_MODEL_TRANSFER_PROTOCOL",
|
|
1314
|
+
"analyze_heldout_model_transfer",
|
|
1315
|
+
"validate_heldout_model_transfer_run",
|
|
1316
|
+
]
|