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.
Files changed (469) hide show
  1. agentinputlab/__init__.py +28 -0
  2. agentinputlab/algorithms/__init__.py +6 -0
  3. agentinputlab/algorithms/acquire/__init__.py +145 -0
  4. agentinputlab/algorithms/acquire/adaptive_rag/__init__.py +43 -0
  5. agentinputlab/algorithms/acquire/adaptive_rag/replay.py +367 -0
  6. agentinputlab/algorithms/acquire/adaptive_rag/runtime.py +1202 -0
  7. agentinputlab/algorithms/acquire/adaptive_rag_common_support.py +542 -0
  8. agentinputlab/algorithms/acquire/hyde.py +296 -0
  9. agentinputlab/algorithms/acquire/hyde_controlled.py +200 -0
  10. agentinputlab/algorithms/acquire/hyde_external.py +148 -0
  11. agentinputlab/algorithms/acquire/ircot.py +28 -0
  12. agentinputlab/algorithms/acquire/ircot_common_support.py +478 -0
  13. agentinputlab/algorithms/acquire/ircot_native.py +355 -0
  14. agentinputlab/algorithms/acquire/ircot_replay.py +327 -0
  15. agentinputlab/algorithms/acquire/qrag/__init__.py +79 -0
  16. agentinputlab/algorithms/acquire/qrag/bridge.py +828 -0
  17. agentinputlab/algorithms/acquire/qrag/common_support.py +891 -0
  18. agentinputlab/algorithms/acquire/qrag/native_axis.py +71 -0
  19. agentinputlab/algorithms/acquire/qrag/reader_adapter.py +139 -0
  20. agentinputlab/algorithms/acquire/r2ag/__init__.py +57 -0
  21. agentinputlab/algorithms/acquire/r2ag/bridge.py +1312 -0
  22. agentinputlab/algorithms/acquire/r2ag/common_support.py +1029 -0
  23. agentinputlab/algorithms/acquire/r2ag/socket_runtime.py +255 -0
  24. agentinputlab/algorithms/clarify/__init__.py +61 -0
  25. agentinputlab/algorithms/clarify/_structured.py +64 -0
  26. agentinputlab/algorithms/clarify/active_task_disambiguation.py +371 -0
  27. agentinputlab/algorithms/clarify/ask_or_assume/__init__.py +17 -0
  28. agentinputlab/algorithms/clarify/ask_or_assume/monitor.py +410 -0
  29. agentinputlab/algorithms/clarify/future_turns.py +379 -0
  30. agentinputlab/algorithms/clarify/udcs.py +255 -0
  31. agentinputlab/algorithms/clarify/udcs_deterministic.py +196 -0
  32. agentinputlab/algorithms/curate/__init__.py +65 -0
  33. agentinputlab/algorithms/curate/acon/__init__.py +27 -0
  34. agentinputlab/algorithms/curate/acon/common.py +284 -0
  35. agentinputlab/algorithms/curate/acon/common_support.py +136 -0
  36. agentinputlab/algorithms/curate/acon/history_bridge.py +309 -0
  37. agentinputlab/algorithms/curate/acon/observation_bridge.py +290 -0
  38. agentinputlab/algorithms/curate/llmlingua/__init__.py +30 -0
  39. agentinputlab/algorithms/curate/llmlingua/adapters.py +537 -0
  40. agentinputlab/algorithms/curate/llmlingua/budget.py +48 -0
  41. agentinputlab/algorithms/curate/llmlingua/controlled.py +175 -0
  42. agentinputlab/algorithms/curate/llmlingua/multilingual.py +105 -0
  43. agentinputlab/algorithms/curate/llmlingua/span_map.py +167 -0
  44. agentinputlab/algorithms/curate/recomp/__init__.py +47 -0
  45. agentinputlab/algorithms/curate/recomp/external.py +1129 -0
  46. agentinputlab/algorithms/curate/recomp/selective.py +304 -0
  47. agentinputlab/algorithms/decompose/__init__.py +107 -0
  48. agentinputlab/algorithms/decompose/decomp/__init__.py +53 -0
  49. agentinputlab/algorithms/decompose/decomp/common_support.py +478 -0
  50. agentinputlab/algorithms/decompose/decomp/planner_component.py +199 -0
  51. agentinputlab/algorithms/decompose/decomp/worker_bridge.py +416 -0
  52. agentinputlab/algorithms/decompose/llm_compiler/__init__.py +35 -0
  53. agentinputlab/algorithms/decompose/llm_compiler/bridge.py +520 -0
  54. agentinputlab/algorithms/decompose/llm_compiler/common_support.py +504 -0
  55. agentinputlab/algorithms/decompose/plan_and_budget/__init__.py +43 -0
  56. agentinputlab/algorithms/decompose/plan_and_budget/cached_soft_budget.py +362 -0
  57. agentinputlab/algorithms/decompose/plan_and_budget/decomposer_component.py +107 -0
  58. agentinputlab/algorithms/decompose/plan_and_budget/full.py +205 -0
  59. agentinputlab/algorithms/decompose/plan_and_budget/hard_cap.py +246 -0
  60. agentinputlab/algorithms/decompose/plan_and_budget/regenerated_soft_budget.py +448 -0
  61. agentinputlab/algorithms/decompose/plan_and_solve/__init__.py +33 -0
  62. agentinputlab/algorithms/decompose/plan_and_solve/plan_component.py +192 -0
  63. agentinputlab/algorithms/decompose/plan_and_solve/ps_prompt.py +127 -0
  64. agentinputlab/algorithms/decompose/self_ask/__init__.py +27 -0
  65. agentinputlab/algorithms/decompose/self_ask/loop.py +362 -0
  66. agentinputlab/algorithms/decompose/self_ask/planner_component.py +117 -0
  67. agentinputlab/algorithms/reformulate/__init__.py +85 -0
  68. agentinputlab/algorithms/reformulate/infocqr/__init__.py +40 -0
  69. agentinputlab/algorithms/reformulate/infocqr/cache_replay.py +362 -0
  70. agentinputlab/algorithms/reformulate/infocqr/external.py +675 -0
  71. agentinputlab/algorithms/reformulate/infocqr/student.py +189 -0
  72. agentinputlab/algorithms/reformulate/query2doc/__init__.py +42 -0
  73. agentinputlab/algorithms/reformulate/query2doc/controlled_live.py +190 -0
  74. agentinputlab/algorithms/reformulate/query2doc/models.py +95 -0
  75. agentinputlab/algorithms/reformulate/query2doc/official_cached.py +335 -0
  76. agentinputlab/algorithms/reformulate/query2doc/querygym_bridge.py +223 -0
  77. agentinputlab/algorithms/reformulate/query2doc/querygym_runtime.py +326 -0
  78. agentinputlab/algorithms/reformulate/reformer/__init__.py +23 -0
  79. agentinputlab/algorithms/reformulate/reformer/external.py +417 -0
  80. agentinputlab/algorithms/reformulate/rrr.py +696 -0
  81. agentinputlab/annotation/__init__.py +5 -0
  82. agentinputlab/annotation/independent.py +428 -0
  83. agentinputlab/annotation/server.py +233 -0
  84. agentinputlab/annotation/static/app.js +121 -0
  85. agentinputlab/annotation/static/index.html +60 -0
  86. agentinputlab/annotation/static/review.css +2 -0
  87. agentinputlab/annotation/static/review.html +10 -0
  88. agentinputlab/annotation/static/review.js +11 -0
  89. agentinputlab/annotation/static/styles.css +55 -0
  90. agentinputlab/annotation/store.py +444 -0
  91. agentinputlab/api.py +368 -0
  92. agentinputlab/artifacts/__init__.py +15 -0
  93. agentinputlab/artifacts/json_file.py +104 -0
  94. agentinputlab/artifacts/manifest.py +98 -0
  95. agentinputlab/artifacts/store.py +157 -0
  96. agentinputlab/backends/__init__.py +98 -0
  97. agentinputlab/backends/embedding/__init__.py +25 -0
  98. agentinputlab/backends/embedding/base.py +145 -0
  99. agentinputlab/backends/embedding/callable.py +75 -0
  100. agentinputlab/backends/embedding/replay.py +129 -0
  101. agentinputlab/backends/llm/__init__.py +31 -0
  102. agentinputlab/backends/llm/base.py +149 -0
  103. agentinputlab/backends/llm/callable.py +108 -0
  104. agentinputlab/backends/llm/decomp_completion.py +88 -0
  105. agentinputlab/backends/llm/final_content_stop.py +72 -0
  106. agentinputlab/backends/llm/gpt_oss_final_channel.py +84 -0
  107. agentinputlab/backends/llm/openai_compatible.py +332 -0
  108. agentinputlab/backends/llm/transformers.py +171 -0
  109. agentinputlab/backends/retrieval/__init__.py +35 -0
  110. agentinputlab/backends/retrieval/base.py +50 -0
  111. agentinputlab/backends/retrieval/dense.py +777 -0
  112. agentinputlab/backends/retrieval/memory.py +119 -0
  113. agentinputlab/backends/retrieval/sqlite_fts.py +155 -0
  114. agentinputlab/backends/user/__init__.py +15 -0
  115. agentinputlab/backends/user/base.py +66 -0
  116. agentinputlab/backends/user/callable.py +54 -0
  117. agentinputlab/backends/user/replay.py +89 -0
  118. agentinputlab/backends/vector.py +38 -0
  119. agentinputlab/benchmarks/__init__.py +246 -0
  120. agentinputlab/benchmarks/acquisition.py +106 -0
  121. agentinputlab/benchmarks/ale.py +540 -0
  122. agentinputlab/benchmarks/appworld_ul.py +669 -0
  123. agentinputlab/benchmarks/assets.py +226 -0
  124. agentinputlab/benchmarks/base.py +68 -0
  125. agentinputlab/benchmarks/beir_archive.py +235 -0
  126. agentinputlab/benchmarks/beir_sample.py +269 -0
  127. agentinputlab/benchmarks/bfcl_native.py +245 -0
  128. agentinputlab/benchmarks/bfcl_v3.py +607 -0
  129. agentinputlab/benchmarks/cache.py +218 -0
  130. agentinputlab/benchmarks/clariq.py +203 -0
  131. agentinputlab/benchmarks/data/registry.json +321 -0
  132. agentinputlab/benchmarks/data/smoke_assets.json +511 -0
  133. agentinputlab/benchmarks/data/statebench_v0_8_1_task_ids.json +475 -0
  134. agentinputlab/benchmarks/data/toolsandbox_165848b_scenario_names.json +1 -0
  135. agentinputlab/benchmarks/execution.py +1111 -0
  136. agentinputlab/benchmarks/interactive.py +257 -0
  137. agentinputlab/benchmarks/ir_query.py +204 -0
  138. agentinputlab/benchmarks/longbench.py +203 -0
  139. agentinputlab/benchmarks/paired_replay.py +479 -0
  140. agentinputlab/benchmarks/preprocess.py +2313 -0
  141. agentinputlab/benchmarks/production.py +236 -0
  142. agentinputlab/benchmarks/qa.py +963 -0
  143. agentinputlab/benchmarks/registry.py +110 -0
  144. agentinputlab/benchmarks/retrieval.py +459 -0
  145. agentinputlab/benchmarks/runtime.py +509 -0
  146. agentinputlab/benchmarks/statebench.py +938 -0
  147. agentinputlab/benchmarks/tau3.py +725 -0
  148. agentinputlab/benchmarks/toolsandbox.py +626 -0
  149. agentinputlab/benchmarks/trec_dl_sample.py +263 -0
  150. agentinputlab/campaign.py +654 -0
  151. agentinputlab/campaign_runner.py +953 -0
  152. agentinputlab/cli/__init__.py +6 -0
  153. agentinputlab/cli/main.py +933 -0
  154. agentinputlab/connectors/__init__.py +46 -0
  155. agentinputlab/connectors/knowledge/__init__.py +4 -0
  156. agentinputlab/connectors/tools/__init__.py +30 -0
  157. agentinputlab/connectors/tools/base.py +57 -0
  158. agentinputlab/connectors/tools/mcp.py +222 -0
  159. agentinputlab/connectors/tools/memory.py +41 -0
  160. agentinputlab/connectors/tools/openapi.py +695 -0
  161. agentinputlab/connectors/tools/schema.py +102 -0
  162. agentinputlab/contracts/__init__.py +91 -0
  163. agentinputlab/contracts/availability.py +24 -0
  164. agentinputlab/contracts/dependency.py +58 -0
  165. agentinputlab/contracts/enums.py +82 -0
  166. agentinputlab/contracts/errors.py +63 -0
  167. agentinputlab/contracts/evidence.py +43 -0
  168. agentinputlab/contracts/intent.py +110 -0
  169. agentinputlab/contracts/lifecycle.py +164 -0
  170. agentinputlab/contracts/patch.py +167 -0
  171. agentinputlab/contracts/serialization.py +93 -0
  172. agentinputlab/contracts/state.py +127 -0
  173. agentinputlab/contracts/trace.py +59 -0
  174. agentinputlab/contracts/worker.py +42 -0
  175. agentinputlab/core/__init__.py +7 -0
  176. agentinputlab/data/__init__.py +32 -0
  177. agentinputlab/data/checksums.py +9 -0
  178. agentinputlab/data/downloader.py +235 -0
  179. agentinputlab/data/http.py +171 -0
  180. agentinputlab/data/index.py +21 -0
  181. agentinputlab/data/overlap.py +28 -0
  182. agentinputlab/data/preprocess.py +32 -0
  183. agentinputlab/data/storage.py +57 -0
  184. agentinputlab/data/trec_sample.py +427 -0
  185. agentinputlab/evaluation/__init__.py +5 -0
  186. agentinputlab/evaluation/outcomes.py +32 -0
  187. agentinputlab/experiments/__init__.py +278 -0
  188. agentinputlab/experiments/analysis.py +981 -0
  189. agentinputlab/experiments/artifacts.py +687 -0
  190. agentinputlab/experiments/automatic_measurement.py +678 -0
  191. agentinputlab/experiments/auxiliary_matrix.py +203 -0
  192. agentinputlab/experiments/bindings.py +430 -0
  193. agentinputlab/experiments/blueprints.py +147 -0
  194. agentinputlab/experiments/builders/__init__.py +45 -0
  195. agentinputlab/experiments/builders/executable_external_payload.py +423 -0
  196. agentinputlab/experiments/builders/external_process_arena.py +1018 -0
  197. agentinputlab/experiments/builders/registry_intervention.py +463 -0
  198. agentinputlab/experiments/cli.py +158 -0
  199. agentinputlab/experiments/controls.py +340 -0
  200. agentinputlab/experiments/driver_guard.py +205 -0
  201. agentinputlab/experiments/drivers/__init__.py +89 -0
  202. agentinputlab/experiments/drivers/external_arena.py +2908 -0
  203. agentinputlab/experiments/drivers/method_process.py +662 -0
  204. agentinputlab/experiments/drivers/parity_process.py +1484 -0
  205. agentinputlab/experiments/drivers/static_production.py +1574 -0
  206. agentinputlab/experiments/executor.py +448 -0
  207. agentinputlab/experiments/loader.py +605 -0
  208. agentinputlab/experiments/measurement.py +675 -0
  209. agentinputlab/experiments/paper_analysis.py +1818 -0
  210. agentinputlab/experiments/parity_identity.py +605 -0
  211. agentinputlab/experiments/plan.py +277 -0
  212. agentinputlab/experiments/production_builders.py +3739 -0
  213. agentinputlab/experiments/readiness.py +432 -0
  214. agentinputlab/experiments/schema.py +514 -0
  215. agentinputlab/experiments/secrets.py +177 -0
  216. agentinputlab/experiments/stateful_analysis.py +1738 -0
  217. agentinputlab/experiments/transfer_analysis.py +1316 -0
  218. agentinputlab/experiments/unseen_analysis.py +1025 -0
  219. agentinputlab/integrations/__init__.py +1 -0
  220. agentinputlab/integrations/action_space/__init__.py +1 -0
  221. agentinputlab/integrations/external_workers/__init__.py +76 -0
  222. agentinputlab/integrations/external_workers/ace.py +431 -0
  223. agentinputlab/integrations/external_workers/base.py +181 -0
  224. agentinputlab/integrations/external_workers/decomp_live.py +249 -0
  225. agentinputlab/integrations/external_workers/decomp_planner.py +30 -0
  226. agentinputlab/integrations/external_workers/infocqr_student.py +280 -0
  227. agentinputlab/integrations/external_workers/ircot.py +576 -0
  228. agentinputlab/integrations/external_workers/llmcompiler_live.py +360 -0
  229. agentinputlab/integrations/external_workers/longllmlingua.py +162 -0
  230. agentinputlab/integrations/external_workers/method.py +314 -0
  231. agentinputlab/integrations/external_workers/process.py +678 -0
  232. agentinputlab/integrations/external_workers/supervisor.py +1071 -0
  233. agentinputlab/integrations/full_architecture/__init__.py +1 -0
  234. agentinputlab/integrations/full_architecture/hyde.py +212 -0
  235. agentinputlab/integrations/full_architecture/plan_and_budget.py +188 -0
  236. agentinputlab/integrations/live_history.py +222 -0
  237. agentinputlab/integrations/prompt_optimization/__init__.py +1 -0
  238. agentinputlab/integrations/training/__init__.py +1 -0
  239. agentinputlab/metrics/__init__.py +50 -0
  240. agentinputlab/metrics/catalog.py +313 -0
  241. agentinputlab/metrics/harm.py +95 -0
  242. agentinputlab/metrics/paired.py +40 -0
  243. agentinputlab/metrics/qa.py +76 -0
  244. agentinputlab/metrics/text.py +33 -0
  245. agentinputlab/metrics/third_party.py +161 -0
  246. agentinputlab/models/__init__.py +4 -0
  247. agentinputlab/observability/__init__.py +56 -0
  248. agentinputlab/observability/budget.py +316 -0
  249. agentinputlab/observability/instrumentation.py +754 -0
  250. agentinputlab/observability/models.py +403 -0
  251. agentinputlab/observability/monitor.py +380 -0
  252. agentinputlab/optimizers/__init__.py +1 -0
  253. agentinputlab/optimizers/clarify/__init__.py +12 -0
  254. agentinputlab/optimizers/context/__init__.py +22 -0
  255. agentinputlab/optimizers/decompose/__init__.py +64 -0
  256. agentinputlab/optimizers/evidence/__init__.py +22 -0
  257. agentinputlab/optimizers/rewrite/__init__.py +30 -0
  258. agentinputlab/parity/__init__.py +5 -0
  259. agentinputlab/parity/base.py +206 -0
  260. agentinputlab/production_campaign.py +763 -0
  261. agentinputlab/py.typed +1 -0
  262. agentinputlab/recipes/__init__.py +333 -0
  263. agentinputlab/recipes/ace.py +418 -0
  264. agentinputlab/recipes/ace_bfcl.py +273 -0
  265. agentinputlab/recipes/ace_common_support.py +169 -0
  266. agentinputlab/recipes/ace_native_plan.py +322 -0
  267. agentinputlab/recipes/ace_online.py +711 -0
  268. agentinputlab/recipes/ace_retrieval.py +330 -0
  269. agentinputlab/recipes/ace_statebench.py +382 -0
  270. agentinputlab/recipes/ace_tau.py +463 -0
  271. agentinputlab/recipes/ace_toolsandbox.py +432 -0
  272. agentinputlab/recipes/acon_guideline.py +22 -0
  273. agentinputlab/recipes/adaptive_rag.py +822 -0
  274. agentinputlab/recipes/llmlingua2_inference.py +146 -0
  275. agentinputlab/recipes/llmlingua2_training.py +796 -0
  276. agentinputlab/recipes/mce.py +1486 -0
  277. agentinputlab/recipes/mce_final.py +335 -0
  278. agentinputlab/recipes/mce_text_fit.py +499 -0
  279. agentinputlab/recipes/mce_text_only.py +298 -0
  280. agentinputlab/recipes/qrag.py +729 -0
  281. agentinputlab/recipes/qrag_inference.py +364 -0
  282. agentinputlab/recipes/r2ag_features.py +236 -0
  283. agentinputlab/recipes/r2ag_inference.py +503 -0
  284. agentinputlab/recipes/r2ag_training.py +948 -0
  285. agentinputlab/recipes/recomp_abstractive.py +592 -0
  286. agentinputlab/recipes/recomp_extractive.py +525 -0
  287. agentinputlab/recipes/reformer.py +17 -0
  288. agentinputlab/recipes/rqrag.py +1516 -0
  289. agentinputlab/recipes/rqrag_common_support.py +193 -0
  290. agentinputlab/recipes/rqrag_completion.py +147 -0
  291. agentinputlab/recipes/skillopt.py +462 -0
  292. agentinputlab/recipes/skillopt_common_support.py +154 -0
  293. agentinputlab/recipes/skillopt_environment.py +165 -0
  294. agentinputlab/recipes/skillopt_environment_cli.py +5 -0
  295. agentinputlab/recipes/skillopt_retrieval.py +188 -0
  296. agentinputlab/recipes/smartsearch.py +897 -0
  297. agentinputlab/recipes/smartsearch_curriculum.py +283 -0
  298. agentinputlab/recipes/smartsearch_grpo_contracts.py +58 -0
  299. agentinputlab/recipes/smartsearch_grpo_data.py +314 -0
  300. agentinputlab/recipes/smartsearch_grpo_meter.py +324 -0
  301. agentinputlab/recipes/smartsearch_grpo_prefix.py +144 -0
  302. agentinputlab/recipes/smartsearch_grpo_rollout.py +119 -0
  303. agentinputlab/recipes/smartsearch_grpo_tools.py +364 -0
  304. agentinputlab/recipes/smartsearch_grpo_training.py +305 -0
  305. agentinputlab/recipes/smartsearch_grpo_transport.py +248 -0
  306. agentinputlab/recipes/smartsearch_grpo_worker.py +364 -0
  307. agentinputlab/recipes/smartsearch_inference.py +524 -0
  308. agentinputlab/recipes/smartsearch_native_data.py +172 -0
  309. agentinputlab/recipes/smartsearch_policy.py +616 -0
  310. agentinputlab/recipes/smartsearch_policy_worker.py +9 -0
  311. agentinputlab/recipes/smartsearch_sampling.py +232 -0
  312. agentinputlab/recipes/smartsearch_teacher.py +203 -0
  313. agentinputlab/recipes/smartsearch_training.py +265 -0
  314. agentinputlab/registry/__init__.py +46 -0
  315. agentinputlab/registry/beta.py +727 -0
  316. agentinputlab/registry/data/algorithms.json +1959 -0
  317. agentinputlab/registry/data/auxiliary_method_profiles.json +34 -0
  318. agentinputlab/registry/loader.py +100 -0
  319. agentinputlab/registry/result_manifest.py +184 -0
  320. agentinputlab/registry/runtime.py +195 -0
  321. agentinputlab/registry/schema.py +449 -0
  322. agentinputlab/runner/__init__.py +30 -0
  323. agentinputlab/runner/balance.py +248 -0
  324. agentinputlab/runner/cache.py +135 -0
  325. agentinputlab/runner/composite.py +130 -0
  326. agentinputlab/runner/engine.py +285 -0
  327. agentinputlab/runner/runtime_guard.py +268 -0
  328. agentinputlab/runner/worker.py +80 -0
  329. agentinputlab/runtime_bootstrap.py +288 -0
  330. agentinputlab/selectors/__init__.py +196 -0
  331. agentinputlab/selectors/advanced.py +1514 -0
  332. agentinputlab/selectors/artifacts.py +1087 -0
  333. agentinputlab/selectors/base.py +112 -0
  334. agentinputlab/selectors/campaigns.py +1893 -0
  335. agentinputlab/selectors/catalog.py +86 -0
  336. agentinputlab/selectors/discovery.py +1860 -0
  337. agentinputlab/selectors/evaluation.py +1348 -0
  338. agentinputlab/selectors/features.py +383 -0
  339. agentinputlab/selectors/learned.py +502 -0
  340. agentinputlab/selectors/no_op.py +28 -0
  341. agentinputlab/selectors/outcome_table.py +475 -0
  342. agentinputlab/selectors/producer.py +853 -0
  343. agentinputlab/selectors/rules.py +109 -0
  344. agentinputlab/selectors/runtime.py +420 -0
  345. agentinputlab/studies/__init__.py +16 -0
  346. agentinputlab/studies/design.py +165 -0
  347. agentinputlab/studies/paired.py +322 -0
  348. agentinputlab/studio/__init__.py +6 -0
  349. agentinputlab/studio/campaigns.py +819 -0
  350. agentinputlab/studio/engine.py +1408 -0
  351. agentinputlab/studio/model_backends.py +425 -0
  352. agentinputlab/studio/prepared.py +410 -0
  353. agentinputlab/studio/server.py +613 -0
  354. agentinputlab/studio/static/app.js +397 -0
  355. agentinputlab/studio/static/campaigns.html +175 -0
  356. agentinputlab/studio/static/campaigns.js +426 -0
  357. agentinputlab/studio/static/index.html +192 -0
  358. agentinputlab/studio/static/result.html +103 -0
  359. agentinputlab/studio/static/result.js +273 -0
  360. agentinputlab/studio/static/styles.css +467 -0
  361. agentinputlab-0.1.0a1.data/data/share/agentinputlab/CITATION.cff +22 -0
  362. agentinputlab-0.1.0a1.dist-info/METADATA +392 -0
  363. agentinputlab-0.1.0a1.dist-info/RECORD +469 -0
  364. agentinputlab-0.1.0a1.dist-info/WHEEL +5 -0
  365. agentinputlab-0.1.0a1.dist-info/entry_points.txt +6 -0
  366. agentinputlab-0.1.0a1.dist-info/licenses/LICENSE +21 -0
  367. agentinputlab-0.1.0a1.dist-info/licenses/NOTICE +31 -0
  368. agentinputlab-0.1.0a1.dist-info/licenses/THIRD_PARTY_NOTICES.md +94 -0
  369. agentinputlab-0.1.0a1.dist-info/top_level.txt +2 -0
  370. workers/README.md +94 -0
  371. workers/ace/README.md +261 -0
  372. workers/ace/__init__.py +1 -0
  373. workers/ace/compatibility_manifest.json +39 -0
  374. workers/ace/driver.py +1682 -0
  375. workers/acon/README.md +215 -0
  376. workers/acon/__init__.py +5 -0
  377. workers/acon/compatibility_manifest.json +93 -0
  378. workers/acon/driver.py +1859 -0
  379. workers/acon/fitted.py +395 -0
  380. workers/acon/guideline.py +470 -0
  381. workers/acon/guideline_source_manifest.json +20 -0
  382. workers/adaptive_rag/README.md +96 -0
  383. workers/adaptive_rag/__init__.py +15 -0
  384. workers/adaptive_rag/compatibility_manifest.json +61 -0
  385. workers/adaptive_rag/driver.py +1470 -0
  386. workers/adaptive_rag/fixture_runtime.py +163 -0
  387. workers/adaptive_rag/runtime.py +252 -0
  388. workers/ask_or_assume/README.md +124 -0
  389. workers/ask_or_assume/__init__.py +1 -0
  390. workers/ask_or_assume/compatibility_manifest.json +36 -0
  391. workers/ask_or_assume/driver.py +1227 -0
  392. workers/decomp/README.md +133 -0
  393. workers/decomp/UPSTREAM_LICENSE.Apache-2.0.txt +201 -0
  394. workers/decomp/__init__.py +5 -0
  395. workers/decomp/compatibility_manifest.json +205 -0
  396. workers/decomp/driver.py +1015 -0
  397. workers/decomp/live.py +137 -0
  398. workers/decomp/runtime.py +231 -0
  399. workers/infocqr/README.md +106 -0
  400. workers/infocqr/__init__.py +1 -0
  401. workers/infocqr/compatibility_manifest.json +84 -0
  402. workers/infocqr/driver.py +1766 -0
  403. workers/ircot/README.md +167 -0
  404. workers/ircot/__init__.py +7 -0
  405. workers/ircot/compatibility_manifest.json +121 -0
  406. workers/ircot/controlled.py +457 -0
  407. workers/ircot/driver.py +1373 -0
  408. workers/ircot/fixture_bindings.json +39 -0
  409. workers/ircot/fixture_config.json +48 -0
  410. workers/ircot/fixture_prompt.txt +2 -0
  411. workers/ircot/native_qa.py +398 -0
  412. workers/ircot/qa_compatibility_manifest.json +57 -0
  413. workers/ircot/runtime.py +97 -0
  414. workers/llmcompiler/README.md +160 -0
  415. workers/llmcompiler/__init__.py +1 -0
  416. workers/llmcompiler/compatibility_manifest.json +45 -0
  417. workers/llmcompiler/driver.py +1514 -0
  418. workers/llmcompiler/export_prompts.py +74 -0
  419. workers/llmcompiler/live.py +174 -0
  420. workers/llmcompiler/patch_manifest.json +147 -0
  421. workers/mce/README.md +198 -0
  422. workers/mce/__init__.py +29 -0
  423. workers/mce/compatibility_manifest.json +115 -0
  424. workers/mce/driver.py +2585 -0
  425. workers/mce/final_eval.py +173 -0
  426. workers/official_arenas/README.md +25 -0
  427. workers/official_arenas/__init__.py +1 -0
  428. workers/official_arenas/capture_records.py +110 -0
  429. workers/official_arenas/driver.py +619 -0
  430. workers/official_arenas/protocol.py +334 -0
  431. workers/official_arenas/providers/__init__.py +1 -0
  432. workers/official_arenas/providers/_live_history.py +228 -0
  433. workers/official_arenas/providers/_message_compat.py +77 -0
  434. workers/official_arenas/providers/appworld_ul.py +196 -0
  435. workers/official_arenas/providers/fixture.py +112 -0
  436. workers/official_arenas/providers/statebench.py +960 -0
  437. workers/official_arenas/providers/tau3.py +1672 -0
  438. workers/official_arenas/providers/tau_retail.py +586 -0
  439. workers/official_arenas/providers/toolsandbox.py +1321 -0
  440. workers/official_arenas/providers/tooltalk.py +699 -0
  441. workers/official_arenas/retail_capture.py +188 -0
  442. workers/official_arenas/retail_driver.py +275 -0
  443. workers/qrag/README.md +172 -0
  444. workers/qrag/__init__.py +1 -0
  445. workers/qrag/compatibility_manifest.json +64 -0
  446. workers/qrag/driver.py +673 -0
  447. workers/r2ag/README.md +154 -0
  448. workers/r2ag/__init__.py +5 -0
  449. workers/r2ag/compatibility_manifest.json +55 -0
  450. workers/r2ag/driver.py +1287 -0
  451. workers/r2ag/feature_schema.json +8 -0
  452. workers/r2ag/runtime.py +589 -0
  453. workers/recomp/README.md +120 -0
  454. workers/recomp/__init__.py +1 -0
  455. workers/recomp/compatibility_manifest.json +43 -0
  456. workers/recomp/driver.py +1653 -0
  457. workers/reformer/README.md +125 -0
  458. workers/reformer/__init__.py +1 -0
  459. workers/reformer/compatibility_manifest.json +68 -0
  460. workers/reformer/driver.py +1459 -0
  461. workers/reformer/induction.py +457 -0
  462. workers/rrr/README.md +126 -0
  463. workers/rrr/__init__.py +1 -0
  464. workers/rrr/compatibility_manifest.json +57 -0
  465. workers/rrr/driver.py +1133 -0
  466. workers/smartsearch/README.md +331 -0
  467. workers/smartsearch/__init__.py +1 -0
  468. workers/smartsearch/compatibility_manifest.json +41 -0
  469. workers/smartsearch/driver.py +1643 -0
@@ -0,0 +1,362 @@
1
+ """MIT-source-compatible Plan-and-Budget allocation and prompt materialization."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ from collections.abc import Mapping, Sequence
7
+ from dataclasses import dataclass, field
8
+ from pathlib import Path
9
+ from types import MappingProxyType
10
+
11
+ from agentinputlab.artifacts import load_pinned_json_mapping
12
+ from agentinputlab.contracts import (
13
+ ArtifactError,
14
+ ExecutionTrace,
15
+ FrozenAgentState,
16
+ InputPatch,
17
+ InterventionContext,
18
+ PatchOp,
19
+ PatchOperation,
20
+ SemanticFamily,
21
+ TraceEvent,
22
+ TracePhase,
23
+ ValidationError,
24
+ )
25
+ from agentinputlab.contracts.enums import StrEnum
26
+
27
+ P_AND_B_UPSTREAM_REVISION = "2ca2d90c6d3d630ec2b11cc22e0f56751f7f2b7e"
28
+
29
+
30
+ class DecaySchedule(StrEnum):
31
+ CONSTANT = "constant"
32
+ LINEAR = "linear"
33
+ POLYNOMIAL = "polynomial"
34
+ EXPONENTIAL = "exponential"
35
+ COSINE = "cosine"
36
+
37
+ @classmethod
38
+ def parse(cls, value: str | DecaySchedule) -> DecaySchedule:
39
+ if isinstance(value, cls):
40
+ return value
41
+ try:
42
+ return cls(value.strip().lower())
43
+ except ValueError as exc:
44
+ raise ValidationError(f"unsupported Plan-and-Budget decay: {value!r}") from exc
45
+
46
+
47
+ @dataclass(frozen=True, slots=True)
48
+ class CachedPlanBudgetRecord:
49
+ record_id: str
50
+ query: str
51
+ steps: tuple[str, ...]
52
+ credits: tuple[float, ...]
53
+ level: int
54
+ audit_warnings: tuple[str, ...] = ()
55
+
56
+ def __post_init__(self) -> None:
57
+ object.__setattr__(self, "steps", tuple(self.steps))
58
+ object.__setattr__(self, "credits", tuple(float(item) for item in self.credits))
59
+ object.__setattr__(self, "audit_warnings", tuple(self.audit_warnings))
60
+ if not self.record_id:
61
+ raise ArtifactError("Plan-and-Budget cached record requires id")
62
+ if not self.query:
63
+ raise ArtifactError("Plan-and-Budget cached record requires query")
64
+ if not self.steps:
65
+ raise ArtifactError("Plan-and-Budget cached record requires steps")
66
+ if len(self.steps) != len(self.credits):
67
+ raise ArtifactError("Plan-and-Budget steps/credits length mismatch")
68
+ if any(not math.isfinite(item) or item < 0 for item in self.credits):
69
+ raise ArtifactError("Plan-and-Budget credits must be finite and non-negative")
70
+ if sum(self.credits) <= 0:
71
+ raise ArtifactError("Plan-and-Budget credits must have positive mass")
72
+ if not 1 <= self.level <= 5:
73
+ raise ArtifactError("Plan-and-Budget level must be in [1, 5]")
74
+
75
+
76
+ def load_cached_record(row: Mapping[str, object]) -> CachedPlanBudgetRecord:
77
+ """Project an upstream row to a solver-visible view, physically dropping gold."""
78
+
79
+ record_id = str(row.get("id", row.get("query_id", "")))
80
+ query = str(row.get("query", row.get("problem", "")))
81
+ raw_steps = row.get("steps", ())
82
+ raw_credits = row.get("credits", ())
83
+ if isinstance(raw_steps, (str, bytes)) or not isinstance(raw_steps, Sequence):
84
+ raise ArtifactError("Plan-and-Budget steps must be a sequence")
85
+ if isinstance(raw_credits, (str, bytes)) or not isinstance(raw_credits, Sequence):
86
+ raise ArtifactError("Plan-and-Budget credits must be a sequence")
87
+ steps = tuple(str(item) for item in raw_steps)
88
+ try:
89
+ credits = tuple(float(item) for item in raw_credits)
90
+ level = int(row.get("level", 0))
91
+ except (TypeError, ValueError) as exc:
92
+ raise ArtifactError("invalid Plan-and-Budget credit/level value") from exc
93
+ warnings = []
94
+ if not 2 <= len(steps) <= 5:
95
+ warnings.append("cached_step_count_outside_prompt_intended_2_to_5")
96
+ if not math.isclose(sum(credits), 100.0, rel_tol=0.0, abs_tol=1e-9):
97
+ warnings.append("cached_credit_sum_not_100")
98
+ if any(key in row for key in ("reference", "solution", "answer", "gold")):
99
+ warnings.append("gold_fields_removed_from_solver_view")
100
+ return CachedPlanBudgetRecord(
101
+ record_id=record_id,
102
+ query=query,
103
+ steps=steps,
104
+ credits=credits,
105
+ level=level,
106
+ audit_warnings=tuple(warnings),
107
+ )
108
+
109
+
110
+ @dataclass(frozen=True, slots=True)
111
+ class PlanAndBudgetCache:
112
+ """Solver-only records loaded from a caller-pinned native cache envelope.
113
+
114
+ Byte verification does not establish authorship, licensing, the generating
115
+ model, or generation cost. Keep that provenance in the trusted source receipt.
116
+ """
117
+
118
+ records: Mapping[str, CachedPlanBudgetRecord]
119
+ artifact_sha256: str
120
+ verification: str = field(default="caller_declared_digest", init=False)
121
+
122
+ def __post_init__(self) -> None:
123
+ if not isinstance(self.artifact_sha256, str) or (
124
+ len(self.artifact_sha256) != 64
125
+ or any(c not in "0123456789abcdef" for c in self.artifact_sha256)
126
+ ):
127
+ raise ArtifactError("Plan-and-Budget cache requires a SHA-256 digest")
128
+ copied = dict(self.records)
129
+ if not copied or any(
130
+ not isinstance(record, CachedPlanBudgetRecord) or key != record.record_id
131
+ for key, record in copied.items()
132
+ ):
133
+ raise ArtifactError("Plan-and-Budget cache requires records keyed by exact id")
134
+ object.__setattr__(self, "records", MappingProxyType(copied))
135
+
136
+ @classmethod
137
+ def from_native_json(
138
+ cls, path: str | Path, *, expected_sha256: str, max_bytes: int = 8 * 1024 * 1024
139
+ ) -> PlanAndBudgetCache:
140
+ """Load the upstream ``{last_question_total, stats: [...]}`` format.
141
+
142
+ References, solutions and answers are physically absent from the returned
143
+ records. This loader does not download assets or run their generator.
144
+ """
145
+ payload = load_pinned_json_mapping(
146
+ path, expected_sha256=expected_sha256, max_bytes=max_bytes
147
+ )
148
+ if set(payload) != {"last_question_total", "stats"}:
149
+ raise ArtifactError("Plan-and-Budget native cache envelope differs")
150
+ if type(payload["last_question_total"]) not in (int, float) or payload["last_question_total"] < 0:
151
+ raise ArtifactError("Plan-and-Budget native cache timing field differs")
152
+ rows = payload["stats"]
153
+ if not isinstance(rows, list) or not rows:
154
+ raise ArtifactError("Plan-and-Budget native cache stats must be a non-empty list")
155
+ records = {}
156
+ for row in rows:
157
+ if not isinstance(row, dict):
158
+ raise ArtifactError("Plan-and-Budget native cache row must be an object")
159
+ required = {"id", "query", "steps", "credits", "level"}
160
+ if not required <= row.keys() or row.keys() - required - {
161
+ "reference", "solution", "answer", "gold"
162
+ }:
163
+ raise ArtifactError("Plan-and-Budget native cache row fields differ")
164
+ if not all(isinstance(row[key], str) and row[key].strip() for key in ("id", "query")):
165
+ raise ArtifactError("Plan-and-Budget native cache id/query must be non-empty strings")
166
+ if not isinstance(row["steps"], list) or any(
167
+ not isinstance(step, str) or not step.strip() for step in row["steps"]
168
+ ):
169
+ raise ArtifactError("Plan-and-Budget native steps must be non-empty strings")
170
+ if not isinstance(row["credits"], list) or any(
171
+ type(credit) not in (int, float) for credit in row["credits"]
172
+ ) or type(row["level"]) is not int:
173
+ raise ArtifactError("Plan-and-Budget native credit/level types differ")
174
+ record = load_cached_record(row)
175
+ if record.record_id in records:
176
+ raise ArtifactError("duplicate Plan-and-Budget native cache record id")
177
+ records[record.record_id] = record
178
+ result = cls(records, expected_sha256.lower())
179
+ object.__setattr__(result, "verification", "caller_sha256_verified")
180
+ return result
181
+
182
+
183
+ def _schedule_weights(schedule: DecaySchedule, count: int) -> tuple[float, ...]:
184
+ values = []
185
+ for index in range(count):
186
+ if schedule is DecaySchedule.CONSTANT:
187
+ weight = 1.0
188
+ elif schedule is DecaySchedule.LINEAR:
189
+ weight = count - index
190
+ elif schedule is DecaySchedule.POLYNOMIAL:
191
+ weight = float((count - index) ** 2)
192
+ elif schedule is DecaySchedule.EXPONENTIAL:
193
+ weight = 0.9**index
194
+ elif schedule is DecaySchedule.COSINE:
195
+ weight = (
196
+ 0.5 * (1.0 + math.cos(math.pi * index / (count - 1))) + 0.1 if count > 1 else 1.0
197
+ )
198
+ else: # pragma: no cover - enum exhaustiveness
199
+ raise ValidationError(f"unsupported schedule: {schedule}")
200
+ values.append(float(weight))
201
+ return tuple(values)
202
+
203
+
204
+ def allocate_tokens(
205
+ credits: Sequence[float],
206
+ total_tokens: int,
207
+ schedule: str | DecaySchedule = DecaySchedule.CONSTANT,
208
+ ) -> tuple[int, ...]:
209
+ """Pure-Python port of upstream ``allocate_tokens``.
210
+
211
+ The upstream name says tokens, although its runtime inserts the allocations
212
+ as soft *word* budgets. The caller must preserve that semantic distinction.
213
+ """
214
+
215
+ if total_tokens < 0:
216
+ raise ValidationError("total_tokens must be non-negative")
217
+ values = tuple(float(item) for item in credits)
218
+ if not values:
219
+ raise ValidationError("credits cannot be empty")
220
+ if any(not math.isfinite(item) or item < 0 for item in values):
221
+ raise ValidationError("credits must be finite and non-negative")
222
+ schedule_value = DecaySchedule.parse(schedule)
223
+ weights = _schedule_weights(schedule_value, len(values))
224
+ combined = tuple(credit * weight for credit, weight in zip(values, weights, strict=True))
225
+ mass = sum(combined)
226
+ if mass <= 0:
227
+ raise ValidationError("weighted credits must have positive mass")
228
+ normalized = tuple(item / mass for item in combined)
229
+ allocations = [math.floor(item * total_tokens) for item in normalized]
230
+ difference = total_tokens - sum(allocations)
231
+ # NumPy argsort tie behavior was not an intentional method contribution.
232
+ # Stable index ordering makes the port deterministic while preserving the
233
+ # upstream descending-combined allocation rule.
234
+ order = sorted(range(len(normalized)), key=lambda index: (-normalized[index], index))
235
+ for index in order[:difference]:
236
+ allocations[index] += 1
237
+ return tuple(allocations)
238
+
239
+
240
+ def render_soft_budget_instruction(
241
+ record: CachedPlanBudgetRecord,
242
+ allocations: Sequence[int],
243
+ ) -> str:
244
+ if len(record.steps) != len(allocations):
245
+ raise ValidationError("steps/allocations length mismatch")
246
+ decomposed = "\n\n".join(
247
+ f"{step} Please only think a little, and directly solve it using up to {budget} words."
248
+ for step, budget in zip(record.steps, allocations, strict=True)
249
+ )
250
+ return (
251
+ f"The problem has difficulty level {record.level} out of 5. "
252
+ "You may follow these sub-questions or use another method that works best "
253
+ "towards the final answer. All credit is awarded for the correct final "
254
+ "answer.\n\n"
255
+ f"{decomposed}"
256
+ )
257
+
258
+
259
+ class PlanAndBudgetCachedSoftBudget:
260
+ method_id = "plan_and_budget"
261
+ release_id = "plan.plan_and_budget.native_cached_soft_budget"
262
+ family = SemanticFamily.DECOMPOSE
263
+
264
+ def __init__(
265
+ self,
266
+ records: Mapping[str, CachedPlanBudgetRecord] | PlanAndBudgetCache,
267
+ *,
268
+ total_word_budget: int,
269
+ schedule: str | DecaySchedule = DecaySchedule.CONSTANT,
270
+ ) -> None:
271
+ if total_word_budget < 0:
272
+ raise ValidationError("total_word_budget must be non-negative")
273
+ self.cache_sha256 = records.artifact_sha256 if isinstance(records, PlanAndBudgetCache) else None
274
+ self.cache_verification = (
275
+ records.verification if isinstance(records, PlanAndBudgetCache) else "caller_mapping_unverified"
276
+ )
277
+ self.records = dict(records.records if isinstance(records, PlanAndBudgetCache) else records)
278
+ self.total_word_budget = total_word_budget
279
+ self.schedule = DecaySchedule.parse(schedule)
280
+
281
+ def propose(self, state: FrozenAgentState, context: InterventionContext) -> InputPatch:
282
+ record_id = state.task_id or str(state.metadata.get("query_id", ""))
283
+ try:
284
+ record = self.records[record_id]
285
+ except KeyError as exc:
286
+ raise ArtifactError(f"no cached Plan-and-Budget record for {record_id!r}") from exc
287
+ if record.query != state.query:
288
+ raise ArtifactError(f"Plan-and-Budget cached query mismatch for {record_id!r}")
289
+ allocations = allocate_tokens(
290
+ record.credits,
291
+ self.total_word_budget,
292
+ self.schedule,
293
+ )
294
+ instruction = render_soft_budget_instruction(record, allocations)
295
+ trace = ExecutionTrace(
296
+ method_id=self.method_id,
297
+ release_id=self.release_id,
298
+ events=(
299
+ TraceEvent(
300
+ TracePhase.PREPARE,
301
+ "cached_plan_budget_record",
302
+ {
303
+ "record_id": record.record_id,
304
+ "steps": record.steps,
305
+ "credits": record.credits,
306
+ "credit_sum": sum(record.credits),
307
+ "level": record.level,
308
+ "audit_warnings": record.audit_warnings,
309
+ "gold_visible_to_solver": False,
310
+ "cache_artifact_sha256": self.cache_sha256,
311
+ },
312
+ ),
313
+ TraceEvent(
314
+ TracePhase.PROPOSE,
315
+ "soft_word_budget_allocation",
316
+ {
317
+ "schedule": self.schedule.value,
318
+ "total_budget": self.total_word_budget,
319
+ "budget_unit": "soft_words",
320
+ "allocation_tie_policy": "stable_source_index",
321
+ "allocations": allocations,
322
+ "decoder_hard_cap_applied": False,
323
+ "instruction": instruction,
324
+ },
325
+ ),
326
+ ),
327
+ counters={
328
+ "optimizer_model_calls": 0,
329
+ "planned_steps": len(record.steps),
330
+ "allocated_soft_words": sum(allocations),
331
+ },
332
+ warnings=record.audit_warnings,
333
+ )
334
+ return InputPatch(
335
+ method_id=self.method_id,
336
+ release_id=self.release_id,
337
+ source_state_hash=state.state_hash,
338
+ operations=(
339
+ PatchOperation(
340
+ PatchOp.APPEND_INSTRUCTION,
341
+ value=instruction,
342
+ target="instruction",
343
+ rationale="Plan-and-Budget cached weighted soft word budgets",
344
+ ),
345
+ ),
346
+ trace=trace,
347
+ implementation_identity=f"minimal_mit_port:junhongmit/P-and-B@{P_AND_B_UPSTREAM_REVISION}",
348
+ profile_kind="official_native",
349
+ metadata={
350
+ "implementation_origin": "official_mit_minimal_port",
351
+ "cached_decomposition": True,
352
+ "budget_unit": "soft_words",
353
+ "allocation_tie_policy": "stable_source_index",
354
+ "numpy_tie_order_parity_claimed": False,
355
+ "hard_decoder_cap": False,
356
+ "gold_fields_removed": True,
357
+ "cache_artifact_sha256": self.cache_sha256,
358
+ "cache_verification": self.cache_verification,
359
+ "historical_cache_generation_cost": "unknown_not_free",
360
+ "paper_result_parity_claimed": False,
361
+ },
362
+ )
@@ -0,0 +1,107 @@
1
+ """Evaluator-blind first-stage component of the controlled P&B adaptation.
2
+
3
+ Shares its existing generalized decomposition prompt/parser unchanged. This is
4
+ not credit assessment, budget allocation, the upstream full solver or a claim
5
+ of native released-cache/paper-result parity.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import math
11
+
12
+ from agentinputlab.backends.llm import GenerationRequest, LLMBackend, ModelCapability
13
+ from agentinputlab.contracts import (
14
+ BudgetExceededError,
15
+ CapabilityError,
16
+ ExecutionTrace,
17
+ ExternalDependencyError,
18
+ FrozenAgentState,
19
+ InputPatch,
20
+ InterventionContext,
21
+ PatchOp,
22
+ PatchOperation,
23
+ SemanticFamily,
24
+ TraceEvent,
25
+ TracePhase,
26
+ ValidationError,
27
+ )
28
+ from agentinputlab.contracts.serialization import content_hash
29
+
30
+ from .cached_soft_budget import P_AND_B_UPSTREAM_REVISION
31
+ from .regenerated_soft_budget import (
32
+ _decomposition_prompt,
33
+ _decomposition_system,
34
+ _parse_decomposition,
35
+ )
36
+
37
+
38
+ class PlanAndBudgetDecomposerComponent:
39
+ method_id = "plan_and_budget"
40
+ release_id = "plan.plan_and_budget.decomposer_component"
41
+ family = SemanticFamily.DECOMPOSE
42
+
43
+ def __init__(self, *, domain="general question answering", initial_level=3,
44
+ decomposition_max_tokens=768, temperature=0.0):
45
+ if not isinstance(domain, str) or not domain.strip():
46
+ raise ValidationError("Plan-and-Budget domain must be non-empty")
47
+ if type(initial_level) is not int or not 1 <= initial_level <= 5:
48
+ raise ValidationError("Plan-and-Budget initial_level must be in [1, 5]")
49
+ if type(decomposition_max_tokens) is not int or decomposition_max_tokens < 1:
50
+ raise ValidationError("decomposition_max_tokens must be positive")
51
+ if isinstance(temperature, bool) or not isinstance(temperature, (int, float)):
52
+ raise ValidationError("temperature must be finite and non-negative")
53
+ if not math.isfinite(temperature) or temperature < 0:
54
+ raise ValidationError("temperature must be finite and non-negative")
55
+ self.domain, self.initial_level = domain, initial_level
56
+ self.decomposition_max_tokens, self.temperature = decomposition_max_tokens, temperature
57
+
58
+ def propose(self, state: FrozenAgentState, context: InterventionContext) -> InputPatch:
59
+ if not state.query.strip():
60
+ raise ValidationError("Plan-and-Budget requires a non-empty query")
61
+ if state.budget.max_model_calls < 1 or state.budget.max_output_tokens < 1:
62
+ raise BudgetExceededError("decomposer component has no generation budget")
63
+ backend = context.backend
64
+ if backend is None:
65
+ raise ExternalDependencyError("decomposer component requires an injected LLMBackend")
66
+ if not isinstance(backend, LLMBackend) or ModelCapability.COMPLETION not in backend.capabilities:
67
+ raise CapabilityError("decomposer component requires completion capability")
68
+ system = _decomposition_system(self.domain)
69
+ prompt = _decomposition_prompt(state.query, level=self.initial_level)
70
+ # Match the existing controlled full profile's FIRST-stage reservation.
71
+ # The component does not spend the reserved half on a credit assessor.
72
+ cap = min(self.decomposition_max_tokens, max(1, state.budget.max_output_tokens // 2))
73
+ request = GenerationRequest(prompt=prompt, system=system, temperature=self.temperature,
74
+ max_tokens=cap, seed=context.seed, metadata={"method_id": self.method_id,
75
+ "release_id": self.release_id, "stage": "decomposition",
76
+ "upstream_revision": P_AND_B_UPSTREAM_REVISION})
77
+ response = backend.generate(request)
78
+ steps, warnings = _parse_decomposition(response.text)
79
+ instruction = "Suggested sub-questions:\n" + "\n\n".join(
80
+ f"{index}. {step}" for index, step in enumerate(steps, 1)
81
+ )
82
+ return InputPatch(method_id=self.method_id, release_id=self.release_id,
83
+ source_state_hash=state.state_hash,
84
+ operations=(PatchOperation(PatchOp.APPEND_INSTRUCTION, value=instruction,
85
+ target="instruction", rationale="controlled P&B decomposition-only component"),),
86
+ implementation_identity=f"controlled_p_and_b_first_stage@{P_AND_B_UPSTREAM_REVISION}",
87
+ profile_kind="controlled_adapter",
88
+ trace=ExecutionTrace(method_id=self.method_id, release_id=self.release_id,
89
+ events=(TraceEvent(TracePhase.PROPOSE, "decomposition_component", {
90
+ "steps": steps, "initial_level": self.initial_level,
91
+ "decomposition_request_sha256": content_hash({"system": system, "prompt": prompt}),
92
+ "optimizer_input_projection": "query_only", "gold_visible_to_optimizer": False,
93
+ "credit_assessment_executed": False, "solver_executed": False}),),
94
+ counters={"model_calls": 1, "optimizer_model_calls": 1,
95
+ "input_tokens": response.usage.input_tokens,
96
+ "output_tokens": response.usage.output_tokens, "planned_steps": len(steps)},
97
+ warnings=warnings),
98
+ metadata={"component_only": True, "full_system": False, "steps": steps,
99
+ "live_decomposition": True, "optimizer_input_projection": "query_only",
100
+ "credit_assessment_executed": False, "budget_allocation_executed": False,
101
+ "solver_executed": False, "hard_decoder_cap": False,
102
+ "gold_fields_visible_to_optimizer": False, "paper_result_parity_claimed": False,
103
+ "source_profile": "native_regenerated_soft_budget_first_stage",
104
+ "decomposition_fallback": "decomposition_parse_fallback_to_direct_solve" in warnings})
105
+
106
+
107
+ __all__ = ["PlanAndBudgetDecomposerComponent"]
@@ -0,0 +1,205 @@
1
+ """Complete P&B preparation, native weighted prompt and observed answer call."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ from collections.abc import Mapping
7
+ from dataclasses import replace
8
+ from types import MappingProxyType
9
+
10
+ from agentinputlab.backends.llm import GenerationRequest, LLMBackend, ModelCapability
11
+ from agentinputlab.contracts import (
12
+ AlgorithmOutputError,
13
+ ArtifactError,
14
+ BudgetExceededError,
15
+ CapabilityError,
16
+ CompositeResult,
17
+ ExecutionTrace,
18
+ ExternalDependencyError,
19
+ FrozenAgentState,
20
+ InterventionContext,
21
+ Message,
22
+ SemanticFamily,
23
+ TraceEvent,
24
+ TracePhase,
25
+ ValidationError,
26
+ )
27
+
28
+ from .cached_soft_budget import (
29
+ P_AND_B_UPSTREAM_REVISION,
30
+ CachedPlanBudgetRecord,
31
+ DecaySchedule,
32
+ PlanAndBudgetCache,
33
+ )
34
+ from .regenerated_soft_budget import PlanAndBudgetRegeneratedSoftBudget
35
+
36
+
37
+ class PlanAndBudgetFull:
38
+ """Run a complete answer-producing workflow, not an input patch.
39
+
40
+ Cached mode requires an exact ID/query match. Live mode regenerates two
41
+ solver-only fields without labels. Both use the original native weighted
42
+ reasoning prompt and level-dependent soft word budgets, followed by one
43
+ generation. The caller retains the benchmark's independent official scorer.
44
+ """
45
+
46
+ method_id = "plan_and_budget"
47
+ release_id = "plan.plan_and_budget.full"
48
+ family = SemanticFamily.DECOMPOSE
49
+
50
+ def __init__(
51
+ self, *, output_format: str,
52
+ records: Mapping[str, CachedPlanBudgetRecord] | PlanAndBudgetCache | None = None,
53
+ domain: str = "general question answering", initial_level: int = 3,
54
+ schedule: str | DecaySchedule = DecaySchedule.CONSTANT,
55
+ decomposition_max_tokens: int = 512, assessment_max_tokens: int = 512,
56
+ max_solver_tokens: int = 512, temperature: float = 0.0,
57
+ ):
58
+ if not isinstance(output_format, str) or not output_format.strip():
59
+ raise ValidationError("P&B full requires an explicit output format")
60
+ if (type(max_solver_tokens) is not int or max_solver_tokens < 1
61
+ or type(temperature) not in (int, float)
62
+ or not math.isfinite(temperature) or temperature < 0):
63
+ raise ValidationError("P&B solver token cap/temperature is invalid")
64
+ self.output_format, self.max_solver_tokens = output_format, max_solver_tokens
65
+ self.temperature = temperature
66
+ self.schedule = DecaySchedule.parse(schedule)
67
+ self.cache_sha256 = records.artifact_sha256 if isinstance(records, PlanAndBudgetCache) else None
68
+ self.cache_verification = records.verification if isinstance(records, PlanAndBudgetCache) else None
69
+ if isinstance(records, PlanAndBudgetCache):
70
+ records = records.records
71
+ if records is not None and (not records or any(
72
+ not isinstance(value, CachedPlanBudgetRecord) or key != value.record_id
73
+ for key, value in records.items()
74
+ )):
75
+ raise ArtifactError("P&B full requires solver-only records keyed by exact ID")
76
+ self.records = MappingProxyType(dict(records)) if records is not None else None
77
+ self.preparation = PlanAndBudgetRegeneratedSoftBudget(
78
+ domain=domain, initial_level=initial_level, schedule=self.schedule,
79
+ decomposition_max_tokens=decomposition_max_tokens,
80
+ assessment_max_tokens=assessment_max_tokens, temperature=temperature,
81
+ )
82
+
83
+ def run(self, state: FrozenAgentState, context: InterventionContext) -> CompositeResult:
84
+ from agentinputlab.integrations.full_architecture.plan_and_budget import (
85
+ PAB_NATIVE_PROMPT_MODE,
86
+ PlanBudgetPromptRequest,
87
+ )
88
+
89
+ if not state.query.strip():
90
+ raise ValidationError("P&B full requires a non-empty query")
91
+ if state.messages or state.tool_names:
92
+ raise CapabilityError("P&B native solver accepts visible QA context, not a tool/history loop")
93
+ needed_calls = 1 if self.records is not None else 3
94
+ if (state.budget.max_model_calls < needed_calls
95
+ or state.budget.max_output_tokens < needed_calls):
96
+ raise BudgetExceededError(f"P&B full requires at least {needed_calls} model calls/tokens")
97
+ backend = context.backend
98
+ if not isinstance(backend, LLMBackend):
99
+ raise ExternalDependencyError("P&B full requires an injected LLMBackend")
100
+ if ModelCapability.CHAT not in backend.capabilities:
101
+ raise CapabilityError("P&B full requires the controlled chat backend binding")
102
+ runtime = context.external_runtime
103
+ if (runtime is None or not callable(getattr(runtime, "run", None))
104
+ or not callable(getattr(runtime, "fingerprint", None))):
105
+ raise ExternalDependencyError("P&B full requires PlanAndBudgetNativePromptRuntime")
106
+ identity = runtime.fingerprint()
107
+ if (identity.get("binding_mode") != PAB_NATIVE_PROMPT_MODE
108
+ or identity.get("upstream_revision") != P_AND_B_UPSTREAM_REVISION):
109
+ raise ArtifactError("P&B full native runtime binding/revision differs")
110
+ events, warnings = (), ()
111
+ input_tokens = output_tokens = prep_calls = 0
112
+ if self.records is not None:
113
+ record = self.records.get(state.task_id)
114
+ if record is None or record.query != state.query:
115
+ raise ArtifactError("P&B full cached ID/query does not match; no live fallback")
116
+ warnings = record.audit_warnings
117
+ else:
118
+ # Reserve at least one output token/call for the solver. Actual
119
+ # provider usage, including failed preparation, is ledger-observed.
120
+ prep_state = replace(state, budget=replace(
121
+ state.budget, max_model_calls=state.budget.max_model_calls - 1,
122
+ max_output_tokens=state.budget.max_output_tokens - 1,
123
+ ))
124
+ patch = self.preparation.propose(prep_state, context)
125
+ decomposition, assessment = patch.trace.events[:2]
126
+ record = CachedPlanBudgetRecord(
127
+ record_id=state.task_id or state.state_hash, query=state.query,
128
+ steps=tuple(decomposition.payload["steps"]),
129
+ credits=tuple(assessment.payload["credits"]),
130
+ level=assessment.payload["evaluated_level"],
131
+ audit_warnings=patch.trace.warnings,
132
+ )
133
+ events, warnings = patch.trace.events[:2], patch.trace.warnings
134
+ input_tokens = patch.trace.counters["input_tokens"]
135
+ output_tokens = patch.trace.counters["output_tokens"]
136
+ prep_calls = 2
137
+ envelope = runtime.run(PlanBudgetPromptRequest(
138
+ record=record, instruction=state.instruction,
139
+ reference="\n\n".join(
140
+ (f"[{block.block_id}] {block.text}" if block.block_id else block.text)
141
+ + f"\nSupport ID: {block.metadata.get('official_support_id', block.block_id)}"
142
+ + (f"\nSource: {block.source}" if block.source else "")
143
+ for block in state.context
144
+ ),
145
+ output_format=self.output_format, schedule=self.schedule.value,
146
+ ))
147
+ if not isinstance(envelope, Mapping) or envelope.get("identity") != identity:
148
+ raise ArtifactError("P&B native prompt response identity differs")
149
+ remaining = state.budget.max_output_tokens - output_tokens
150
+ if remaining < 1:
151
+ raise BudgetExceededError("P&B preparation exhausted the solver output budget")
152
+ request = GenerationRequest(
153
+ messages=tuple(Message(**message) for message in envelope["messages"]),
154
+ temperature=self.temperature, max_tokens=min(self.max_solver_tokens, remaining),
155
+ seed=context.seed + prep_calls,
156
+ metadata={"release_id": self.release_id, "stage": "native_weighted_solver",
157
+ "upstream_revision": P_AND_B_UPSTREAM_REVISION},
158
+ )
159
+ response = backend.generate(request)
160
+ if not isinstance(response.text, str) or not response.text.strip():
161
+ raise AlgorithmOutputError("P&B solver returned an empty final answer; no retry")
162
+ if response.usage.output_tokens > request.max_tokens:
163
+ raise BudgetExceededError("P&B solver usage exceeded its requested output cap")
164
+ return CompositeResult(
165
+ method_id=self.method_id, release_id=self.release_id,
166
+ source_state_hash=state.state_hash, final_answer=response.text,
167
+ evidence=state.context,
168
+ trace=ExecutionTrace(
169
+ method_id=self.method_id, release_id=self.release_id,
170
+ events=(*events, TraceEvent(TracePhase.PREPARE, "native_soft_word_allocation", {
171
+ "allocations": envelope["allocations"],
172
+ "total_soft_words": envelope["soft_word_budget"],
173
+ "schedule": self.schedule.value, "tie_policy": "native_numpy_argsort",
174
+ }), TraceEvent(TracePhase.OBSERVE, "solver_answer", {
175
+ "request_hash": request.request_hash, "finish_reason": response.finish_reason,
176
+ "max_output_tokens": request.max_tokens, "seed": request.seed,
177
+ })),
178
+ counters={"model_calls": prep_calls + 1, "optimizer_model_calls": prep_calls,
179
+ "input_tokens": input_tokens + response.usage.input_tokens,
180
+ "output_tokens": output_tokens + response.usage.output_tokens},
181
+ warnings=warnings,
182
+ ),
183
+ implementation_identity=f"native_weighted_solver:P-and-B@{P_AND_B_UPSTREAM_REVISION}",
184
+ profile_kind="controlled_adapter",
185
+ metadata={
186
+ "cached_decomposition": self.records is not None,
187
+ "cache_artifact_sha256": self.cache_sha256,
188
+ "cache_verification": self.cache_verification,
189
+ "native_prompt_runtime": identity,
190
+ "solver_calls": 1, "per_step_model_calls": False,
191
+ "budget_unit": "soft_words", "per_step_hard_token_cap": False,
192
+ "decoder_output_cap": request.max_tokens,
193
+ "native_sampling_defaults_preserved": False,
194
+ "sampling_policy": "explicit_caller_temperature_seed_cap_and_backend_defaults",
195
+ "native_retry_policy_preserved": False,
196
+ "transport_policy": "one_attempt_no_implicit_retry",
197
+ "native_gold_evaluator_executed": False,
198
+ "official_scoring": "caller_owned_separate_benchmark_scorer",
199
+ "gold_fields_visible_to_optimizer": False,
200
+ "paper_result_parity_claimed": False,
201
+ },
202
+ )
203
+
204
+
205
+ __all__ = ["PlanAndBudgetFull"]