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,157 @@
|
|
|
1
|
+
"""Checksum-verified local artifact store with atomic writes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import os
|
|
7
|
+
import tempfile
|
|
8
|
+
from collections.abc import Iterable
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
from agentinputlab.contracts.errors import ArtifactError
|
|
13
|
+
|
|
14
|
+
from .manifest import ArtifactManifest
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def sha256_file(path: str | Path, *, chunk_size: int = 1024 * 1024) -> str:
|
|
18
|
+
digest = hashlib.sha256()
|
|
19
|
+
with Path(path).open("rb") as handle:
|
|
20
|
+
while chunk := handle.read(chunk_size):
|
|
21
|
+
digest.update(chunk)
|
|
22
|
+
return digest.hexdigest()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(slots=True)
|
|
26
|
+
class ArtifactStore:
|
|
27
|
+
root: Path
|
|
28
|
+
|
|
29
|
+
def __init__(self, root: str | Path) -> None:
|
|
30
|
+
self.root = Path(root).expanduser().resolve()
|
|
31
|
+
self.root.mkdir(parents=True, exist_ok=True)
|
|
32
|
+
|
|
33
|
+
def path_for(self, manifest: ArtifactManifest) -> Path:
|
|
34
|
+
candidate = (self.root / manifest.artifact_id / manifest.revision / "payload").resolve()
|
|
35
|
+
if self.root not in candidate.parents:
|
|
36
|
+
raise ArtifactError("artifact path escaped store root")
|
|
37
|
+
return candidate
|
|
38
|
+
|
|
39
|
+
def verify(self, manifest: ArtifactManifest) -> Path:
|
|
40
|
+
path = self.path_for(manifest)
|
|
41
|
+
if not path.is_file():
|
|
42
|
+
raise ArtifactError(f"artifact missing: {manifest.artifact_id}@{manifest.revision}")
|
|
43
|
+
if manifest.size_bytes is not None and path.stat().st_size != manifest.size_bytes:
|
|
44
|
+
raise ArtifactError(f"artifact size mismatch: {manifest.artifact_id}")
|
|
45
|
+
if manifest.sha256 and sha256_file(path) != manifest.sha256:
|
|
46
|
+
raise ArtifactError(f"artifact checksum mismatch: {manifest.artifact_id}")
|
|
47
|
+
return path
|
|
48
|
+
|
|
49
|
+
def put_bytes(self, manifest: ArtifactManifest, content: bytes) -> Path:
|
|
50
|
+
digest = hashlib.sha256(content).hexdigest()
|
|
51
|
+
if manifest.sha256 and digest != manifest.sha256:
|
|
52
|
+
raise ArtifactError(
|
|
53
|
+
f"refusing materialization: checksum mismatch for {manifest.artifact_id}"
|
|
54
|
+
)
|
|
55
|
+
if manifest.size_bytes is not None and len(content) != manifest.size_bytes:
|
|
56
|
+
raise ArtifactError(
|
|
57
|
+
f"refusing materialization: size mismatch for {manifest.artifact_id}"
|
|
58
|
+
)
|
|
59
|
+
destination = self.path_for(manifest)
|
|
60
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
61
|
+
if destination.exists():
|
|
62
|
+
if destination.is_file() and destination.read_bytes() == content:
|
|
63
|
+
return self.verify(manifest)
|
|
64
|
+
raise ArtifactError(
|
|
65
|
+
"refusing to overwrite an existing artifact revision with different content: "
|
|
66
|
+
f"{manifest.artifact_id}@{manifest.revision}"
|
|
67
|
+
)
|
|
68
|
+
descriptor, temporary_name = tempfile.mkstemp(
|
|
69
|
+
prefix=".partial-",
|
|
70
|
+
dir=destination.parent,
|
|
71
|
+
)
|
|
72
|
+
try:
|
|
73
|
+
with os.fdopen(descriptor, "wb") as handle:
|
|
74
|
+
handle.write(content)
|
|
75
|
+
handle.flush()
|
|
76
|
+
os.fsync(handle.fileno())
|
|
77
|
+
try:
|
|
78
|
+
# Linking a fully flushed temporary file is atomic and, unlike
|
|
79
|
+
# os.replace(), cannot overwrite a concurrently materialized
|
|
80
|
+
# artifact revision.
|
|
81
|
+
os.link(temporary_name, destination)
|
|
82
|
+
except FileExistsError:
|
|
83
|
+
if not destination.is_file() or destination.read_bytes() != content:
|
|
84
|
+
raise ArtifactError(
|
|
85
|
+
"refusing concurrent overwrite of artifact revision: "
|
|
86
|
+
f"{manifest.artifact_id}@{manifest.revision}"
|
|
87
|
+
) from None
|
|
88
|
+
finally:
|
|
89
|
+
if os.path.exists(temporary_name):
|
|
90
|
+
os.unlink(temporary_name)
|
|
91
|
+
return self.verify(manifest)
|
|
92
|
+
|
|
93
|
+
def import_file(self, manifest: ArtifactManifest, source: str | Path) -> Path:
|
|
94
|
+
source_path = Path(source).resolve()
|
|
95
|
+
if not source_path.is_file():
|
|
96
|
+
raise ArtifactError(f"source artifact is not a regular file: {source_path}")
|
|
97
|
+
with source_path.open("rb") as handle:
|
|
98
|
+
return self.put_stream(manifest, iter(lambda: handle.read(1024 * 1024), b""))
|
|
99
|
+
|
|
100
|
+
def put_stream(
|
|
101
|
+
self,
|
|
102
|
+
manifest: ArtifactManifest,
|
|
103
|
+
chunks: Iterable[bytes],
|
|
104
|
+
*,
|
|
105
|
+
max_bytes: int | None = None,
|
|
106
|
+
) -> Path:
|
|
107
|
+
"""Hash bounded chunks to a temporary file and publish create-only.
|
|
108
|
+
|
|
109
|
+
A network interruption, size violation, or bad checksum never leaves a
|
|
110
|
+
usable payload. Concurrent downloads cannot replace an existing revision.
|
|
111
|
+
Neither the incoming payload nor an existing payload is buffered in RAM.
|
|
112
|
+
"""
|
|
113
|
+
if max_bytes is not None and max_bytes < 0:
|
|
114
|
+
raise ArtifactError("stream size limit must be non-negative")
|
|
115
|
+
destination = self.path_for(manifest)
|
|
116
|
+
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
117
|
+
descriptor, temporary_name = tempfile.mkstemp(prefix=".partial-", dir=destination.parent)
|
|
118
|
+
digest = hashlib.sha256()
|
|
119
|
+
size = 0
|
|
120
|
+
try:
|
|
121
|
+
with os.fdopen(descriptor, "wb") as handle:
|
|
122
|
+
for chunk in chunks:
|
|
123
|
+
if not isinstance(chunk, bytes):
|
|
124
|
+
raise ArtifactError("artifact stream must yield bytes")
|
|
125
|
+
size += len(chunk)
|
|
126
|
+
if (max_bytes is not None and size > max_bytes) or (
|
|
127
|
+
manifest.size_bytes is not None and size > manifest.size_bytes
|
|
128
|
+
):
|
|
129
|
+
raise ArtifactError("artifact stream exceeds size limit")
|
|
130
|
+
digest.update(chunk)
|
|
131
|
+
handle.write(chunk)
|
|
132
|
+
if manifest.size_bytes is not None and size != manifest.size_bytes:
|
|
133
|
+
raise ArtifactError(
|
|
134
|
+
f"refusing materialization: size mismatch for {manifest.artifact_id}"
|
|
135
|
+
)
|
|
136
|
+
if manifest.sha256 and digest.hexdigest() != manifest.sha256:
|
|
137
|
+
raise ArtifactError(
|
|
138
|
+
f"refusing materialization: checksum mismatch for {manifest.artifact_id}"
|
|
139
|
+
)
|
|
140
|
+
handle.flush()
|
|
141
|
+
os.fsync(handle.fileno())
|
|
142
|
+
try:
|
|
143
|
+
os.link(temporary_name, destination)
|
|
144
|
+
except FileExistsError:
|
|
145
|
+
if (
|
|
146
|
+
not destination.is_file()
|
|
147
|
+
or destination.stat().st_size != size
|
|
148
|
+
or sha256_file(destination) != digest.hexdigest()
|
|
149
|
+
):
|
|
150
|
+
raise ArtifactError(
|
|
151
|
+
"refusing concurrent overwrite of artifact revision: "
|
|
152
|
+
f"{manifest.artifact_id}@{manifest.revision}"
|
|
153
|
+
) from None
|
|
154
|
+
finally:
|
|
155
|
+
if os.path.exists(temporary_name):
|
|
156
|
+
os.unlink(temporary_name)
|
|
157
|
+
return destination
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Backend contracts for LLMs, retrieval, embedding, and user simulators."""
|
|
2
|
+
|
|
3
|
+
from .embedding import (
|
|
4
|
+
CallableEmbeddingBackend,
|
|
5
|
+
DeterministicHashEmbeddingBackend,
|
|
6
|
+
EmbeddingBackend,
|
|
7
|
+
EmbeddingRequest,
|
|
8
|
+
EmbeddingResponse,
|
|
9
|
+
EmbeddingUsage,
|
|
10
|
+
ReplayEmbeddingBackend,
|
|
11
|
+
)
|
|
12
|
+
from .llm import (
|
|
13
|
+
FINAL_CONTENT_STOP_POLICY_ID,
|
|
14
|
+
CallableBackend,
|
|
15
|
+
DecompCompletionBackend,
|
|
16
|
+
FinalContentStopBackend,
|
|
17
|
+
GenerationRequest,
|
|
18
|
+
GenerationResponse,
|
|
19
|
+
LLMBackend,
|
|
20
|
+
ModelCapability,
|
|
21
|
+
OpenAICompatibleBackend,
|
|
22
|
+
ReplayBackend,
|
|
23
|
+
TransformersBackend,
|
|
24
|
+
Usage,
|
|
25
|
+
require_capabilities,
|
|
26
|
+
)
|
|
27
|
+
from .retrieval import (
|
|
28
|
+
DENSE_RETRIEVER_PROFILE_IDS,
|
|
29
|
+
RETRIEVER_PROFILES,
|
|
30
|
+
BatchTextEncoder,
|
|
31
|
+
DenseIndexSummary,
|
|
32
|
+
Document,
|
|
33
|
+
EmbeddingBackendEncoder,
|
|
34
|
+
FunctionRetriever,
|
|
35
|
+
InMemoryBM25Retriever,
|
|
36
|
+
RetrievalResult,
|
|
37
|
+
Retriever,
|
|
38
|
+
RetrieverProfile,
|
|
39
|
+
SentenceTransformerDenseRetriever,
|
|
40
|
+
SQLiteFTS5Retriever,
|
|
41
|
+
build_retriever,
|
|
42
|
+
retriever_profile,
|
|
43
|
+
)
|
|
44
|
+
from .user import (
|
|
45
|
+
CallableUserResponder,
|
|
46
|
+
ReplayTurn,
|
|
47
|
+
ReplayUserResponder,
|
|
48
|
+
UserRequest,
|
|
49
|
+
UserResponder,
|
|
50
|
+
UserResponse,
|
|
51
|
+
)
|
|
52
|
+
from .vector import DenseEmbedder, VectorSearcher
|
|
53
|
+
|
|
54
|
+
__all__ = [
|
|
55
|
+
"DENSE_RETRIEVER_PROFILE_IDS",
|
|
56
|
+
"FINAL_CONTENT_STOP_POLICY_ID",
|
|
57
|
+
"RETRIEVER_PROFILES",
|
|
58
|
+
"BatchTextEncoder",
|
|
59
|
+
"CallableBackend",
|
|
60
|
+
"CallableEmbeddingBackend",
|
|
61
|
+
"CallableUserResponder",
|
|
62
|
+
"DecompCompletionBackend",
|
|
63
|
+
"DenseEmbedder",
|
|
64
|
+
"DenseIndexSummary",
|
|
65
|
+
"DeterministicHashEmbeddingBackend",
|
|
66
|
+
"Document",
|
|
67
|
+
"EmbeddingBackend",
|
|
68
|
+
"EmbeddingBackendEncoder",
|
|
69
|
+
"EmbeddingRequest",
|
|
70
|
+
"EmbeddingResponse",
|
|
71
|
+
"EmbeddingUsage",
|
|
72
|
+
"FinalContentStopBackend",
|
|
73
|
+
"FunctionRetriever",
|
|
74
|
+
"GenerationRequest",
|
|
75
|
+
"GenerationResponse",
|
|
76
|
+
"InMemoryBM25Retriever",
|
|
77
|
+
"LLMBackend",
|
|
78
|
+
"ModelCapability",
|
|
79
|
+
"OpenAICompatibleBackend",
|
|
80
|
+
"ReplayBackend",
|
|
81
|
+
"ReplayEmbeddingBackend",
|
|
82
|
+
"ReplayTurn",
|
|
83
|
+
"ReplayUserResponder",
|
|
84
|
+
"RetrievalResult",
|
|
85
|
+
"Retriever",
|
|
86
|
+
"RetrieverProfile",
|
|
87
|
+
"SQLiteFTS5Retriever",
|
|
88
|
+
"SentenceTransformerDenseRetriever",
|
|
89
|
+
"TransformersBackend",
|
|
90
|
+
"Usage",
|
|
91
|
+
"UserRequest",
|
|
92
|
+
"UserResponder",
|
|
93
|
+
"UserResponse",
|
|
94
|
+
"VectorSearcher",
|
|
95
|
+
"build_retriever",
|
|
96
|
+
"require_capabilities",
|
|
97
|
+
"retriever_profile",
|
|
98
|
+
]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""Standard embedding seams and dependency-free fixture implementations."""
|
|
2
|
+
|
|
3
|
+
from .base import (
|
|
4
|
+
EmbeddingBackend,
|
|
5
|
+
EmbeddingRequest,
|
|
6
|
+
EmbeddingResponse,
|
|
7
|
+
EmbeddingUsage,
|
|
8
|
+
normalize_vector,
|
|
9
|
+
validate_embedding_response,
|
|
10
|
+
)
|
|
11
|
+
from .callable import CallableEmbeddingBackend, EmbeddingClient
|
|
12
|
+
from .replay import DeterministicHashEmbeddingBackend, ReplayEmbeddingBackend
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"CallableEmbeddingBackend",
|
|
16
|
+
"DeterministicHashEmbeddingBackend",
|
|
17
|
+
"EmbeddingBackend",
|
|
18
|
+
"EmbeddingClient",
|
|
19
|
+
"EmbeddingRequest",
|
|
20
|
+
"EmbeddingResponse",
|
|
21
|
+
"EmbeddingUsage",
|
|
22
|
+
"ReplayEmbeddingBackend",
|
|
23
|
+
"normalize_vector",
|
|
24
|
+
"validate_embedding_response",
|
|
25
|
+
]
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""Backend-neutral embedding request, response, and validation contracts."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import math
|
|
6
|
+
from collections.abc import Mapping
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from typing import Any, Protocol, runtime_checkable
|
|
9
|
+
|
|
10
|
+
from agentinputlab.contracts.errors import ValidationError
|
|
11
|
+
from agentinputlab.contracts.serialization import content_hash, freeze_mapping
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _is_finite_nonnegative_number(value: Any) -> bool:
|
|
15
|
+
if isinstance(value, bool) or not isinstance(value, (int, float)):
|
|
16
|
+
return False
|
|
17
|
+
try:
|
|
18
|
+
return math.isfinite(value) and value >= 0
|
|
19
|
+
except (OverflowError, TypeError, ValueError):
|
|
20
|
+
return False
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True, slots=True)
|
|
24
|
+
class EmbeddingRequest:
|
|
25
|
+
texts: tuple[str, ...]
|
|
26
|
+
normalize: bool = False
|
|
27
|
+
dimensions: int | None = None
|
|
28
|
+
metadata: Mapping[str, Any] = field(default_factory=dict)
|
|
29
|
+
|
|
30
|
+
def __post_init__(self) -> None:
|
|
31
|
+
object.__setattr__(self, "texts", tuple(self.texts))
|
|
32
|
+
object.__setattr__(self, "metadata", freeze_mapping(self.metadata))
|
|
33
|
+
if not all(isinstance(text, str) for text in self.texts):
|
|
34
|
+
raise ValidationError("embedding request texts must all be strings")
|
|
35
|
+
if self.dimensions is not None and self.dimensions < 1:
|
|
36
|
+
raise ValidationError("embedding request dimensions must be positive")
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def request_hash(self) -> str:
|
|
40
|
+
return content_hash(self)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass(frozen=True, slots=True)
|
|
44
|
+
class EmbeddingUsage:
|
|
45
|
+
input_count: int = 0
|
|
46
|
+
input_tokens: int | None = None
|
|
47
|
+
cost_usd: float | None = None
|
|
48
|
+
|
|
49
|
+
def __post_init__(self) -> None:
|
|
50
|
+
if isinstance(self.input_count, bool) or not isinstance(self.input_count, int):
|
|
51
|
+
raise ValidationError("embedding usage input_count must be a non-negative integer")
|
|
52
|
+
if self.input_count < 0:
|
|
53
|
+
raise ValidationError("embedding usage input_count must be a non-negative integer")
|
|
54
|
+
if self.input_tokens is not None and (
|
|
55
|
+
isinstance(self.input_tokens, bool)
|
|
56
|
+
or not isinstance(self.input_tokens, int)
|
|
57
|
+
or self.input_tokens < 0
|
|
58
|
+
):
|
|
59
|
+
raise ValidationError(
|
|
60
|
+
"embedding usage input_tokens must be a non-negative integer or None"
|
|
61
|
+
)
|
|
62
|
+
if self.cost_usd is not None and not _is_finite_nonnegative_number(self.cost_usd):
|
|
63
|
+
raise ValidationError(
|
|
64
|
+
"embedding usage cost_usd must be finite and non-negative or None"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@dataclass(frozen=True, slots=True)
|
|
69
|
+
class EmbeddingResponse:
|
|
70
|
+
vectors: tuple[tuple[float, ...], ...]
|
|
71
|
+
model: str = ""
|
|
72
|
+
usage: EmbeddingUsage = field(default_factory=EmbeddingUsage)
|
|
73
|
+
metadata: Mapping[str, Any] = field(default_factory=dict)
|
|
74
|
+
|
|
75
|
+
def __post_init__(self) -> None:
|
|
76
|
+
vectors = tuple(tuple(float(value) for value in vector) for vector in self.vectors)
|
|
77
|
+
object.__setattr__(self, "vectors", vectors)
|
|
78
|
+
object.__setattr__(self, "metadata", freeze_mapping(self.metadata))
|
|
79
|
+
dimensions = {len(vector) for vector in vectors}
|
|
80
|
+
if len(dimensions) > 1:
|
|
81
|
+
raise ValidationError("embedding response vectors have inconsistent dimensions")
|
|
82
|
+
if vectors and dimensions == {0}:
|
|
83
|
+
raise ValidationError("embedding response vectors must not be empty")
|
|
84
|
+
if any(not math.isfinite(value) for vector in vectors for value in vector):
|
|
85
|
+
raise ValidationError("embedding response contains a non-finite value")
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def dimensions(self) -> int | None:
|
|
89
|
+
return len(self.vectors[0]) if self.vectors else None
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@runtime_checkable
|
|
93
|
+
class EmbeddingBackend(Protocol):
|
|
94
|
+
model_id: str
|
|
95
|
+
|
|
96
|
+
def embed(self, request: EmbeddingRequest) -> EmbeddingResponse:
|
|
97
|
+
"""Embed a batch without changing input order."""
|
|
98
|
+
|
|
99
|
+
def fingerprint(self) -> Mapping[str, Any]:
|
|
100
|
+
"""Return stable, secret-free identity fields."""
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def normalize_vector(vector: tuple[float, ...]) -> tuple[float, ...]:
|
|
104
|
+
norm = math.sqrt(sum(value * value for value in vector))
|
|
105
|
+
if norm == 0:
|
|
106
|
+
return vector
|
|
107
|
+
return tuple(value / norm for value in vector)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def validate_embedding_response(
|
|
111
|
+
request: EmbeddingRequest,
|
|
112
|
+
response: EmbeddingResponse,
|
|
113
|
+
*,
|
|
114
|
+
backend_dimensions: int | None = None,
|
|
115
|
+
) -> EmbeddingResponse:
|
|
116
|
+
if len(response.vectors) != len(request.texts):
|
|
117
|
+
raise ValidationError(
|
|
118
|
+
"embedding response count does not match request: "
|
|
119
|
+
f"{len(response.vectors)} != {len(request.texts)}"
|
|
120
|
+
)
|
|
121
|
+
required_dimensions = request.dimensions or backend_dimensions
|
|
122
|
+
if required_dimensions is not None and any(
|
|
123
|
+
len(vector) != required_dimensions for vector in response.vectors
|
|
124
|
+
):
|
|
125
|
+
raise ValidationError(
|
|
126
|
+
f"embedding response dimension does not match required {required_dimensions}"
|
|
127
|
+
)
|
|
128
|
+
if request.normalize:
|
|
129
|
+
return EmbeddingResponse(
|
|
130
|
+
vectors=tuple(normalize_vector(vector) for vector in response.vectors),
|
|
131
|
+
model=response.model,
|
|
132
|
+
usage=response.usage,
|
|
133
|
+
metadata=response.metadata,
|
|
134
|
+
)
|
|
135
|
+
return response
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
__all__ = [
|
|
139
|
+
"EmbeddingBackend",
|
|
140
|
+
"EmbeddingRequest",
|
|
141
|
+
"EmbeddingResponse",
|
|
142
|
+
"EmbeddingUsage",
|
|
143
|
+
"normalize_vector",
|
|
144
|
+
"validate_embedding_response",
|
|
145
|
+
]
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Embedding backend using an explicitly injected callable client."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable, Iterable, Mapping
|
|
6
|
+
from dataclasses import dataclass, field
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from agentinputlab.contracts.errors import ValidationError
|
|
10
|
+
from agentinputlab.contracts.serialization import content_hash, freeze_mapping
|
|
11
|
+
|
|
12
|
+
from .base import (
|
|
13
|
+
EmbeddingBackend,
|
|
14
|
+
EmbeddingRequest,
|
|
15
|
+
EmbeddingResponse,
|
|
16
|
+
EmbeddingUsage,
|
|
17
|
+
validate_embedding_response,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
EmbeddingClient = Callable[
|
|
21
|
+
[EmbeddingRequest],
|
|
22
|
+
EmbeddingResponse | Iterable[Iterable[float]],
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(slots=True)
|
|
27
|
+
class CallableEmbeddingBackend(EmbeddingBackend):
|
|
28
|
+
"""Adapt a local function, SDK client, RPC bridge, or test double.
|
|
29
|
+
|
|
30
|
+
The callable itself is never fingerprinted through ``repr``. Callers must
|
|
31
|
+
supply stable identity fields for any behavior that affects an experiment.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
client: EmbeddingClient
|
|
35
|
+
model_id: str
|
|
36
|
+
revision: str = "unversioned"
|
|
37
|
+
dimensions: int | None = None
|
|
38
|
+
identity: Mapping[str, Any] = field(default_factory=dict)
|
|
39
|
+
network: bool = False
|
|
40
|
+
|
|
41
|
+
def __post_init__(self) -> None:
|
|
42
|
+
if not self.revision or self.revision == "unversioned":
|
|
43
|
+
raise ValidationError("callable embedding requires an explicit stable revision")
|
|
44
|
+
if not self.identity:
|
|
45
|
+
raise ValidationError("callable embedding requires explicit identity fields")
|
|
46
|
+
self.identity = freeze_mapping(self.identity)
|
|
47
|
+
|
|
48
|
+
def embed(self, request: EmbeddingRequest) -> EmbeddingResponse:
|
|
49
|
+
raw = self.client(request)
|
|
50
|
+
if isinstance(raw, EmbeddingResponse):
|
|
51
|
+
response = raw
|
|
52
|
+
else:
|
|
53
|
+
response = EmbeddingResponse(
|
|
54
|
+
vectors=tuple(tuple(float(value) for value in vector) for vector in raw),
|
|
55
|
+
model=self.model_id,
|
|
56
|
+
usage=EmbeddingUsage(input_count=len(request.texts)),
|
|
57
|
+
)
|
|
58
|
+
return validate_embedding_response(
|
|
59
|
+
request,
|
|
60
|
+
response,
|
|
61
|
+
backend_dimensions=self.dimensions,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
def fingerprint(self) -> Mapping[str, Any]:
|
|
65
|
+
return {
|
|
66
|
+
"backend": "agentinputlab.callable_embedding.v1",
|
|
67
|
+
"model_id": self.model_id,
|
|
68
|
+
"revision": self.revision,
|
|
69
|
+
"dimensions": self.dimensions,
|
|
70
|
+
"identity_hash": content_hash(self.identity),
|
|
71
|
+
"network": self.network,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
__all__ = ["CallableEmbeddingBackend", "EmbeddingClient"]
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""Offline replay and deterministic fixture embedding backends."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
from collections.abc import Mapping, Sequence
|
|
7
|
+
from dataclasses import dataclass, field
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from agentinputlab.contracts.errors import ValidationError
|
|
11
|
+
from agentinputlab.contracts.serialization import content_hash
|
|
12
|
+
|
|
13
|
+
from .base import (
|
|
14
|
+
EmbeddingBackend,
|
|
15
|
+
EmbeddingRequest,
|
|
16
|
+
EmbeddingResponse,
|
|
17
|
+
EmbeddingUsage,
|
|
18
|
+
validate_embedding_response,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(slots=True)
|
|
23
|
+
class ReplayEmbeddingBackend(EmbeddingBackend):
|
|
24
|
+
"""Replay exact text-to-vector fixtures; missing texts fail closed."""
|
|
25
|
+
|
|
26
|
+
vectors: Mapping[str, Sequence[float]]
|
|
27
|
+
model_id: str = "replay-embedding"
|
|
28
|
+
revision: str = "fixture-v1"
|
|
29
|
+
_vectors: Mapping[str, tuple[float, ...]] = field(init=False, repr=False)
|
|
30
|
+
_dimensions: int | None = field(init=False, repr=False)
|
|
31
|
+
|
|
32
|
+
def __post_init__(self) -> None:
|
|
33
|
+
converted = {
|
|
34
|
+
text: tuple(float(value) for value in vector) for text, vector in self.vectors.items()
|
|
35
|
+
}
|
|
36
|
+
EmbeddingResponse(vectors=tuple(converted.values()), model=self.model_id)
|
|
37
|
+
dimensions = {len(vector) for vector in converted.values()}
|
|
38
|
+
if len(dimensions) > 1:
|
|
39
|
+
raise ValidationError("replay embedding fixtures have inconsistent dimensions")
|
|
40
|
+
self._vectors = converted
|
|
41
|
+
self._dimensions = next(iter(dimensions), None)
|
|
42
|
+
|
|
43
|
+
def embed(self, request: EmbeddingRequest) -> EmbeddingResponse:
|
|
44
|
+
missing = [text for text in request.texts if text not in self._vectors]
|
|
45
|
+
if missing:
|
|
46
|
+
raise ValidationError(
|
|
47
|
+
f"replay embedding fixture is missing {len(missing)} requested text(s)"
|
|
48
|
+
)
|
|
49
|
+
response = EmbeddingResponse(
|
|
50
|
+
vectors=tuple(self._vectors[text] for text in request.texts),
|
|
51
|
+
model=self.model_id,
|
|
52
|
+
usage=EmbeddingUsage(input_count=len(request.texts)),
|
|
53
|
+
metadata={"replay": True},
|
|
54
|
+
)
|
|
55
|
+
return validate_embedding_response(
|
|
56
|
+
request,
|
|
57
|
+
response,
|
|
58
|
+
backend_dimensions=self._dimensions,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
def fingerprint(self) -> Mapping[str, Any]:
|
|
62
|
+
fixtures = [(text, self._vectors[text]) for text in sorted(self._vectors)]
|
|
63
|
+
return {
|
|
64
|
+
"backend": "agentinputlab.replay_embedding.v1",
|
|
65
|
+
"model_id": self.model_id,
|
|
66
|
+
"revision": self.revision,
|
|
67
|
+
"dimensions": self._dimensions,
|
|
68
|
+
"fixture_count": len(fixtures),
|
|
69
|
+
"fixture_hash": content_hash(fixtures),
|
|
70
|
+
"network": False,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@dataclass(frozen=True, slots=True)
|
|
75
|
+
class DeterministicHashEmbeddingBackend(EmbeddingBackend):
|
|
76
|
+
"""Small dependency-free embedding backend for tests only."""
|
|
77
|
+
|
|
78
|
+
model_id: str = "fixture-hash-embedding"
|
|
79
|
+
dimensions: int = 32
|
|
80
|
+
salt: str = "agentinputlab-v1"
|
|
81
|
+
|
|
82
|
+
def __post_init__(self) -> None:
|
|
83
|
+
if self.dimensions < 1:
|
|
84
|
+
raise ValidationError("hash embedding dimensions must be positive")
|
|
85
|
+
|
|
86
|
+
def _vector(self, text: str) -> tuple[float, ...]:
|
|
87
|
+
values: list[float] = []
|
|
88
|
+
counter = 0
|
|
89
|
+
while len(values) < self.dimensions:
|
|
90
|
+
payload = f"{self.salt}\0{counter}\0{text}".encode()
|
|
91
|
+
digest = hashlib.sha256(payload).digest()
|
|
92
|
+
for offset in range(0, len(digest), 4):
|
|
93
|
+
integer = int.from_bytes(digest[offset : offset + 4], "big")
|
|
94
|
+
values.append((integer / 0xFFFFFFFF) * 2.0 - 1.0)
|
|
95
|
+
if len(values) == self.dimensions:
|
|
96
|
+
break
|
|
97
|
+
counter += 1
|
|
98
|
+
return tuple(values)
|
|
99
|
+
|
|
100
|
+
def embed(self, request: EmbeddingRequest) -> EmbeddingResponse:
|
|
101
|
+
if request.dimensions is not None and request.dimensions != self.dimensions:
|
|
102
|
+
raise ValidationError(
|
|
103
|
+
f"hash embedding dimension is fixed at {self.dimensions}, "
|
|
104
|
+
f"requested {request.dimensions}"
|
|
105
|
+
)
|
|
106
|
+
response = EmbeddingResponse(
|
|
107
|
+
vectors=tuple(self._vector(text) for text in request.texts),
|
|
108
|
+
model=self.model_id,
|
|
109
|
+
usage=EmbeddingUsage(input_count=len(request.texts)),
|
|
110
|
+
metadata={"fixture_only": True},
|
|
111
|
+
)
|
|
112
|
+
return validate_embedding_response(
|
|
113
|
+
request,
|
|
114
|
+
response,
|
|
115
|
+
backend_dimensions=self.dimensions,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
def fingerprint(self) -> Mapping[str, Any]:
|
|
119
|
+
return {
|
|
120
|
+
"backend": "agentinputlab.hash_embedding.v1",
|
|
121
|
+
"model_id": self.model_id,
|
|
122
|
+
"dimensions": self.dimensions,
|
|
123
|
+
"salt_hash": content_hash(self.salt),
|
|
124
|
+
"fixture_only": True,
|
|
125
|
+
"network": False,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
__all__ = ["DeterministicHashEmbeddingBackend", "ReplayEmbeddingBackend"]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Language-model backend implementations."""
|
|
2
|
+
|
|
3
|
+
from .base import (
|
|
4
|
+
GenerationRequest,
|
|
5
|
+
GenerationResponse,
|
|
6
|
+
LLMBackend,
|
|
7
|
+
ModelCapability,
|
|
8
|
+
Usage,
|
|
9
|
+
require_capabilities,
|
|
10
|
+
)
|
|
11
|
+
from .callable import CallableBackend, ReplayBackend
|
|
12
|
+
from .decomp_completion import DecompCompletionBackend
|
|
13
|
+
from .final_content_stop import FINAL_CONTENT_STOP_POLICY_ID, FinalContentStopBackend
|
|
14
|
+
from .openai_compatible import OpenAICompatibleBackend
|
|
15
|
+
from .transformers import TransformersBackend
|
|
16
|
+
|
|
17
|
+
__all__ = [
|
|
18
|
+
"FINAL_CONTENT_STOP_POLICY_ID",
|
|
19
|
+
"CallableBackend",
|
|
20
|
+
"DecompCompletionBackend",
|
|
21
|
+
"FinalContentStopBackend",
|
|
22
|
+
"GenerationRequest",
|
|
23
|
+
"GenerationResponse",
|
|
24
|
+
"LLMBackend",
|
|
25
|
+
"ModelCapability",
|
|
26
|
+
"OpenAICompatibleBackend",
|
|
27
|
+
"ReplayBackend",
|
|
28
|
+
"TransformersBackend",
|
|
29
|
+
"Usage",
|
|
30
|
+
"require_capabilities",
|
|
31
|
+
]
|