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,754 @@
|
|
|
1
|
+
"""Transparent monitoring wrappers for runtime dependencies."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import time
|
|
6
|
+
from collections.abc import Mapping
|
|
7
|
+
from contextlib import suppress
|
|
8
|
+
from dataclasses import dataclass, replace
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from agentinputlab.backends.llm.base import GenerationRequest, GenerationResponse, LLMBackend
|
|
12
|
+
from agentinputlab.backends.retrieval.base import RetrievalResult, Retriever
|
|
13
|
+
from agentinputlab.backends.vector import DenseEmbedder, VectorSearcher
|
|
14
|
+
from agentinputlab.connectors.tools.base import ToolCall, ToolConnector, ToolResult, ToolSpec
|
|
15
|
+
from agentinputlab.contracts.errors import (
|
|
16
|
+
AlgorithmOutputError,
|
|
17
|
+
BudgetExceededError,
|
|
18
|
+
ExternalDependencyError,
|
|
19
|
+
ValidationError,
|
|
20
|
+
)
|
|
21
|
+
from agentinputlab.contracts.lifecycle import InterventionContext
|
|
22
|
+
from agentinputlab.contracts.state import FrozenAgentState
|
|
23
|
+
|
|
24
|
+
from .budget import BudgetLedger, PricingCatalog
|
|
25
|
+
from .models import EventKind, ResourceReceipt, ResourceUsage
|
|
26
|
+
from .monitor import RunMonitor
|
|
27
|
+
|
|
28
|
+
_EXTERNAL_USAGE_INTEGER_FIELDS = (
|
|
29
|
+
"model_calls",
|
|
30
|
+
"retrieval_calls",
|
|
31
|
+
"tool_calls",
|
|
32
|
+
"embedding_calls",
|
|
33
|
+
"unpriced_model_calls",
|
|
34
|
+
"input_tokens",
|
|
35
|
+
"output_tokens",
|
|
36
|
+
)
|
|
37
|
+
_EXTERNAL_USAGE_FLOAT_FIELDS = (
|
|
38
|
+
"cpu_seconds",
|
|
39
|
+
"accelerator_seconds",
|
|
40
|
+
"cost_usd",
|
|
41
|
+
"compute_cost_usd",
|
|
42
|
+
)
|
|
43
|
+
_EXTERNAL_USAGE_REQUIRED_FIELDS = (
|
|
44
|
+
"model_calls",
|
|
45
|
+
"retrieval_calls",
|
|
46
|
+
"input_tokens",
|
|
47
|
+
"output_tokens",
|
|
48
|
+
)
|
|
49
|
+
_EXTERNAL_USAGE_FIELDS = frozenset((*_EXTERNAL_USAGE_INTEGER_FIELDS, *_EXTERNAL_USAGE_FLOAT_FIELDS))
|
|
50
|
+
_EXTERNAL_RESERVATION_FIELDS = frozenset(
|
|
51
|
+
("model_calls", "retrieval_calls", "tool_calls", "embedding_calls")
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def normalize_external_usage(envelope: object) -> ResourceUsage:
|
|
56
|
+
"""Validate a common, lossless usage envelope for external executors.
|
|
57
|
+
|
|
58
|
+
Model and retrieval call counts plus both token directions are mandatory.
|
|
59
|
+
A model call without an explicit provider cost is conservatively marked
|
|
60
|
+
unpriced, which makes a configured cost budget fail closed.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
if not isinstance(envelope, Mapping):
|
|
64
|
+
raise AlgorithmOutputError("external runtime response requires a usage mapping")
|
|
65
|
+
if any(not isinstance(key, str) for key in envelope):
|
|
66
|
+
raise AlgorithmOutputError("external runtime usage keys must be strings")
|
|
67
|
+
unknown = set(envelope) - _EXTERNAL_USAGE_FIELDS
|
|
68
|
+
if unknown:
|
|
69
|
+
raise AlgorithmOutputError(
|
|
70
|
+
"external runtime usage contains unsupported fields: " + ", ".join(sorted(unknown))
|
|
71
|
+
)
|
|
72
|
+
missing = [field for field in _EXTERNAL_USAGE_REQUIRED_FIELDS if field not in envelope]
|
|
73
|
+
if missing:
|
|
74
|
+
raise AlgorithmOutputError(
|
|
75
|
+
"external runtime usage lacks required fields: " + ", ".join(missing)
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
values = dict(envelope)
|
|
79
|
+
model_calls = values["model_calls"]
|
|
80
|
+
if isinstance(model_calls, bool) or not isinstance(model_calls, int) or model_calls < 0:
|
|
81
|
+
raise AlgorithmOutputError("external runtime model_calls must be a non-negative integer")
|
|
82
|
+
if "cost_usd" not in values:
|
|
83
|
+
if "unpriced_model_calls" in values and values["unpriced_model_calls"] != model_calls:
|
|
84
|
+
raise AlgorithmOutputError(
|
|
85
|
+
"external runtime usage without cost_usd must mark every model call unpriced"
|
|
86
|
+
)
|
|
87
|
+
values["unpriced_model_calls"] = model_calls
|
|
88
|
+
else:
|
|
89
|
+
values.setdefault("unpriced_model_calls", 0)
|
|
90
|
+
for field in _EXTERNAL_USAGE_INTEGER_FIELDS:
|
|
91
|
+
values.setdefault(field, 0)
|
|
92
|
+
for field in _EXTERNAL_USAGE_FLOAT_FIELDS:
|
|
93
|
+
values.setdefault(field, 0.0)
|
|
94
|
+
try:
|
|
95
|
+
usage = ResourceUsage(**values)
|
|
96
|
+
except ValidationError as exc:
|
|
97
|
+
raise AlgorithmOutputError(f"invalid external runtime usage: {exc}") from exc
|
|
98
|
+
if usage.unpriced_model_calls > usage.model_calls:
|
|
99
|
+
raise AlgorithmOutputError("unpriced_model_calls cannot exceed model_calls")
|
|
100
|
+
return usage
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def external_usage_counters(usage: ResourceUsage) -> dict[str, int | float]:
|
|
104
|
+
"""Return counters accepted by ``InterventionRunner`` trace reconciliation."""
|
|
105
|
+
|
|
106
|
+
if not isinstance(usage, ResourceUsage):
|
|
107
|
+
raise TypeError("usage must be a ResourceUsage")
|
|
108
|
+
return {
|
|
109
|
+
field: getattr(usage, field)
|
|
110
|
+
for field in (*_EXTERNAL_USAGE_INTEGER_FIELDS, *_EXTERNAL_USAGE_FLOAT_FIELDS)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _request_reservation(request: object) -> ResourceUsage:
|
|
115
|
+
planner = getattr(request, "external_reservation", None)
|
|
116
|
+
if not callable(planner):
|
|
117
|
+
return ResourceUsage()
|
|
118
|
+
envelope = planner()
|
|
119
|
+
if not isinstance(envelope, Mapping):
|
|
120
|
+
raise ValidationError("external reservation plan must be a mapping")
|
|
121
|
+
if any(not isinstance(key, str) for key in envelope):
|
|
122
|
+
raise ValidationError("external reservation plan keys must be strings")
|
|
123
|
+
unknown = set(envelope) - _EXTERNAL_RESERVATION_FIELDS
|
|
124
|
+
if unknown:
|
|
125
|
+
raise ValidationError(
|
|
126
|
+
"external reservation plan contains unsupported fields: " + ", ".join(sorted(unknown))
|
|
127
|
+
)
|
|
128
|
+
try:
|
|
129
|
+
return ResourceUsage(**dict(envelope))
|
|
130
|
+
except ValidationError as exc:
|
|
131
|
+
raise ValidationError(f"invalid external reservation plan: {exc}") from exc
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _usage_delta(actual: ResourceUsage, reserved: ResourceUsage) -> ResourceUsage:
|
|
135
|
+
values: dict[str, int | float] = {}
|
|
136
|
+
for field in (*_EXTERNAL_USAGE_INTEGER_FIELDS, *_EXTERNAL_USAGE_FLOAT_FIELDS):
|
|
137
|
+
difference = getattr(actual, field) - getattr(reserved, field)
|
|
138
|
+
if difference < 0:
|
|
139
|
+
raise AlgorithmOutputError(
|
|
140
|
+
f"external runtime usage {field} is below its pre-execution reservation"
|
|
141
|
+
)
|
|
142
|
+
values[field] = difference
|
|
143
|
+
return ResourceUsage(**values)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _raise_for_declared_external_failure(request: object, result: object) -> None:
|
|
147
|
+
hook = getattr(request, "raise_for_external_status", None)
|
|
148
|
+
if callable(hook):
|
|
149
|
+
hook(result)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _response_usage(result: object) -> ResourceUsage:
|
|
153
|
+
return normalize_external_usage(_response_usage_envelope(result))
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def _response_usage_envelope(result: object) -> object:
|
|
157
|
+
return result.get("usage") if isinstance(result, Mapping) else getattr(result, "usage", None)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@dataclass(slots=True)
|
|
161
|
+
class ObservedExternalRuntime:
|
|
162
|
+
"""Monitor a fingerprinted worker/runtime injected through the run context."""
|
|
163
|
+
|
|
164
|
+
inner: Any
|
|
165
|
+
monitor: RunMonitor
|
|
166
|
+
ledger: BudgetLedger
|
|
167
|
+
run_id: str
|
|
168
|
+
|
|
169
|
+
@property
|
|
170
|
+
def worker_id(self) -> str:
|
|
171
|
+
return str(getattr(self.inner, "worker_id", "external-runtime"))
|
|
172
|
+
|
|
173
|
+
def fingerprint(self) -> Mapping[str, Any]:
|
|
174
|
+
fingerprint = getattr(self.inner, "fingerprint", None)
|
|
175
|
+
if not callable(fingerprint):
|
|
176
|
+
raise ValidationError("external runtime must expose fingerprint()")
|
|
177
|
+
identity = fingerprint()
|
|
178
|
+
if not isinstance(identity, Mapping) or not identity:
|
|
179
|
+
raise ValidationError("external runtime fingerprint must be a non-empty mapping")
|
|
180
|
+
return identity
|
|
181
|
+
|
|
182
|
+
def call(self, payload: Any) -> Any:
|
|
183
|
+
return self._execute("call", payload)
|
|
184
|
+
|
|
185
|
+
def call_controlled(self, request: Any) -> Any:
|
|
186
|
+
"""Call a mapping-based worker while retaining request control hooks."""
|
|
187
|
+
|
|
188
|
+
serializer = getattr(request, "as_dict", None)
|
|
189
|
+
if not callable(serializer):
|
|
190
|
+
raise ValidationError("controlled external request must expose as_dict()")
|
|
191
|
+
return self._execute("call", request, delegated_request=serializer())
|
|
192
|
+
|
|
193
|
+
def invoke(self, payload: Any) -> Any:
|
|
194
|
+
return self._execute("invoke", payload)
|
|
195
|
+
|
|
196
|
+
def reformulate(self, request: Any) -> Any:
|
|
197
|
+
return self._execute("reformulate", request)
|
|
198
|
+
|
|
199
|
+
def select(self, request: Any) -> Any:
|
|
200
|
+
return self._execute("select", request)
|
|
201
|
+
|
|
202
|
+
def run(self, request: Any) -> Any:
|
|
203
|
+
return self._execute("run", request)
|
|
204
|
+
|
|
205
|
+
def _execute(
|
|
206
|
+
self,
|
|
207
|
+
operation: str,
|
|
208
|
+
request: Any,
|
|
209
|
+
*,
|
|
210
|
+
delegated_request: Any = None,
|
|
211
|
+
) -> Any:
|
|
212
|
+
method = getattr(self.inner, operation, None)
|
|
213
|
+
if not callable(method):
|
|
214
|
+
raise ValidationError(f"external runtime does not implement {operation}()")
|
|
215
|
+
component = f"external_runtime.{operation}"
|
|
216
|
+
started = time.perf_counter_ns()
|
|
217
|
+
self.monitor.emit(
|
|
218
|
+
EventKind.STAGE_STARTED,
|
|
219
|
+
run_id=self.run_id,
|
|
220
|
+
component=component,
|
|
221
|
+
payload={"runtime_fingerprint": dict(self.fingerprint())},
|
|
222
|
+
)
|
|
223
|
+
reservation = _request_reservation(request)
|
|
224
|
+
if reservation != ResourceUsage():
|
|
225
|
+
try:
|
|
226
|
+
self.ledger.reserve_pending(reservation)
|
|
227
|
+
except BudgetExceededError:
|
|
228
|
+
self.monitor.emit(
|
|
229
|
+
EventKind.BUDGET_EXCEEDED,
|
|
230
|
+
run_id=self.run_id,
|
|
231
|
+
component=component,
|
|
232
|
+
)
|
|
233
|
+
raise
|
|
234
|
+
try:
|
|
235
|
+
result = method(request if delegated_request is None else delegated_request)
|
|
236
|
+
except Exception as exc:
|
|
237
|
+
self._record_resource_receipt(component=component)
|
|
238
|
+
self._settle_runtime_exception(reservation, component=component)
|
|
239
|
+
self.monitor.record_failure(
|
|
240
|
+
exc,
|
|
241
|
+
run_id=self.run_id,
|
|
242
|
+
category="external_runtime_error",
|
|
243
|
+
stage=component,
|
|
244
|
+
)
|
|
245
|
+
raise
|
|
246
|
+
self._record_resource_receipt(component=component)
|
|
247
|
+
try:
|
|
248
|
+
_raise_for_declared_external_failure(request, result)
|
|
249
|
+
except (ExternalDependencyError, AlgorithmOutputError) as exc:
|
|
250
|
+
# A declared model/algorithm failure can carry fully known actual
|
|
251
|
+
# usage. It is distinct from a malformed usage envelope: settle
|
|
252
|
+
# those tokens before propagating the original typed failure.
|
|
253
|
+
self._settle_declared_failure(result, reservation, component=component)
|
|
254
|
+
self.monitor.record_failure(
|
|
255
|
+
exc,
|
|
256
|
+
run_id=self.run_id,
|
|
257
|
+
category="external_runtime_error",
|
|
258
|
+
stage=component,
|
|
259
|
+
)
|
|
260
|
+
raise
|
|
261
|
+
try:
|
|
262
|
+
usage = _response_usage(result)
|
|
263
|
+
_usage_delta(usage, reservation)
|
|
264
|
+
except AlgorithmOutputError as exc:
|
|
265
|
+
# The external side effect already happened. Preserve a known
|
|
266
|
+
# minimum model call and unknown price before rejecting telemetry,
|
|
267
|
+
# without double-counting a call already reserved above.
|
|
268
|
+
minimum_actual = reservation + ResourceUsage(
|
|
269
|
+
model_calls=0 if reservation.model_calls else 1,
|
|
270
|
+
unpriced_model_calls=max(1, reservation.model_calls),
|
|
271
|
+
)
|
|
272
|
+
self.monitor.record_failure(
|
|
273
|
+
exc,
|
|
274
|
+
run_id=self.run_id,
|
|
275
|
+
category="external_usage_error",
|
|
276
|
+
stage=component,
|
|
277
|
+
)
|
|
278
|
+
self._settle_actual(minimum_actual, reservation, component=component)
|
|
279
|
+
raise
|
|
280
|
+
self._settle_actual(usage, reservation, component=component)
|
|
281
|
+
self.monitor.emit(
|
|
282
|
+
EventKind.STAGE_FINISHED,
|
|
283
|
+
run_id=self.run_id,
|
|
284
|
+
component=component,
|
|
285
|
+
payload={
|
|
286
|
+
"duration_ms": (time.perf_counter_ns() - started) / 1_000_000,
|
|
287
|
+
"usage": usage.as_dict(),
|
|
288
|
+
},
|
|
289
|
+
)
|
|
290
|
+
return result
|
|
291
|
+
|
|
292
|
+
def _record_resource_receipt(self, *, component: str) -> None:
|
|
293
|
+
receipt = getattr(self.inner, "last_resource_receipt", None)
|
|
294
|
+
if isinstance(receipt, ResourceReceipt):
|
|
295
|
+
self.monitor.record_resource_receipt(
|
|
296
|
+
receipt,
|
|
297
|
+
run_id=self.run_id,
|
|
298
|
+
component=component,
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
def _settle_actual(
|
|
302
|
+
self,
|
|
303
|
+
actual: ResourceUsage,
|
|
304
|
+
reservation: ResourceUsage,
|
|
305
|
+
*,
|
|
306
|
+
component: str,
|
|
307
|
+
) -> None:
|
|
308
|
+
delta = _usage_delta(actual, reservation)
|
|
309
|
+
try:
|
|
310
|
+
self.ledger.charge_actual(delta)
|
|
311
|
+
except BudgetExceededError:
|
|
312
|
+
self.ledger.commit_pending(reservation)
|
|
313
|
+
self.monitor.record_usage(actual, run_id=self.run_id, component=component)
|
|
314
|
+
self.monitor.emit(
|
|
315
|
+
EventKind.BUDGET_EXCEEDED,
|
|
316
|
+
run_id=self.run_id,
|
|
317
|
+
component=component,
|
|
318
|
+
)
|
|
319
|
+
raise
|
|
320
|
+
self.ledger.commit_pending(reservation)
|
|
321
|
+
self.monitor.record_usage(actual, run_id=self.run_id, component=component)
|
|
322
|
+
|
|
323
|
+
def _settle_declared_failure(
|
|
324
|
+
self,
|
|
325
|
+
result: object,
|
|
326
|
+
reservation: ResourceUsage,
|
|
327
|
+
*,
|
|
328
|
+
component: str,
|
|
329
|
+
) -> None:
|
|
330
|
+
envelope = _response_usage_envelope(result)
|
|
331
|
+
explicitly_unconsumed = (
|
|
332
|
+
isinstance(result, Mapping) and result.get("consumed") is False and envelope is None
|
|
333
|
+
)
|
|
334
|
+
if explicitly_unconsumed:
|
|
335
|
+
self._cancel_pending(reservation)
|
|
336
|
+
return
|
|
337
|
+
try:
|
|
338
|
+
actual = normalize_external_usage(envelope)
|
|
339
|
+
except AlgorithmOutputError:
|
|
340
|
+
self._commit_failed_minimum(reservation, component=component)
|
|
341
|
+
return
|
|
342
|
+
self._cancel_pending(reservation)
|
|
343
|
+
try:
|
|
344
|
+
self.ledger.charge_actual(actual)
|
|
345
|
+
except BudgetExceededError:
|
|
346
|
+
# The typed worker failure remains the primary cell-invalidating
|
|
347
|
+
# exception, while the irreversible overage remains on the ledger.
|
|
348
|
+
self.monitor.emit(
|
|
349
|
+
EventKind.BUDGET_EXCEEDED,
|
|
350
|
+
run_id=self.run_id,
|
|
351
|
+
component=component,
|
|
352
|
+
)
|
|
353
|
+
self.monitor.record_usage(actual, run_id=self.run_id, component=component)
|
|
354
|
+
|
|
355
|
+
def _commit_failed_minimum(
|
|
356
|
+
self,
|
|
357
|
+
reservation: ResourceUsage,
|
|
358
|
+
*,
|
|
359
|
+
component: str,
|
|
360
|
+
) -> None:
|
|
361
|
+
"""Retain the reserved lower bound unless zero consumption was explicit."""
|
|
362
|
+
|
|
363
|
+
if reservation == ResourceUsage():
|
|
364
|
+
return
|
|
365
|
+
minimum_actual = reservation + ResourceUsage(unpriced_model_calls=reservation.model_calls)
|
|
366
|
+
# The declared worker failure remains the primary exception. The
|
|
367
|
+
# reservation was accepted before the side effect and is therefore the
|
|
368
|
+
# only trustworthy lower bound when failure telemetry is absent/broken.
|
|
369
|
+
with suppress(BudgetExceededError):
|
|
370
|
+
self._settle_actual(minimum_actual, reservation, component=component)
|
|
371
|
+
|
|
372
|
+
def _settle_runtime_exception(
|
|
373
|
+
self,
|
|
374
|
+
reservation: ResourceUsage,
|
|
375
|
+
*,
|
|
376
|
+
component: str,
|
|
377
|
+
) -> None:
|
|
378
|
+
if reservation == ResourceUsage():
|
|
379
|
+
return
|
|
380
|
+
minimum_actual = reservation + ResourceUsage(unpriced_model_calls=reservation.model_calls)
|
|
381
|
+
# Preserve the runtime exception as the primary failure. Any budget
|
|
382
|
+
# overage remains sticky and the usage is already recorded.
|
|
383
|
+
with suppress(BudgetExceededError):
|
|
384
|
+
self._settle_actual(minimum_actual, reservation, component=component)
|
|
385
|
+
|
|
386
|
+
def _cancel_pending(self, reservation: ResourceUsage) -> None:
|
|
387
|
+
if reservation != ResourceUsage():
|
|
388
|
+
self.ledger.cancel_pending(reservation)
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
@dataclass(slots=True)
|
|
392
|
+
class ObservedLLMBackend:
|
|
393
|
+
inner: LLMBackend
|
|
394
|
+
monitor: RunMonitor
|
|
395
|
+
ledger: BudgetLedger
|
|
396
|
+
run_id: str
|
|
397
|
+
pricing: PricingCatalog | None = None
|
|
398
|
+
|
|
399
|
+
@property
|
|
400
|
+
def model_id(self) -> str:
|
|
401
|
+
return self.inner.model_id
|
|
402
|
+
|
|
403
|
+
@property
|
|
404
|
+
def capabilities(self) -> Any:
|
|
405
|
+
return self.inner.capabilities
|
|
406
|
+
|
|
407
|
+
def fingerprint(self) -> Mapping[str, Any]:
|
|
408
|
+
return self.inner.fingerprint()
|
|
409
|
+
|
|
410
|
+
def generate(self, request: GenerationRequest) -> GenerationResponse:
|
|
411
|
+
started = time.perf_counter_ns()
|
|
412
|
+
self.monitor.emit(
|
|
413
|
+
EventKind.STAGE_STARTED,
|
|
414
|
+
run_id=self.run_id,
|
|
415
|
+
component="llm",
|
|
416
|
+
payload={"model_id": self.model_id, "request_hash": request.request_hash},
|
|
417
|
+
)
|
|
418
|
+
call_usage = ResourceUsage(model_calls=1)
|
|
419
|
+
try:
|
|
420
|
+
self.ledger.reserve(call_usage)
|
|
421
|
+
except BudgetExceededError:
|
|
422
|
+
self.monitor.emit(EventKind.BUDGET_EXCEEDED, run_id=self.run_id, component="llm")
|
|
423
|
+
raise
|
|
424
|
+
self.monitor.record_usage(call_usage, run_id=self.run_id, component="llm")
|
|
425
|
+
try:
|
|
426
|
+
response = self.inner.generate(request)
|
|
427
|
+
except Exception as exc:
|
|
428
|
+
# An invocation without a usable response still counts as an
|
|
429
|
+
# attempt. Its token/cost consumption is unknown, even if a price
|
|
430
|
+
# table exists; do not silently report the failed call as free.
|
|
431
|
+
unknown_usage = ResourceUsage(unpriced_model_calls=1)
|
|
432
|
+
try:
|
|
433
|
+
self.ledger.charge_actual(unknown_usage)
|
|
434
|
+
except BudgetExceededError:
|
|
435
|
+
self.monitor.emit(EventKind.BUDGET_EXCEEDED, run_id=self.run_id, component="llm")
|
|
436
|
+
self.monitor.record_usage(unknown_usage, run_id=self.run_id, component="llm")
|
|
437
|
+
self.monitor.emit(
|
|
438
|
+
EventKind.STAGE_FINISHED,
|
|
439
|
+
run_id=self.run_id,
|
|
440
|
+
component="llm",
|
|
441
|
+
payload={"status": "failed", "usage_status": "unknown",
|
|
442
|
+
"token_counters": "known_lower_bound_only"},
|
|
443
|
+
)
|
|
444
|
+
self.monitor.record_failure(
|
|
445
|
+
exc,
|
|
446
|
+
run_id=self.run_id,
|
|
447
|
+
category="backend_error",
|
|
448
|
+
stage="llm",
|
|
449
|
+
)
|
|
450
|
+
raise
|
|
451
|
+
cost = response.usage.cost_usd
|
|
452
|
+
unpriced_calls = 0
|
|
453
|
+
if cost is None:
|
|
454
|
+
catalog = self.pricing or PricingCatalog()
|
|
455
|
+
if catalog.has_price(self.model_id):
|
|
456
|
+
cost = catalog.estimate(
|
|
457
|
+
self.model_id,
|
|
458
|
+
input_tokens=response.usage.input_tokens,
|
|
459
|
+
output_tokens=response.usage.output_tokens,
|
|
460
|
+
)
|
|
461
|
+
else:
|
|
462
|
+
cost = 0.0
|
|
463
|
+
unpriced_calls = 1
|
|
464
|
+
usage = ResourceUsage(
|
|
465
|
+
unpriced_model_calls=unpriced_calls,
|
|
466
|
+
input_tokens=response.usage.input_tokens,
|
|
467
|
+
output_tokens=response.usage.output_tokens,
|
|
468
|
+
cost_usd=cost,
|
|
469
|
+
)
|
|
470
|
+
try:
|
|
471
|
+
self.ledger.charge_actual(usage)
|
|
472
|
+
except BudgetExceededError:
|
|
473
|
+
# The provider has already returned, so its usage is irreversible
|
|
474
|
+
# and must remain visible even though the budget gate now fails.
|
|
475
|
+
self.monitor.record_usage(usage, run_id=self.run_id, component="llm")
|
|
476
|
+
self.monitor.emit(EventKind.BUDGET_EXCEEDED, run_id=self.run_id, component="llm")
|
|
477
|
+
raise
|
|
478
|
+
self.monitor.record_usage(usage, run_id=self.run_id, component="llm")
|
|
479
|
+
self.monitor.emit(
|
|
480
|
+
EventKind.STAGE_FINISHED,
|
|
481
|
+
run_id=self.run_id,
|
|
482
|
+
component="llm",
|
|
483
|
+
payload={
|
|
484
|
+
"duration_ms": (time.perf_counter_ns() - started) / 1_000_000,
|
|
485
|
+
"finish_reason": response.finish_reason,
|
|
486
|
+
},
|
|
487
|
+
)
|
|
488
|
+
return response
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
@dataclass(slots=True)
|
|
492
|
+
class ObservedRetriever:
|
|
493
|
+
inner: Retriever
|
|
494
|
+
monitor: RunMonitor
|
|
495
|
+
ledger: BudgetLedger
|
|
496
|
+
run_id: str
|
|
497
|
+
|
|
498
|
+
@property
|
|
499
|
+
def retriever_id(self) -> str:
|
|
500
|
+
return self.inner.retriever_id
|
|
501
|
+
|
|
502
|
+
def fingerprint(self) -> Mapping[str, Any]:
|
|
503
|
+
return self.inner.fingerprint()
|
|
504
|
+
|
|
505
|
+
def retrieve(self, query: str, *, top_k: int = 5) -> tuple[RetrievalResult, ...]:
|
|
506
|
+
started = time.perf_counter_ns()
|
|
507
|
+
self.monitor.emit(
|
|
508
|
+
EventKind.STAGE_STARTED,
|
|
509
|
+
run_id=self.run_id,
|
|
510
|
+
component="retriever",
|
|
511
|
+
payload={"top_k": top_k},
|
|
512
|
+
)
|
|
513
|
+
usage = ResourceUsage(retrieval_calls=1)
|
|
514
|
+
try:
|
|
515
|
+
self.ledger.reserve(usage)
|
|
516
|
+
except BudgetExceededError:
|
|
517
|
+
self.monitor.emit(
|
|
518
|
+
EventKind.BUDGET_EXCEEDED,
|
|
519
|
+
run_id=self.run_id,
|
|
520
|
+
component="retriever",
|
|
521
|
+
)
|
|
522
|
+
raise
|
|
523
|
+
self.monitor.record_usage(usage, run_id=self.run_id, component="retriever")
|
|
524
|
+
try:
|
|
525
|
+
results = self.inner.retrieve(query, top_k=top_k)
|
|
526
|
+
except Exception as exc:
|
|
527
|
+
self.monitor.record_failure(
|
|
528
|
+
exc,
|
|
529
|
+
run_id=self.run_id,
|
|
530
|
+
category="retrieval_error",
|
|
531
|
+
stage="retriever",
|
|
532
|
+
)
|
|
533
|
+
raise
|
|
534
|
+
self.monitor.emit(
|
|
535
|
+
EventKind.STAGE_FINISHED,
|
|
536
|
+
run_id=self.run_id,
|
|
537
|
+
component="retriever",
|
|
538
|
+
payload={
|
|
539
|
+
"duration_ms": (time.perf_counter_ns() - started) / 1_000_000,
|
|
540
|
+
"result_count": len(results),
|
|
541
|
+
},
|
|
542
|
+
)
|
|
543
|
+
return results
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
@dataclass(slots=True)
|
|
547
|
+
class ObservedDenseEmbedder:
|
|
548
|
+
inner: DenseEmbedder
|
|
549
|
+
monitor: RunMonitor
|
|
550
|
+
ledger: BudgetLedger
|
|
551
|
+
run_id: str
|
|
552
|
+
|
|
553
|
+
@property
|
|
554
|
+
def embedder_id(self) -> str:
|
|
555
|
+
return self.inner.embedder_id
|
|
556
|
+
|
|
557
|
+
def fingerprint(self) -> Mapping[str, Any]:
|
|
558
|
+
return self.inner.fingerprint()
|
|
559
|
+
|
|
560
|
+
def embed(self, texts: Any) -> Any:
|
|
561
|
+
started = time.perf_counter_ns()
|
|
562
|
+
self.monitor.emit(
|
|
563
|
+
EventKind.STAGE_STARTED,
|
|
564
|
+
run_id=self.run_id,
|
|
565
|
+
component="embedding",
|
|
566
|
+
payload={"input_count": len(texts)},
|
|
567
|
+
)
|
|
568
|
+
usage = ResourceUsage(embedding_calls=1)
|
|
569
|
+
self.ledger.reserve(usage)
|
|
570
|
+
self.monitor.record_usage(usage, run_id=self.run_id, component="embedding")
|
|
571
|
+
try:
|
|
572
|
+
vectors = self.inner.embed(texts)
|
|
573
|
+
except Exception as exc:
|
|
574
|
+
self.monitor.record_failure(
|
|
575
|
+
exc,
|
|
576
|
+
run_id=self.run_id,
|
|
577
|
+
category="embedding_error",
|
|
578
|
+
stage="embedding",
|
|
579
|
+
)
|
|
580
|
+
raise
|
|
581
|
+
self.monitor.emit(
|
|
582
|
+
EventKind.STAGE_FINISHED,
|
|
583
|
+
run_id=self.run_id,
|
|
584
|
+
component="embedding",
|
|
585
|
+
payload={
|
|
586
|
+
"duration_ms": (time.perf_counter_ns() - started) / 1_000_000,
|
|
587
|
+
"vector_count": len(vectors),
|
|
588
|
+
},
|
|
589
|
+
)
|
|
590
|
+
return vectors
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
@dataclass(slots=True)
|
|
594
|
+
class ObservedVectorSearcher:
|
|
595
|
+
inner: VectorSearcher
|
|
596
|
+
monitor: RunMonitor
|
|
597
|
+
ledger: BudgetLedger
|
|
598
|
+
run_id: str
|
|
599
|
+
|
|
600
|
+
@property
|
|
601
|
+
def searcher_id(self) -> str:
|
|
602
|
+
return self.inner.searcher_id
|
|
603
|
+
|
|
604
|
+
def fingerprint(self) -> Mapping[str, Any]:
|
|
605
|
+
return self.inner.fingerprint()
|
|
606
|
+
|
|
607
|
+
def search(self, vector: Any, *, top_k: int) -> Any:
|
|
608
|
+
started = time.perf_counter_ns()
|
|
609
|
+
self.monitor.emit(
|
|
610
|
+
EventKind.STAGE_STARTED,
|
|
611
|
+
run_id=self.run_id,
|
|
612
|
+
component="vector_search",
|
|
613
|
+
payload={"top_k": top_k},
|
|
614
|
+
)
|
|
615
|
+
usage = ResourceUsage(retrieval_calls=1)
|
|
616
|
+
try:
|
|
617
|
+
self.ledger.reserve(usage)
|
|
618
|
+
except BudgetExceededError:
|
|
619
|
+
self.monitor.emit(
|
|
620
|
+
EventKind.BUDGET_EXCEEDED,
|
|
621
|
+
run_id=self.run_id,
|
|
622
|
+
component="vector_search",
|
|
623
|
+
)
|
|
624
|
+
raise
|
|
625
|
+
self.monitor.record_usage(usage, run_id=self.run_id, component="vector_search")
|
|
626
|
+
try:
|
|
627
|
+
results = self.inner.search(vector, top_k=top_k)
|
|
628
|
+
except Exception as exc:
|
|
629
|
+
self.monitor.record_failure(
|
|
630
|
+
exc,
|
|
631
|
+
run_id=self.run_id,
|
|
632
|
+
category="retrieval_error",
|
|
633
|
+
stage="vector_search",
|
|
634
|
+
)
|
|
635
|
+
raise
|
|
636
|
+
self.monitor.emit(
|
|
637
|
+
EventKind.STAGE_FINISHED,
|
|
638
|
+
run_id=self.run_id,
|
|
639
|
+
component="vector_search",
|
|
640
|
+
payload={
|
|
641
|
+
"duration_ms": (time.perf_counter_ns() - started) / 1_000_000,
|
|
642
|
+
"result_count": len(results),
|
|
643
|
+
},
|
|
644
|
+
)
|
|
645
|
+
return results
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
@dataclass(slots=True)
|
|
649
|
+
class ObservedToolConnector:
|
|
650
|
+
inner: ToolConnector
|
|
651
|
+
monitor: RunMonitor
|
|
652
|
+
ledger: BudgetLedger
|
|
653
|
+
run_id: str
|
|
654
|
+
|
|
655
|
+
def list_tools(self) -> tuple[ToolSpec, ...]:
|
|
656
|
+
return self.inner.list_tools()
|
|
657
|
+
|
|
658
|
+
def fingerprint(self) -> Mapping[str, Any]:
|
|
659
|
+
return self.inner.fingerprint()
|
|
660
|
+
|
|
661
|
+
def call(self, request: ToolCall) -> ToolResult:
|
|
662
|
+
started = time.perf_counter_ns()
|
|
663
|
+
self.monitor.emit(
|
|
664
|
+
EventKind.STAGE_STARTED,
|
|
665
|
+
run_id=self.run_id,
|
|
666
|
+
component="tool",
|
|
667
|
+
payload={"tool_name": request.name, "call_id": request.call_id},
|
|
668
|
+
)
|
|
669
|
+
usage = ResourceUsage(tool_calls=1)
|
|
670
|
+
try:
|
|
671
|
+
self.ledger.reserve(usage)
|
|
672
|
+
except BudgetExceededError:
|
|
673
|
+
self.monitor.emit(EventKind.BUDGET_EXCEEDED, run_id=self.run_id, component="tool")
|
|
674
|
+
raise
|
|
675
|
+
self.monitor.record_usage(usage, run_id=self.run_id, component="tool")
|
|
676
|
+
try:
|
|
677
|
+
result = self.inner.call(request)
|
|
678
|
+
except Exception as exc:
|
|
679
|
+
self.monitor.record_failure(
|
|
680
|
+
exc,
|
|
681
|
+
run_id=self.run_id,
|
|
682
|
+
category="tool_error",
|
|
683
|
+
stage="tool",
|
|
684
|
+
)
|
|
685
|
+
raise
|
|
686
|
+
self.monitor.emit(
|
|
687
|
+
EventKind.STAGE_FINISHED,
|
|
688
|
+
run_id=self.run_id,
|
|
689
|
+
component="tool",
|
|
690
|
+
payload={
|
|
691
|
+
"duration_ms": (time.perf_counter_ns() - started) / 1_000_000,
|
|
692
|
+
"error": bool(result.error),
|
|
693
|
+
},
|
|
694
|
+
)
|
|
695
|
+
return result
|
|
696
|
+
|
|
697
|
+
|
|
698
|
+
def instrument_context(
|
|
699
|
+
context: InterventionContext,
|
|
700
|
+
state: FrozenAgentState,
|
|
701
|
+
monitor: RunMonitor,
|
|
702
|
+
*,
|
|
703
|
+
run_id: str,
|
|
704
|
+
pricing: PricingCatalog | None = None,
|
|
705
|
+
) -> InterventionContext:
|
|
706
|
+
"""Return a per-run context with transparent runtime accounting wrappers."""
|
|
707
|
+
|
|
708
|
+
ledger = context.budget_ledger or BudgetLedger(state.budget)
|
|
709
|
+
if not isinstance(ledger, BudgetLedger):
|
|
710
|
+
raise TypeError("context.budget_ledger must be a BudgetLedger")
|
|
711
|
+
if ledger.budget != state.budget:
|
|
712
|
+
raise ValueError("context budget ledger does not match the frozen state budget")
|
|
713
|
+
ledger.claim_for_run(run_id)
|
|
714
|
+
backend = context.backend
|
|
715
|
+
if isinstance(backend, ObservedLLMBackend):
|
|
716
|
+
backend = backend.inner
|
|
717
|
+
if backend is not None:
|
|
718
|
+
backend = ObservedLLMBackend(backend, monitor, ledger, run_id, pricing)
|
|
719
|
+
dense_embedder = context.dense_embedder
|
|
720
|
+
if isinstance(dense_embedder, ObservedDenseEmbedder):
|
|
721
|
+
dense_embedder = dense_embedder.inner
|
|
722
|
+
if dense_embedder is not None:
|
|
723
|
+
dense_embedder = ObservedDenseEmbedder(dense_embedder, monitor, ledger, run_id)
|
|
724
|
+
retriever = context.retriever
|
|
725
|
+
if isinstance(retriever, ObservedRetriever):
|
|
726
|
+
retriever = retriever.inner
|
|
727
|
+
if retriever is not None:
|
|
728
|
+
retriever = ObservedRetriever(retriever, monitor, ledger, run_id)
|
|
729
|
+
vector_searcher = context.vector_searcher
|
|
730
|
+
if isinstance(vector_searcher, ObservedVectorSearcher):
|
|
731
|
+
vector_searcher = vector_searcher.inner
|
|
732
|
+
if vector_searcher is not None:
|
|
733
|
+
vector_searcher = ObservedVectorSearcher(vector_searcher, monitor, ledger, run_id)
|
|
734
|
+
tools = context.tools
|
|
735
|
+
if isinstance(tools, ObservedToolConnector):
|
|
736
|
+
tools = tools.inner
|
|
737
|
+
if tools is not None:
|
|
738
|
+
tools = ObservedToolConnector(tools, monitor, ledger, run_id)
|
|
739
|
+
external_runtime = context.external_runtime
|
|
740
|
+
if isinstance(external_runtime, ObservedExternalRuntime):
|
|
741
|
+
external_runtime = external_runtime.inner
|
|
742
|
+
if external_runtime is not None:
|
|
743
|
+
external_runtime = ObservedExternalRuntime(external_runtime, monitor, ledger, run_id)
|
|
744
|
+
return replace(
|
|
745
|
+
context,
|
|
746
|
+
backend=backend,
|
|
747
|
+
dense_embedder=dense_embedder,
|
|
748
|
+
retriever=retriever,
|
|
749
|
+
vector_searcher=vector_searcher,
|
|
750
|
+
tools=tools,
|
|
751
|
+
external_runtime=external_runtime,
|
|
752
|
+
budget_ledger=ledger,
|
|
753
|
+
monitor=monitor,
|
|
754
|
+
)
|