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,699 @@
1
+ """Official ToolTalk full-set provider at the pinned Microsoft revision."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import copy
6
+ import hashlib
7
+ import json
8
+ import os
9
+ import subprocess
10
+ import sys
11
+ import types
12
+ from collections.abc import Mapping, Sequence
13
+ from pathlib import Path
14
+ from typing import Any
15
+
16
+ from ..protocol import (
17
+ OfficialArenaError,
18
+ ProviderArmResult,
19
+ content_hash,
20
+ intervention_usage,
21
+ materialized_state,
22
+ require_materialized_budget,
23
+ resolve_shared_budget_config,
24
+ validate_dependency_hashes,
25
+ visible_shared_budget,
26
+ )
27
+ from ._message_compat import coalesce_chat_system_messages
28
+
29
+ _BUDGET_STOP = "I could not complete the task within the shared run budget."
30
+ _SENT2VEC_REVISION = "c2830440298372a76a5deccdac1b25da71530009"
31
+ _DISTILBERT_REVISION = "12040accade4e8a0f71eabdb258fecc2e7e948be"
32
+
33
+
34
+ def _install_sent2vec_compatibility() -> None:
35
+ """Install pdrm83/sent2vec's exact BERT-CLS path without unused extras.
36
+
37
+ ToolTalk imports ``sent2vec.vectorizer.Vectorizer`` globally, while the
38
+ official package imports gensim and spaCy even though its default runtime
39
+ uses only DistilBERT. This source-locked shim preserves the 0.3.0 default
40
+ algorithm (tokenizer.encode, zero padding, first hidden-state CLS vector)
41
+ and pins the otherwise floating Hugging Face model revision.
42
+ """
43
+
44
+ if "sent2vec.vectorizer" in sys.modules:
45
+ return
46
+
47
+ class Vectorizer:
48
+ def __init__(self, pretrained_weights: str = "distilbert-base-uncased", **_: Any):
49
+ if pretrained_weights != "distilbert-base-uncased":
50
+ raise OfficialArenaError("ToolTalk sent2vec model differs")
51
+ import torch
52
+ from transformers import DistilBertModel, DistilBertTokenizer
53
+
54
+ self._torch = torch
55
+ self._device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
56
+ self._tokenizer = DistilBertTokenizer.from_pretrained(
57
+ pretrained_weights,
58
+ revision=_DISTILBERT_REVISION,
59
+ )
60
+ self._model = DistilBertModel.from_pretrained(
61
+ pretrained_weights,
62
+ revision=_DISTILBERT_REVISION,
63
+ )
64
+ self.vectors: list[Any] = []
65
+
66
+ def run(self, sentences: list[str], **_: Any) -> None:
67
+ import numpy as np
68
+
69
+ if not isinstance(sentences, list) or any(
70
+ not isinstance(item, str) for item in sentences
71
+ ):
72
+ raise TypeError("sent2vec requires a list of strings")
73
+ tokenized = [
74
+ self._tokenizer.encode(item, add_special_tokens=True) for item in sentences
75
+ ]
76
+ maximum = max(len(item) for item in tokenized)
77
+ padded = np.array([item + [0] * (maximum - len(item)) for item in tokenized])
78
+ input_ids = self._torch.tensor(padded).type(self._torch.LongTensor).to(self._device)
79
+ model = self._model.to(self._device)
80
+ model.eval()
81
+ with self._torch.no_grad():
82
+ vectors = model(input_ids)[0][:, 0, :].cpu().numpy()
83
+ self.vectors.extend(vectors[index] for index in range(vectors.shape[0]))
84
+
85
+ package = types.ModuleType("sent2vec")
86
+ package.__path__ = [] # type: ignore[attr-defined]
87
+ vectorizer = types.ModuleType("sent2vec.vectorizer")
88
+ vectorizer.Vectorizer = Vectorizer
89
+ package.vectorizer = vectorizer # type: ignore[attr-defined]
90
+ sys.modules["sent2vec"] = package
91
+ sys.modules["sent2vec.vectorizer"] = vectorizer
92
+
93
+
94
+ def _sha256(path: Path) -> str:
95
+ digest = hashlib.sha256()
96
+ with path.open("rb") as handle:
97
+ for block in iter(lambda: handle.read(1024 * 1024), b""):
98
+ digest.update(block)
99
+ return digest.hexdigest()
100
+
101
+
102
+ def _system_prompt(metadata: Mapping[str, Any]) -> str:
103
+ return (
104
+ "You are a helpful assistant. Here is some user data:"
105
+ f"\nlocation: {metadata['location']}"
106
+ f"\ntimestamp: {metadata['timestamp']}"
107
+ f"\nusername (if logged in): {metadata.get('username')}"
108
+ )
109
+
110
+
111
+ def _tool_schemas() -> list[dict[str, Any]]:
112
+ from tooltalk.apis import ALL_APIS
113
+
114
+ schemas: list[dict[str, Any]] = []
115
+ for api in ALL_APIS:
116
+ legacy = dict(api.to_openai_doc(False))
117
+ required = legacy.pop("required", [])
118
+ parameters = dict(legacy["parameters"])
119
+ parameters["required"] = list(required)
120
+ schemas.append(
121
+ {
122
+ "type": "function",
123
+ "function": {
124
+ "name": legacy["name"],
125
+ "description": legacy["description"],
126
+ "parameters": parameters,
127
+ },
128
+ }
129
+ )
130
+ return schemas
131
+
132
+
133
+ class _Predictor:
134
+ """OpenAI-compatible predictor preserving ToolTalk's official turn loop."""
135
+
136
+ def __init__(
137
+ self,
138
+ *,
139
+ model: str,
140
+ base_url: str,
141
+ api_key: str,
142
+ materialized: Mapping[str, Any],
143
+ budget: Mapping[str, Any],
144
+ optimizer_usage: Mapping[str, int | float],
145
+ seed: int,
146
+ max_output_tokens_per_call: int,
147
+ history_transform: Any = None,
148
+ ) -> None:
149
+ from openai import OpenAI
150
+
151
+ self.client = OpenAI(api_key=api_key, base_url=base_url, timeout=600.0, max_retries=0)
152
+ self.model = model
153
+ self.materialized = materialized
154
+ self.seed = seed
155
+ self.tools = _tool_schemas()
156
+ self.first_prediction = True
157
+ self.model_calls = 0
158
+ self.tool_calls = 0
159
+ self.input_tokens = 0
160
+ self.output_tokens = 0
161
+ self.max_model_calls = max(
162
+ 0, int(budget["max_model_calls"]) - int(optimizer_usage.get("model_calls", 0))
163
+ )
164
+ self.max_tool_calls = max(
165
+ 0, int(budget["max_tool_calls"]) - int(optimizer_usage.get("tool_calls", 0))
166
+ )
167
+ self.max_output_tokens = max(
168
+ 0, int(budget["max_output_tokens"]) - int(optimizer_usage.get("output_tokens", 0))
169
+ )
170
+ context_cap = budget.get("max_context_tokens")
171
+ self.max_input_tokens = (
172
+ 2**63 - 1
173
+ if context_cap is None
174
+ else max(0, int(context_cap) - int(optimizer_usage.get("input_tokens", 0)))
175
+ )
176
+ self.max_output_tokens_per_call = max_output_tokens_per_call
177
+ self.hard_stops = 0
178
+ self.history_transform = history_transform
179
+ self.history_usage: dict[str, int | float] = {}
180
+ self._history_raw_boundary: list[dict[str, Any]] | None = None
181
+ self._history_logical_boundary: list[dict[str, Any]] | None = None
182
+
183
+ def _history_messages(self, messages: list[dict[str, Any]]) -> list[dict[str, Any]]:
184
+ if self.history_transform is None:
185
+ return messages
186
+ # ToolTalk's official executor starts every user turn from committed
187
+ # ground-truth history. Predicted tool actions are a temporary rollout,
188
+ # not an append-only extension of that history across user turns. The
189
+ # transformer therefore observes only committed user boundaries; reuse
190
+ # its view plus the exact temporary tool suffix within the same turn.
191
+ if not messages or messages[-1].get("role") != "user":
192
+ raw = self._history_raw_boundary
193
+ logical = self._history_logical_boundary
194
+ if raw is None or logical is None:
195
+ raise OfficialArenaError("ToolTalk live history requires an initial user boundary")
196
+ if len(messages) < len(raw) or messages[:len(raw)] != raw:
197
+ raise OfficialArenaError("ToolTalk temporary tool rollout changed its user boundary")
198
+ result = copy.deepcopy(logical) + copy.deepcopy(messages[len(raw):])
199
+ from agentinputlab.integrations.live_history import _balanced_tool_frames
200
+ if not _balanced_tool_frames(result):
201
+ raise OfficialArenaError("ToolTalk temporary rollout orphaned native tool frames")
202
+ return result
203
+ from agentinputlab.observability import external_usage_counters, normalize_external_usage
204
+
205
+ remaining = {
206
+ "max_model_calls": self.max_model_calls - self.model_calls
207
+ - int(self.history_usage.get("model_calls", 0)),
208
+ "max_output_tokens": self.max_output_tokens - self.output_tokens
209
+ - int(self.history_usage.get("output_tokens", 0)),
210
+ }
211
+ transformed = self.history_transform.transform(
212
+ copy.deepcopy(messages), state=copy.deepcopy(self.materialized),
213
+ remaining_budget=dict(remaining),
214
+ )
215
+ if not isinstance(transformed, Mapping) or set(transformed) != {"messages", "usage"}:
216
+ raise OfficialArenaError("ToolTalk history transform response fields differ")
217
+ raw_usage = transformed["usage"]
218
+ if not isinstance(raw_usage, Mapping) or not {"model_calls", "output_tokens"} <= raw_usage.keys():
219
+ raise OfficialArenaError("ToolTalk history transform requires actual call/output usage")
220
+ if raw_usage["model_calls"] and not {"input_tokens", "retrieval_calls"} <= raw_usage.keys():
221
+ raise OfficialArenaError("ToolTalk history model calls require complete actual usage")
222
+ usage = external_usage_counters(normalize_external_usage({
223
+ "model_calls": 0, "retrieval_calls": 0, "input_tokens": 0, "output_tokens": 0,
224
+ **raw_usage,
225
+ }))
226
+ if not usage["model_calls"] and (usage["input_tokens"] or usage["output_tokens"]):
227
+ raise OfficialArenaError("ToolTalk skipped history transform cannot report model tokens")
228
+ for key, value in usage.items():
229
+ self.history_usage[key] = self.history_usage.get(key, 0) + value
230
+ if usage["tool_calls"] or usage["retrieval_calls"] or usage["embedding_calls"]:
231
+ raise OfficialArenaError("ToolTalk history transform cannot execute tools or retrieval")
232
+ if usage["model_calls"] >= remaining["max_model_calls"] or usage["output_tokens"] >= remaining["max_output_tokens"]:
233
+ raise OfficialArenaError("ToolTalk history transform failed to reserve downstream budget")
234
+ result = transformed["messages"]
235
+ if not isinstance(result, (list, tuple)) or len(result) < 2 or any(
236
+ not isinstance(row, Mapping) or not isinstance(row.get("role"), str)
237
+ for row in result
238
+ ):
239
+ raise OfficialArenaError("ToolTalk history transform messages are invalid")
240
+ if result[0]["role"] != "system" or result[1]["role"] != "user":
241
+ raise OfficialArenaError("ToolTalk history transform must preserve system/user session framing")
242
+ from agentinputlab.integrations.live_history import _balanced_tool_frames
243
+ if not _balanced_tool_frames(result):
244
+ raise OfficialArenaError("ToolTalk history transform orphaned native tool frames")
245
+ self._history_raw_boundary = copy.deepcopy(messages)
246
+ self._history_logical_boundary = copy.deepcopy([dict(row) for row in result])
247
+ return copy.deepcopy(self._history_logical_boundary)
248
+
249
+ def _messages(
250
+ self,
251
+ metadata: Mapping[str, Any],
252
+ history: Sequence[Mapping[str, Any]],
253
+ ) -> list[dict[str, Any]]:
254
+ additions = [str(self.materialized.get("instruction", ""))]
255
+ additions.extend(
256
+ str(item.get("text", ""))
257
+ for item in self.materialized.get("context", [])
258
+ if isinstance(item, Mapping)
259
+ )
260
+ official = _system_prompt(metadata)
261
+ injected = "\n\n".join(item for item in additions if item and item != official)
262
+ system = official if not injected else official + "\n\n" + injected
263
+ messages: list[dict[str, Any]] = [{"role": "system", "content": system}]
264
+ first_user = True
265
+ tool_index = 0
266
+ for turn in history:
267
+ role = turn.get("role")
268
+ if role in {"user", "assistant"}:
269
+ text = turn.get("text", "")
270
+ if role == "user" and first_user:
271
+ text = self.materialized["query"]
272
+ first_user = False
273
+ messages.append({"role": role, "content": str(text)})
274
+ elif role == "api":
275
+ tool_index += 1
276
+ call_id = f"tooltalk_{tool_index:03d}"
277
+ request = turn["request"]
278
+ messages.append(
279
+ {
280
+ "role": "assistant",
281
+ "content": None,
282
+ "tool_calls": [
283
+ {
284
+ "id": call_id,
285
+ "type": "function",
286
+ "function": {
287
+ "name": request["api_name"],
288
+ "arguments": json.dumps(
289
+ request["parameters"],
290
+ ensure_ascii=False,
291
+ sort_keys=True,
292
+ ),
293
+ },
294
+ }
295
+ ],
296
+ }
297
+ )
298
+ messages.append(
299
+ {
300
+ "role": "tool",
301
+ "tool_call_id": call_id,
302
+ "content": json.dumps(
303
+ {
304
+ "response": turn.get("response"),
305
+ "exception": turn.get("exception"),
306
+ },
307
+ ensure_ascii=False,
308
+ sort_keys=True,
309
+ ),
310
+ }
311
+ )
312
+ return coalesce_chat_system_messages(messages)
313
+
314
+ def __call__(
315
+ self,
316
+ metadata: Mapping[str, Any],
317
+ history: Sequence[Mapping[str, Any]],
318
+ ) -> Mapping[str, Any]:
319
+ visible_metadata = self.materialized.get("metadata", {})
320
+ clarification = (
321
+ visible_metadata.get("clarification_request")
322
+ if isinstance(visible_metadata, Mapping)
323
+ else None
324
+ )
325
+ if self.first_prediction and isinstance(clarification, str) and clarification.strip():
326
+ self.first_prediction = False
327
+ return {"role": "assistant", "text": clarification}
328
+ self.first_prediction = False
329
+
330
+ remaining_output = self.max_output_tokens - self.output_tokens - int(self.history_usage.get("output_tokens", 0))
331
+ if self.model_calls + self.history_usage.get("model_calls", 0) >= self.max_model_calls or remaining_output < 1:
332
+ self.hard_stops += 1
333
+ return {"role": "assistant", "text": _BUDGET_STOP}
334
+ messages = self._messages(metadata, history)
335
+ messages = self._history_messages(messages)
336
+ remaining_output = self.max_output_tokens - self.output_tokens - int(self.history_usage.get("output_tokens", 0))
337
+ if self.input_tokens + self.history_usage.get("input_tokens", 0) > self.max_input_tokens:
338
+ self.hard_stops += 1
339
+ return {"role": "assistant", "text": _BUDGET_STOP}
340
+ response = self.client.chat.completions.create(
341
+ model=self.model,
342
+ messages=messages,
343
+ tools=self.tools,
344
+ tool_choice="auto",
345
+ parallel_tool_calls=False,
346
+ temperature=0,
347
+ seed=self.seed + self.model_calls,
348
+ max_tokens=min(
349
+ self.max_output_tokens_per_call,
350
+ remaining_output,
351
+ ),
352
+ extra_body={"chat_template_kwargs": {"enable_thinking": False}},
353
+ )
354
+ self.model_calls += 1
355
+ usage = getattr(response, "usage", None)
356
+ self.input_tokens += int(getattr(usage, "prompt_tokens", 0) or 0)
357
+ self.output_tokens += int(getattr(usage, "completion_tokens", 0) or 0)
358
+ if (self.input_tokens + self.history_usage.get("input_tokens", 0) > self.max_input_tokens
359
+ or self.output_tokens + self.history_usage.get("output_tokens", 0) > self.max_output_tokens):
360
+ self.hard_stops += 1
361
+ return {"role": "assistant", "text": _BUDGET_STOP}
362
+ message = response.choices[0].message
363
+ calls = list(message.tool_calls or ())
364
+ if calls:
365
+ if self.tool_calls >= self.max_tool_calls:
366
+ self.hard_stops += 1
367
+ return {"role": "assistant", "text": _BUDGET_STOP}
368
+ call = calls[0]
369
+ self.tool_calls += 1
370
+ try:
371
+ parameters = json.loads(call.function.arguments)
372
+ if not isinstance(parameters, dict):
373
+ parameters = None
374
+ except (TypeError, json.JSONDecodeError):
375
+ parameters = None
376
+ return {
377
+ "role": "api",
378
+ "request": {
379
+ "api_name": call.function.name,
380
+ "parameters": parameters,
381
+ },
382
+ "metadata": {
383
+ "model": self.model,
384
+ "finish_reason": response.choices[0].finish_reason,
385
+ },
386
+ }
387
+ return {"role": "assistant", "text": message.content or ""}
388
+
389
+ def usage(self) -> dict[str, int | float]:
390
+ usage = {
391
+ "model_calls": self.model_calls,
392
+ "tool_calls": self.tool_calls,
393
+ "input_tokens": self.input_tokens,
394
+ "output_tokens": self.output_tokens,
395
+ "cost_usd": 0.0,
396
+ "unpriced_model_calls": self.model_calls,
397
+ }
398
+ for key, value in self.history_usage.items():
399
+ usage[key] = usage.get(key, 0) + value
400
+ return usage
401
+
402
+
403
+ class ToolTalkProvider:
404
+ benchmark_id = "tooltalk.full"
405
+ source_revision = "e05f4ce6132c80ed33392b81535b077d56ab28fd"
406
+ scorer_id = "tooltalk.official_conversation_success.v1"
407
+ scorer_revision = "122fb0872f116c9a3b531ea24ba3d1b19bd8c75e4785863dfb4add9617fa157e"
408
+ conversation_set_sha256 = (
409
+ "ce9a691f52830a3aef7e5c0665bf30676c536bfdd0ffb0e534770d10d793227d"
410
+ )
411
+
412
+ _REQUIRED = frozenset(
413
+ {
414
+ "dataset_parts",
415
+ "limit",
416
+ "api_mode",
417
+ "agent_model",
418
+ "agent_base_url",
419
+ "agent_key_env",
420
+ "locked_dependency_hashes",
421
+ }
422
+ )
423
+ _OPTIONAL = frozenset({"budget_override"})
424
+
425
+ def __init__(self, *, history_transform: Any = None) -> None:
426
+ if history_transform is not None and not all(
427
+ callable(getattr(history_transform, name, None)) for name in ("transform", "fingerprint")
428
+ ):
429
+ raise OfficialArenaError("ToolTalk history transform requires transform and fingerprint")
430
+ self.history_transform = history_transform
431
+
432
+ def doctor(self, config: Mapping[str, Any]) -> tuple[str, ...]:
433
+ try:
434
+ self._validate_config(config)
435
+ head = subprocess.check_output(
436
+ ["git", "rev-parse", "HEAD"],
437
+ text=True,
438
+ stderr=subprocess.DEVNULL,
439
+ ).strip()
440
+ if head != self.source_revision:
441
+ raise OfficialArenaError("ToolTalk checkout revision differs")
442
+ _install_sent2vec_compatibility()
443
+ from tooltalk.apis import ALL_APIS
444
+ from tooltalk.evaluation.tool_executor import ToolExecutor
445
+
446
+ if len(ALL_APIS) != 28:
447
+ raise OfficialArenaError("ToolTalk official tool catalog differs")
448
+ counts = {part: len(list((Path("data") / part).glob("*.json"))) for part in ("easy", "tooltalk")}
449
+ if counts != {"easy": 28, "tooltalk": 50}:
450
+ raise OfficialArenaError("ToolTalk full-set inventory differs")
451
+ ToolExecutor(init_database_dir="data/databases")
452
+ except Exception as exc:
453
+ return (f"{type(exc).__name__}: {exc}",)
454
+ return ()
455
+
456
+ def capture(
457
+ self,
458
+ config: Mapping[str, Any],
459
+ *,
460
+ output_root: Path,
461
+ ) -> tuple[Mapping[str, Any], ...]:
462
+ del output_root
463
+ parsed = self._validate_config(config)
464
+ _install_sent2vec_compatibility()
465
+ schemas = _tool_schemas()
466
+ tool_names = [item["function"]["name"] for item in schemas]
467
+ rows: list[Mapping[str, Any]] = []
468
+ for part in parsed["dataset_parts"]:
469
+ for path in sorted((Path("data") / part).glob("*.json")):
470
+ raw = path.read_bytes()
471
+ conversation = json.loads(raw)
472
+ opening = conversation["conversation"][0]
473
+ if opening.get("role") != "user":
474
+ raise OfficialArenaError("ToolTalk conversation has no opening user turn")
475
+ checkpoint_id = f"{part}:{conversation['conversation_id']}"
476
+ instruction = _system_prompt(conversation["metadata"])
477
+ visible_state = {
478
+ "query": opening["text"],
479
+ "task_id": checkpoint_id,
480
+ "instruction": instruction,
481
+ "context": [
482
+ {
483
+ "text": json.dumps(schemas, ensure_ascii=False, sort_keys=True),
484
+ "block_id": "official_tool_catalog",
485
+ "source": "tooltalk.apis.ALL_APIS",
486
+ "score": None,
487
+ "metadata": {"api_mode": "all"},
488
+ }
489
+ ],
490
+ "messages": [
491
+ {"role": "user", "content": opening["text"], "name": None}
492
+ ],
493
+ "tool_names": tool_names,
494
+ "metadata": {
495
+ "benchmark_id": self.benchmark_id,
496
+ "difficulty": part,
497
+ "conversation_id": conversation["conversation_id"],
498
+ "checkpoint_phase": "turn_zero",
499
+ "clarification_roundtrip_available": True,
500
+ "state_restore_available": True,
501
+ },
502
+ "budget": visible_shared_budget(
503
+ parsed,
504
+ {
505
+ "max_model_calls": 16,
506
+ "max_retrieval_calls": 8,
507
+ "max_tool_calls": 9,
508
+ "max_output_tokens": 8192,
509
+ "max_context_tokens": None,
510
+ "max_cost_usd": None,
511
+ },
512
+ ),
513
+ }
514
+ rows.append(
515
+ {
516
+ "checkpoint_id": checkpoint_id,
517
+ "group_key": checkpoint_id,
518
+ "visible_state": visible_state,
519
+ "eligible_families": [
520
+ "reformulate",
521
+ "decompose",
522
+ "acquire",
523
+ "clarify",
524
+ "curate",
525
+ ],
526
+ "protected": {
527
+ "dataset_part": part,
528
+ "relative_path": path.as_posix(),
529
+ "conversation_sha256": hashlib.sha256(raw).hexdigest(),
530
+ "conversation_id": conversation["conversation_id"],
531
+ "locked_dependency_hashes": parsed["locked_dependency_hashes"],
532
+ },
533
+ }
534
+ )
535
+ if len(rows) >= parsed["limit"]:
536
+ return tuple(rows)
537
+ if not rows:
538
+ raise OfficialArenaError("ToolTalk capture found no conversations")
539
+ return tuple(rows)
540
+
541
+ def run_arm(
542
+ self,
543
+ config: Mapping[str, Any],
544
+ *,
545
+ replay_record: Mapping[str, Any],
546
+ arm_payload: Mapping[str, Any],
547
+ seed: int,
548
+ role: str,
549
+ work_dir: Path,
550
+ ) -> ProviderArmResult:
551
+ parsed = self._validate_config(config)
552
+ prediction_path = work_dir / "predicted-conversation.json"
553
+ evaluation_path = work_dir / "native-evaluation.json"
554
+ trajectory_path = work_dir / "trajectory.json"
555
+ history_path = work_dir / "live-history.json"
556
+ artifacts = (prediction_path, evaluation_path, trajectory_path)
557
+ if self.history_transform is not None:
558
+ artifacts += (history_path,)
559
+ if any(path.exists() for path in artifacts):
560
+ raise OfficialArenaError("ToolTalk requires a fresh work directory")
561
+ state = materialized_state(arm_payload)
562
+ budget = require_materialized_budget(state, parsed)
563
+ optimizer_usage = intervention_usage(arm_payload)
564
+ protected = replay_record["protected"]
565
+ path = Path(protected["relative_path"])
566
+ raw = path.read_bytes()
567
+ if _sha256(path) != protected["conversation_sha256"]:
568
+ raise OfficialArenaError("ToolTalk protected conversation differs")
569
+ conversation = json.loads(raw)
570
+ if conversation.get("conversation_id") != protected["conversation_id"]:
571
+ raise OfficialArenaError("ToolTalk protected conversation identity differs")
572
+ api_key = os.environ.get(parsed["agent_key_env"])
573
+ if not api_key:
574
+ raise OfficialArenaError(
575
+ f"ToolTalk environment {parsed['agent_key_env']} is missing"
576
+ )
577
+ override = parsed.get("budget_override")
578
+ per_call_cap = (
579
+ int(override["max_output_tokens_per_call"])
580
+ if isinstance(override, Mapping)
581
+ else 512
582
+ )
583
+ # Fresh execution processes need the pinned import shim before the
584
+ # predictor imports tooltalk.apis; capture()/doctor() need not precede
585
+ # every restored native episode in the same Python process.
586
+ _install_sent2vec_compatibility()
587
+ predictor = _Predictor(
588
+ model=parsed["agent_model"],
589
+ base_url=parsed["agent_base_url"],
590
+ api_key=api_key,
591
+ materialized=state,
592
+ budget=budget,
593
+ optimizer_usage=optimizer_usage,
594
+ seed=seed,
595
+ max_output_tokens_per_call=per_call_cap,
596
+ history_transform=self.history_transform,
597
+ )
598
+ from tooltalk.evaluation.tool_executor import ToolExecutor
599
+
600
+ executor = ToolExecutor(init_database_dir="data/databases")
601
+ try:
602
+ evaluated = executor.run_conversation(copy.deepcopy(conversation), predictor)
603
+ finally:
604
+ if self.history_transform is not None:
605
+ with history_path.open("x", encoding="utf-8") as handle:
606
+ json.dump({
607
+ "fingerprint": self.history_transform.fingerprint(),
608
+ "records": list(getattr(self.history_transform, "records", ())),
609
+ "history_usage": predictor.history_usage,
610
+ "agent_and_history_usage": predictor.usage(),
611
+ "original_shared_budget": dict(budget),
612
+ "native_boundary_protocol": "tooltalk.committed_user_turns.v1",
613
+ }, handle, ensure_ascii=False, sort_keys=True, indent=2, allow_nan=False)
614
+ handle.write("\n")
615
+ # Preserve the actual episode before scoring, including scorer failures.
616
+ # Exclusive creation keeps an earlier attempt's evidence immutable.
617
+ with prediction_path.open("x", encoding="utf-8") as handle:
618
+ json.dump(evaluated, handle, ensure_ascii=False, indent=2, sort_keys=True,
619
+ allow_nan=False)
620
+ handle.write("\n")
621
+ evaluated = executor.evaluate_predictions(evaluated)
622
+ with evaluation_path.open("x", encoding="utf-8") as handle:
623
+ json.dump(evaluated, handle, ensure_ascii=False, indent=2, sort_keys=True,
624
+ allow_nan=False)
625
+ handle.write("\n")
626
+ metrics = evaluated["metrics"]
627
+ trace = {
628
+ "provider": "tooltalk",
629
+ "source_revision": self.source_revision,
630
+ "conversation_id": protected["conversation_id"],
631
+ "dataset_part": protected["dataset_part"],
632
+ "role": role,
633
+ "seed": seed,
634
+ "metrics": metrics,
635
+ "generation_controls": {
636
+ "hard_stops": predictor.hard_stops,
637
+ "shared_budget": dict(budget),
638
+ "optimizer_usage": dict(optimizer_usage),
639
+ },
640
+ "prediction_trace_sha256": content_hash(evaluated["conversation"]),
641
+ "native_artifacts": {
642
+ "prediction": {"path": prediction_path.name, "sha256": _sha256(prediction_path)},
643
+ "evaluation": {"path": evaluation_path.name, "sha256": _sha256(evaluation_path)},
644
+ },
645
+ }
646
+ if self.history_transform is not None:
647
+ trace["live_history_transform"] = self.history_transform.fingerprint()
648
+ trace["live_history_artifact"] = {"path": history_path.name, "sha256": _sha256(history_path)}
649
+ trace["live_history_boundary_protocol"] = "tooltalk.committed_user_turns.v1"
650
+ with trajectory_path.open("x", encoding="utf-8") as handle:
651
+ json.dump(trace, handle, ensure_ascii=False, indent=2, sort_keys=True,
652
+ allow_nan=False)
653
+ handle.write("\n")
654
+ return ProviderArmResult(
655
+ metrics={
656
+ "official_success": float(metrics["success"]),
657
+ "precision": float(metrics["precision"]),
658
+ "recall": float(metrics["recall"]),
659
+ "action_precision": float(metrics["action_precision"]),
660
+ "bad_action_rate": float(metrics["bad_action_rate"]),
661
+ "soft_success": float(metrics["soft_success"]),
662
+ "adapter_hard_stops": float(predictor.hard_stops),
663
+ },
664
+ trace=trace,
665
+ usage=predictor.usage(),
666
+ runtime_instance_id=content_hash(
667
+ {
668
+ "provider": "tooltalk",
669
+ "checkpoint_id": replay_record["checkpoint_id"],
670
+ "role": role,
671
+ "seed": seed,
672
+ "work_dir": str(work_dir),
673
+ }
674
+ ),
675
+ )
676
+
677
+ def _validate_config(self, config: Mapping[str, Any]) -> Mapping[str, Any]:
678
+ config = resolve_shared_budget_config(config)
679
+ if not isinstance(config, Mapping) or set(config) not in {
680
+ self._REQUIRED,
681
+ self._REQUIRED | self._OPTIONAL,
682
+ }:
683
+ raise OfficialArenaError("ToolTalk provider config fields are invalid")
684
+ if list(config["dataset_parts"]) != ["easy", "tooltalk"]:
685
+ raise OfficialArenaError("ToolTalk full set must use easy then tooltalk")
686
+ limit = config["limit"]
687
+ if isinstance(limit, bool) or not isinstance(limit, int) or not 1 <= limit <= 78:
688
+ raise OfficialArenaError("ToolTalk limit must be between 1 and 78")
689
+ if config["api_mode"] != "all":
690
+ raise OfficialArenaError("ToolTalk paper protocol requires api_mode=all")
691
+ for name in ("agent_model", "agent_base_url", "agent_key_env"):
692
+ if not isinstance(config[name], str) or not config[name].strip():
693
+ raise OfficialArenaError(f"ToolTalk {name} is invalid")
694
+ validate_dependency_hashes(config["locked_dependency_hashes"], label="ToolTalk")
695
+ return config
696
+
697
+
698
+ def factory() -> ToolTalkProvider:
699
+ return ToolTalkProvider()