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,324 @@
1
+ """One coordinator-owned, fail-closed cost ledger for native GRPO workers.
2
+
3
+ Workers must send reservations and settlements to this SAME instance (for
4
+ example through a serial Ray actor). Instantiating a ledger per rank is not
5
+ aggregate enforcement. No model, optimizer or Ray cluster is started here.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import threading
10
+ from dataclasses import dataclass
11
+
12
+ from agentinputlab.contracts import BudgetExceededError, ExternalDependencyError, ValidationError
13
+
14
+ from .smartsearch_grpo_tools import _new_output, _save
15
+ from .smartsearch_teacher import SmartSearchTeacherCompletion
16
+
17
+
18
+ @dataclass(frozen=True, slots=True)
19
+ class SmartSearchGRPOCostLimits:
20
+ policy_requests: int
21
+ policy_output_tokens: int
22
+ helper_requests: int
23
+ helper_output_tokens: int
24
+ actor_ranks: int
25
+ optimizer_steps_per_rank: int
26
+
27
+ def __post_init__(self):
28
+ if any(type(getattr(self, name)) is not int or getattr(self, name) < 1
29
+ for name in self.__dataclass_fields__) or self.actor_ranks > 4:
30
+ raise ValidationError("SmartSearch GRPO needs positive aggregate cost limits and one to four actor ranks")
31
+
32
+
33
+ class SmartSearchGRPOCostLedger:
34
+ """Reserve before neural work; retain unknown usage and every rank's costs.
35
+
36
+ Input token counts are logical prompt tokens, not measured physical model
37
+ forwards. Returned output counts include ALL generated samples, before the
38
+ native selector drops any. Optimizer counters are per rank; synchronized
39
+ updates are never computed by summing ranks.
40
+ """
41
+
42
+ def __init__(self, *, output_root, limits: SmartSearchGRPOCostLimits):
43
+ if not isinstance(limits, SmartSearchGRPOCostLimits):
44
+ raise ValidationError("SmartSearch GRPO requires typed aggregate cost limits")
45
+ self.root = _new_output(output_root)
46
+ self.limits, self._lock = limits, threading.RLock()
47
+ self._failed, self._number = False, 0
48
+ self._pending = {}
49
+ self._invalid_usage_reports = []
50
+ self._costs = {kind: dict(requests=0, responses=0, logical_input_tokens=0,
51
+ output_tokens=0, reserved_output_tokens=0, generated_samples=0)
52
+ for kind in ("policy", "helper")}
53
+ self._steps = {str(rank): dict(attempts=0, responses=0) for rank in range(limits.actor_ranks)}
54
+ _save(self.root, "claim.json", dict(limits=limits, coordinator_owned=True,
55
+ all_generated_samples_counted=True, physical_forwards_not_claimed=True,
56
+ synchronized_updates_not_sum_of_rank_steps=True, no_automatic_retry=True))
57
+
58
+ def _healthy(self):
59
+ if self._failed:
60
+ raise ExternalDependencyError("SmartSearch GRPO run has a retained failure; no automatic neural retry")
61
+
62
+ def _event(self, name, value):
63
+ self._number += 1
64
+ try:
65
+ _save(self.root, f"event-{self._number:08d}-{name}.json", value)
66
+ except BaseException:
67
+ self._failed = True
68
+ raise
69
+
70
+ def _reject(self, message, *, budget=False):
71
+ self._failed = True
72
+ self._event("rejected", dict(error=message, accept_checkpoint=False, no_automatic_retry=True))
73
+ error = BudgetExceededError if budget else ExternalDependencyError
74
+ raise error(message)
75
+
76
+ def reserve(self, *, kind, worker, input_token_counts, samples, max_new_tokens):
77
+ """Return an opaque ticket, shared across all worker/rank clients."""
78
+ with self._lock:
79
+ self._healthy()
80
+ if not isinstance(kind, str) or kind not in self._costs or not isinstance(worker, str) or not worker.strip() or (
81
+ len(worker) > 128 or not isinstance(input_token_counts, (tuple, list))
82
+ or not input_token_counts or len(input_token_counts) > 10000
83
+ or any(type(n) is not int or n < 0 for n in input_token_counts)
84
+ or type(samples) is not int or not 1 <= samples <= 64
85
+ or type(max_new_tokens) is not int or max_new_tokens < 1
86
+ or max_new_tokens > (2048 if kind == "helper" else 8192)
87
+ or (kind == "helper" and (samples != 1 or len(input_token_counts) != 1))
88
+ ):
89
+ raise ValidationError("SmartSearch GRPO generation reservation is invalid")
90
+ number = len(input_token_counts) * samples
91
+ reservation = number * max_new_tokens
92
+ costs = self._costs[kind]
93
+ if costs["requests"] >= getattr(self.limits, kind + "_requests") or (
94
+ costs["output_tokens"] + costs["reserved_output_tokens"] + reservation
95
+ > getattr(self.limits, kind + "_output_tokens")
96
+ ):
97
+ self._reject("SmartSearch GRPO aggregate generation budget exhausted", budget=True)
98
+ ticket = f"generation-{self._number + 1:08d}"
99
+ item = dict(ticket=ticket, kind=kind, worker=worker, input_token_counts=list(input_token_counts),
100
+ samples=samples, output_samples=number, max_new_tokens=max_new_tokens,
101
+ reserved_output_tokens=reservation)
102
+ self._event("generation-reserved", item)
103
+ self._pending[ticket] = item
104
+ costs["requests"] += 1
105
+ costs["logical_input_tokens"] += sum(input_token_counts)
106
+ costs["reserved_output_tokens"] += reservation
107
+ return ticket
108
+
109
+ def settle(self, ticket, *, output_token_counts):
110
+ with self._lock:
111
+ # Another rank may have failed while this paid request was in
112
+ # flight. Still retain its measured cost; never clear the latch.
113
+ if not isinstance(ticket, str) or ticket not in self._pending:
114
+ self._reject("SmartSearch GRPO ticket is unknown or already settled")
115
+ item = self._pending[ticket]
116
+ # Validation failures keep the entire reservation: usage is not
117
+ # assumed zero when the provider omitted or malformed its report.
118
+ if not isinstance(output_token_counts, (list, tuple)) or (
119
+ len(output_token_counts) != item["output_samples"]
120
+ or any(type(n) is not int or n < 0 or n > item["max_new_tokens"]
121
+ for n in output_token_counts)
122
+ ):
123
+ report = dict(ticket=ticket, kind=item["kind"],
124
+ reported_output_tokens=sum(n for n in output_token_counts if type(n) is int and n >= 0)
125
+ if isinstance(output_token_counts, (list, tuple)) and len(output_token_counts) <= 10000 else None,
126
+ reservation_retained=True)
127
+ self._invalid_usage_reports.append(report)
128
+ self._event("invalid-usage-report", report)
129
+ self._reject("SmartSearch GRPO provider token/sample counts differ from its reservation")
130
+ self._event("generation-settled", dict(ticket=ticket, output_token_counts=list(output_token_counts)))
131
+ costs = self._costs[item["kind"]]
132
+ costs["responses"] += 1
133
+ costs["output_tokens"] += sum(output_token_counts)
134
+ costs["generated_samples"] += len(output_token_counts)
135
+ costs["reserved_output_tokens"] -= item["reserved_output_tokens"]
136
+ del self._pending[ticket]
137
+
138
+ def fail(self, ticket, *, error_type):
139
+ """Retain the pre-call reservation after a failed/unknown provider call."""
140
+ with self._lock:
141
+ if not isinstance(error_type, str) or not error_type or len(error_type) > 128:
142
+ raise ValidationError("SmartSearch GRPO failure requires a bounded exception type")
143
+ self._failed = True
144
+ self._event("provider-failed", dict(ticket=ticket, error_type=error_type,
145
+ ticket_pending=ticket in self._pending, accept_checkpoint=False, no_automatic_retry=True))
146
+
147
+ def optimizer_begin(self, rank):
148
+ with self._lock:
149
+ self._healthy()
150
+ if type(rank) is not int or str(rank) not in self._steps:
151
+ raise ValidationError("SmartSearch GRPO optimizer rank is outside its admitted actor mesh")
152
+ cost = self._steps[str(rank)]
153
+ if cost["attempts"] != cost["responses"]:
154
+ self._reject("SmartSearch GRPO optimizer already has an unresolved step")
155
+ if cost["attempts"] >= self.limits.optimizer_steps_per_rank:
156
+ self._reject("SmartSearch GRPO actor optimizer step quota exhausted", budget=True)
157
+ self._event("optimizer-begin", dict(rank=rank, step=cost["attempts"] + 1))
158
+ cost["attempts"] += 1
159
+
160
+ def optimizer_end(self, rank):
161
+ with self._lock:
162
+ # Account for a concurrent rank's already-completed native step
163
+ # even when a different worker has invalidated this run.
164
+ if type(rank) is not int or str(rank) not in self._steps:
165
+ raise ValidationError("SmartSearch GRPO optimizer rank is outside its admitted actor mesh")
166
+ cost = self._steps[str(rank)]
167
+ if cost["attempts"] != cost["responses"] + 1:
168
+ self._reject("SmartSearch GRPO optimizer settlement has no pending step")
169
+ self._event("optimizer-end", dict(rank=rank, step=cost["attempts"]))
170
+ cost["responses"] += 1
171
+
172
+ def snapshot(self):
173
+ with self._lock:
174
+ return dict(failed=self._failed, costs={kind: dict(value) for kind, value in self._costs.items()},
175
+ optimizer_rank_steps={rank: dict(value) for rank, value in self._steps.items()},
176
+ pending_generation_tickets=sorted(self._pending),
177
+ invalid_usage_reports=[dict(row) for row in self._invalid_usage_reports],
178
+ physical_model_forwards_measured=False)
179
+
180
+ def assert_healthy(self, *, expected_optimizer_steps=None):
181
+ with self._lock:
182
+ self._healthy()
183
+ if self._pending or any(n["attempts"] != n["responses"] for n in self._steps.values()):
184
+ raise ExternalDependencyError("SmartSearch GRPO has unresolved paid work; checkpoint not accepted")
185
+ steps = [n["responses"] for n in self._steps.values()]
186
+ if len(set(steps)) != 1:
187
+ raise ExternalDependencyError("SmartSearch GRPO actor rank step counts differ")
188
+ if expected_optimizer_steps is not None and (
189
+ type(expected_optimizer_steps) is not int or expected_optimizer_steps < 1
190
+ or steps[0] != expected_optimizer_steps
191
+ ):
192
+ raise ExternalDependencyError("SmartSearch GRPO actual actor steps differ from the admitted plan")
193
+ return {**self.snapshot(), "synchronized_optimizer_steps": steps[0]}
194
+
195
+
196
+ def observe_native_grpo_optimizer(optimizer, *, ledger, rank):
197
+ """Observe native AdamW.step without replacing loss, gradients or schedule.
198
+
199
+ ``ledger`` may be a synchronous RPC client for the sole coordinator. A
200
+ failed step is unresolved and the wrapper is latched; it cannot be retried.
201
+ """
202
+ if not callable(getattr(optimizer, "step", None)) or any(
203
+ not callable(getattr(ledger, name, None)) for name in ("optimizer_begin", "optimizer_end", "fail")
204
+ ) or type(rank) is not int or rank < 0 or getattr(optimizer, "_agentinputlab_grpo_observed", False):
205
+ raise ValidationError("SmartSearch GRPO optimizer observer needs one native optimizer/rank and shared ledger")
206
+ original, failed = optimizer.step, False
207
+
208
+ def step(*args, **kwargs):
209
+ nonlocal failed
210
+ if failed:
211
+ raise ExternalDependencyError("SmartSearch GRPO optimizer failed; no automatic step retry")
212
+ try:
213
+ ledger.optimizer_begin(rank)
214
+ result = original(*args, **kwargs)
215
+ ledger.optimizer_end(rank)
216
+ return result
217
+ except BaseException as exc:
218
+ failed = True
219
+ ledger.fail(f"optimizer-rank-{rank}", error_type=type(exc).__name__)
220
+ raise
221
+
222
+ optimizer.step = step
223
+ optimizer._agentinputlab_grpo_observed = True
224
+ return optimizer
225
+
226
+
227
+ def meter_smartsearch_grpo_helper(generate, *, ledger, worker, fingerprint, count_input_tokens):
228
+ """Place native prefix AND reward helper clients behind one shared quota.
229
+
230
+ Host this callback at the sole teacher coordinator. Keep the provider's
231
+ original text, sampling and stop behavior. This does not construct a model
232
+ or replace either native parser. A distributed executor supplies an RPC
233
+ client to this callback, not a new independent quota per rank.
234
+ """
235
+ if not callable(generate) or not callable(count_input_tokens) or any(
236
+ not callable(getattr(ledger, name, None)) for name in ("reserve", "settle", "fail")
237
+ ) or not isinstance(worker, str) or not worker.strip():
238
+ raise ValidationError("SmartSearch GRPO helper requires a measured provider and sole shared ledger")
239
+ SmartSearchTeacherCompletion("", 0, 0, fingerprint)
240
+ lock, failed = threading.Lock(), False
241
+
242
+ def complete(prompt, *, temperature, max_new_tokens, stop, seed):
243
+ nonlocal failed
244
+ with lock:
245
+ if failed:
246
+ raise ExternalDependencyError("SmartSearch GRPO helper failed; no automatic provider retry")
247
+ if not isinstance(prompt, str) or temperature != .6 or type(max_new_tokens) is not int or max_new_tokens != 2048 or (
248
+ type(seed) is not int or seed < 0 or not isinstance(stop, (tuple, list))
249
+ or tuple(stop) not in ((), ("</answer>",))
250
+ ):
251
+ raise ValidationError("SmartSearch GRPO helper request differs from its native contract")
252
+ tokens = count_input_tokens(prompt)
253
+ ticket = ledger.reserve(kind="helper", worker=worker, input_token_counts=[tokens],
254
+ samples=1, max_new_tokens=max_new_tokens)
255
+ try:
256
+ result = generate(prompt, temperature=temperature, max_new_tokens=max_new_tokens, stop=stop, seed=seed)
257
+ if not isinstance(result, SmartSearchTeacherCompletion):
258
+ raise ExternalDependencyError("SmartSearch GRPO helper omitted typed usage")
259
+ ledger.settle(ticket, output_token_counts=[result.output_tokens])
260
+ if result.input_tokens != tokens or result.model_fingerprint_sha256 != fingerprint:
261
+ raise ExternalDependencyError("SmartSearch GRPO helper identity/input accounting differs")
262
+ return result
263
+ except BaseException as exc:
264
+ failed = True
265
+ ledger.fail(ticket, error_type=type(exc).__name__)
266
+ raise
267
+
268
+ return complete
269
+
270
+
271
+ class MeteredNativeGRPOEngine:
272
+ """Transparent observer of the pinned rollout's vLLM.generate seam.
273
+
274
+ Inputs and returned RequestOutput objects are passed through unchanged.
275
+ All engine outputs are settled before native prefix/group selection, so
276
+ later truncation cannot hide their cost. No token/stop/n/temperature value
277
+ is rewritten. Use only with the pinned native rollout and its TP=1 config.
278
+ """
279
+
280
+ def __init__(self, engine, *, ledger, worker):
281
+ if not callable(getattr(engine, "generate", None)) or any(
282
+ not callable(getattr(ledger, name, None)) for name in ("reserve", "settle", "fail")
283
+ ) or not isinstance(worker, str) or not worker.strip():
284
+ raise ValidationError("SmartSearch GRPO engine observer requires native generation and a shared ledger")
285
+ self._engine, self._ledger, self._worker = engine, ledger, worker
286
+ self._failed = False
287
+
288
+ def __getattr__(self, name):
289
+ return getattr(self._engine, name)
290
+
291
+ def generate(self, *args, **kwargs):
292
+ if self._failed:
293
+ raise ExternalDependencyError("SmartSearch GRPO engine failed; no automatic generation retry")
294
+ prompts, params = kwargs.get("prompts"), kwargs.get("sampling_params")
295
+ if args or not isinstance(prompts, list) or not prompts or any(
296
+ not isinstance(p, dict) or set(p) != {"prompt_token_ids"}
297
+ or not isinstance(p["prompt_token_ids"], list) or not p["prompt_token_ids"]
298
+ for p in prompts
299
+ ):
300
+ raise ValidationError("SmartSearch GRPO engine seam differs from the pinned token-only native call")
301
+ samples, cap = getattr(params, "n", None), getattr(params, "max_tokens", None)
302
+ ticket = self._ledger.reserve(kind="policy", worker=self._worker,
303
+ input_token_counts=[len(p["prompt_token_ids"]) for p in prompts],
304
+ samples=samples, max_new_tokens=cap)
305
+ try:
306
+ result = self._engine.generate(*args, **kwargs)
307
+ if not isinstance(result, list) or len(result) != len(prompts):
308
+ raise ExternalDependencyError("SmartSearch native engine returned a different prompt count")
309
+ counts = []
310
+ for row in result:
311
+ outputs = getattr(row, "outputs", None)
312
+ if not isinstance(outputs, (tuple, list)) or len(outputs) != samples:
313
+ raise ExternalDependencyError("SmartSearch native engine returned a different sample count")
314
+ for output in outputs:
315
+ ids = getattr(output, "token_ids", None)
316
+ if not isinstance(ids, (tuple, list)):
317
+ raise ExternalDependencyError("SmartSearch native engine omitted measured output token IDs")
318
+ counts.append(len(ids))
319
+ self._ledger.settle(ticket, output_token_counts=counts)
320
+ return result
321
+ except BaseException as exc:
322
+ self._failed = True
323
+ self._ledger.fail(ticket, error_type=type(exc).__name__)
324
+ raise
@@ -0,0 +1,144 @@
1
+ """Pinned native GRPO query refinement with measured, non-retrying transport."""
2
+ from __future__ import annotations
3
+ import __future__
4
+
5
+ import ast
6
+ import re
7
+ import threading
8
+ from collections.abc import Mapping
9
+ from pathlib import Path
10
+
11
+ from agentinputlab.contracts import BudgetExceededError, ExternalDependencyError, ValidationError
12
+ from agentinputlab.contracts.serialization import content_hash
13
+
14
+ from .qrag import _sha
15
+ from .smartsearch_grpo_data import verify_smartsearch_grpo_source
16
+ from .smartsearch_grpo_tools import _new_output, _save
17
+ from .smartsearch_teacher import SmartSearchTeacherCompletion, SmartSearchTeacherControls
18
+
19
+ _PATH = "src/verl/workers/rollout/vllm_rollout/generate_new_prompts.py"
20
+
21
+
22
+ class SmartSearchNativeGRPOPrefixBuilder:
23
+ """Execute the native tensor/parser/refinement functions without raw HTTP.
24
+
25
+ This TRAIN-only instance binds explicit references. Both native helper
26
+ operations use their original 2048-token, temperature0.6, NO-stop request;
27
+ unlike offline curriculum refinement, no closing tag is appended here.
28
+ Quotas are per instance. A distributed executor must enforce an aggregate
29
+ helper quota rather than silently allocating this allowance to every rank.
30
+ """
31
+
32
+ def __init__(self, generate, *, checkout, references: Mapping, model_fingerprint_sha256,
33
+ controls: SmartSearchTeacherControls, output_root):
34
+ if not callable(generate) or not isinstance(controls, SmartSearchTeacherControls) or (
35
+ not isinstance(references, Mapping) or not references
36
+ ):
37
+ raise ValidationError("SmartSearch GRPO prefixes require explicit TRAIN references and provider")
38
+ clean = {}
39
+ for question, answers in references.items():
40
+ if not isinstance(question, str) or not question.strip() or not isinstance(answers, (list, tuple)) or (
41
+ not answers or any(not isinstance(a, str) or not a.strip() for a in answers)
42
+ ) or question.strip() in clean:
43
+ raise ValidationError("SmartSearch GRPO prefix references are invalid or collide")
44
+ clean[question.strip()] = tuple(answers)
45
+ SmartSearchTeacherCompletion("", 0, 0, model_fingerprint_sha256)
46
+ source, binding = verify_smartsearch_grpo_source(checkout)
47
+ path = source / _PATH
48
+ output = Path(output_root).resolve(strict=False)
49
+ if output.is_relative_to(source) or source.is_relative_to(output):
50
+ raise ValidationError("SmartSearch GRPO prefix output must not overlap native source")
51
+ try:
52
+ import torch
53
+ import torch.nn.functional as functional
54
+ except ImportError as exc:
55
+ raise ExternalDependencyError("Install the native SmartSearch GRPO torch runtime") from exc
56
+ self.root = _new_output(output_root)
57
+ self.generate, self.controls, self.references = generate, controls, clean
58
+ self.fingerprint, self.failed = model_fingerprint_sha256, False
59
+ self._lock = threading.Lock()
60
+ self.usage = dict(prefix_attempts=0, prefix_responses=0, prefixes_produced=0,
61
+ model_attempts=0, model_responses=0, input_tokens=0, output_tokens=0,
62
+ unknown_output_token_reservations=0)
63
+ tree = ast.parse(path.read_bytes())
64
+ functions = [n for n in tree.body if isinstance(n, ast.FunctionDef) and n.name != "generate_response"]
65
+ namespace = dict(re=re, torch=torch, F=functional, generate_response=self._complete)
66
+ exec(compile(ast.Module(body=functions, type_ignores=[]), str(path), "exec",
67
+ flags=__future__.annotations.compiler_flag), namespace)
68
+ self._native = namespace["generate_new_prompts"]
69
+ self.source_path, self.source_sha = path, _sha(path)
70
+ _save(self.root, "claim.json", dict(native_source=binding, native_prefix_sha256=self.source_sha,
71
+ references_sha256=content_hash(clean), reference_split="train", controls=controls,
72
+ model_fingerprint_sha256=self.fingerprint, native_tensor_parser_selection_unchanged=True,
73
+ native_helper_stop=[], no_closing_tag_append=True, no_http_empty_fallback=True))
74
+
75
+ def _complete(self, prompt):
76
+ usage, cap = self.usage, 2048
77
+ if not isinstance(prompt, str) or len(prompt.encode()) > self.controls.max_input_bytes:
78
+ raise ValidationError("SmartSearch GRPO prefix helper input exceeds its byte bound")
79
+ if usage['model_attempts'] >= self.controls.max_model_calls or (
80
+ usage['output_tokens'] + usage['unknown_output_token_reservations'] + cap
81
+ > self.controls.max_total_output_tokens
82
+ ):
83
+ raise BudgetExceededError("SmartSearch GRPO prefix helper cannot admit its native2048-token cap")
84
+ usage['model_attempts'] += 1
85
+ usage['unknown_output_token_reservations'] += cap
86
+ number = usage['model_attempts']
87
+ _save(self.root, f"helper-{number:06d}-request.json", dict(prompt=prompt, temperature=.6,
88
+ max_new_tokens=cap, stop=[], seed=self.controls.seed, reference_split="train"))
89
+ result = self.generate(prompt, temperature=.6, max_new_tokens=cap, stop=(), seed=self.controls.seed)
90
+ if not isinstance(result, SmartSearchTeacherCompletion):
91
+ raise ExternalDependencyError("SmartSearch GRPO prefix helper requires typed measured usage")
92
+ usage['model_responses'] += 1
93
+ usage['input_tokens'] += result.input_tokens
94
+ usage['output_tokens'] += result.output_tokens
95
+ usage['unknown_output_token_reservations'] -= cap
96
+ _save(self.root, f"helper-{number:06d}-response.json", result)
97
+ if result.model_fingerprint_sha256 != self.fingerprint:
98
+ raise ExternalDependencyError("SmartSearch GRPO prefix helper model identity changed")
99
+ if result.output_tokens > cap:
100
+ raise BudgetExceededError("SmartSearch GRPO prefix helper exceeded the requested token cap")
101
+ return result.text
102
+
103
+ def __call__(self, prompts, tokenizer, ground_truth):
104
+ with self._lock:
105
+ if self.failed:
106
+ raise ExternalDependencyError("SmartSearch GRPO prefix failed; no automatic helper retry")
107
+ try:
108
+ if self.usage['prefix_attempts'] >= self.controls.max_rollout_rows:
109
+ raise BudgetExceededError("SmartSearch GRPO prefix row quota exhausted")
110
+ if _sha(self.source_path) != self.source_sha:
111
+ raise ExternalDependencyError("SmartSearch native prefix source changed")
112
+ trajectory = tokenizer.decode(prompts.batch['input_ids'][0])
113
+ if len(trajectory.encode()) > self.controls.max_input_bytes:
114
+ raise ValidationError("SmartSearch GRPO prefix trajectory exceeds its byte bound")
115
+ match = re.search(r'<\|im_start\|>user\n(.*?)<\|im_end\|>', trajectory, re.DOTALL)
116
+ answers = (ground_truth,) if isinstance(ground_truth, str) else tuple(ground_truth)
117
+ if not match or self.references.get(match.group(1).strip()) != answers:
118
+ raise ValidationError("SmartSearch GRPO prefix input is not its bound TRAIN reference")
119
+ self.usage['prefix_attempts'] += 1
120
+ number = self.usage['prefix_attempts']
121
+ _save(self.root, f"prefix-{number:06d}-request.json", dict(
122
+ trajectory_sha256=content_hash(trajectory), ground_truth_sha256=content_hash(answers)))
123
+ result = self._native(prompts, tokenizer, ground_truth)
124
+ if not isinstance(result, tuple) or len(result) != 2 or len(result[0]) != len(result[1]):
125
+ raise ExternalDependencyError("SmartSearch native prefix tensor collection differs")
126
+ self.usage['prefix_responses'] += 1
127
+ self.usage['prefixes_produced'] += len(result[0])
128
+ _save(self.root, f"prefix-{number:06d}-response.json", dict(prefix_count=len(result[0]),
129
+ shapes=[[list(t.shape) for t in values] for values in result], usage=self.usage))
130
+ return result
131
+ except BaseException as exc:
132
+ self.failed = True
133
+ _save(self.root, "failed.json", dict(error_type=type(exc).__name__, error=str(exc),
134
+ usage=self.usage, no_automatic_retry=True, accept_checkpoint=False))
135
+ raise
136
+
137
+ def assert_healthy(self):
138
+ with self._lock:
139
+ if self.failed or self.usage['prefix_attempts'] != self.usage['prefix_responses'] or (
140
+ self.usage['model_attempts'] != self.usage['model_responses']
141
+ or self.usage['unknown_output_token_reservations']
142
+ ):
143
+ raise ExternalDependencyError("SmartSearch GRPO prefix has an unresolved/failed request")
144
+ return dict(self.usage)
@@ -0,0 +1,119 @@
1
+ """Batch-assembly repairs for the exact native SmartSearch GRPO rollout.
2
+
3
+ No native file is modified. The original group/selection/truncation logic and
4
+ single-trajectory generator remain intact; a fresh worker supplies its explicit
5
+ metered prefix builder instead of the upstream hardcoded network helper.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import ast
10
+ import copy
11
+ import hashlib
12
+ import inspect
13
+ from collections.abc import Mapping
14
+ from pathlib import Path
15
+
16
+ from agentinputlab.contracts import ExternalDependencyError, ValidationError
17
+ from agentinputlab.contracts.serialization import to_jsonable
18
+
19
+ from .qrag import _sha
20
+ from .smartsearch_grpo_data import verify_smartsearch_grpo_source
21
+
22
+ _PATH = "src/verl/workers/rollout/vllm_rollout/vllm_rollout_spmd.py"
23
+ _CLASS = "vLLMRolloutWithTool"
24
+
25
+
26
+ def _name(node, expected):
27
+ return isinstance(node, ast.Name) and node.id == expected
28
+
29
+
30
+ def _batch_contract_ast(method):
31
+ """Move one pinned assembly block; refuse a structurally different source."""
32
+ method = copy.deepcopy(method)
33
+ loops = [n for n in method.body if isinstance(n, ast.While) and _name(n.test, "active_indices")]
34
+ if len(loops) != 1:
35
+ raise ExternalDependencyError("SmartSearch native active-rollout loop differs")
36
+ loop = loops[0]
37
+ outer = [n for n in loop.body if isinstance(n, ast.For) and isinstance(n.target, ast.Tuple)
38
+ and [_n.id for _n in n.target.elts if isinstance(_n, ast.Name)] == ["i", "idx"]]
39
+ if len(outer) != 1:
40
+ raise ExternalDependencyError("SmartSearch native per-input prefix loop differs")
41
+ outer = outer[0]
42
+ starts = [i for i, n in enumerate(outer.body) if isinstance(n, ast.Assign)
43
+ and len(n.targets) == 1 and _name(n.targets[0], "prefix_input_ids")
44
+ and isinstance(n.value, ast.Call) and isinstance(n.value.func, ast.Attribute)
45
+ and _name(n.value.func.value, "torch") and n.value.func.attr == "stack"]
46
+ if len(starts) != 1:
47
+ raise ExternalDependencyError("SmartSearch native prefix stack block differs")
48
+ position = starts[0]
49
+ tail = outer.body[position:]
50
+ if len(tail) != 11 or not isinstance(tail[-1], ast.For):
51
+ raise ExternalDependencyError("SmartSearch native assembly statement inventory differs")
52
+ for statement, name in zip(tail[:5], ("prefix_input_ids", "prefix_loss_mask", "input_ids",
53
+ "attention_mask", "position_ids"), strict=True):
54
+ expected = ast.parse(f"{name} = torch.stack({name}_list, dim=0)").body[0]
55
+ if ast.dump(statement) != ast.dump(expected):
56
+ raise ExternalDependencyError("SmartSearch native prefix tensor assembly differs")
57
+ if ast.dump(outer.iter) != ast.dump(ast.parse("enumerate(active_indices)", mode="eval").body):
58
+ raise ExternalDependencyError("SmartSearch native prefix input selection differs")
59
+ if ast.dump(tail[-1].iter) != ast.dump(ast.parse("enumerate(index)", mode="eval").body):
60
+ raise ExternalDependencyError("SmartSearch native generated-prefix selection differs")
61
+ selected = [n for n in tail if isinstance(n, ast.Assign) and len(n.targets) == 1
62
+ and isinstance(n.targets[0], ast.Attribute) and _name(n.targets[0].value, "new_prompts")
63
+ and n.targets[0].attr == "non_tensor_batch"]
64
+ if len(selected) != 1 or ast.dump(selected[0].value) != ast.dump(ast.parse("prompts.non_tensor_batch", mode="eval").body):
65
+ raise ExternalDependencyError("SmartSearch native prefix metadata assignment differs")
66
+ selected[0].value = ast.parse("prompts.select_idxs(index).non_tensor_batch", mode="eval").body
67
+ outer.body = outer.body[:position]
68
+ insertion = loop.body.index(outer) + 1
69
+ loop.body.insert(insertion, ast.If(test=ast.Name(id="prefix_input_ids_list", ctx=ast.Load()), body=tail, orelse=[]))
70
+ return ast.fix_missing_locations(method)
71
+
72
+
73
+ def _compile_batch_contract(method, namespace, prefix_builder, filename):
74
+ repaired = _batch_contract_ast(method)
75
+ local = dict(namespace)
76
+ local["generate_new_prompts"] = prefix_builder
77
+ exec(compile(ast.Module(body=[repaired], type_ignores=[]), filename, "exec"), local)
78
+ return local[method.name], repaired
79
+
80
+
81
+ def install_native_rollout_batch_contracts(*, checkout, rollout_class, prefix_builder, prefix_builder_binding):
82
+ """Install source-bound assembly fixes in one fresh native worker.
83
+
84
+ Caller must provide a metered, fail-closed native prefix-builder seam and
85
+ its provenance. There is intentionally no default hardcoded HTTP helper.
86
+ The executor must meter ALL actual generation calls, including outputs
87
+ subsequently discarded by unchanged native group truncation.
88
+ """
89
+ if not isinstance(rollout_class, type) or rollout_class.__name__ != _CLASS or not callable(prefix_builder):
90
+ raise ValidationError("SmartSearch rollout repair requires the native class and explicit prefix provider")
91
+ if not isinstance(prefix_builder_binding, Mapping) or not prefix_builder_binding:
92
+ raise ValidationError("SmartSearch rollout prefix provider needs explicit provenance")
93
+ binding = to_jsonable(prefix_builder_binding)
94
+ if getattr(rollout_class, "_agentinputlab_batch_contract_installed", False):
95
+ raise ExternalDependencyError("SmartSearch rollout contracts are already installed; use a fresh native worker")
96
+ source, source_binding = verify_smartsearch_grpo_source(checkout)
97
+ path = source / _PATH
98
+ original_method = inspect.unwrap(rollout_class.generate_sequences)
99
+ if not hasattr(original_method, "__code__") or Path(original_method.__code__.co_filename).resolve() != path:
100
+ raise ExternalDependencyError("SmartSearch rollout method was not loaded from the pinned native source")
101
+ tree = ast.parse(path.read_text())
102
+ owners = [n for n in tree.body if isinstance(n, ast.ClassDef) and n.name == _CLASS]
103
+ methods = [n for owner in owners for n in owner.body if isinstance(n, ast.FunctionDef) and n.name == "generate_sequences"]
104
+ if len(owners) != 1 or len(methods) != 1:
105
+ raise ExternalDependencyError("SmartSearch native rollout class surface differs")
106
+ method = methods[0]
107
+ implementation, repaired = _compile_batch_contract(method, original_method.__globals__, prefix_builder, str(path))
108
+ record = dict(native_source=source_binding, native_rollout_sha256=_sha(path),
109
+ original_method_ast_sha256=hashlib.sha256(ast.dump(method).encode()).hexdigest(),
110
+ adapter_method_ast_sha256=hashlib.sha256(ast.dump(repaired).encode()).hexdigest(),
111
+ adapter_toolkit_sha256=_sha(Path(__file__)), prefix_builder_binding=binding,
112
+ native_source_files_modified=False, native_single_trajectory_generator_replaced=False,
113
+ native_group_size_and_selection_unchanged=True, prefix_batch_generated_once=True,
114
+ empty_prefix_batch_skipped=True, prefix_metadata_selected_by_original_indices=True,
115
+ all_generated_and_discarded_outputs_require_metering=True,
116
+ full_grpo_training_certified=False)
117
+ rollout_class.generate_sequences = implementation
118
+ rollout_class._agentinputlab_batch_contract_installed = True
119
+ return record