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,379 @@
|
|
|
1
|
+
"""Future-turn outcome modeling for clarification selection.
|
|
2
|
+
|
|
3
|
+
This is a controlled inference-time adapter of Zhang, Knox, and Choi (ICLR
|
|
4
|
+
2025). The official method learns from double-turn preference labels. The
|
|
5
|
+
adapter retains the paper's defining comparison—rank a direct answer and
|
|
6
|
+
clarifying questions by their simulated future outcomes—but performs that
|
|
7
|
+
comparison at inference time because the authors did not publish checkpoints.
|
|
8
|
+
It must therefore not be described as official checkpoint or result parity.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import re
|
|
14
|
+
from dataclasses import dataclass
|
|
15
|
+
from typing import Any
|
|
16
|
+
|
|
17
|
+
from agentinputlab.backends.llm import GenerationRequest, LLMBackend, ModelCapability
|
|
18
|
+
from agentinputlab.backends.llm.base import require_capabilities
|
|
19
|
+
from agentinputlab.contracts import (
|
|
20
|
+
AlgorithmOutputError,
|
|
21
|
+
ExecutionTrace,
|
|
22
|
+
ExternalDependencyError,
|
|
23
|
+
FrozenAgentState,
|
|
24
|
+
InputPatch,
|
|
25
|
+
InterventionContext,
|
|
26
|
+
PatchOp,
|
|
27
|
+
PatchOperation,
|
|
28
|
+
SemanticFamily,
|
|
29
|
+
TraceEvent,
|
|
30
|
+
TracePhase,
|
|
31
|
+
ValidationError,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
from ._structured import parse_json_object, string_list, visible_problem
|
|
35
|
+
|
|
36
|
+
FUTURE_TURNS_UPSTREAM_COMMIT = "cfda2bdf3946de19a7ab4e7a8bc764ee8526ef95"
|
|
37
|
+
FUTURE_TURNS_RELEASE = "clarify.future_turns.future_outcome_match"
|
|
38
|
+
FUTURE_TURNS_PROMPT_PROTOCOL = "agentinputlab.future-turn-clarification.v1"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass(frozen=True, slots=True)
|
|
42
|
+
class FutureTurnControls:
|
|
43
|
+
max_interpretations: int = 5
|
|
44
|
+
max_candidates: int = 3
|
|
45
|
+
max_tokens: int = 768
|
|
46
|
+
temperature: float = 0.0
|
|
47
|
+
|
|
48
|
+
def __post_init__(self) -> None:
|
|
49
|
+
if not 2 <= self.max_interpretations <= 10:
|
|
50
|
+
raise ValidationError("future-turn max_interpretations must be in [2, 10]")
|
|
51
|
+
if not 1 <= self.max_candidates <= 8:
|
|
52
|
+
raise ValidationError("future-turn max_candidates must be in [1, 8]")
|
|
53
|
+
if self.max_tokens < 128:
|
|
54
|
+
raise ValidationError("future-turn max_tokens must be at least 128")
|
|
55
|
+
if self.temperature < 0:
|
|
56
|
+
raise ValidationError("future-turn temperature must be non-negative")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass(frozen=True, slots=True)
|
|
60
|
+
class FutureTurnOutcome:
|
|
61
|
+
clarification_answer: str
|
|
62
|
+
tailored_response: str
|
|
63
|
+
abstain: bool
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclass(frozen=True, slots=True)
|
|
67
|
+
class FutureTurnCandidate:
|
|
68
|
+
question: str
|
|
69
|
+
outcomes: tuple[FutureTurnOutcome, ...]
|
|
70
|
+
utility: float
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass(slots=True)
|
|
74
|
+
class FutureTurnClarifier:
|
|
75
|
+
"""Select clarification only when simulated future utility beats direct answer."""
|
|
76
|
+
|
|
77
|
+
backend: LLMBackend | None = None
|
|
78
|
+
controls: FutureTurnControls = FutureTurnControls()
|
|
79
|
+
method_id: str = "future_turns"
|
|
80
|
+
release_id: str = FUTURE_TURNS_RELEASE
|
|
81
|
+
family: SemanticFamily = SemanticFamily.CLARIFY
|
|
82
|
+
|
|
83
|
+
def __post_init__(self) -> None:
|
|
84
|
+
if not isinstance(self.controls, FutureTurnControls):
|
|
85
|
+
raise ValidationError("future-turn controls must be FutureTurnControls")
|
|
86
|
+
|
|
87
|
+
def propose(self, state: FrozenAgentState, context: InterventionContext) -> InputPatch:
|
|
88
|
+
backend = self.backend or context.backend
|
|
89
|
+
if backend is None:
|
|
90
|
+
raise ExternalDependencyError("future-turn clarification requires an LLM backend")
|
|
91
|
+
require_capabilities(
|
|
92
|
+
backend,
|
|
93
|
+
{ModelCapability.CHAT, ModelCapability.JSON_OBJECT, ModelCapability.SEED},
|
|
94
|
+
)
|
|
95
|
+
calls: list[dict[str, Any]] = []
|
|
96
|
+
analysis = self._call(
|
|
97
|
+
backend,
|
|
98
|
+
system=(
|
|
99
|
+
"Identify plausible user interpretations without using hidden benchmark labels. "
|
|
100
|
+
"Return JSON only."
|
|
101
|
+
),
|
|
102
|
+
prompt=(
|
|
103
|
+
f"{visible_problem(state)}\n\n"
|
|
104
|
+
'Return {"interpretations":[...],"direct_answer":"...",'
|
|
105
|
+
'"direct_supported_ids":[0,...]}. List distinct plausible intended tasks. '
|
|
106
|
+
"direct_supported_ids are interpretations safely satisfied by the direct answer."
|
|
107
|
+
),
|
|
108
|
+
seed=context.seed,
|
|
109
|
+
phase="interpretations_and_direct_answer",
|
|
110
|
+
calls=calls,
|
|
111
|
+
)
|
|
112
|
+
interpretations = string_list(
|
|
113
|
+
analysis.get("interpretations"),
|
|
114
|
+
label="future-turn interpretations",
|
|
115
|
+
minimum=1,
|
|
116
|
+
maximum=self.controls.max_interpretations,
|
|
117
|
+
)
|
|
118
|
+
direct_answer = analysis.get("direct_answer")
|
|
119
|
+
if not isinstance(direct_answer, str) or not direct_answer.strip():
|
|
120
|
+
raise AlgorithmOutputError("future-turn direct_answer must be non-empty text")
|
|
121
|
+
direct_ids = _integer_ids(
|
|
122
|
+
analysis.get("direct_supported_ids"),
|
|
123
|
+
upper=len(interpretations),
|
|
124
|
+
label="direct_supported_ids",
|
|
125
|
+
)
|
|
126
|
+
direct_utility = len(direct_ids) / len(interpretations)
|
|
127
|
+
|
|
128
|
+
candidates: tuple[FutureTurnCandidate, ...] = ()
|
|
129
|
+
if len(interpretations) > 1:
|
|
130
|
+
generated = self._call(
|
|
131
|
+
backend,
|
|
132
|
+
system=(
|
|
133
|
+
"Generate concise clarifying questions that distinguish the supplied user "
|
|
134
|
+
"interpretations. Return JSON only."
|
|
135
|
+
),
|
|
136
|
+
prompt=(
|
|
137
|
+
f"{visible_problem(state)}\n\n"
|
|
138
|
+
f"Interpretations:\n{_numbered(interpretations)}\n\n"
|
|
139
|
+
f'Return {{"questions":[...]}} with at most '
|
|
140
|
+
f"{self.controls.max_candidates} targeted questions."
|
|
141
|
+
),
|
|
142
|
+
seed=context.seed + 1,
|
|
143
|
+
phase="candidate_questions",
|
|
144
|
+
calls=calls,
|
|
145
|
+
)
|
|
146
|
+
questions = string_list(
|
|
147
|
+
generated.get("questions"),
|
|
148
|
+
label="future-turn candidate questions",
|
|
149
|
+
minimum=1,
|
|
150
|
+
maximum=self.controls.max_candidates,
|
|
151
|
+
)
|
|
152
|
+
candidates = tuple(
|
|
153
|
+
self._simulate_candidate(
|
|
154
|
+
backend,
|
|
155
|
+
state=state,
|
|
156
|
+
interpretations=interpretations,
|
|
157
|
+
question=question,
|
|
158
|
+
seed=context.seed + 2 + index,
|
|
159
|
+
calls=calls,
|
|
160
|
+
)
|
|
161
|
+
for index, question in enumerate(questions)
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
best = max(candidates, key=lambda item: item.utility, default=None)
|
|
165
|
+
should_clarify = best is not None and best.utility > direct_utility
|
|
166
|
+
operation = (
|
|
167
|
+
PatchOperation(
|
|
168
|
+
PatchOp.REQUEST_CLARIFICATION,
|
|
169
|
+
best.question,
|
|
170
|
+
target="user",
|
|
171
|
+
rationale="Simulated double-turn utility exceeded direct-answer utility.",
|
|
172
|
+
)
|
|
173
|
+
if should_clarify
|
|
174
|
+
else PatchOperation(
|
|
175
|
+
PatchOp.NO_OP,
|
|
176
|
+
rationale=(
|
|
177
|
+
"The direct response covered at least as many modeled interpretations as "
|
|
178
|
+
"the best simulated clarification."
|
|
179
|
+
),
|
|
180
|
+
)
|
|
181
|
+
)
|
|
182
|
+
counters = _usage_counters(calls)
|
|
183
|
+
trace = ExecutionTrace(
|
|
184
|
+
method_id=self.method_id,
|
|
185
|
+
release_id=self.release_id,
|
|
186
|
+
events=(
|
|
187
|
+
TraceEvent(
|
|
188
|
+
TracePhase.PREPARE,
|
|
189
|
+
"future_turn_interpretations",
|
|
190
|
+
{
|
|
191
|
+
"count": len(interpretations),
|
|
192
|
+
"direct_supported": len(direct_ids),
|
|
193
|
+
"direct_utility": direct_utility,
|
|
194
|
+
},
|
|
195
|
+
),
|
|
196
|
+
TraceEvent(
|
|
197
|
+
TracePhase.PROPOSE,
|
|
198
|
+
"future_outcome_preference",
|
|
199
|
+
{
|
|
200
|
+
"candidate_count": len(candidates),
|
|
201
|
+
"candidate_utilities": [item.utility for item in candidates],
|
|
202
|
+
"selected_question": best.question if should_clarify else "",
|
|
203
|
+
"clarification_selected": should_clarify,
|
|
204
|
+
},
|
|
205
|
+
),
|
|
206
|
+
),
|
|
207
|
+
counters=counters,
|
|
208
|
+
warnings=(
|
|
209
|
+
"controlled_inference_time_adapter_not_released_trained_checkpoint",
|
|
210
|
+
"future_outcomes_are_model_simulations_not_hidden_user_labels",
|
|
211
|
+
),
|
|
212
|
+
)
|
|
213
|
+
return InputPatch(
|
|
214
|
+
method_id=self.method_id,
|
|
215
|
+
release_id=self.release_id,
|
|
216
|
+
source_state_hash=state.state_hash,
|
|
217
|
+
operations=(operation,),
|
|
218
|
+
trace=trace,
|
|
219
|
+
implementation_identity=(f"future_turn_outcome_match@{FUTURE_TURNS_UPSTREAM_COMMIT}"),
|
|
220
|
+
profile_kind="controlled_adapter",
|
|
221
|
+
metadata={
|
|
222
|
+
"protocol": FUTURE_TURNS_PROMPT_PROTOCOL,
|
|
223
|
+
"upstream_commit": FUTURE_TURNS_UPSTREAM_COMMIT,
|
|
224
|
+
"interpretation_count": len(interpretations),
|
|
225
|
+
"direct_utility": direct_utility,
|
|
226
|
+
"candidate_utilities": [item.utility for item in candidates],
|
|
227
|
+
"clarification_selected": should_clarify,
|
|
228
|
+
"official_checkpoint_used": False,
|
|
229
|
+
"paper_result_parity_claimed": False,
|
|
230
|
+
"backend_fingerprint": dict(backend.fingerprint()),
|
|
231
|
+
},
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
def _simulate_candidate(
|
|
235
|
+
self,
|
|
236
|
+
backend: LLMBackend,
|
|
237
|
+
*,
|
|
238
|
+
state: FrozenAgentState,
|
|
239
|
+
interpretations: tuple[str, ...],
|
|
240
|
+
question: str,
|
|
241
|
+
seed: int,
|
|
242
|
+
calls: list[dict[str, Any]],
|
|
243
|
+
) -> FutureTurnCandidate:
|
|
244
|
+
response = self._call(
|
|
245
|
+
backend,
|
|
246
|
+
system=(
|
|
247
|
+
"Simulate the next user turn and the tailored assistant response for each "
|
|
248
|
+
"possible interpretation. A clarification answer must not reveal the final "
|
|
249
|
+
"answer verbatim. Return JSON only."
|
|
250
|
+
),
|
|
251
|
+
prompt=(
|
|
252
|
+
f"{visible_problem(state)}\n\n"
|
|
253
|
+
f"Interpretations:\n{_numbered(interpretations)}\n\n"
|
|
254
|
+
f"Clarifying question: {question}\n\n"
|
|
255
|
+
'Return {"outcomes":[{"interpretation_id":0,'
|
|
256
|
+
'"clarification_answer":"...","tailored_response":"..."},...]}. '
|
|
257
|
+
"Include every interpretation exactly once. Use empty strings when a "
|
|
258
|
+
"future answer or tailored response cannot be produced. "
|
|
259
|
+
"Keep each clarification_answer under 12 words and each tailored_response "
|
|
260
|
+
"under 24 words so the JSON object is complete within the output budget."
|
|
261
|
+
),
|
|
262
|
+
seed=seed,
|
|
263
|
+
phase="simulate_future_turn",
|
|
264
|
+
calls=calls,
|
|
265
|
+
)
|
|
266
|
+
raw = response.get("outcomes")
|
|
267
|
+
if not isinstance(raw, list):
|
|
268
|
+
raise AlgorithmOutputError("future-turn outcomes must be a JSON array")
|
|
269
|
+
indexed: dict[int, FutureTurnOutcome] = {}
|
|
270
|
+
for item in raw:
|
|
271
|
+
if not isinstance(item, dict):
|
|
272
|
+
raise AlgorithmOutputError("future-turn outcome entries must be objects")
|
|
273
|
+
identifier = item.get("interpretation_id")
|
|
274
|
+
if isinstance(identifier, bool) or not isinstance(identifier, int):
|
|
275
|
+
raise AlgorithmOutputError("future-turn interpretation_id must be an integer")
|
|
276
|
+
if identifier in indexed or not 0 <= identifier < len(interpretations):
|
|
277
|
+
raise AlgorithmOutputError("future-turn interpretation_id is invalid or duplicated")
|
|
278
|
+
answer = item.get("clarification_answer")
|
|
279
|
+
tailored = item.get("tailored_response")
|
|
280
|
+
if not isinstance(answer, str) or not isinstance(tailored, str):
|
|
281
|
+
raise AlgorithmOutputError("future-turn simulated answers must be strings")
|
|
282
|
+
clean_answer = answer.strip()
|
|
283
|
+
clean_tailored = tailored.strip()
|
|
284
|
+
# The host derives whether the future turn is usable from required
|
|
285
|
+
# text fields; it never trusts an unconstrained model-authored flag.
|
|
286
|
+
indexed[identifier] = FutureTurnOutcome(
|
|
287
|
+
clean_answer,
|
|
288
|
+
clean_tailored,
|
|
289
|
+
not clean_answer or not clean_tailored,
|
|
290
|
+
)
|
|
291
|
+
if set(indexed) != set(range(len(interpretations))):
|
|
292
|
+
raise AlgorithmOutputError("future-turn outcomes must cover every interpretation")
|
|
293
|
+
outcomes = tuple(indexed[index] for index in range(len(interpretations)))
|
|
294
|
+
useful = [
|
|
295
|
+
item
|
|
296
|
+
for item in outcomes
|
|
297
|
+
if not item.abstain
|
|
298
|
+
and item.clarification_answer
|
|
299
|
+
and item.tailored_response
|
|
300
|
+
and not _leaks_response(item.clarification_answer, item.tailored_response)
|
|
301
|
+
]
|
|
302
|
+
coverage = len(useful) / len(outcomes)
|
|
303
|
+
diversity = len({_normalize(item.tailored_response) for item in useful}) / len(outcomes)
|
|
304
|
+
return FutureTurnCandidate(
|
|
305
|
+
question=question,
|
|
306
|
+
outcomes=outcomes,
|
|
307
|
+
utility=(coverage + diversity) / 2.0,
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
def _call(
|
|
311
|
+
self,
|
|
312
|
+
backend: LLMBackend,
|
|
313
|
+
*,
|
|
314
|
+
system: str,
|
|
315
|
+
prompt: str,
|
|
316
|
+
seed: int,
|
|
317
|
+
phase: str,
|
|
318
|
+
calls: list[dict[str, Any]],
|
|
319
|
+
) -> Any:
|
|
320
|
+
request = GenerationRequest(
|
|
321
|
+
prompt=prompt,
|
|
322
|
+
system=system,
|
|
323
|
+
temperature=self.controls.temperature,
|
|
324
|
+
max_tokens=self.controls.max_tokens,
|
|
325
|
+
seed=seed,
|
|
326
|
+
response_format={"type": "json_object"},
|
|
327
|
+
metadata={
|
|
328
|
+
"method_id": self.method_id,
|
|
329
|
+
"release_id": self.release_id,
|
|
330
|
+
"phase": phase,
|
|
331
|
+
},
|
|
332
|
+
)
|
|
333
|
+
response = backend.generate(request)
|
|
334
|
+
calls.append(
|
|
335
|
+
{
|
|
336
|
+
"request_hash": request.request_hash,
|
|
337
|
+
"input_tokens": response.usage.input_tokens,
|
|
338
|
+
"output_tokens": response.usage.output_tokens,
|
|
339
|
+
"cost_usd": response.usage.cost_usd,
|
|
340
|
+
}
|
|
341
|
+
)
|
|
342
|
+
return parse_json_object(response.text, label=f"future-turn {phase}")
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def _integer_ids(value: Any, *, upper: int, label: str) -> tuple[int, ...]:
|
|
346
|
+
if not isinstance(value, list):
|
|
347
|
+
raise AlgorithmOutputError(f"future-turn {label} must be a JSON array")
|
|
348
|
+
result: list[int] = []
|
|
349
|
+
for item in value:
|
|
350
|
+
if isinstance(item, bool) or not isinstance(item, int) or not 0 <= item < upper:
|
|
351
|
+
raise AlgorithmOutputError(f"future-turn {label} contains an invalid index")
|
|
352
|
+
if item not in result:
|
|
353
|
+
result.append(item)
|
|
354
|
+
return tuple(result)
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
def _normalize(text: str) -> str:
|
|
358
|
+
return re.sub(r"\W+", "", text.casefold())
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
def _leaks_response(answer: str, response: str) -> bool:
|
|
362
|
+
normalized_answer = _normalize(answer)
|
|
363
|
+
normalized_response = _normalize(response)
|
|
364
|
+
return bool(normalized_response) and normalized_response in normalized_answer
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def _numbered(items: tuple[str, ...]) -> str:
|
|
368
|
+
return "\n".join(f"{index}. {item}" for index, item in enumerate(items))
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def _usage_counters(calls: list[dict[str, Any]]) -> dict[str, int | float]:
|
|
372
|
+
priced = [item["cost_usd"] for item in calls if item["cost_usd"] is not None]
|
|
373
|
+
return {
|
|
374
|
+
"model_calls": len(calls),
|
|
375
|
+
"input_tokens": sum(int(item["input_tokens"]) for item in calls),
|
|
376
|
+
"output_tokens": sum(int(item["output_tokens"]) for item in calls),
|
|
377
|
+
"cost_usd": sum(float(item) for item in priced),
|
|
378
|
+
"unpriced_model_calls": sum(item["cost_usd"] is None for item in calls),
|
|
379
|
+
}
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"""Prompt-native UDCS component preserving the repository routing semantics."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
|
|
8
|
+
from agentinputlab.backends.llm import GenerationRequest, LLMBackend, ModelCapability
|
|
9
|
+
from agentinputlab.backends.llm.base import require_capabilities
|
|
10
|
+
from agentinputlab.contracts import (
|
|
11
|
+
AlgorithmOutputError,
|
|
12
|
+
ExecutionTrace,
|
|
13
|
+
ExternalDependencyError,
|
|
14
|
+
FrozenAgentState,
|
|
15
|
+
InputPatch,
|
|
16
|
+
InterventionContext,
|
|
17
|
+
PatchOp,
|
|
18
|
+
PatchOperation,
|
|
19
|
+
SemanticFamily,
|
|
20
|
+
TraceEvent,
|
|
21
|
+
TracePhase,
|
|
22
|
+
ValidationError,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
_PROBABILITY = r"[\d.]+"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass(frozen=True, slots=True)
|
|
29
|
+
class UDCSDecision:
|
|
30
|
+
think: str
|
|
31
|
+
u_request: float
|
|
32
|
+
u_request_explanation: str
|
|
33
|
+
action: str
|
|
34
|
+
confidence: float
|
|
35
|
+
explanation: str
|
|
36
|
+
raw_text: str
|
|
37
|
+
clamped_fields: tuple[str, ...] = ()
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def requests_clarification(self) -> bool:
|
|
41
|
+
return self.action.strip().lower().startswith("request_clarification")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def parse_udcs_response(text: str) -> UDCSDecision:
|
|
45
|
+
"""Parse the six repository tags.
|
|
46
|
+
|
|
47
|
+
This intentionally preserves the upstream behavior: ``think`` and both
|
|
48
|
+
explanations may be empty, action falls back to a fenced block/full output,
|
|
49
|
+
and numeric uncertainty/confidence values are clamped to ``[0, 1]``.
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
if not isinstance(text, str) or not text.strip():
|
|
53
|
+
raise AlgorithmOutputError("UDCS response must be non-empty text")
|
|
54
|
+
think = _optional_tag(text, "think")
|
|
55
|
+
action = _parse_action(text)
|
|
56
|
+
u_raw = _required_probability(text, "u_request")
|
|
57
|
+
confidence_raw = _required_probability(text, "confidence")
|
|
58
|
+
clamped: list[str] = []
|
|
59
|
+
u_request = _clamp(u_raw)
|
|
60
|
+
confidence = _clamp(confidence_raw)
|
|
61
|
+
if u_request != u_raw:
|
|
62
|
+
clamped.append("u_request")
|
|
63
|
+
if confidence != confidence_raw:
|
|
64
|
+
clamped.append("confidence")
|
|
65
|
+
return UDCSDecision(
|
|
66
|
+
think=think,
|
|
67
|
+
u_request=u_request,
|
|
68
|
+
u_request_explanation=_optional_tag(text, "u_request_explanation"),
|
|
69
|
+
action=action,
|
|
70
|
+
confidence=confidence,
|
|
71
|
+
explanation=_optional_tag(text, "explanation"),
|
|
72
|
+
raw_text=text,
|
|
73
|
+
clamped_fields=tuple(clamped),
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _optional_tag(text: str, tag: str) -> str:
|
|
78
|
+
match = re.search(rf"<{tag}>(.*?)</{tag}>", text, re.DOTALL)
|
|
79
|
+
return match.group(1).strip() if match else ""
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _required_probability(text: str, tag: str) -> float:
|
|
83
|
+
match = re.search(rf"<{tag}>\s*({_PROBABILITY})\s*</{tag}>", text)
|
|
84
|
+
if not match:
|
|
85
|
+
raise AlgorithmOutputError(f"UDCS response is missing a valid <{tag}> value")
|
|
86
|
+
try:
|
|
87
|
+
return float(match.group(1))
|
|
88
|
+
except ValueError as exc:
|
|
89
|
+
raise AlgorithmOutputError(f"UDCS <{tag}> value is not numeric") from exc
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _parse_action(text: str) -> str:
|
|
93
|
+
match = re.search(r"<action>(.*?)</action>", text, re.DOTALL)
|
|
94
|
+
if match:
|
|
95
|
+
return match.group(1).strip()
|
|
96
|
+
fenced = re.search(r"```(?:\w+)?\s*(.*?)\s*```", text, re.DOTALL)
|
|
97
|
+
if fenced:
|
|
98
|
+
return fenced.group(1).strip()
|
|
99
|
+
return text.strip()
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _clamp(value: float) -> float:
|
|
103
|
+
return max(0.0, min(1.0, value))
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@dataclass(slots=True)
|
|
107
|
+
class UDCSPromptNativePolicy:
|
|
108
|
+
"""One-step prompt-native component from the UDCS Proposed-v4 runner.
|
|
109
|
+
|
|
110
|
+
The threshold is stated in the prompt but is deliberately *not* enforced
|
|
111
|
+
in Python. This reproduces the pinned repository semantics. A
|
|
112
|
+
deterministic threshold router must use a different release ID.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
backend: LLMBackend | None = None
|
|
116
|
+
clarification_threshold: float = 0.5
|
|
117
|
+
temperature: float = 0.0
|
|
118
|
+
max_tokens: int = 800
|
|
119
|
+
method_id: str = "udcs"
|
|
120
|
+
release_id: str = "clarify.udcs.repo_native_prompt_route"
|
|
121
|
+
family: SemanticFamily = SemanticFamily.CLARIFY
|
|
122
|
+
|
|
123
|
+
def __post_init__(self) -> None:
|
|
124
|
+
if not 0.0 <= self.clarification_threshold <= 1.0:
|
|
125
|
+
raise ValidationError("UDCS clarification_threshold must be in [0, 1]")
|
|
126
|
+
if self.temperature < 0:
|
|
127
|
+
raise ValidationError("UDCS temperature must be non-negative")
|
|
128
|
+
if self.max_tokens < 1:
|
|
129
|
+
raise ValidationError("UDCS max_tokens must be positive")
|
|
130
|
+
|
|
131
|
+
def propose(self, state: FrozenAgentState, context: InterventionContext) -> InputPatch:
|
|
132
|
+
backend = self.backend or context.backend
|
|
133
|
+
if backend is None:
|
|
134
|
+
raise ExternalDependencyError("UDCS requires an injected chat backend")
|
|
135
|
+
require_capabilities(backend, {ModelCapability.CHAT})
|
|
136
|
+
response = backend.generate(
|
|
137
|
+
GenerationRequest(
|
|
138
|
+
prompt=_build_user_prompt(state, self.clarification_threshold),
|
|
139
|
+
system=_system_prompt(),
|
|
140
|
+
temperature=self.temperature,
|
|
141
|
+
max_tokens=self.max_tokens,
|
|
142
|
+
seed=context.seed,
|
|
143
|
+
stop=(),
|
|
144
|
+
metadata={
|
|
145
|
+
"method_id": self.method_id,
|
|
146
|
+
"release_id": self.release_id,
|
|
147
|
+
"routing_semantics": "prompt_native",
|
|
148
|
+
},
|
|
149
|
+
)
|
|
150
|
+
)
|
|
151
|
+
decision = parse_udcs_response(response.text)
|
|
152
|
+
warns = tuple(f"clamped_{name}" for name in decision.clamped_fields)
|
|
153
|
+
trace = ExecutionTrace(
|
|
154
|
+
method_id=self.method_id,
|
|
155
|
+
release_id=self.release_id,
|
|
156
|
+
events=(
|
|
157
|
+
TraceEvent(
|
|
158
|
+
TracePhase.PREPARE,
|
|
159
|
+
"prompt_native_threshold",
|
|
160
|
+
{
|
|
161
|
+
"threshold": self.clarification_threshold,
|
|
162
|
+
"python_enforced": False,
|
|
163
|
+
},
|
|
164
|
+
),
|
|
165
|
+
TraceEvent(
|
|
166
|
+
TracePhase.PROPOSE,
|
|
167
|
+
"parsed_udcs_decision",
|
|
168
|
+
{
|
|
169
|
+
"think": decision.think,
|
|
170
|
+
"u_request": decision.u_request,
|
|
171
|
+
"u_request_explanation": decision.u_request_explanation,
|
|
172
|
+
"action": decision.action,
|
|
173
|
+
"confidence": decision.confidence,
|
|
174
|
+
"explanation": decision.explanation,
|
|
175
|
+
"threshold_disagreement": (
|
|
176
|
+
decision.u_request >= self.clarification_threshold
|
|
177
|
+
and not decision.requests_clarification
|
|
178
|
+
),
|
|
179
|
+
},
|
|
180
|
+
),
|
|
181
|
+
),
|
|
182
|
+
counters={"model_calls": 1},
|
|
183
|
+
warnings=warns,
|
|
184
|
+
)
|
|
185
|
+
if decision.requests_clarification:
|
|
186
|
+
operation = PatchOperation(
|
|
187
|
+
PatchOp.REQUEST_CLARIFICATION,
|
|
188
|
+
_clarification_request(decision),
|
|
189
|
+
target="user",
|
|
190
|
+
rationale=decision.u_request_explanation,
|
|
191
|
+
)
|
|
192
|
+
else:
|
|
193
|
+
operation = PatchOperation(
|
|
194
|
+
PatchOp.NO_OP,
|
|
195
|
+
rationale=(
|
|
196
|
+
"UDCS prompt-native model selected a non-clarification action; "
|
|
197
|
+
"the repository does not enforce the numerical threshold"
|
|
198
|
+
),
|
|
199
|
+
)
|
|
200
|
+
return InputPatch(
|
|
201
|
+
method_id=self.method_id,
|
|
202
|
+
release_id=self.release_id,
|
|
203
|
+
source_state_hash=state.state_hash,
|
|
204
|
+
operations=(operation,),
|
|
205
|
+
trace=trace,
|
|
206
|
+
implementation_identity="thin_prompt_native_component",
|
|
207
|
+
profile_kind="official_native",
|
|
208
|
+
metadata={
|
|
209
|
+
"u_request": decision.u_request,
|
|
210
|
+
"confidence": decision.confidence,
|
|
211
|
+
"raw_action": decision.action,
|
|
212
|
+
"threshold": self.clarification_threshold,
|
|
213
|
+
"threshold_enforced": False,
|
|
214
|
+
"backend_fingerprint": dict(backend.fingerprint()),
|
|
215
|
+
},
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def _system_prompt() -> str:
|
|
220
|
+
return (
|
|
221
|
+
"You are an interactive agent. Follow the available-action contract. "
|
|
222
|
+
"Return all six XML-like fields requested by the user message."
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
def _build_user_prompt(state: FrozenAgentState, threshold: float) -> str:
|
|
227
|
+
context = "\n\n".join(block.text for block in state.context) or "(none)"
|
|
228
|
+
actions = "\n".join(f"- {name}" for name in state.tool_names) or "(none)"
|
|
229
|
+
history = "\n".join(f"{message.role}: {message.content}" for message in state.messages)
|
|
230
|
+
return (
|
|
231
|
+
f"# Goal\n\n{state.query}\n\n"
|
|
232
|
+
f"# Instruction\n\n{state.instruction or '(none)'}\n\n"
|
|
233
|
+
f"# Current Observation\n\n{context}\n\n"
|
|
234
|
+
f"# Available Actions\n\n{actions}\n"
|
|
235
|
+
"- request_clarification\n\n"
|
|
236
|
+
f"# History\n\n{history or '(none)'}\n\n"
|
|
237
|
+
"# Next action\n\n"
|
|
238
|
+
"Reason inside <think>...</think>. Assess request uncertainty from 0.0 to 1.0 "
|
|
239
|
+
"inside <u_request>...</u_request>, then explain it inside "
|
|
240
|
+
"<u_request_explanation>...</u_request_explanation>. "
|
|
241
|
+
f"If u_request >= {threshold}, your action MUST be request_clarification. "
|
|
242
|
+
"Put the selected action inside <action>...</action>. Finally provide "
|
|
243
|
+
"<confidence>...</confidence> and <explanation>...</explanation>."
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def _clarification_request(decision: UDCSDecision) -> str:
|
|
248
|
+
action = decision.action.strip()
|
|
249
|
+
if ":" in action:
|
|
250
|
+
requested = action.split(":", 1)[1].strip()
|
|
251
|
+
if requested:
|
|
252
|
+
return requested
|
|
253
|
+
if decision.u_request_explanation:
|
|
254
|
+
return decision.u_request_explanation
|
|
255
|
+
return "Please clarify the missing or ambiguous details in your request."
|