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,283 @@
1
+ """Pinned native SmartSearch curriculum preparation, separate from inference.
2
+
3
+ These APIs do not train a model or manufacture process rewards. They consume
4
+ recorded training-only rollouts and call the original redundancy/SFT/DPO/prefix
5
+ converters. The complete SFT/DPO/GRPO training recipe remains a separate gate.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import contextlib
10
+ import hashlib
11
+ import importlib.util
12
+ import io
13
+ import json
14
+ import math
15
+ import os
16
+ import subprocess
17
+ from collections.abc import Mapping, Sequence
18
+ from dataclasses import dataclass, field
19
+ from pathlib import Path
20
+ from typing import Any
21
+
22
+ from agentinputlab.contracts import ExternalDependencyError, ValidationError
23
+ from agentinputlab.contracts.serialization import content_hash, freeze_mapping, to_jsonable
24
+
25
+ from .smartsearch import SMARTSEARCH_UPSTREAM_COMMIT
26
+
27
+ _FILES = {
28
+ "redundancy": "scripts/data_construction/detect_redundancy.py",
29
+ "sft": "scripts/data_construction/transfer_sft.py",
30
+ "dpo": "scripts/data_construction/transfer_dpo.py",
31
+ "prefix": "scripts/data_construction/transfer_regenerate.py",
32
+ "reward": "scripts/data_construction/process_reward.py",
33
+ "refinement": "scripts/data_construction/query_refinement.py",
34
+ }
35
+ _PREPARATION_KEYS = ("redundancy", "sft", "dpo", "prefix")
36
+
37
+
38
+ @dataclass(frozen=True, slots=True)
39
+ class SmartSearchTrainingCase:
40
+ case_id: str
41
+ question: str
42
+ split: str
43
+ source_reference: Mapping[str, Any] = field(default_factory=dict)
44
+
45
+ def __post_init__(self) -> None:
46
+ if not isinstance(self.case_id, str) or not self.case_id.strip():
47
+ raise ValidationError("SmartSearch training case requires a non-empty ID")
48
+ if not isinstance(self.question, str) or not self.question.strip():
49
+ raise ValidationError("SmartSearch training case requires a non-empty question")
50
+ if self.split not in {"train", "validation", "test"}:
51
+ raise ValidationError("SmartSearch training case split is invalid")
52
+ try:
53
+ object.__setattr__(self, "source_reference", freeze_mapping(self.source_reference))
54
+ except (TypeError, ValueError) as exc:
55
+ raise ValidationError("SmartSearch case provenance is not canonical JSON") from exc
56
+
57
+
58
+ def _question_hash(question: str) -> str:
59
+ # This additional overlap check is not a model-input transformation.
60
+ return content_hash(" ".join(question.split()).casefold())
61
+
62
+
63
+ def validate_smartsearch_training_splits(
64
+ train: Sequence[SmartSearchTrainingCase],
65
+ validation: Sequence[SmartSearchTrainingCase],
66
+ test: Sequence[SmartSearchTrainingCase] = (),
67
+ ) -> Mapping[str, Any]:
68
+ if not train or not validation:
69
+ raise ValidationError("SmartSearch curriculum needs non-empty training and validation collections")
70
+ audit = {}
71
+ seen_ids: set[str] = set()
72
+ seen_questions: set[str] = set()
73
+ for name, cases in (("train", train), ("validation", validation), ("test", test)):
74
+ if any(not isinstance(case, SmartSearchTrainingCase) or case.split != name for case in cases):
75
+ raise ValidationError("SmartSearch curriculum case split label mismatch")
76
+ ids = tuple(case.case_id for case in cases)
77
+ hashes = tuple(_question_hash(case.question) for case in cases)
78
+ if len(ids) != len(set(ids)) or len(hashes) != len(set(hashes)):
79
+ raise ValidationError("SmartSearch curriculum split contains duplicate IDs/questions")
80
+ if set(ids) & seen_ids or set(hashes) & seen_questions:
81
+ raise ValidationError("SmartSearch fitting, validation and test collections overlap")
82
+ seen_ids.update(ids)
83
+ seen_questions.update(hashes)
84
+ audit[name] = {"case_ids": ids, "question_hashes": hashes,
85
+ "case_hashes": tuple(content_hash(case) for case in cases)}
86
+ return freeze_mapping(audit)
87
+
88
+
89
+ def verify_smartsearch_preparation_source(
90
+ checkout: str | Path, *, include_teacher: bool = False,
91
+ ) -> Mapping[str, Any]:
92
+ """Bind the exact upstream Git objects and their on-disk converter bytes."""
93
+ root = Path(checkout)
94
+ if root.is_symlink() or not root.is_dir():
95
+ raise ExternalDependencyError("SmartSearch preparation requires a regular pinned Git checkout")
96
+ root = root.resolve()
97
+
98
+ def git(*args: str) -> bytes:
99
+ try:
100
+ result = subprocess.run(
101
+ ["git", "-c", "core.fsmonitor=false", "-c", f"core.hooksPath={os.devnull}",
102
+ "-C", str(root), *args], capture_output=True, check=True, timeout=30,
103
+ env={"PATH": os.defpath, "LANG": "C", "LC_ALL": "C",
104
+ "GIT_CONFIG_NOSYSTEM": "1", "GIT_CONFIG_GLOBAL": os.devnull,
105
+ "GIT_OPTIONAL_LOCKS": "0", "GIT_TERMINAL_PROMPT": "0"},
106
+ )
107
+ except (OSError, subprocess.SubprocessError) as exc:
108
+ raise ExternalDependencyError("SmartSearch preparation source Git verification failed") from exc
109
+ return result.stdout
110
+
111
+ if git("rev-parse", "HEAD").decode().strip() != SMARTSEARCH_UPSTREAM_COMMIT:
112
+ raise ExternalDependencyError("SmartSearch preparation source revision changed")
113
+ if Path(git("rev-parse", "--show-toplevel").decode().strip()).resolve() != root:
114
+ raise ExternalDependencyError("SmartSearch preparation checkout is not the repository root")
115
+ if git("status", "--porcelain", "--untracked-files=all").strip():
116
+ raise ExternalDependencyError("SmartSearch preparation requires an unchanged source checkout")
117
+ files = {}
118
+ keys = tuple(_FILES) if include_teacher else _PREPARATION_KEYS
119
+ for relative in (_FILES[key] for key in keys):
120
+ path = root
121
+ for component in Path(relative).parts:
122
+ path = path / component
123
+ if path.is_symlink():
124
+ raise ExternalDependencyError("SmartSearch preparation source contains a symlink")
125
+ if not path.is_file():
126
+ raise ExternalDependencyError(f"SmartSearch native preparation file is missing: {relative}")
127
+ actual = path.read_bytes()
128
+ expected = git("show", f"{SMARTSEARCH_UPSTREAM_COMMIT}:{relative}")
129
+ if actual != expected:
130
+ raise ExternalDependencyError(f"SmartSearch native preparation file changed: {relative}")
131
+ files[relative] = hashlib.sha256(actual).hexdigest()
132
+ return freeze_mapping({"source_commit": SMARTSEARCH_UPSTREAM_COMMIT, "files": files,
133
+ "root": str(root), "preparation_math_modified": False})
134
+
135
+
136
+ def _native_converter(root: Path, key: str, source: Mapping[str, Any]) -> Any:
137
+ path = root / _FILES[key]
138
+ source_bytes = path.read_bytes()
139
+ if hashlib.sha256(source_bytes).hexdigest() != source["files"][_FILES[key]]:
140
+ raise ExternalDependencyError("SmartSearch preparation source changed before import")
141
+ name = f"_agentinputlab_smartsearch_{key}_{source['files'][_FILES[key]][:12]}"
142
+ spec = importlib.util.spec_from_file_location(name, path)
143
+ if spec is None or spec.loader is None:
144
+ raise ExternalDependencyError("SmartSearch native converter could not be imported")
145
+ module = importlib.util.module_from_spec(spec)
146
+ try:
147
+ # Compile the verified bytes, never an unbound pre-existing .pyc cache.
148
+ exec(compile(source_bytes, str(path), "exec"), module.__dict__)
149
+ except ImportError as exc:
150
+ raise ExternalDependencyError("Install agentinputlab[smartsearch-prepare] in the preparation worker") from exc
151
+ class_name = {"redundancy": "Redundancy", "reward": "SearchEvaluation",
152
+ "refinement": "Rewrite"}.get(key, "Transfer")
153
+ constructor = getattr(module, class_name, None)
154
+ if not callable(constructor):
155
+ raise ExternalDependencyError("SmartSearch native converter class signature changed")
156
+ return constructor("controlled-provider-no-network") if key in {"reward", "refinement"} else constructor()
157
+
158
+
159
+ def _scored_rows(
160
+ value: Sequence[Mapping[str, Any]], allowed_questions: set[str], max_rows: int,
161
+ ) -> list[dict[str, Any]]:
162
+ if not isinstance(value, (tuple, list)) or len(value) > max_rows:
163
+ raise ValidationError("SmartSearch recorded rollout collection exceeds its explicit bound")
164
+ rows = []
165
+ for row in value:
166
+ if not isinstance(row, Mapping) or row.get("question") not in allowed_questions:
167
+ raise ValidationError("SmartSearch curriculum rollout is outside the allowed training questions")
168
+ if not isinstance(row.get("response"), str) or not isinstance(row.get("process_scores"), (list, tuple)):
169
+ raise ValidationError("SmartSearch curriculum requires recorded response and process scores")
170
+ metric = row.get("outcome_score")
171
+ score = metric.get("f1") if isinstance(metric, Mapping) else None
172
+ if isinstance(score, bool) or not isinstance(score, (float, int)) or not math.isfinite(score) or not 0 <= score <= 1:
173
+ raise ValidationError("SmartSearch curriculum requires a measured finite outcome F1")
174
+ for process in row["process_scores"]:
175
+ if not isinstance(process, Mapping) or not isinstance(process.get("score"), str) or process["score"] not in {"", "0", "1"}:
176
+ raise ValidationError("SmartSearch native process-score representation is invalid")
177
+ try:
178
+ rows.append(json.loads(json.dumps(to_jsonable(row), allow_nan=False)))
179
+ except (TypeError, ValueError) as exc:
180
+ raise ValidationError("SmartSearch scored rollout is not canonical JSON") from exc
181
+ return rows
182
+
183
+
184
+ @dataclass(frozen=True, slots=True)
185
+ class SmartSearchCurriculumArtifact:
186
+ root: str
187
+ artifact_id: str
188
+ sft_count: int
189
+ dpo_count: int
190
+ prefix_count: int
191
+ source_fingerprint_sha256: str
192
+ split_audit_sha256: str
193
+ output_hashes: Mapping[str, str]
194
+
195
+ def __post_init__(self) -> None:
196
+ object.__setattr__(self, "output_hashes", freeze_mapping(self.output_hashes))
197
+
198
+
199
+ @dataclass(frozen=True, slots=True)
200
+ class SmartSearchCurriculumPreparation:
201
+ max_rollout_rows: int = 1000
202
+ max_input_bytes: int = 16 * 1024 * 1024
203
+
204
+ def __post_init__(self) -> None:
205
+ if type(self.max_rollout_rows) is not int or self.max_rollout_rows < 1 or (
206
+ type(self.max_input_bytes) is not int or self.max_input_bytes < 1
207
+ ):
208
+ raise ValidationError("SmartSearch curriculum limits must be positive integers")
209
+
210
+ def prepare(
211
+ self, *, checkout: str | Path, output_root: str | Path,
212
+ train: Sequence[SmartSearchTrainingCase], validation: Sequence[SmartSearchTrainingCase],
213
+ initial_scored_rollouts: Sequence[Mapping[str, Any]],
214
+ regenerated_scored_rollouts: Sequence[Mapping[str, Any]],
215
+ test: Sequence[SmartSearchTrainingCase] = (),
216
+ rollout_provenance: Mapping[str, Any],
217
+ ) -> SmartSearchCurriculumArtifact:
218
+ audit = validate_smartsearch_training_splits(train, validation, test)
219
+ if not isinstance(rollout_provenance, Mapping) or not rollout_provenance:
220
+ raise ValidationError("SmartSearch recorded rollouts require explicit producer provenance")
221
+ allowed = {case.question for case in train}
222
+ initial = _scored_rows(initial_scored_rollouts, allowed, self.max_rollout_rows)
223
+ regenerated = _scored_rows(regenerated_scored_rollouts, allowed, self.max_rollout_rows)
224
+ if not initial:
225
+ raise ValidationError("SmartSearch curriculum needs initial recorded training rollouts")
226
+ raw_inputs = {"initial": initial, "regenerated": regenerated,
227
+ "producer_provenance": to_jsonable(rollout_provenance)}
228
+ encoded = json.dumps(raw_inputs, ensure_ascii=False, allow_nan=False).encode()
229
+ if len(encoded) > self.max_input_bytes:
230
+ raise ValidationError("SmartSearch curriculum input exceeds its explicit byte bound")
231
+ source = verify_smartsearch_preparation_source(checkout)
232
+ source_root = Path(source["root"])
233
+ root = Path(output_root)
234
+ if root.is_symlink() or root.exists():
235
+ raise ValidationError("SmartSearch curriculum output must be a new directory")
236
+ root = root.resolve(strict=False)
237
+ if root.is_relative_to(source_root) or source_root.is_relative_to(root):
238
+ raise ValidationError("SmartSearch curriculum outputs must not overlap source checkout")
239
+ root.mkdir(parents=True, exist_ok=False)
240
+
241
+ def save(name: str, value: Any) -> None:
242
+ with (root / name).open("x", encoding="utf-8") as stream:
243
+ json.dump(to_jsonable(value), stream, ensure_ascii=False, sort_keys=True, allow_nan=False)
244
+
245
+ save("claim.json", {"source": source, "split_audit": audit, "input_hash": content_hash(raw_inputs),
246
+ "rollout_provenance": rollout_provenance, "model_calls_performed": 0})
247
+ try:
248
+ with contextlib.redirect_stdout(io.StringIO()), contextlib.redirect_stderr(io.StringIO()):
249
+ redundancy = _native_converter(source_root, "redundancy", source)
250
+ initial_checked = redundancy.detect_redundancy(initial)
251
+ regenerated_checked = redundancy.detect_redundancy(regenerated)
252
+ sft = _native_converter(source_root, "sft", source).transfer(initial_checked)
253
+ dpo = _native_converter(source_root, "dpo", source).transfer(initial_checked, regenerated_checked)
254
+ prefix = _native_converter(source_root, "prefix", source).transfer(initial_checked)
255
+ for values in (sft, dpo, prefix):
256
+ if not isinstance(values, list):
257
+ raise ExternalDependencyError("SmartSearch native converter returned a non-list")
258
+ for relative, digest in source["files"].items():
259
+ if hashlib.sha256((source_root / relative).read_bytes()).hexdigest() != digest:
260
+ raise ExternalDependencyError("SmartSearch preparation source changed during execution")
261
+ outputs = {"native-initial-scored.json": initial_checked,
262
+ "native-regenerated-scored.json": regenerated_checked,
263
+ "sft.json": sft, "dpo.json": dpo, "prefix.json": prefix}
264
+ for name, value in outputs.items():
265
+ save(name, value)
266
+ hashes = {name: hashlib.sha256((root / name).read_bytes()).hexdigest() for name in outputs}
267
+ manifest = {"schema": "agentinputlab.smartsearch.native-curriculum-data.v1",
268
+ "source": source, "split_audit": audit, "outputs": hashes,
269
+ "sft_count": len(sft), "dpo_count": len(dpo), "prefix_count": len(prefix),
270
+ "initial_rollout_count": len(initial), "regenerated_rollout_count": len(regenerated),
271
+ "input_hash": content_hash(raw_inputs), "rollout_provenance": rollout_provenance,
272
+ "model_calls_performed": 0, "neural_training_performed": False,
273
+ "native_selection_thresholds_changed": False, "empty_selection_is_not_training_success": True}
274
+ artifact_id = content_hash(manifest)
275
+ save("manifest.json", {**manifest, "artifact_id": artifact_id})
276
+ return SmartSearchCurriculumArtifact(
277
+ str(root), artifact_id, len(sft), len(dpo), len(prefix), content_hash(source),
278
+ content_hash(audit), hashes,
279
+ )
280
+ except Exception as exc:
281
+ save("failed.json", {"error_type": type(exc).__name__, "error": str(exc),
282
+ "model_calls_performed": 0, "neural_training_performed": False})
283
+ raise
@@ -0,0 +1,58 @@
1
+ """Execution contracts for the pinned native GRPO driver, not reward math.
2
+
3
+ The native manager omits ``reward_extra_info`` while its PPO driver indexes
4
+ that key and catches failures by invoking the manager again. Complete the
5
+ dictionary without another scoring pass, and latch failures across the whole
6
+ batch so a fallback cannot repeat already consumed helper calls.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ from collections.abc import Mapping
11
+
12
+ from agentinputlab.contracts import ExternalDependencyError, ValidationError
13
+
14
+
15
+ class NativeGRPORewardManagerContract:
16
+ """Keep native rewards unchanged and prohibit automatic batch retries.
17
+
18
+ This adapter does not itself load a model or certify a GRPO fit. The
19
+ execution worker must construct its manager from the verified native
20
+ source, bind the metered scorer, and retain original per-item costs.
21
+ """
22
+
23
+ def __init__(self, native_manager):
24
+ if not callable(native_manager):
25
+ raise ValidationError("SmartSearch GRPO requires a callable native reward manager")
26
+ self.native_manager = native_manager
27
+ self.native_calls = 0
28
+ self._failed = False
29
+
30
+ def __call__(self, data, return_dict=False, curr_save_path=None):
31
+ if self._failed:
32
+ raise ExternalDependencyError("SmartSearch native reward batch failed; no automatic scoring retry")
33
+ if type(return_dict) is not bool:
34
+ raise ValidationError("SmartSearch reward dictionary flag must be a boolean")
35
+ try:
36
+ self.native_calls += 1
37
+ result = self.native_manager(data, return_dict=return_dict, curr_save_path=curr_save_path)
38
+ if not return_dict:
39
+ return result
40
+ if not isinstance(result, Mapping):
41
+ # The native manager's explicit cached-rm branch returns the
42
+ # exact cached tensor, even when return_dict=True.
43
+ batch = getattr(data, "batch", None)
44
+ cached = batch.get("rm_scores") if hasattr(batch, "get") else None
45
+ if cached is None or result is not cached:
46
+ raise ExternalDependencyError("SmartSearch native reward dictionary contract differs")
47
+ result = {"reward_tensor": result}
48
+ if "reward_tensor" not in result or result["reward_tensor"] is None:
49
+ raise ExternalDependencyError("SmartSearch native reward tensor is missing")
50
+ extras = result.get("reward_extra_info", {})
51
+ if not isinstance(extras, Mapping):
52
+ raise ExternalDependencyError("SmartSearch native reward extra-info mapping differs")
53
+ # Preserve the original tensor object and existing extra fields.
54
+ # No tensor arithmetic, rescaling, default positive or re-score.
55
+ return {**result, "reward_extra_info": extras}
56
+ except BaseException:
57
+ self._failed = True
58
+ raise
@@ -0,0 +1,314 @@
1
+ """Pinned native SmartSearch GRPO data/configuration, with explicit split roles."""
2
+ from __future__ import annotations
3
+
4
+ import json
5
+ import math
6
+ from collections.abc import Mapping, Sequence
7
+ from dataclasses import dataclass
8
+ from pathlib import Path
9
+ from urllib.parse import urlsplit
10
+
11
+ from agentinputlab.contracts import ExternalDependencyError, ValidationError
12
+ from agentinputlab.contracts.serialization import content_hash, to_jsonable
13
+
14
+ from .qrag import _file, _sha
15
+ from .smartsearch import SMARTSEARCH_TOOL_SCHEMA
16
+ from .smartsearch_curriculum import (
17
+ SmartSearchTrainingCase,
18
+ _question_hash,
19
+ validate_smartsearch_training_splits,
20
+ )
21
+ from .smartsearch_grpo_tools import SMARTSEARCH_GRPO_ENVIRONMENT
22
+ from .smartsearch_sampling import verify_smartsearch_sampling_source
23
+
24
+ GRPO_DATA_PROTOCOL = "agentinputlab.smartsearch.native_grpo_data.v1"
25
+ _SOURCE = {
26
+ "data/prepare_dataset.py": "abf1dc41c410e8716c02b8651c9ef3fb3bbba6d52b50ae86db8325ecf5154554",
27
+ "scripts/train/train.sh": "07903f49e46bf18a0d764b6e92c1430d0a651523751fee653dec112379c66d72",
28
+ "src/verl/trainer/main_ppo.py": "6eace6c898923fe2e25081f473801c9439a709eb02d1968944f1f2cd2602f258",
29
+ "src/verl/trainer/config/ppo_trainer.yaml": "8a239cda92c40d520df0344857b5f51d6550254c449d28841e1de3f5b3feb1d7",
30
+ "src/verl/utils/dataset/rl_dataset.py": "06a599f81f7288fdd183111b15207c37e0c32e2d9399c8e9289edba637bf5f26",
31
+ "src/verl/workers/rollout/vllm_rollout/generate_new_prompts.py": "bc1f7d2a16d599e7f180406c9cd356034f1bb5ce0e97b5fb09d6264a11511615",
32
+ "src/verl/workers/rollout/vllm_rollout/vllm_rollout_spmd.py": "064aa3d6682149620c5b55239379199130941dc05d6fc5ed13026987b2867453",
33
+ "src/verl/workers/reward_manager/re_call.py": "0b239aaa9ee0c21b693359569e3f091bc650d537d7cf2a63e478c8fb4d976a7b",
34
+ "src/verl/trainer/ppo/ray_trainer.py": "465e1b53dfa9f0bfcdb597957cef64ea18941e5e75a2af17a48c0ecfd00ab3e2",
35
+ "src/verl/workers/actor/dp_actor.py": "09923f0891e2ca913e1eb860bfa7e62537b10b1f4527b9647784f7063ba86a8d",
36
+ "src/verl/workers/fsdp_workers.py": "65aa287db53a3308d5b579f47cf557ab8333231e26625ed62bbb65ca90153833",
37
+ "src/verl/utils/checkpoint/fsdp_checkpoint_manager.py": "640556d9c0801602818fcfd52aa6d2d066b49bf30f30eb0a81c08efde2495f4a",
38
+ }
39
+
40
+
41
+ def verify_smartsearch_grpo_source(checkout):
42
+ root, binding = verify_smartsearch_sampling_source(checkout)
43
+ for name, expected in _SOURCE.items():
44
+ path = _file(root / name, "SmartSearch native GRPO source")
45
+ if not path.is_relative_to(root) or _sha(path) != expected:
46
+ raise ExternalDependencyError("SmartSearch native GRPO source/configuration changed")
47
+ return root, {**binding, "grpo_source": dict(_SOURCE)}
48
+
49
+
50
+ def _save(root, name, value):
51
+ encoded = json.dumps(to_jsonable(value), ensure_ascii=False, sort_keys=True, allow_nan=False)
52
+ with (root / name).open("x", encoding="utf-8") as stream:
53
+ stream.write(encoded)
54
+
55
+
56
+ @dataclass(frozen=True, slots=True)
57
+ class SmartSearchGRPOExample:
58
+ case: SmartSearchTrainingCase
59
+ golden_answers: tuple[str, ...]
60
+
61
+ def __post_init__(self):
62
+ if not isinstance(self.case, SmartSearchTrainingCase) or self.case.split not in {"train", "validation"}:
63
+ raise ValidationError("SmartSearch GRPO examples must declare training/development case roles")
64
+ answers = self.golden_answers
65
+ if not isinstance(answers, (tuple, list)) or not answers or any(
66
+ not isinstance(value, str) or not value.strip() for value in answers
67
+ ):
68
+ raise ValidationError("SmartSearch GRPO examples require nonempty native reference answers")
69
+ object.__setattr__(self, "golden_answers", tuple(answers))
70
+
71
+
72
+ @dataclass(frozen=True, slots=True)
73
+ class SmartSearchGRPODataArtifact:
74
+ root: Path
75
+ artifact_id: str
76
+ train_rows: int
77
+ validation_rows: int
78
+
79
+ @classmethod
80
+ def load(cls, root, *, max_rows=10000, max_file_bytes=64 * 1024 * 1024):
81
+ if any(type(n) is not int or n < 1 for n in (max_rows, max_file_bytes)):
82
+ raise ValidationError("SmartSearch GRPO artifact read limits must be positive integers")
83
+ folder = Path(root)
84
+ if folder.is_symlink() or not folder.is_dir():
85
+ raise ValidationError("SmartSearch GRPO data artifact must be a regular directory")
86
+ folder = folder.resolve()
87
+ record = json.loads(_file(folder / "manifest.json", "GRPO data manifest").read_text())
88
+ identity = record.pop("artifact_id", None)
89
+ if record.get("schema") != GRPO_DATA_PROTOCOL or identity != content_hash(record):
90
+ raise ValidationError("SmartSearch GRPO data artifact identity differs")
91
+ if set(record.get("outputs", {})) != {"train.parquet", "validation.parquet"}:
92
+ raise ValidationError("SmartSearch GRPO data artifact has an incomplete closure")
93
+ for name, digest in record["outputs"].items():
94
+ path = _file(folder / name, "GRPO native data")
95
+ if path.stat().st_size > max_file_bytes or _sha(path) != digest:
96
+ raise ValidationError("SmartSearch GRPO native data bytes changed")
97
+ for key in ("train_rows", "validation_rows"):
98
+ if type(record.get(key)) is not int or record[key] < 1:
99
+ raise ValidationError("SmartSearch GRPO data has an empty declared split")
100
+ try:
101
+ import pyarrow.parquet as pq
102
+ except ImportError as exc:
103
+ raise ExternalDependencyError("Install agentinputlab[benchmarks] to verify native GRPO data") from exc
104
+ for split in ("train", "validation"):
105
+ path = folder / f"{split}.parquet"
106
+ declared = record[split + "_rows"]
107
+ if pq.read_metadata(path).num_rows != declared or declared > max_rows:
108
+ raise ValidationError("SmartSearch GRPO parquet row count differs or exceeds its read limit")
109
+ rows = pq.read_table(path).to_pylist()
110
+ hashes = []
111
+ for row in rows:
112
+ if set(row) != {"data_source", "question", "ability", "reward_model", "extra_info"} or (
113
+ row["data_source"] != "re_call" or row["ability"] != "re_call"
114
+ ) or not isinstance(row["question"], str) or not row["question"].strip():
115
+ raise ValidationError("SmartSearch GRPO native logical fields differ")
116
+ reward, extra = row["reward_model"], row["extra_info"]
117
+ if not isinstance(reward, dict) or set(reward) != {"style", "ground_truth"} or (
118
+ reward["style"] != "rule" or not isinstance(reward["ground_truth"], list)
119
+ or not reward["ground_truth"] or any(not isinstance(v, str) or not v.strip() for v in reward["ground_truth"])
120
+ ) or not isinstance(extra, dict) or set(extra) != {"env", "func_schemas"} or (
121
+ extra["env"] != SMARTSEARCH_GRPO_ENVIRONMENT
122
+ or json.loads(extra["func_schemas"]) != to_jsonable(SMARTSEARCH_TOOL_SCHEMA)
123
+ ):
124
+ raise ValidationError("SmartSearch GRPO reference/tool field contract differs")
125
+ hashes.append(_question_hash(row["question"]))
126
+ audit = record.get("split_audit", {}).get(split, {})
127
+ if hashes != audit.get("question_hashes") or len(set(hashes)) != declared:
128
+ raise ValidationError("SmartSearch GRPO native questions differ from their declared split")
129
+ if set(record["split_audit"]["train"]["question_hashes"]) & set(
130
+ record["split_audit"]["validation"]["question_hashes"]
131
+ ):
132
+ raise ValidationError("SmartSearch GRPO data artifact splits overlap")
133
+ return cls(folder, identity, record["train_rows"], record["validation_rows"])
134
+
135
+
136
+ def prepare_smartsearch_grpo_data(
137
+ *, checkout, output_root, train: Sequence[SmartSearchGRPOExample],
138
+ validation: Sequence[SmartSearchGRPOExample], data_provenance: Mapping,
139
+ test: Sequence[SmartSearchTrainingCase] = (), max_rows: int = 10000,
140
+ max_input_bytes: int = 64 * 1024 * 1024,
141
+ ):
142
+ """Write exact native logical rows without upstream's test-to-dev sampling.
143
+
144
+ Corpus/retrieval is a separate frozen input. References remain in reward_model
145
+ and never enter the question field. The environment is replaced with the
146
+ fixed non-executable retrieval identifier. No model is loaded or fit here.
147
+ """
148
+ if any(type(n) is not int or n < 1 for n in (max_rows, max_input_bytes)) or (
149
+ not isinstance(data_provenance, Mapping) or not data_provenance
150
+ ):
151
+ raise ValidationError("SmartSearch GRPO preparation needs explicit limits and provenance")
152
+ for rows in (train, validation):
153
+ if not isinstance(rows, (tuple, list)) or not rows or len(rows) > max_rows or any(
154
+ not isinstance(row, SmartSearchGRPOExample) for row in rows
155
+ ):
156
+ raise ValidationError("SmartSearch GRPO preparation split exceeds its explicit row bound")
157
+ train, validation = tuple(train), tuple(validation)
158
+ data_provenance = to_jsonable(data_provenance)
159
+ audit = validate_smartsearch_training_splits([r.case for r in train], [r.case for r in validation], test)
160
+ encoded = json.dumps(to_jsonable({"train": train, "validation": validation,
161
+ "provenance": data_provenance}), allow_nan=False).encode()
162
+ if len(encoded) > max_input_bytes:
163
+ raise ValidationError("SmartSearch GRPO data inputs exceed the explicit byte bound")
164
+ source, binding = verify_smartsearch_grpo_source(checkout)
165
+ root = Path(output_root)
166
+ if root.is_symlink() or root.exists():
167
+ raise ValidationError("SmartSearch GRPO preparation must be create-only")
168
+ root = root.resolve(strict=False)
169
+ if root.is_relative_to(source) or source.is_relative_to(root):
170
+ raise ValidationError("SmartSearch GRPO preparation output must not overlap native source")
171
+ try:
172
+ import pyarrow as pa
173
+ import pyarrow.parquet as pq
174
+ except ImportError as exc:
175
+ raise ExternalDependencyError("Install agentinputlab[benchmarks] for native GRPO parquet data") from exc
176
+ root.mkdir(parents=True, exist_ok=False)
177
+ _save(root, "claim.json", {"source": binding, "split_audit": audit,
178
+ "inputs_sha256": content_hash({"train": train, "validation": validation}),
179
+ "data_provenance": data_provenance, "model_calls": 0, "optimizer_steps": 0})
180
+ try:
181
+ schema_text = json.dumps(to_jsonable(SMARTSEARCH_TOOL_SCHEMA), indent=4)
182
+ for name, rows in (("train", train), ("validation", validation)):
183
+ native_rows = [{"data_source": "re_call", "question": row.case.question,
184
+ "ability": "re_call", "reward_model": {"style": "rule", "ground_truth": list(row.golden_answers)},
185
+ "extra_info": {"env": SMARTSEARCH_GRPO_ENVIRONMENT, "func_schemas": schema_text}}
186
+ for row in rows]
187
+ pq.write_table(pa.Table.from_pylist(native_rows), root / f"{name}.parquet", compression="snappy")
188
+ if pq.read_table(root / f"{name}.parquet").to_pylist() != native_rows:
189
+ raise ExternalDependencyError("SmartSearch GRPO parquet roundtrip changed native rows")
190
+ manifest = {"schema": GRPO_DATA_PROTOCOL, "source": binding, "split_audit": audit,
191
+ "train_rows": len(train), "validation_rows": len(validation),
192
+ "outputs": {name: _sha(root / name) for name in ("train.parquet", "validation.parquet")},
193
+ "data_provenance": data_provenance, "model_calls": 0, "optimizer_steps": 0,
194
+ "native_logical_fields_unchanged": True, "fixed_environment_identifier_adapter": True,
195
+ "no_native_test_to_dev_downsampling": True}
196
+ _save(root, "manifest.json", {**manifest, "artifact_id": content_hash(manifest)})
197
+ return SmartSearchGRPODataArtifact.load(root, max_rows=max_rows, max_file_bytes=max_input_bytes * 2 + 1024**2)
198
+ except Exception as exc:
199
+ _save(root, "failed.json", {"error_type": type(exc).__name__, "error": str(exc),
200
+ "model_calls": 0, "optimizer_steps": 0})
201
+ raise
202
+
203
+
204
+ @dataclass(frozen=True, slots=True)
205
+ class SmartSearchGRPOControls:
206
+ train_batch_size: int = 256
207
+ ppo_mini_batch_size: int = 64
208
+ rollout_samples: int = 8
209
+ total_epochs: int = 2
210
+ gpu_processes: int = 4
211
+ gpu_memory_utilization: float = .8
212
+ max_optimizer_steps: int = 10000
213
+ seed: int = 17
214
+ bounded_training_variant: bool = False
215
+
216
+ def __post_init__(self):
217
+ names = ("train_batch_size", "ppo_mini_batch_size", "rollout_samples", "total_epochs",
218
+ "gpu_processes", "max_optimizer_steps")
219
+ if any(type(getattr(self, n)) is not int or getattr(self, n) < 1 for n in names) or (
220
+ type(self.seed) is not int or self.seed < 0 or type(self.bounded_training_variant) is not bool
221
+ ):
222
+ raise ValidationError("SmartSearch GRPO controls require explicit positive integer bounds")
223
+ if not 1 <= self.gpu_processes <= 4 or self.rollout_samples < 2 or (
224
+ self.ppo_mini_batch_size > self.train_batch_size or self.train_batch_size % self.ppo_mini_batch_size
225
+ ) or (self.train_batch_size * self.rollout_samples) % self.gpu_processes or (
226
+ (self.ppo_mini_batch_size * self.rollout_samples) % self.gpu_processes
227
+ ):
228
+ raise ValidationError("SmartSearch GRPO native batch/sample/GPU divisibility differs")
229
+ utilization = self.gpu_memory_utilization
230
+ if isinstance(utilization, bool) or not isinstance(utilization, (float, int)) or (
231
+ not math.isfinite(utilization) or not 0 < utilization <= .95
232
+ ):
233
+ raise ValidationError("SmartSearch GRPO GPU cache allowance is invalid")
234
+ if (self.train_batch_size, self.ppo_mini_batch_size, self.rollout_samples, self.total_epochs) != (
235
+ 256, 64, 8, 2
236
+ ) and not self.bounded_training_variant:
237
+ raise ValidationError("Changing native GRPO batch/n/epochs requires an explicit labeled training variant")
238
+
239
+ def planned_steps(self, train_rows):
240
+ """Native dataloader/global steps, not the number of actor updates."""
241
+ if type(train_rows) is not int or train_rows < self.train_batch_size:
242
+ raise ValidationError("SmartSearch native drop_last would produce an empty GRPO training loader")
243
+ steps = train_rows // self.train_batch_size * self.total_epochs
244
+ if steps > self.max_optimizer_steps:
245
+ raise ValidationError("SmartSearch native optimizer plan exceeds the declared cap; it is not truncated")
246
+ return steps
247
+
248
+ def planned_actor_optimizer_steps(self, train_rows, *, ppo_epochs):
249
+ """Synchronized actor updates per rank, before any neural work.
250
+
251
+ Native FSDP normalizes the PPO minibatch by rollout_n/world_size;
252
+ those factors cancel when dividing each rank's local training batch.
253
+ Do not sum synchronized rank counters into extra distributed updates.
254
+ The executor must still meter actual optimizer calls on every rank.
255
+ """
256
+ if type(ppo_epochs) is not int or ppo_epochs < 1:
257
+ raise ValidationError("SmartSearch native PPO epochs must be a positive integer")
258
+ global_steps = self.planned_steps(train_rows)
259
+ steps = global_steps * (self.train_batch_size // self.ppo_mini_batch_size) * ppo_epochs
260
+ if steps > self.max_optimizer_steps:
261
+ raise ValidationError("SmartSearch native actor optimizer plan exceeds the declared cap; it is not truncated")
262
+ return steps
263
+
264
+
265
+ def _native_grpo_config(source, *, model, data, output_root, controls, sandbox_url, reward_module):
266
+ try:
267
+ import yaml
268
+ except ImportError as exc:
269
+ raise ExternalDependencyError("Install agentinputlab[yaml] to build native GRPO config") from exc
270
+ if not isinstance(sandbox_url, str):
271
+ raise ValidationError("SmartSearch GRPO fixed tool URL must be operator-owned loopback HTTP")
272
+ try:
273
+ url = urlsplit(sandbox_url)
274
+ port = url.port
275
+ except ValueError as exc:
276
+ raise ValidationError("SmartSearch GRPO fixed tool URL is malformed") from exc
277
+ if url.scheme != "http" or url.hostname != "127.0.0.1" or not port or (
278
+ url.username or url.password or url.query or url.fragment
279
+ ):
280
+ raise ValidationError("SmartSearch GRPO fixed tool URL must be operator-owned loopback HTTP")
281
+ controls.planned_steps(data.train_rows)
282
+ config = yaml.safe_load((Path(source) / "src/verl/trainer/config/ppo_trainer.yaml").read_text())
283
+ config["data"].update(train_files=str(data.root / "train.parquet"), val_files=str(data.root / "validation.parquet"),
284
+ prompt_key="question", train_batch_size=controls.train_batch_size, max_prompt_length=8192,
285
+ max_response_length=8192, use_re_call=True, prompt_template_name="re_call_template_sys",
286
+ search_url=sandbox_url, filter_overlong_prompts=True, trust_remote_code=False, seed=controls.seed,
287
+ cache_dir=str(Path(output_root) / "data-cache"))
288
+ policy = config["actor_rollout_ref"]
289
+ policy["model"].update(path=str(model), enable_gradient_checkpointing=True, use_remove_padding=True)
290
+ actor = policy["actor"]
291
+ controls.planned_actor_optimizer_steps(data.train_rows, ppo_epochs=actor["ppo_epochs"])
292
+ actor["optim"]["lr"] = 1e-6
293
+ actor.update(ppo_mini_batch_size=controls.ppo_mini_batch_size, use_dynamic_bsz=True,
294
+ ppo_max_token_len_per_gpu=32768, use_kl_loss=True, kl_loss_coef=.001, kl_loss_type="low_var_kl")
295
+ actor["fsdp_config"].update(param_offload=False, optimizer_offload=False)
296
+ # Preserve native shards plus its HF config/tokenizer metadata. The native
297
+ # checkpoint manager does NOT export HF weights; the live actor observer
298
+ # separately gathers the actual trained state into safe HF tensors.
299
+ actor["checkpoint"]["contents"] = [*actor["checkpoint"]["contents"], "hf_model"]
300
+ policy["rollout"].update(log_prob_max_token_len_per_gpu=65536, tensor_model_parallel_size=1,
301
+ name="vllm_with_tool", gpu_memory_utilization=controls.gpu_memory_utilization,
302
+ n=controls.rollout_samples, max_turns=5, sandbox_url=sandbox_url, enforce_eager=False, free_cache_engine=False)
303
+ policy["ref"]["log_prob_max_token_len_per_gpu"] = 65536
304
+ policy["ref"]["fsdp_config"]["param_offload"] = True
305
+ config["algorithm"].update(adv_estimator="grpo")
306
+ config["algorithm"]["kl_ctrl"]["kl_coef"] = .001
307
+ config["reward_model"]["reward_manager"] = "re_call"
308
+ config["custom_reward_function"].update(path=str(reward_module), name="compute_score")
309
+ config["trainer"].update(critic_warmup=0, logger=["console"], project_name="agentinputlab-smartsearch",
310
+ experiment_name="native-grpo", n_gpus_per_node=controls.gpu_processes, nnodes=1,
311
+ save_freq=10, test_freq=10, total_epochs=controls.total_epochs, resume_mode="disable",
312
+ resume_from_path=None, default_hdfs_dir=None, default_local_dir=str(output_root),
313
+ rollout_save_path=str(Path(output_root) / "rollouts"))
314
+ return config