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,479 @@
|
|
|
1
|
+
"""Generic fail-closed contracts for atomic external paired replay.
|
|
2
|
+
|
|
3
|
+
Stateful arenas cannot establish a fair pair by scoring two callbacks
|
|
4
|
+
sequentially. The external runtime must own one atomic operation that restores
|
|
5
|
+
the same protected origin twice, runs both arms in independent runtime
|
|
6
|
+
instances, invokes the locked scorer, and returns one complete receipt.
|
|
7
|
+
|
|
8
|
+
This module defines that transport-neutral boundary. It does not certify any
|
|
9
|
+
of the four interactive arenas as pairing-ready; each still needs a separately
|
|
10
|
+
verified upstream runtime bridge.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import math
|
|
16
|
+
import re
|
|
17
|
+
from collections.abc import Mapping
|
|
18
|
+
from dataclasses import dataclass, field
|
|
19
|
+
from typing import Any, Protocol, runtime_checkable
|
|
20
|
+
|
|
21
|
+
from agentinputlab.contracts.errors import ValidationError
|
|
22
|
+
from agentinputlab.contracts.serialization import deep_freeze_jsonable, freeze_mapping
|
|
23
|
+
from agentinputlab.observability import ResourceReceipt, ResourceUsage
|
|
24
|
+
|
|
25
|
+
ATOMIC_EXTERNAL_PAIR_CONTRACT = "agentinputlab.atomic_external_pair.v1"
|
|
26
|
+
_SHA256 = re.compile(r"^[0-9a-f]{64}$")
|
|
27
|
+
_ROLES = ("baseline", "treatment")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass(frozen=True, slots=True)
|
|
31
|
+
class AtomicReplayArmRequest:
|
|
32
|
+
"""One canonically serializable intervention artifact for external replay."""
|
|
33
|
+
|
|
34
|
+
role: str
|
|
35
|
+
arm_id: str
|
|
36
|
+
payload: Any = field(repr=False)
|
|
37
|
+
|
|
38
|
+
def __post_init__(self) -> None:
|
|
39
|
+
_require_role(self.role)
|
|
40
|
+
_require_text(self.arm_id, label="atomic replay arm_id")
|
|
41
|
+
try:
|
|
42
|
+
object.__setattr__(self, "payload", deep_freeze_jsonable(self.payload))
|
|
43
|
+
except (TypeError, ValueError) as exc:
|
|
44
|
+
raise ValidationError(
|
|
45
|
+
f"atomic replay arm payload must be canonically serializable: {exc}"
|
|
46
|
+
) from exc
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@dataclass(frozen=True, slots=True)
|
|
50
|
+
class AtomicReplayRequest:
|
|
51
|
+
"""Complete two-arm request bound to one protected checkpoint origin."""
|
|
52
|
+
|
|
53
|
+
benchmark_id: str
|
|
54
|
+
checkpoint_id: str
|
|
55
|
+
source_revision: str
|
|
56
|
+
origin_state_hash: str
|
|
57
|
+
replay_identity: str
|
|
58
|
+
seed: int
|
|
59
|
+
locked_dependency_hashes: Mapping[str, str]
|
|
60
|
+
arms: tuple[AtomicReplayArmRequest, ...]
|
|
61
|
+
|
|
62
|
+
def __post_init__(self) -> None:
|
|
63
|
+
for label in ("benchmark_id", "checkpoint_id", "source_revision"):
|
|
64
|
+
_require_text(getattr(self, label), label=f"atomic replay {label}")
|
|
65
|
+
_require_sha256(self.origin_state_hash, label="atomic replay origin_state_hash")
|
|
66
|
+
_require_sha256(self.replay_identity, label="atomic replay replay_identity")
|
|
67
|
+
_require_seed(self.seed)
|
|
68
|
+
dependencies = _validated_dependency_hashes(self.locked_dependency_hashes)
|
|
69
|
+
arms = tuple(self.arms)
|
|
70
|
+
_require_arm_types(
|
|
71
|
+
arms,
|
|
72
|
+
AtomicReplayArmRequest,
|
|
73
|
+
label="atomic replay request",
|
|
74
|
+
)
|
|
75
|
+
_require_complete_arms(arms, label="atomic replay request")
|
|
76
|
+
object.__setattr__(self, "locked_dependency_hashes", dependencies)
|
|
77
|
+
object.__setattr__(self, "arms", arms)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@dataclass(frozen=True, slots=True)
|
|
81
|
+
class AtomicReplayArmReceipt:
|
|
82
|
+
"""Per-arm proof fields emitted by the external runtime."""
|
|
83
|
+
|
|
84
|
+
role: str
|
|
85
|
+
arm_id: str
|
|
86
|
+
origin_state_hash: str
|
|
87
|
+
replay_identity: str
|
|
88
|
+
seed: int
|
|
89
|
+
locked_dependency_hashes: Mapping[str, str]
|
|
90
|
+
runtime_instance_id: str
|
|
91
|
+
completed: bool
|
|
92
|
+
|
|
93
|
+
def __post_init__(self) -> None:
|
|
94
|
+
_require_role(self.role)
|
|
95
|
+
_require_text(self.arm_id, label="atomic replay receipt arm_id")
|
|
96
|
+
_require_sha256(
|
|
97
|
+
self.origin_state_hash,
|
|
98
|
+
label="atomic replay receipt origin_state_hash",
|
|
99
|
+
)
|
|
100
|
+
_require_sha256(
|
|
101
|
+
self.replay_identity,
|
|
102
|
+
label="atomic replay receipt replay_identity",
|
|
103
|
+
)
|
|
104
|
+
_require_seed(self.seed)
|
|
105
|
+
_require_sha256(
|
|
106
|
+
self.runtime_instance_id,
|
|
107
|
+
label="atomic replay receipt runtime_instance_id",
|
|
108
|
+
)
|
|
109
|
+
if self.completed is not True:
|
|
110
|
+
raise ValidationError("atomic replay receipt requires a completed arm")
|
|
111
|
+
object.__setattr__(
|
|
112
|
+
self,
|
|
113
|
+
"locked_dependency_hashes",
|
|
114
|
+
_validated_dependency_hashes(self.locked_dependency_hashes),
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@dataclass(frozen=True, slots=True)
|
|
119
|
+
class AtomicReplayReceipt:
|
|
120
|
+
"""One indivisible receipt covering both restored runtime executions."""
|
|
121
|
+
|
|
122
|
+
benchmark_id: str
|
|
123
|
+
checkpoint_id: str
|
|
124
|
+
source_revision: str
|
|
125
|
+
bridge_id: str
|
|
126
|
+
bridge_revision: str
|
|
127
|
+
scorer_id: str
|
|
128
|
+
scorer_revision: str
|
|
129
|
+
origin_state_hash: str
|
|
130
|
+
replay_identity: str
|
|
131
|
+
seed: int
|
|
132
|
+
locked_dependency_hashes: Mapping[str, str]
|
|
133
|
+
arms: tuple[AtomicReplayArmReceipt, ...]
|
|
134
|
+
|
|
135
|
+
def __post_init__(self) -> None:
|
|
136
|
+
for label in (
|
|
137
|
+
"benchmark_id",
|
|
138
|
+
"checkpoint_id",
|
|
139
|
+
"source_revision",
|
|
140
|
+
"bridge_id",
|
|
141
|
+
"scorer_id",
|
|
142
|
+
):
|
|
143
|
+
_require_text(getattr(self, label), label=f"atomic replay receipt {label}")
|
|
144
|
+
for label in ("bridge_revision", "scorer_revision", "origin_state_hash"):
|
|
145
|
+
_require_sha256(
|
|
146
|
+
getattr(self, label),
|
|
147
|
+
label=f"atomic replay receipt {label}",
|
|
148
|
+
)
|
|
149
|
+
_require_sha256(
|
|
150
|
+
self.replay_identity,
|
|
151
|
+
label="atomic replay receipt replay_identity",
|
|
152
|
+
)
|
|
153
|
+
_require_seed(self.seed)
|
|
154
|
+
dependencies = _validated_dependency_hashes(self.locked_dependency_hashes)
|
|
155
|
+
arms = tuple(self.arms)
|
|
156
|
+
_require_arm_types(
|
|
157
|
+
arms,
|
|
158
|
+
AtomicReplayArmReceipt,
|
|
159
|
+
label="atomic replay receipt",
|
|
160
|
+
)
|
|
161
|
+
_require_complete_arms(arms, label="atomic replay receipt")
|
|
162
|
+
if len({arm.runtime_instance_id for arm in arms}) != 2:
|
|
163
|
+
raise ValidationError(
|
|
164
|
+
"atomic replay arms must use different runtime instance identities"
|
|
165
|
+
)
|
|
166
|
+
for arm in arms:
|
|
167
|
+
if (
|
|
168
|
+
arm.origin_state_hash != self.origin_state_hash
|
|
169
|
+
or arm.replay_identity != self.replay_identity
|
|
170
|
+
or arm.seed != self.seed
|
|
171
|
+
or arm.locked_dependency_hashes != dependencies
|
|
172
|
+
):
|
|
173
|
+
raise ValidationError(
|
|
174
|
+
"atomic replay arm receipt differs from the shared origin, seed, "
|
|
175
|
+
"replay identity, or locked dependencies"
|
|
176
|
+
)
|
|
177
|
+
object.__setattr__(self, "locked_dependency_hashes", dependencies)
|
|
178
|
+
object.__setattr__(self, "arms", arms)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@dataclass(frozen=True, slots=True)
|
|
182
|
+
class AtomicReplayArmResult:
|
|
183
|
+
"""Official scorer output and execution accounting for one arm."""
|
|
184
|
+
|
|
185
|
+
role: str
|
|
186
|
+
arm_id: str
|
|
187
|
+
metrics: Mapping[str, float]
|
|
188
|
+
trace_hash: str
|
|
189
|
+
usage: ResourceUsage = field(default_factory=ResourceUsage)
|
|
190
|
+
|
|
191
|
+
def __post_init__(self) -> None:
|
|
192
|
+
_require_role(self.role)
|
|
193
|
+
_require_text(self.arm_id, label="atomic replay result arm_id")
|
|
194
|
+
_require_sha256(self.trace_hash, label="atomic replay result trace_hash")
|
|
195
|
+
if not isinstance(self.usage, ResourceUsage):
|
|
196
|
+
raise TypeError("atomic replay result usage must be ResourceUsage")
|
|
197
|
+
object.__setattr__(self, "metrics", _validated_metrics(self.metrics))
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
@dataclass(frozen=True, slots=True)
|
|
201
|
+
class AtomicReplayPairResult:
|
|
202
|
+
"""Typed all-or-nothing result returned by an atomic bridge call."""
|
|
203
|
+
|
|
204
|
+
receipt: AtomicReplayReceipt
|
|
205
|
+
arms: tuple[AtomicReplayArmResult, ...]
|
|
206
|
+
resource_receipts: tuple[ResourceReceipt, ...] = ()
|
|
207
|
+
|
|
208
|
+
def __post_init__(self) -> None:
|
|
209
|
+
if not isinstance(self.receipt, AtomicReplayReceipt):
|
|
210
|
+
raise TypeError("atomic replay pair result requires AtomicReplayReceipt")
|
|
211
|
+
arms = tuple(self.arms)
|
|
212
|
+
_require_arm_types(
|
|
213
|
+
arms,
|
|
214
|
+
AtomicReplayArmResult,
|
|
215
|
+
label="atomic replay pair result",
|
|
216
|
+
)
|
|
217
|
+
_require_complete_arms(arms, label="atomic replay pair result")
|
|
218
|
+
expected = {(arm.role, arm.arm_id) for arm in self.receipt.arms}
|
|
219
|
+
actual = {(arm.role, arm.arm_id) for arm in arms}
|
|
220
|
+
if actual != expected:
|
|
221
|
+
raise ValidationError(
|
|
222
|
+
"atomic replay result arms differ from the completed receipt arms"
|
|
223
|
+
)
|
|
224
|
+
metric_keys = tuple(sorted(arms[0].metrics))
|
|
225
|
+
if tuple(sorted(arms[1].metrics)) != metric_keys:
|
|
226
|
+
raise ValidationError("atomic replay arm metric schemas differ")
|
|
227
|
+
resource_receipts = tuple(self.resource_receipts)
|
|
228
|
+
if any(not isinstance(item, ResourceReceipt) for item in resource_receipts):
|
|
229
|
+
raise TypeError(
|
|
230
|
+
"atomic replay pair resource_receipts must contain ResourceReceipt values"
|
|
231
|
+
)
|
|
232
|
+
object.__setattr__(self, "arms", arms)
|
|
233
|
+
object.__setattr__(self, "resource_receipts", resource_receipts)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
@runtime_checkable
|
|
237
|
+
class AtomicExternalReplayBridge(Protocol):
|
|
238
|
+
"""Distinct protocol that a legacy single-arm bridge cannot satisfy."""
|
|
239
|
+
|
|
240
|
+
atomic_replay_contract: str
|
|
241
|
+
benchmark_id: str
|
|
242
|
+
source_revision: str
|
|
243
|
+
bridge_id: str
|
|
244
|
+
bridge_revision: str
|
|
245
|
+
scorer_id: str
|
|
246
|
+
scorer_revision: str
|
|
247
|
+
locked_dependency_hashes: Mapping[str, str]
|
|
248
|
+
|
|
249
|
+
def evaluate_pair(self, request: AtomicReplayRequest) -> AtomicReplayPairResult: ...
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@dataclass(frozen=True, slots=True)
|
|
253
|
+
class AtomicPairedReplayRecord:
|
|
254
|
+
"""Validated paired result with evaluator-derived metric deltas."""
|
|
255
|
+
|
|
256
|
+
receipt: AtomicReplayReceipt
|
|
257
|
+
baseline: AtomicReplayArmResult
|
|
258
|
+
treatment: AtomicReplayArmResult
|
|
259
|
+
metric_deltas: Mapping[str, float]
|
|
260
|
+
resource_receipts: tuple[ResourceReceipt, ...] = ()
|
|
261
|
+
|
|
262
|
+
def __post_init__(self) -> None:
|
|
263
|
+
if not isinstance(self.receipt, AtomicReplayReceipt):
|
|
264
|
+
raise TypeError("atomic paired replay record requires AtomicReplayReceipt")
|
|
265
|
+
if not isinstance(self.baseline, AtomicReplayArmResult) or not isinstance(
|
|
266
|
+
self.treatment,
|
|
267
|
+
AtomicReplayArmResult,
|
|
268
|
+
):
|
|
269
|
+
raise TypeError("atomic paired replay record requires typed arm results")
|
|
270
|
+
if self.baseline.role != "baseline" or self.treatment.role != "treatment":
|
|
271
|
+
raise ValidationError("atomic paired replay record has incorrect arm roles")
|
|
272
|
+
receipt_arms = {(arm.role, arm.arm_id) for arm in self.receipt.arms}
|
|
273
|
+
result_arms = {
|
|
274
|
+
(self.baseline.role, self.baseline.arm_id),
|
|
275
|
+
(self.treatment.role, self.treatment.arm_id),
|
|
276
|
+
}
|
|
277
|
+
if result_arms != receipt_arms:
|
|
278
|
+
raise ValidationError(
|
|
279
|
+
"atomic paired replay record arms differ from the completed receipt"
|
|
280
|
+
)
|
|
281
|
+
expected = tuple(sorted(self.baseline.metrics))
|
|
282
|
+
if tuple(sorted(self.treatment.metrics)) != expected:
|
|
283
|
+
raise ValidationError("atomic paired replay metric schemas differ")
|
|
284
|
+
deltas = _validated_metrics(self.metric_deltas)
|
|
285
|
+
if tuple(sorted(deltas)) != expected:
|
|
286
|
+
raise ValidationError("atomic paired replay delta schema differs from arm metrics")
|
|
287
|
+
for key in expected:
|
|
288
|
+
if deltas[key] != self.treatment.metrics[key] - self.baseline.metrics[key]:
|
|
289
|
+
raise ValidationError(f"atomic paired replay metric delta {key!r} is inconsistent")
|
|
290
|
+
resource_receipts = tuple(self.resource_receipts)
|
|
291
|
+
if any(not isinstance(item, ResourceReceipt) for item in resource_receipts):
|
|
292
|
+
raise TypeError(
|
|
293
|
+
"atomic paired replay resource_receipts must contain ResourceReceipt values"
|
|
294
|
+
)
|
|
295
|
+
object.__setattr__(self, "metric_deltas", deltas)
|
|
296
|
+
object.__setattr__(self, "resource_receipts", resource_receipts)
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
class AtomicExternalReplayRunner:
|
|
300
|
+
"""Call a verified atomic bridge exactly once and validate its full receipt."""
|
|
301
|
+
|
|
302
|
+
def run(
|
|
303
|
+
self,
|
|
304
|
+
bridge: AtomicExternalReplayBridge,
|
|
305
|
+
request: AtomicReplayRequest,
|
|
306
|
+
) -> AtomicPairedReplayRecord:
|
|
307
|
+
if not isinstance(request, AtomicReplayRequest):
|
|
308
|
+
raise TypeError("atomic replay request must be AtomicReplayRequest")
|
|
309
|
+
if not isinstance(bridge, AtomicExternalReplayBridge):
|
|
310
|
+
raise TypeError(
|
|
311
|
+
"bridge must implement AtomicExternalReplayBridge.evaluate_pair(); "
|
|
312
|
+
"single-arm evaluation bridges are not accepted"
|
|
313
|
+
)
|
|
314
|
+
bridge_dependencies = _validate_bridge(bridge)
|
|
315
|
+
if (
|
|
316
|
+
bridge.benchmark_id != request.benchmark_id
|
|
317
|
+
or bridge.source_revision != request.source_revision
|
|
318
|
+
or bridge_dependencies != request.locked_dependency_hashes
|
|
319
|
+
):
|
|
320
|
+
raise ValidationError(
|
|
321
|
+
"atomic bridge identity or locked dependencies differ from the request"
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
result = bridge.evaluate_pair(request)
|
|
325
|
+
if not isinstance(result, AtomicReplayPairResult):
|
|
326
|
+
raise ValidationError(
|
|
327
|
+
"atomic external bridge must return AtomicReplayPairResult; "
|
|
328
|
+
"partial or bare metric results are not accepted"
|
|
329
|
+
)
|
|
330
|
+
_validate_receipt_against_request(result.receipt, request, bridge)
|
|
331
|
+
by_role = {arm.role: arm for arm in result.arms}
|
|
332
|
+
baseline = by_role["baseline"]
|
|
333
|
+
treatment = by_role["treatment"]
|
|
334
|
+
resource_receipts = result.resource_receipts
|
|
335
|
+
bridge_resource_receipt = getattr(bridge, "last_resource_receipt", None)
|
|
336
|
+
if bridge_resource_receipt is not None:
|
|
337
|
+
if not isinstance(bridge_resource_receipt, ResourceReceipt):
|
|
338
|
+
raise TypeError(
|
|
339
|
+
"atomic bridge last_resource_receipt must be a ResourceReceipt or null"
|
|
340
|
+
)
|
|
341
|
+
if bridge_resource_receipt not in resource_receipts:
|
|
342
|
+
resource_receipts = (*resource_receipts, bridge_resource_receipt)
|
|
343
|
+
return AtomicPairedReplayRecord(
|
|
344
|
+
receipt=result.receipt,
|
|
345
|
+
baseline=baseline,
|
|
346
|
+
treatment=treatment,
|
|
347
|
+
metric_deltas={
|
|
348
|
+
key: treatment.metrics[key] - baseline.metrics[key] for key in baseline.metrics
|
|
349
|
+
},
|
|
350
|
+
resource_receipts=resource_receipts,
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
def _validate_bridge(
|
|
355
|
+
bridge: AtomicExternalReplayBridge,
|
|
356
|
+
) -> Mapping[str, str]:
|
|
357
|
+
if bridge.atomic_replay_contract != ATOMIC_EXTERNAL_PAIR_CONTRACT:
|
|
358
|
+
raise ValidationError("atomic external bridge contract version is unsupported")
|
|
359
|
+
for label in ("benchmark_id", "source_revision", "bridge_id", "scorer_id"):
|
|
360
|
+
_require_text(getattr(bridge, label), label=f"atomic bridge {label}")
|
|
361
|
+
_require_sha256(bridge.bridge_revision, label="atomic bridge bridge_revision")
|
|
362
|
+
_require_sha256(bridge.scorer_revision, label="atomic bridge scorer_revision")
|
|
363
|
+
return _validated_dependency_hashes(bridge.locked_dependency_hashes)
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def _validate_receipt_against_request(
|
|
367
|
+
receipt: AtomicReplayReceipt,
|
|
368
|
+
request: AtomicReplayRequest,
|
|
369
|
+
bridge: AtomicExternalReplayBridge,
|
|
370
|
+
) -> None:
|
|
371
|
+
expected = {
|
|
372
|
+
"benchmark_id": request.benchmark_id,
|
|
373
|
+
"checkpoint_id": request.checkpoint_id,
|
|
374
|
+
"source_revision": request.source_revision,
|
|
375
|
+
"bridge_id": bridge.bridge_id,
|
|
376
|
+
"bridge_revision": bridge.bridge_revision,
|
|
377
|
+
"scorer_id": bridge.scorer_id,
|
|
378
|
+
"scorer_revision": bridge.scorer_revision,
|
|
379
|
+
"origin_state_hash": request.origin_state_hash,
|
|
380
|
+
"replay_identity": request.replay_identity,
|
|
381
|
+
"seed": request.seed,
|
|
382
|
+
}
|
|
383
|
+
for field_name, value in expected.items():
|
|
384
|
+
if getattr(receipt, field_name) != value:
|
|
385
|
+
raise ValidationError(
|
|
386
|
+
f"atomic replay receipt {field_name} differs from its request or bridge"
|
|
387
|
+
)
|
|
388
|
+
if receipt.locked_dependency_hashes != request.locked_dependency_hashes:
|
|
389
|
+
raise ValidationError("atomic replay receipt locked dependencies differ from request")
|
|
390
|
+
requested_arms = {(arm.role, arm.arm_id) for arm in request.arms}
|
|
391
|
+
received_arms = {(arm.role, arm.arm_id) for arm in receipt.arms}
|
|
392
|
+
if requested_arms != received_arms:
|
|
393
|
+
raise ValidationError("atomic replay receipt arms differ from request arms")
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
def _require_complete_arms(arms: tuple[Any, ...], *, label: str) -> None:
|
|
397
|
+
if len(arms) != 2:
|
|
398
|
+
raise ValidationError(f"{label} requires exactly two arms")
|
|
399
|
+
roles = tuple(sorted(getattr(arm, "role", "") for arm in arms))
|
|
400
|
+
if roles != _ROLES:
|
|
401
|
+
raise ValidationError(f"{label} requires baseline and treatment roles")
|
|
402
|
+
identifiers = [getattr(arm, "arm_id", "") for arm in arms]
|
|
403
|
+
if len(set(identifiers)) != 2:
|
|
404
|
+
raise ValidationError(f"{label} requires unique arm IDs")
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def _require_arm_types(
|
|
408
|
+
arms: tuple[Any, ...],
|
|
409
|
+
expected_type: type[Any],
|
|
410
|
+
*,
|
|
411
|
+
label: str,
|
|
412
|
+
) -> None:
|
|
413
|
+
if not all(isinstance(arm, expected_type) for arm in arms):
|
|
414
|
+
raise TypeError(f"{label} requires {expected_type.__name__} instances")
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def _require_role(value: Any) -> None:
|
|
418
|
+
if value not in _ROLES:
|
|
419
|
+
raise ValidationError("atomic replay arm role must be baseline or treatment")
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
def _validated_dependency_hashes(value: Mapping[str, str]) -> Mapping[str, str]:
|
|
423
|
+
if not isinstance(value, Mapping) or not value:
|
|
424
|
+
raise ValidationError("atomic replay locked_dependency_hashes must be non-empty")
|
|
425
|
+
dependencies: dict[str, str] = {}
|
|
426
|
+
for name, digest in value.items():
|
|
427
|
+
_require_text(name, label="atomic replay dependency name")
|
|
428
|
+
_require_sha256(digest, label=f"atomic replay dependency {name!r}")
|
|
429
|
+
dependencies[name] = digest
|
|
430
|
+
return freeze_mapping(dependencies)
|
|
431
|
+
|
|
432
|
+
|
|
433
|
+
def _validated_metrics(value: Mapping[str, float]) -> Mapping[str, float]:
|
|
434
|
+
if not isinstance(value, Mapping) or not value:
|
|
435
|
+
raise ValidationError("atomic replay metrics must be a non-empty mapping")
|
|
436
|
+
metrics: dict[str, float] = {}
|
|
437
|
+
for name, raw in value.items():
|
|
438
|
+
_require_text(name, label="atomic replay metric name")
|
|
439
|
+
if isinstance(raw, bool) or not isinstance(raw, (int, float)):
|
|
440
|
+
raise ValidationError(f"atomic replay metric {name!r} must be numeric")
|
|
441
|
+
numeric = float(raw)
|
|
442
|
+
if not math.isfinite(numeric):
|
|
443
|
+
raise ValidationError(f"atomic replay metric {name!r} must be finite")
|
|
444
|
+
metrics[name] = numeric
|
|
445
|
+
return freeze_mapping(metrics)
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def _require_text(value: Any, *, label: str) -> None:
|
|
449
|
+
if (
|
|
450
|
+
not isinstance(value, str)
|
|
451
|
+
or not value.strip()
|
|
452
|
+
or value != value.strip()
|
|
453
|
+
or any(not character.isprintable() for character in value)
|
|
454
|
+
):
|
|
455
|
+
raise ValidationError(f"{label} must be trimmed, non-empty printable text")
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
def _require_sha256(value: Any, *, label: str) -> None:
|
|
459
|
+
if not isinstance(value, str) or _SHA256.fullmatch(value) is None:
|
|
460
|
+
raise ValidationError(f"{label} must be a lowercase SHA-256 digest")
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
def _require_seed(value: Any) -> None:
|
|
464
|
+
if isinstance(value, bool) or not isinstance(value, int) or value < 0:
|
|
465
|
+
raise ValidationError("atomic replay seed must be a non-negative integer")
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
__all__ = [
|
|
469
|
+
"ATOMIC_EXTERNAL_PAIR_CONTRACT",
|
|
470
|
+
"AtomicExternalReplayBridge",
|
|
471
|
+
"AtomicExternalReplayRunner",
|
|
472
|
+
"AtomicPairedReplayRecord",
|
|
473
|
+
"AtomicReplayArmReceipt",
|
|
474
|
+
"AtomicReplayArmRequest",
|
|
475
|
+
"AtomicReplayArmResult",
|
|
476
|
+
"AtomicReplayPairResult",
|
|
477
|
+
"AtomicReplayReceipt",
|
|
478
|
+
"AtomicReplayRequest",
|
|
479
|
+
]
|