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,616 @@
1
+ """Native full-SFT / LoRA-DPO policy stages for SmartSearch's curriculum.
2
+
3
+ The pinned LLaMA-Factory owns data collation, losses, optimizer, scheduler and
4
+ checkpoint export. This module binds data/source/models, mounts fresh paths,
5
+ observes native steps and retains failure costs. GRPO/full-pipeline completion
6
+ is deliberately not claimed by these policy-stage APIs.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import importlib
11
+ import importlib.metadata
12
+ import importlib.util
13
+ import json
14
+ import math
15
+ import os
16
+ import subprocess
17
+ import sys
18
+ import time
19
+ from collections.abc import Mapping
20
+ from contextlib import contextmanager, redirect_stderr, redirect_stdout
21
+ from dataclasses import dataclass
22
+ from pathlib import Path
23
+
24
+ from agentinputlab.contracts import ExternalDependencyError, ValidationError
25
+ from agentinputlab.contracts.serialization import content_hash, to_jsonable
26
+
27
+ from .llmlingua2_training import _closed_files
28
+ from .qrag import _file, _sha
29
+ from .recomp_extractive import _LOCK, _scope
30
+ from .smartsearch_curriculum import _question_hash, verify_smartsearch_preparation_source
31
+ from .smartsearch_native_data import verify_smartsearch_native_data_source
32
+
33
+ POLICY_PROTOCOL = "agentinputlab.smartsearch.native_policy_stage.v1"
34
+ MODEL_SCHEMA = "agentinputlab.smartsearch.policy_snapshot.v1"
35
+ _CONFIGS = {
36
+ "sft": ("LLaMA-Factory/examples/train_full/qwen_full_sft.yaml",
37
+ "bc92534ece9249ebb54e02bfd6a7c22dd9424fa77a908a25e39936a68a91d471"),
38
+ "dpo": ("LLaMA-Factory/examples/train_lora/qwen_lora_dpo.yaml",
39
+ "1176f154ed14b5f9c0b9fec08424717689e92ca7ec2f47eb4712b0be0cc69394"),
40
+ "merge": ("LLaMA-Factory/examples/merge_lora/qwen_lora_dpo.yaml",
41
+ "c2176e4152139518bf75f371659b1e6970805307ff106e78dce7f93c39ea4cea"),
42
+ }
43
+ _ZERO3 = "LLaMA-Factory/examples/deepspeed/ds_z3_config.json"
44
+ _ZERO3_SHA = "6e2753c870561658babe45922114f14ad899d5e4cfb6deb38fe47935ee60dc6f"
45
+ _TRAIN_SOURCE = {
46
+ "LLaMA-Factory/src/llamafactory/train/tuner.py": "2e7b0bbd3db765ab140be8539f36c4c72e9bf53572ff43e719aed944fcde113a",
47
+ "LLaMA-Factory/src/llamafactory/train/sft/workflow.py": "eadb7829102c234d00464ca7895ea9bf33993d9503d7b713770012be4ef44735",
48
+ "LLaMA-Factory/src/llamafactory/train/sft/trainer.py": "66e2c3dbbe0acda54090edb6e29a9e3fbc0bd7ed7aaf808bacac61d624e3172b",
49
+ "LLaMA-Factory/src/llamafactory/train/dpo/workflow.py": "12e03b82dc61ac8c0149be9f2f6aef1919e4519d794e27ccf909970a740fc678",
50
+ "LLaMA-Factory/src/llamafactory/train/dpo/trainer.py": "f1af018d741a5f3a4cde2d654ce027f6bb4396bf88f1328d273ab669b71ac1d0",
51
+ }
52
+
53
+
54
+ @dataclass(frozen=True, slots=True)
55
+ class SmartSearchPolicyFitControls:
56
+ seed: int = 17
57
+ max_optimizer_steps: int = 10000
58
+ max_data_bytes: int = 16 * 1024 * 1024
59
+ min_free_output_bytes: int = 32 * 1024**3
60
+ gpu_processes: int = 1
61
+
62
+ def __post_init__(self):
63
+ for name in ("seed", "max_optimizer_steps", "max_data_bytes", "min_free_output_bytes"):
64
+ value = getattr(self, name)
65
+ if type(value) is not int or value < (0 if name == "seed" else 1):
66
+ raise ValidationError("SmartSearch policy stage controls require positive integer caps")
67
+ if type(self.gpu_processes) is not int or not 1 <= self.gpu_processes <= 4:
68
+ raise ValidationError("SmartSearch policy fitting supports one to four operator-selected GPUs")
69
+
70
+
71
+ def _save(root, name, value):
72
+ with (root / name).open("x", encoding="utf-8") as stream:
73
+ json.dump(to_jsonable(value), stream, ensure_ascii=False, sort_keys=True, allow_nan=False)
74
+
75
+
76
+ def _source(checkout):
77
+ binding = dict(verify_smartsearch_preparation_source(checkout))
78
+ root = Path(binding["root"])
79
+ # These exact configs are part of the pinned upstream Git checkout. Never
80
+ # load caller-authored YAML with a Python object constructor.
81
+ checks = dict(_CONFIGS.values()) | {_ZERO3: _ZERO3_SHA} | _TRAIN_SOURCE
82
+ for relative, expected in checks.items():
83
+ path = _file(root / relative, "SmartSearch native training config")
84
+ if not path.is_relative_to(root) or _sha(path) != expected:
85
+ raise ExternalDependencyError("SmartSearch native training configuration changed")
86
+ binding["policy_configs"] = checks
87
+ return root, binding
88
+
89
+
90
+ def _model(root, manifest, manifest_sha256):
91
+ supplied = Path(root)
92
+ if supplied.is_symlink() or not supplied.is_dir():
93
+ raise ValidationError("SmartSearch policy requires a mounted regular model snapshot")
94
+ folder = supplied.resolve()
95
+ config = json.loads(_file(folder / "config.json", "policy model config").read_text())
96
+ tokenizer = json.loads(_file(folder / "tokenizer_config.json", "policy tokenizer config").read_text())
97
+ if config.get("quantization_config"):
98
+ raise ExternalDependencyError(
99
+ "SmartSearch native full-SFT/LoRA-merge pipeline does not support a quantized base; "
100
+ "no silent dequantization or replacement precision is applied"
101
+ )
102
+ if config.get("auto_map") or tokenizer.get("auto_map"):
103
+ raise ExternalDependencyError("SmartSearch policy fitting does not execute model remote code")
104
+ if not str(config.get("model_type", "")).startswith("qwen"):
105
+ raise ExternalDependencyError(
106
+ "SmartSearch's pinned policy configs use the Qwen template; another model family "
107
+ "requires an explicitly defined training variant, not an implicit prompt-template change"
108
+ )
109
+ folder, closure = _closed_files(folder, manifest, manifest_sha256, MODEL_SCHEMA)
110
+ names = closure["files"]
111
+ if not any(name.endswith(".safetensors") for name in names) or any(
112
+ name.endswith((".py", ".bin", ".pt", ".pkl", ".pickle")) for name in names
113
+ ):
114
+ raise ValidationError("SmartSearch policy snapshot must use safe, code-free safetensors")
115
+ if "adapter_config.json" in names:
116
+ raise ValidationError("SmartSearch full policy snapshot cannot be an implicit LoRA adapter")
117
+ if not isinstance(closure.get("revision"), str) or closure["revision"].lower() in {"", "main", "latest", "head"}:
118
+ raise ValidationError("SmartSearch policy snapshot requires an immutable revision")
119
+ return folder, closure
120
+
121
+
122
+ def _curriculum(root, stage, byte_cap):
123
+ folder = Path(root)
124
+ if folder.is_symlink() or not folder.is_dir():
125
+ raise ValidationError("SmartSearch policy curriculum root must be a regular directory")
126
+ folder = folder.resolve()
127
+ manifest = json.loads(_file(folder / "manifest.json", "curriculum manifest").read_text())
128
+ artifact_id = manifest.pop("artifact_id", None)
129
+ if artifact_id != content_hash(manifest) or manifest.get("schema") != "agentinputlab.smartsearch.native-curriculum-data.v1":
130
+ raise ValidationError("SmartSearch curriculum artifact identity differs")
131
+ if manifest.get("rollout_provenance", {}).get("fixture_only"):
132
+ raise ValidationError("SmartSearch neural fitting cannot consume fixture-only rollouts")
133
+ name = f"{stage}.json"
134
+ path = _file(folder / name, "curriculum rows")
135
+ if path.stat().st_size > byte_cap or _sha(path) != manifest.get("outputs", {}).get(name):
136
+ raise ValidationError("SmartSearch native curriculum rows changed or exceed byte cap")
137
+ rows = json.loads(path.read_text())
138
+ if not isinstance(rows, list) or not rows:
139
+ raise ValidationError("SmartSearch native selection is empty; no replacement examples are manufactured")
140
+ audit = manifest.get("split_audit", {})
141
+ training_hashes = set(audit.get("train", {}).get("question_hashes", []))
142
+ heldout_hashes = set(audit.get("validation", {}).get("question_hashes", [])) | set(
143
+ audit.get("test", {}).get("question_hashes", []))
144
+ if not training_hashes or not audit.get("validation", {}).get("case_ids") or training_hashes & heldout_hashes:
145
+ raise ValidationError("SmartSearch curriculum lacks disjoint native train/validation/test audit")
146
+ keys = ("instruction", "input", "output") if stage == "sft" else ("instruction", "input", "chosen", "rejected")
147
+ for row in rows:
148
+ if not isinstance(row, dict) or any(not isinstance(row.get(k), str) or not row[k].strip() for k in keys):
149
+ raise ValidationError("SmartSearch native policy row is incomplete")
150
+ if _question_hash(row["input"]) not in training_hashes:
151
+ raise ValidationError("SmartSearch policy row is not a declared training question")
152
+ return rows, manifest, artifact_id
153
+
154
+
155
+ def _native_config(source, stage, model, root, seed):
156
+ try:
157
+ import yaml
158
+ except ImportError as exc:
159
+ raise ExternalDependencyError("Install agentinputlab[yaml] to build native SmartSearch policy configs") from exc
160
+ config = yaml.safe_load((source / _CONFIGS[stage][0]).read_text())
161
+ if not isinstance(config, dict):
162
+ raise ExternalDependencyError("SmartSearch native policy configuration must be a mapping")
163
+ config.update(model_name_or_path=str(model), trust_remote_code=False)
164
+ if stage == "merge":
165
+ config.update(export_dir=str(root / "checkpoint"))
166
+ return config
167
+ # Only paths, explicit seed, cache/telemetry and create-only execution
168
+ # controls differ. Native loss/rank/LR/batches/epochs/cutoff/ZeRO stay intact.
169
+ config.update(
170
+ dataset=f"mine_{stage}", dataset_dir=str(root / "data"),
171
+ output_dir=str(root / "checkpoint"), deepspeed=str(source / _ZERO3),
172
+ seed=seed, data_seed=seed, overwrite_cache=False, overwrite_output_dir=False,
173
+ push_to_hub=False, report_to="none", resume_from_checkpoint=None,
174
+ )
175
+ return config
176
+
177
+
178
+ def _source_import(source, native_data_source=None):
179
+ name = "llamafactory"
180
+ prefix = source / "LLaMA-Factory/src"
181
+ previous = list(sys.path)
182
+ if any(n == name or n.startswith(name + ".") for n in sys.modules):
183
+ raise ExternalDependencyError("Run each native SmartSearch policy stage in a fresh dedicated process")
184
+ sys.path.insert(0, str(prefix))
185
+ try:
186
+ if native_data_source is not None:
187
+ bound = verify_smartsearch_native_data_source(source, native_data_source["root"])
188
+ if bound != native_data_source:
189
+ raise ExternalDependencyError("SmartSearch native data supplement launch binding changed")
190
+ package = importlib.import_module(name)
191
+ if not Path(package.__file__).resolve().is_relative_to(prefix):
192
+ raise ExternalDependencyError("SmartSearch native package was shadowed")
193
+ # Mount this package only; never add an alternative framework root
194
+ # to sys.path or the original package's general search path.
195
+ data = Path(bound["root"]) / "data"
196
+ spec = importlib.util.spec_from_file_location(
197
+ "llamafactory.data", data / "__init__.py", submodule_search_locations=[str(data)])
198
+ module = importlib.util.module_from_spec(spec)
199
+ sys.modules[spec.name] = module
200
+ package.data = module
201
+ spec.loader.exec_module(module)
202
+ module = importlib.import_module("llamafactory.train.tuner")
203
+ if not Path(module.__file__).resolve().is_relative_to(prefix):
204
+ raise ExternalDependencyError("SmartSearch native trainer was shadowed by another installation")
205
+ return module
206
+ finally:
207
+ sys.path[:] = previous
208
+
209
+
210
+ def _observer(counters, max_steps):
211
+ from transformers import TrainerCallback
212
+
213
+ class Observer(TrainerCallback):
214
+ def on_train_begin(self, args, state, control, **kwargs):
215
+ if state.max_steps < 1 or state.max_steps > max_steps:
216
+ raise ValidationError("SmartSearch native optimizer plan exceeds the caller's step cap")
217
+ counters["planned_optimizer_steps"] = state.max_steps
218
+ model = kwargs.get("model")
219
+ if model is None:
220
+ raise ExternalDependencyError("SmartSearch native trainer did not expose its policy")
221
+
222
+ def before(module, args, kwargs):
223
+ counters["forward_attempts"] += 1
224
+ inputs = kwargs.get("input_ids")
225
+ if inputs is None and args:
226
+ inputs = args[0]
227
+ counters["input_token_positions"] += int(inputs.numel()) if hasattr(inputs, "numel") else 0
228
+
229
+ def after(module, args, output):
230
+ counters["forward_responses"] += 1
231
+
232
+ self.before = model.register_forward_pre_hook(before, with_kwargs=True)
233
+ self.after = model.register_forward_hook(after)
234
+
235
+ def on_step_end(self, args, state, control, **kwargs):
236
+ counters["optimizer_steps"] = state.global_step
237
+ if state.global_step > max_steps:
238
+ raise ValidationError("SmartSearch native optimizer exceeded its declared step cap")
239
+
240
+ def on_log(self, args, state, control, logs=None, **kwargs):
241
+ if logs:
242
+ record = {}
243
+ for key, value in logs.items():
244
+ if isinstance(value, float) and not math.isfinite(value):
245
+ counters["nonfinite_native_metrics"] += 1
246
+ record[key] = repr(value)
247
+ elif isinstance(value, (float, int, str, bool)):
248
+ record[key] = value
249
+ counters["native_logs"].append(record)
250
+
251
+ def on_train_end(self, args, state, control, **kwargs):
252
+ self.before.remove()
253
+ self.after.remove()
254
+
255
+ return Observer()
256
+
257
+
258
+ @contextmanager
259
+ def _environment(root, seed):
260
+ overrides = {"HF_DATASETS_OFFLINE": "1", "HF_HUB_DISABLE_TELEMETRY": "1", "WANDB_MODE": "disabled"}
261
+ previous = {name: os.environ.get(name) for name in overrides}
262
+ try:
263
+ with _scope(root, seed):
264
+ os.environ.update(overrides)
265
+ yield
266
+ finally:
267
+ for name, value in previous.items():
268
+ if value is None:
269
+ os.environ.pop(name, None)
270
+ else:
271
+ os.environ[name] = value
272
+
273
+
274
+ @dataclass(frozen=True, slots=True)
275
+ class SmartSearchPolicyStageArtifact:
276
+ root: Path
277
+ artifact_id: str
278
+ stage: str
279
+
280
+ @property
281
+ def checkpoint(self):
282
+ return self.root / "checkpoint"
283
+
284
+ @classmethod
285
+ def load(cls, root):
286
+ supplied = Path(root)
287
+ if supplied.is_symlink() or not supplied.is_dir():
288
+ raise ValidationError("SmartSearch policy artifact root is invalid")
289
+ folder = supplied.resolve()
290
+ record = json.loads(_file(folder / "artifact.json", "policy artifact").read_text())
291
+ identity = record.pop("artifact_id", None)
292
+ if identity != content_hash(record) or record.get("protocol") != POLICY_PROTOCOL or record.get("stage") not in {"sft", "dpo", "merged_dpo"}:
293
+ raise ValidationError("SmartSearch policy artifact identity differs")
294
+ for key, name in (("fit_plan_sha256", "fit-plan.json"), ("fit_terminal_sha256", "fit-terminal.json")):
295
+ if _sha(_file(folder / name, "policy receipt")) != record.get(key):
296
+ raise ValidationError("SmartSearch policy artifact plan/terminal changed")
297
+ terminal = json.loads((folder / "fit-terminal.json").read_text())
298
+ if record["stage"] == "merged_dpo":
299
+ plan = json.loads((folder / "fit-plan.json").read_text())
300
+ if terminal.get("status") != "merged_candidate" or not plan.get("dpo_artifact_id"):
301
+ raise ValidationError("SmartSearch merged policy has no fitted adapter binding")
302
+ elif terminal.get("status") != "trained_candidate" or terminal.get("usage", {}).get("optimizer_steps", 0) < 1:
303
+ raise ValidationError("SmartSearch policy artifact has no completed optimizer step")
304
+ files = record.get("checkpoint_files")
305
+ if not isinstance(files, dict) or not files or not any(n.endswith(".safetensors") for n in files):
306
+ raise ValidationError("SmartSearch policy artifact has no safe checkpoint closure")
307
+ for name, digest in files.items():
308
+ if not isinstance(name, str) or Path(name).name != name or name in {".", ".."}:
309
+ raise ValidationError("SmartSearch policy checkpoint file path is unsafe")
310
+ if _sha(_file(folder / "checkpoint" / name, "policy checkpoint")) != digest:
311
+ raise ValidationError("SmartSearch policy checkpoint bytes changed")
312
+ return cls(folder, identity, record["stage"])
313
+
314
+ def materialize_snapshot(self, output_root):
315
+ """Copy final SFT weights/tokenizer only; never pickle/optimizer state.
316
+
317
+ DPO is still an adapter and needs native merge before becoming a policy.
318
+ This explicit copy has a storage cost; the original training log and
319
+ checkpoints remain untouched.
320
+ """
321
+ import shutil
322
+
323
+ current = self.load(self.root)
324
+ if current.stage == "dpo":
325
+ raise ValidationError("SmartSearch LoRA-DPO adapter must be natively merged before policy export")
326
+ record = json.loads((current.root / "artifact.json").read_text())
327
+ root = Path(output_root)
328
+ if root.exists() or root.is_symlink():
329
+ raise ValidationError("SmartSearch policy snapshot must be create-only")
330
+ root = root.resolve(strict=False)
331
+ if root.is_relative_to(current.root) or current.root.is_relative_to(root):
332
+ raise ValidationError("SmartSearch policy snapshot must not overlap the training artifact")
333
+ files = record["checkpoint_files"]
334
+ if not {"config.json", "tokenizer_config.json"} <= files.keys():
335
+ raise ValidationError("SmartSearch policy checkpoint lacks model/tokenizer configuration")
336
+ for name in files:
337
+ if Path(name).suffix not in {".safetensors", ".json", ".model", ".txt", ".jinja"}:
338
+ raise ValidationError("SmartSearch policy export refuses executable/binary payloads")
339
+ # Keep native training reports in the training artifact, not in the
340
+ # inference snapshot. The latter closes only model/tokenizer payloads.
341
+ hf_metadata = {"config.json", "generation_config.json", "tokenizer.json", "tokenizer_config.json",
342
+ "special_tokens_map.json", "added_tokens.json", "vocab.json", "vocab.txt", "merges.txt"}
343
+ files = {name: digest for name, digest in files.items() if name in hf_metadata or
344
+ name.endswith((".safetensors", ".safetensors.index.json", ".model", ".jinja"))}
345
+ parent = root.parent
346
+ while not parent.exists():
347
+ parent = parent.parent
348
+ required = sum((current.checkpoint / name).stat().st_size for name in files)
349
+ if shutil.disk_usage(parent).free < required:
350
+ raise ExternalDependencyError("SmartSearch policy snapshot copy lacks output capacity")
351
+ root.mkdir(parents=True, exist_ok=False)
352
+ (root / "model").mkdir()
353
+ for name, digest in files.items():
354
+ shutil.copyfile(current.checkpoint / name, root / "model" / name)
355
+ if _sha(root / "model" / name) != digest:
356
+ raise ValidationError("SmartSearch policy changed while copying its safe closure")
357
+ manifest = {"schema": MODEL_SCHEMA, "revision": "artifact:" + current.artifact_id,
358
+ "files": files, "training_artifact_id": current.artifact_id,
359
+ "toolkit_exporter_sha256": _sha(Path(__file__))}
360
+ _save(root, "model-manifest.json", manifest)
361
+ return {"model_root": str(root / "model"), "model_manifest": str(root / "model-manifest.json"),
362
+ "model_manifest_sha256": _sha(root / "model-manifest.json")}
363
+
364
+
365
+ class SmartSearchNativePolicyTraining:
366
+ """Execute original LLaMA-Factory SFT/DPO; not the complete GRPO recipe."""
367
+
368
+ def __init__(self, controls=None):
369
+ self.controls = SmartSearchPolicyFitControls(**controls) if isinstance(controls, Mapping) else controls or SmartSearchPolicyFitControls()
370
+ if not isinstance(self.controls, SmartSearchPolicyFitControls):
371
+ raise ValidationError("SmartSearch policy fitting requires typed controls")
372
+
373
+ def fit(
374
+ self, *, stage, checkout, model_root, model_manifest, model_manifest_sha256,
375
+ curriculum_root, output_root, source_and_data_acknowledged=False, native_data_root=None,
376
+ ):
377
+ if source_and_data_acknowledged is not True or stage not in {"sft", "dpo"}:
378
+ raise ValidationError("SmartSearch policy stage needs explicit source/data acknowledgement and sft/dpo")
379
+ source, source_binding = _source(checkout)
380
+ if native_data_root is None:
381
+ raise ExternalDependencyError("Prepare SmartSearch's pinned native data source and pass native_data_root")
382
+ native_data_source = verify_smartsearch_native_data_source(source, native_data_root)
383
+ model, closure = _model(model_root, model_manifest, model_manifest_sha256)
384
+ rows, curriculum, curriculum_id = _curriculum(curriculum_root, stage, self.controls.max_data_bytes)
385
+ root = Path(output_root)
386
+ if root.exists() or root.is_symlink():
387
+ raise ValidationError("SmartSearch policy output must be create-only; no automatic retry")
388
+ root = root.resolve(strict=False)
389
+ protected = (source, model, Path(curriculum_root).resolve())
390
+ if any(root.is_relative_to(p) or p.is_relative_to(root) for p in protected):
391
+ raise ValidationError("SmartSearch policy output must not overlap mounted assets")
392
+ import shutil
393
+
394
+ parent = root.parent
395
+ while not parent.exists():
396
+ parent = parent.parent
397
+ if shutil.disk_usage(parent).free < self.controls.min_free_output_bytes:
398
+ raise ExternalDependencyError("SmartSearch native policy output capacity is insufficient")
399
+ config = _native_config(source, stage, model, root, self.controls.seed)
400
+ root.mkdir(parents=True, exist_ok=False)
401
+ (root / "data").mkdir()
402
+ _save(root / "data", f"{stage}.json", rows)
403
+ dataset = {"file_name": f"{stage}.json", "columns": {"prompt": "instruction", "query": "input"}}
404
+ if stage == "sft":
405
+ dataset["columns"]["response"] = "output"
406
+ else:
407
+ dataset["ranking"] = True
408
+ dataset["columns"].update(chosen="chosen", rejected="rejected")
409
+ _save(root / "data", "dataset_info.json", {f"mine_{stage}": dataset})
410
+ versions = {}
411
+ for name in ("torch", "transformers", "trl", "datasets", "peft", "accelerate", "deepspeed"):
412
+ try:
413
+ versions[name] = importlib.metadata.version(name)
414
+ except importlib.metadata.PackageNotFoundError:
415
+ versions[name] = None
416
+ plan = {"protocol": POLICY_PROTOCOL, "stage": stage, "source": source_binding,
417
+ "native_data_source": native_data_source,
418
+ "controls": self.controls, "native_config": config, "model_manifest_sha256": model_manifest_sha256,
419
+ "model_revision": closure["revision"], "curriculum_artifact_id": curriculum_id,
420
+ "split_audit": curriculum["split_audit"], "training_only": True,
421
+ "native_loss_optimizer_scheduler_unchanged": True, "dependency_versions": versions,
422
+ "toolkit_policy_sha256": _sha(Path(__file__)),
423
+ "toolkit_worker_sha256": _sha(Path(__file__).with_name("smartsearch_policy_worker.py"))}
424
+ _save(root, "fit-plan.json", plan)
425
+ counters = {"rank_receipts": {}, "rank_usage_complete": False,
426
+ "forward_attempts": None, "forward_responses": None,
427
+ "optimizer_steps": None, "nonfinite_native_metrics": None}
428
+ started = time.monotonic()
429
+ try:
430
+ command = [sys.executable, "-m", "torch.distributed.run", "--standalone", "--nnodes=1",
431
+ f"--nproc_per_node={self.controls.gpu_processes}", "--max_restarts=0", "--module",
432
+ "agentinputlab.recipes.smartsearch_policy_worker", str(root),
433
+ _sha(root / "fit-plan.json")]
434
+ _save(root, "launch.json", {"argv": command, "no_automatic_retry": True,
435
+ "visible_devices": os.environ.get("CUDA_VISIBLE_DEVICES")})
436
+ with (root / "native.log").open("xb") as log:
437
+ process = subprocess.run(command, stdout=log, stderr=subprocess.STDOUT, check=False)
438
+ _collect_rank_usage(root, self.controls.gpu_processes, counters)
439
+ if process.returncode:
440
+ raise ExternalDependencyError(f"SmartSearch native distributed trainer exited {process.returncode}; see native.log")
441
+ if not counters["rank_usage_complete"] or any(
442
+ value.get("status") != "completed" for value in counters["rank_receipts"].values()
443
+ ):
444
+ raise ExternalDependencyError("SmartSearch native rank receipts are incomplete")
445
+ if not counters["distributed_optimizer_step_agreement"]:
446
+ raise ExternalDependencyError("SmartSearch distributed ranks disagree on native optimizer steps")
447
+ checkpoint = root / "checkpoint"
448
+ tensors = [p for p in checkpoint.iterdir() if p.name.endswith(".safetensors")]
449
+ if counters["optimizer_steps"] < 1 or not tensors or any(p.is_symlink() for p in tensors):
450
+ raise ExternalDependencyError("SmartSearch native policy did not produce a trained safe checkpoint")
451
+ if counters["nonfinite_native_metrics"]:
452
+ raise ExternalDependencyError("SmartSearch native training recorded a non-finite loss")
453
+ files = {p.name: _sha(p) for p in checkpoint.iterdir()
454
+ if p.is_file() and p.suffix in {".safetensors", ".json", ".model", ".txt", ".jinja"}}
455
+ terminal = {"status": "trained_candidate", "stage": stage, "usage": counters,
456
+ "elapsed_seconds": time.monotonic() - started, "checkpoint_files": files,
457
+ "heldout_evaluation_completed": False, "full_sft_dpo_grpo_completed": False}
458
+ _save(root, "fit-terminal.json", terminal)
459
+ artifact = {"protocol": POLICY_PROTOCOL, "stage": stage,
460
+ "fit_plan_sha256": _sha(root / "fit-plan.json"),
461
+ "fit_terminal_sha256": _sha(root / "fit-terminal.json"),
462
+ "checkpoint_files": files, "base_model_manifest_sha256": model_manifest_sha256,
463
+ "source_commit": source_binding["source_commit"], "curriculum_artifact_id": curriculum_id}
464
+ artifact["artifact_id"] = content_hash(artifact)
465
+ _save(root, "artifact.json", artifact)
466
+ return SmartSearchPolicyStageArtifact.load(root)
467
+ except Exception as exc:
468
+ _collect_rank_usage(root, self.controls.gpu_processes, counters)
469
+ _save(root, "failed.json", {"error_type": type(exc).__name__, "error": str(exc),
470
+ "usage": counters, "elapsed_seconds": time.monotonic() - started,
471
+ "no_automatic_retry": True})
472
+ raise
473
+
474
+ def merge(
475
+ self, *, checkout, model_root, model_manifest, model_manifest_sha256,
476
+ dpo_artifact_root, output_root, source_and_data_acknowledged=False, native_data_root=None,
477
+ ):
478
+ """Native CPU LoRA merge with the exact SFT base; no new training."""
479
+ if source_and_data_acknowledged is not True:
480
+ raise ValidationError("SmartSearch native merge requires explicit source/data acknowledgement")
481
+ source, source_binding = _source(checkout)
482
+ if native_data_root is None:
483
+ raise ExternalDependencyError("Prepare SmartSearch's pinned native data source and pass native_data_root")
484
+ native_data_source = verify_smartsearch_native_data_source(source, native_data_root)
485
+ model, closure = _model(model_root, model_manifest, model_manifest_sha256)
486
+ adapter = SmartSearchPolicyStageArtifact.load(dpo_artifact_root)
487
+ record = json.loads((adapter.root / "artifact.json").read_text())
488
+ if adapter.stage != "dpo" or record["base_model_manifest_sha256"] != model_manifest_sha256:
489
+ raise ValidationError("SmartSearch DPO adapter and native merge base do not match")
490
+ root = Path(output_root)
491
+ if root.exists() or root.is_symlink():
492
+ raise ValidationError("SmartSearch native merge must use a new output directory")
493
+ root = root.resolve(strict=False)
494
+ if any(root.is_relative_to(p) or p.is_relative_to(root) for p in (source, model, adapter.root)):
495
+ raise ValidationError("SmartSearch native merge output overlaps a protected input")
496
+ config = _native_config(source, "merge", model, root, self.controls.seed)
497
+ config["adapter_name_or_path"] = str(adapter.checkpoint)
498
+ root.mkdir(parents=True, exist_ok=False)
499
+ controls = to_jsonable(self.controls)
500
+ controls["gpu_processes"] = 1 # original merge export_device=cpu
501
+ plan = {"protocol": POLICY_PROTOCOL, "operation": "merge", "source": source_binding,
502
+ "native_data_source": native_data_source,
503
+ "controls": controls, "native_config": config, "model_revision": closure["revision"],
504
+ "model_manifest_sha256": model_manifest_sha256, "dpo_artifact_id": adapter.artifact_id,
505
+ "toolkit_policy_sha256": _sha(Path(__file__)),
506
+ "toolkit_worker_sha256": _sha(Path(__file__).with_name("smartsearch_policy_worker.py"))}
507
+ _save(root, "fit-plan.json", plan)
508
+ usage = {"rank_receipts": {}, "rank_usage_complete": False, "forward_attempts": None,
509
+ "forward_responses": None, "optimizer_steps": None}
510
+ started = time.monotonic()
511
+ try:
512
+ command = [sys.executable, "-m", "agentinputlab.recipes.smartsearch_policy_worker",
513
+ str(root), _sha(root / "fit-plan.json")]
514
+ _save(root, "launch.json", {"argv": command, "no_automatic_retry": True, "export_device": "cpu"})
515
+ with (root / "native.log").open("xb") as log:
516
+ process = subprocess.run(command, stdout=log, stderr=subprocess.STDOUT, check=False)
517
+ _collect_rank_usage(root, 1, usage)
518
+ if process.returncode or not usage["rank_usage_complete"] or usage["rank_receipts"]["0"]["status"] != "completed":
519
+ raise ExternalDependencyError("SmartSearch native LoRA merge did not complete; see retained native logs")
520
+ checkpoint = root / "checkpoint"
521
+ files = {p.name: _sha(p) for p in checkpoint.iterdir()
522
+ if p.is_file() and not p.is_symlink() and p.suffix in {".safetensors", ".json", ".model", ".txt", ".jinja"}}
523
+ if not any(name.endswith(".safetensors") for name in files) or "config.json" not in files:
524
+ raise ExternalDependencyError("SmartSearch native merge did not export safe policy weights")
525
+ _save(root, "fit-terminal.json", {"status": "merged_candidate", "usage": usage,
526
+ "elapsed_seconds": time.monotonic() - started,
527
+ "full_sft_dpo_grpo_completed": False})
528
+ artifact = {"protocol": POLICY_PROTOCOL, "stage": "merged_dpo",
529
+ "fit_plan_sha256": _sha(root / "fit-plan.json"),
530
+ "fit_terminal_sha256": _sha(root / "fit-terminal.json"),
531
+ "checkpoint_files": files, "base_model_manifest_sha256": model_manifest_sha256,
532
+ "source_commit": source_binding["source_commit"], "dpo_artifact_id": adapter.artifact_id}
533
+ artifact["artifact_id"] = content_hash(artifact)
534
+ _save(root, "artifact.json", artifact)
535
+ return SmartSearchPolicyStageArtifact.load(root)
536
+ except Exception as exc:
537
+ _collect_rank_usage(root, 1, usage)
538
+ _save(root, "failed.json", {"error_type": type(exc).__name__, "error": str(exc), "usage": usage,
539
+ "elapsed_seconds": time.monotonic() - started, "no_automatic_retry": True})
540
+ raise
541
+
542
+
543
+ def _collect_rank_usage(root, world_size, counters):
544
+ records = {}
545
+ errors = []
546
+ expected_plan = _sha(root / "fit-plan.json")
547
+ for rank in range(world_size):
548
+ path = root / f"rank-{rank}-terminal.json"
549
+ if path.is_file() and not path.is_symlink():
550
+ try:
551
+ row = json.loads(path.read_text())
552
+ if row.get("rank") != rank or row.get("plan_sha256") != expected_plan or row.get("status") not in {"completed", "failed"}:
553
+ raise ValueError("rank/plan/status binding differs")
554
+ usage = row["usage"]
555
+ for name in ("forward_attempts", "forward_responses", "input_token_positions", "nonfinite_native_metrics", "optimizer_steps"):
556
+ if type(usage.get(name)) is not int or usage[name] < 0:
557
+ raise ValueError("rank usage is not a measured nonnegative integer")
558
+ records[str(rank)] = row
559
+ except (KeyError, TypeError, ValueError) as exc:
560
+ errors.append({"rank": rank, "error": str(exc)})
561
+ counters["rank_receipts"] = records
562
+ counters["rank_parse_errors"] = errors
563
+ counters["rank_usage_complete"] = len(records) == world_size
564
+ if counters["rank_usage_complete"]:
565
+ usages = [row["usage"] for row in records.values()]
566
+ for key in ("forward_attempts", "forward_responses", "input_token_positions", "nonfinite_native_metrics"):
567
+ counters[key] = sum(row[key] for row in usages)
568
+ steps = {row["optimizer_steps"] for row in usages}
569
+ counters["optimizer_steps"] = min(steps)
570
+ counters["distributed_optimizer_step_agreement"] = len(steps) == 1
571
+
572
+
573
+ def run_native_policy_rank(output_root, plan_sha256):
574
+ """Distributed worker body; invoked once per rank by native torchrun."""
575
+ root = Path(output_root).resolve()
576
+ path = _file(root / "fit-plan.json", "policy launch plan")
577
+ if _sha(path) != plan_sha256:
578
+ raise ValidationError("SmartSearch distributed policy plan identity differs")
579
+ plan = json.loads(path.read_text())
580
+ if _sha(Path(__file__)) != plan.get("toolkit_policy_sha256") or _sha(
581
+ Path(__file__).with_name("smartsearch_policy_worker.py")
582
+ ) != plan.get("toolkit_worker_sha256"):
583
+ raise ValidationError("SmartSearch child toolkit bytes differ from the launcher")
584
+ controls = SmartSearchPolicyFitControls(**plan["controls"])
585
+ merge = plan.get("operation") == "merge"
586
+ rank = 0 if merge else int(os.environ.get("RANK", "-1"))
587
+ if not merge and (not 0 <= rank < controls.gpu_processes or int(os.environ.get("WORLD_SIZE", "0")) != controls.gpu_processes):
588
+ raise ValidationError("SmartSearch policy rank must be launched by the bound distributed runtime")
589
+ rank_root = root / f"rank-{rank}-workspace"
590
+ rank_root.mkdir(exist_ok=False)
591
+ counters = {"forward_attempts": 0, "forward_responses": 0, "input_token_positions": 0,
592
+ "forward_observation_scope": "primary_policy_after_on_train_begin",
593
+ "unobserved_reference_forward_calls": None,
594
+ "optimizer_steps": 0, "planned_optimizer_steps": None, "native_logs": [],
595
+ "nonfinite_native_metrics": 0}
596
+ started = time.monotonic()
597
+ try:
598
+ source = Path(plan["source"]["root"])
599
+ for relative, digest in plan["source"]["policy_configs"].items():
600
+ if _sha(_file(source / relative, "native worker source")) != digest:
601
+ raise ExternalDependencyError("SmartSearch distributed native source/config changed")
602
+ with _LOCK, _environment(rank_root, controls.seed), (root / f"native-rank-{rank}.log").open("x") as log, redirect_stdout(log), redirect_stderr(log):
603
+ trainer = _source_import(source, plan.get("native_data_source"))
604
+ if merge:
605
+ trainer.export_model(args=plan["native_config"])
606
+ else:
607
+ trainer.run_exp(args=plan["native_config"], callbacks=[_observer(counters, controls.max_optimizer_steps)])
608
+ _save(root, f"rank-{rank}-terminal.json", {"status": "completed", "rank": rank,
609
+ "plan_sha256": plan_sha256, "usage": counters,
610
+ "elapsed_seconds": time.monotonic() - started})
611
+ except Exception as exc:
612
+ _save(root, f"rank-{rank}-terminal.json", {"status": "failed", "rank": rank,
613
+ "plan_sha256": plan_sha256, "usage": counters,
614
+ "error_type": type(exc).__name__, "error": str(exc),
615
+ "elapsed_seconds": time.monotonic() - started})
616
+ raise
@@ -0,0 +1,9 @@
1
+ """Fresh-process, distributed native SmartSearch policy-stage entrypoint."""
2
+ import sys
3
+
4
+ from .smartsearch_policy import run_native_policy_rank
5
+
6
+ if __name__ == "__main__":
7
+ if len(sys.argv) != 3:
8
+ raise SystemExit("expected a create-only policy output root and pinned plan SHA-256")
9
+ run_native_policy_rank(sys.argv[1], sys.argv[2])