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,729 @@
1
+ """Pinned Q-RAG value-policy training with native rollout, rewards and updates.
2
+
3
+ Run fit in a dedicated process. Hydra's dataset transport reads the caller's
4
+ closed native records; QADatasetAdapter, QAEnv, GroundTruthFeedback,
5
+ ParallelTextEnv and PQN own all label projection, rollout and gradient math.
6
+ Training checkpoints are new artifacts, never aliases of the released policy.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import hashlib
12
+ import importlib.metadata
13
+ import json
14
+ import math
15
+ import os
16
+ import runpy
17
+ import shutil
18
+ import subprocess
19
+ import sys
20
+ import time
21
+ from collections.abc import Mapping
22
+ from contextlib import contextmanager, redirect_stderr, redirect_stdout
23
+ from dataclasses import asdict, dataclass
24
+ from pathlib import Path
25
+
26
+ from agentinputlab.algorithms.acquire.qrag.bridge import QRAG_UPSTREAM_COMMIT
27
+ from agentinputlab.algorithms.acquire.qrag.common_support import (
28
+ _source_import,
29
+ _unused_vllm_import_compatibility,
30
+ )
31
+ from agentinputlab.contracts import ExternalDependencyError, ValidationError
32
+ from agentinputlab.contracts.serialization import content_hash
33
+
34
+ from .recomp_extractive import _LOCK, _save, _scope
35
+
36
+ RELEASE = "training.qrag.value_policy"
37
+ PROTOCOL = "agentinputlab.qrag.native_value_fit.v1"
38
+ SOURCE_FILES = {
39
+ "train_q_rag.py": "e412a85fe6c2fe06eb6c0f406c8b824fe6063d975dbfb54b8c3c1615558fa4c2",
40
+ "envs/parallel_env.py": "d77f6f79ba3a5aecf09795075274378ccb806ec0514ed8b2d625e1e9e5d93853",
41
+ "envs/qa_env.py": "267c27c248f332478bf810a50f097a898a818cf6f8f4bd7b70a2893312c0eae1",
42
+ "envs/qa_dataset_adapter.py": "b2cf231177a1f079f7fdb213838df2ab967caf6c9977df5447bc31cf8abba5f3",
43
+ "rl/agents/pqn.py": "5e69ee5e20f098c101ceebb0c3713a3e63ffcd0a1b614d7180c1b474465cce39",
44
+ "rl/q_module.py": "8f5e50f1033aa04a326bba2ba14eff2ff8631d494f01913179652644e7832148",
45
+ "rl/bert_predictor.py": "7d82d0749afd0b57d1416dd6c39477f164fd710421f23faaadbd8a29e2f142c8",
46
+ "rl/optim.py": "1b54bee66a2496a6cfa5c07365e573ecd597b218e3055b4bd8c8997275a02459",
47
+ "rl/feedback/feedback.py": "d28a12b111c81ce30d1fee701282e36f5b4c67b6bad30de4d62ac547b99bc7d3",
48
+ "configs/training.yaml": "eb0bae23a1c9a6e18cb83e2596b9197b7ed36cee55a546be66f1bfdf83220f4e",
49
+ "configs/algo/pqn_e5_hotpotqa.yaml": "f333f83f4b0b0b7337468970a9b95a9672556c85cdb6248c3f7f25755e20c2f8",
50
+ "configs/envs/hotpotqa.yaml": "1820a78023a04b133ec3da97f86927b5910bdc3389807825dc32a213d4a5156a",
51
+ "configs/feedback/defaults.yaml": "c14bfa71848eb6381438592a85bf7ed1edf2d8ef109dfed0d061ded601aa53ad",
52
+ "configs/logger/logging.yaml": "38dea1930fd7c69e5782db3d64dbf23c73811711d8f0f2637ad20973c7e0f501",
53
+ }
54
+ SOURCE_RECEIPT_SHA256 = "f722670a11ed666d95130a61f54d0556764e0fab6b780503226646079af2a57a"
55
+ TASKS = {"hotpotqa", "2WikiMultihopQA", "musique", "babilong"}
56
+
57
+
58
+ def _sha(path):
59
+ value = hashlib.sha256()
60
+ with Path(path).open("rb") as stream:
61
+ for block in iter(lambda: stream.read(1024 * 1024), b""):
62
+ value.update(block)
63
+ return value.hexdigest()
64
+
65
+
66
+ def _file(value, label):
67
+ path = Path(value).expanduser()
68
+ if path.is_symlink() or not path.is_file():
69
+ raise ValidationError(f"Q-RAG {label} requires a regular non-symlink file")
70
+ return path.resolve()
71
+
72
+
73
+ def _text(value):
74
+ return isinstance(value, str) and bool(value.strip()) and "\0" not in value
75
+
76
+
77
+ @dataclass(frozen=True, slots=True)
78
+ class QRAGFitControls:
79
+ steps_count: int = 50000
80
+ batch_size: int = 64
81
+ accumulate_grads: int = 2
82
+ environments: int = 4
83
+ learning_start: int = 200
84
+ eval_interval: int = 500
85
+ eval_episodes: int = 300
86
+ warmup_steps: int = 1000
87
+ seed: int = 17
88
+ device: str = "cuda:0"
89
+ task: str = "hotpotqa"
90
+ max_optimizer_steps: int = 50000
91
+ max_data_bytes: int = 64 * 1024 * 1024
92
+ min_free_output_bytes: int = 128 * 1024**3
93
+
94
+ def __post_init__(self):
95
+ for name in (
96
+ "steps_count",
97
+ "batch_size",
98
+ "accumulate_grads",
99
+ "environments",
100
+ "learning_start",
101
+ "eval_interval",
102
+ "eval_episodes",
103
+ "warmup_steps",
104
+ "seed",
105
+ "max_optimizer_steps",
106
+ "max_data_bytes",
107
+ "min_free_output_bytes",
108
+ ):
109
+ value = getattr(self, name)
110
+ lower = 0 if name in {"learning_start", "warmup_steps", "seed"} else 1
111
+ if type(value) is not int or value < lower:
112
+ raise ValidationError(f"Q-RAG fit {name} must be an integer in range")
113
+ if self.steps_count > self.max_optimizer_steps:
114
+ raise ValidationError("Q-RAG optimizer plan exceeds the declared step cap")
115
+ if self.task not in TASKS or self.device not in {"cpu", "cuda:0"}:
116
+ raise ValidationError(
117
+ "Q-RAG fit needs a supported native labeled task and one logical device"
118
+ )
119
+
120
+
121
+ def audit_qrag_training_data(train_file, dev_file, controls):
122
+ """Reject missing labels and cross-split leakage; do not invent support labels."""
123
+ queries, identities, audit = {}, {}, {}
124
+ paths = {"train": _file(train_file, "train data"), "dev": _file(dev_file, "dev data")}
125
+ for split, path in paths.items():
126
+ if path.stat().st_size > controls.max_data_bytes:
127
+ raise ValidationError("Q-RAG data exceeds the declared byte cap")
128
+ rows = json.loads(path.read_text(encoding="utf-8"))
129
+ if not isinstance(rows, list) or not rows:
130
+ raise ValidationError("Q-RAG native data must be a non-empty record array")
131
+ seen, qs = set(), set()
132
+ for row in rows:
133
+ if (
134
+ not isinstance(row, dict)
135
+ or not _text(row.get("question"))
136
+ or not _text(row.get("answer"))
137
+ ):
138
+ raise ValidationError("Q-RAG training requires native question and answer text")
139
+ task = controls.task
140
+ identifier = (
141
+ row.get("_id") if task in {"hotpotqa", "2WikiMultihopQA"} else row.get("id")
142
+ )
143
+ if task == "babilong":
144
+ identifier = row.get("id", content_hash(row["question"]))
145
+ if not _text(identifier) or identifier in seen:
146
+ raise ValidationError("Q-RAG native training IDs must be non-empty and unique")
147
+ seen.add(identifier)
148
+ query = " ".join(row["question"].casefold().split())
149
+ if query in qs:
150
+ raise ValidationError("Q-RAG duplicated training query")
151
+ qs.add(query)
152
+ if task in {"hotpotqa", "2WikiMultihopQA"}:
153
+ context, support = row.get("context"), row.get("supporting_facts")
154
+ if (
155
+ not isinstance(context, list)
156
+ or not context
157
+ or not isinstance(support, list)
158
+ or not support
159
+ ):
160
+ raise ValidationError(
161
+ "Q-RAG native training requires context and real support labels"
162
+ )
163
+ titles = {}
164
+ for item in context:
165
+ if (
166
+ not isinstance(item, list)
167
+ or len(item) != 2
168
+ or not _text(item[0])
169
+ or not isinstance(item[1], list)
170
+ or not item[1]
171
+ or not all(_text(x) for x in item[1])
172
+ or item[0] in titles
173
+ ):
174
+ raise ValidationError("Q-RAG native context titles/sentences are invalid")
175
+ titles[item[0]] = item[1]
176
+ if any(
177
+ not isinstance(s, list)
178
+ or len(s) != 2
179
+ or not _text(s[0])
180
+ or s[0] not in titles
181
+ or type(s[1]) is not int
182
+ or not 0 <= s[1] < len(titles[s[0]])
183
+ for s in support
184
+ ):
185
+ raise ValidationError(
186
+ "Q-RAG support label references unavailable source sentences"
187
+ )
188
+ elif task == "musique":
189
+ paragraphs, decomposition = row.get("paragraphs"), row.get("question_decomposition")
190
+ if (
191
+ not isinstance(paragraphs, list)
192
+ or not paragraphs
193
+ or not isinstance(decomposition, list)
194
+ or not decomposition
195
+ ):
196
+ raise ValidationError(
197
+ "Q-RAG MuSiQue requires native paragraphs and decomposition labels"
198
+ )
199
+ if any(
200
+ not isinstance(p, dict)
201
+ or not isinstance(p.get("title"), str)
202
+ or "\0" in p["title"]
203
+ or not _text(p.get("paragraph_text"))
204
+ for p in paragraphs
205
+ ):
206
+ raise ValidationError("Q-RAG native MuSiQue paragraph text is invalid")
207
+ if any(
208
+ not isinstance(d, dict)
209
+ or type(d.get("paragraph_support_idx")) is not int
210
+ or not 0 <= d["paragraph_support_idx"] < len(paragraphs)
211
+ for d in decomposition
212
+ ):
213
+ raise ValidationError("Q-RAG MuSiQue support label is invalid")
214
+ else:
215
+ chunks, labels = row.get("chunks"), row.get("references_idx")
216
+ if not isinstance(chunks, list) or not chunks or not all(_text(x) for x in chunks):
217
+ raise ValidationError("Q-RAG Babilong requires real native chunks")
218
+ if (
219
+ not isinstance(labels, list)
220
+ or not labels
221
+ or any(type(i) is not int or not 0 <= i < len(chunks) for i in labels)
222
+ ):
223
+ raise ValidationError("Q-RAG Babilong requires valid native reference indices")
224
+ queries[split], identities[split] = qs, seen
225
+ audit[split] = dict(
226
+ path=str(path),
227
+ sha256=_sha(path),
228
+ rows=len(rows),
229
+ query_set_sha256=content_hash(sorted(qs)),
230
+ )
231
+ if (
232
+ paths["train"] == paths["dev"]
233
+ or queries["train"] & queries["dev"]
234
+ or identities["train"] & identities["dev"]
235
+ ):
236
+ raise ValidationError("Q-RAG train/dev IDs and queries must be disjoint")
237
+ return dict(
238
+ files=audit,
239
+ query_overlap=False,
240
+ id_overlap=False,
241
+ task=controls.task,
242
+ native_updates=controls.steps_count * controls.accumulate_grads,
243
+ optimizer_steps=controls.steps_count,
244
+ transitions_per_rollout=math.ceil(controls.batch_size / controls.environments)
245
+ * controls.environments,
246
+ native_support_labels_required=True,
247
+ no_dummy_or_fabricated_reward_labels=True,
248
+ )
249
+
250
+
251
+ class _NativeRecords:
252
+ def __init__(self, path, task, expected_sha256):
253
+ if _sha(_file(path, "native dataset")) != expected_sha256:
254
+ raise ValidationError("Q-RAG native dataset differs from the fitted input plan")
255
+ self.rows = json.loads(Path(path).read_text(encoding="utf-8"))
256
+ if _sha(path) != expected_sha256:
257
+ raise ValidationError("Q-RAG native dataset changed while being loaded")
258
+ self.task = task
259
+
260
+ def name(self):
261
+ return self.task
262
+
263
+ def __len__(self):
264
+ return len(self.rows)
265
+
266
+ def __getitem__(self, index):
267
+ return self.rows[index]
268
+
269
+
270
+ class NativeQRAGDataset:
271
+ """Hydra data-format seam; the upstream adapter still projects every label."""
272
+
273
+ def __new__(cls, path, task, expected_sha256):
274
+ from envs.qa_dataset_adapter import QADatasetAdapter
275
+
276
+ return QADatasetAdapter(_NativeRecords(path, task, expected_sha256))
277
+
278
+
279
+ def validate_qrag_training_source(checkout):
280
+ supplied = Path(checkout).expanduser()
281
+ if supplied.is_symlink() or not supplied.is_dir():
282
+ raise ValidationError("Q-RAG training needs a regular mounted source directory")
283
+ root = supplied.resolve()
284
+ if (root / ".git").exists():
285
+
286
+ def git(*args):
287
+ return subprocess.check_output(
288
+ ["git", "-C", str(root), *args], text=True, timeout=30
289
+ ).strip()
290
+
291
+ if git("rev-parse", "HEAD") != QRAG_UPSTREAM_COMMIT or git(
292
+ "status", "--porcelain=v1", "--untracked-files=all"
293
+ ):
294
+ raise ExternalDependencyError("Q-RAG source checkout must be pinned and clean")
295
+ else:
296
+ receipt = _file(root / "agentinputlab-source-receipt.json", "source receipt")
297
+ if _sha(receipt) != SOURCE_RECEIPT_SHA256:
298
+ raise ExternalDependencyError("Q-RAG full native source receipt differs")
299
+ data = json.loads(receipt.read_text())
300
+ expected = {r["path"]: r for r in data["files"]}
301
+ actual = set()
302
+ for p in root.rglob("*"):
303
+ if "__pycache__" in p.parts or p.suffix == ".pyc":
304
+ continue
305
+ if p.is_symlink():
306
+ raise ExternalDependencyError("Q-RAG mounted source contains a symlink")
307
+ if p.is_file() and p.name != receipt.name:
308
+ relative = p.relative_to(root).as_posix()
309
+ actual.add(relative)
310
+ row = expected.get(relative)
311
+ if row is None or p.stat().st_size != row["size"] or _sha(p) != row["sha256"]:
312
+ raise ExternalDependencyError("Q-RAG full mounted source file differs")
313
+ if actual != set(expected):
314
+ raise ExternalDependencyError("Q-RAG source closure has missing files")
315
+ for name, expected in SOURCE_FILES.items():
316
+ p = _file(root / name, "native source")
317
+ if not p.is_relative_to(root) or _sha(p) != expected:
318
+ raise ExternalDependencyError(f"Q-RAG pinned native training source differs: {name}")
319
+ return root
320
+
321
+
322
+ def validate_qrag_initial_model(folder, manifest, expected_sha256):
323
+ from .llmlingua2_training import _closed_files
324
+
325
+ root, data = _closed_files(
326
+ folder, manifest, expected_sha256, "agentinputlab.qrag.initial_model.v1"
327
+ )
328
+ if not {"model.safetensors", "config.json", "tokenizer_config.json"} <= data["files"].keys():
329
+ raise ValidationError("Q-RAG initialization needs safe model and tokenizer files")
330
+ if any(n.endswith((".bin", ".pkl", ".pickle", ".py")) for n in data["files"]):
331
+ raise ValidationError("Q-RAG initial model contains an unsafe payload")
332
+ model = json.loads((root / "config.json").read_text())
333
+ tokenizer = json.loads((root / "tokenizer_config.json").read_text())
334
+ if (
335
+ model.get("model_type") != "xlm-roberta"
336
+ or model.get("hidden_size") != 1024
337
+ or model.get("num_hidden_layers") != 24
338
+ or model.get("auto_map")
339
+ or tokenizer.get("auto_map")
340
+ ):
341
+ raise ValidationError(
342
+ "native E5 PQN initialization needs the full standard 24-layer 1024-dim architecture"
343
+ )
344
+ return root, data
345
+
346
+
347
+ def _parameter_hashes(module):
348
+ return {
349
+ name: hashlib.sha256(
350
+ value.detach()
351
+ .cpu()
352
+ .contiguous()
353
+ .view(-1)
354
+ .view(dtype=__import__("torch").uint8)
355
+ .numpy()
356
+ .tobytes()
357
+ ).hexdigest()
358
+ for name, value in module.named_parameters()
359
+ }
360
+
361
+
362
+ def _counted_embedding_forward(original, observed):
363
+ """Observe direct ``.forward`` and ``__call__`` without replacing outputs."""
364
+
365
+ def forward(module, *args, **kwargs):
366
+ observed["embedding_forward_attempts"] += 1
367
+ response = original(module, *args, **kwargs)
368
+ observed["embedding_forward_responses"] += 1
369
+ return response
370
+
371
+ return forward
372
+
373
+
374
+ class _NativeCheckpointStore:
375
+ """Serialize each unchanged native update once; preserve best/last names."""
376
+
377
+ def __init__(self, root, native_save, events):
378
+ self.root, self.native_save, self.events = root.resolve(), native_save, events
379
+ self.snapshots = {}
380
+
381
+ def __call__(self, agent, checkpoint_path, verbose=False):
382
+ destination = Path(checkpoint_path).absolute()
383
+ if not destination.resolve().is_relative_to(self.root) or destination.is_symlink():
384
+ raise ValidationError("Q-RAG checkpoint output escapes its unique fit directory")
385
+ step = agent._update_step
386
+ created = step not in self.snapshots
387
+ if created:
388
+ cached = self.root / "native-checkpoints" / f"update-{step:08d}.pt"
389
+ if cached.exists():
390
+ raise ValidationError("Q-RAG native checkpoint snapshot already exists")
391
+ self.native_save(agent, str(cached), verbose=verbose)
392
+ self.snapshots[step] = cached
393
+ cached = self.snapshots[step]
394
+ destination.parent.mkdir(parents=True, exist_ok=True)
395
+ temporary = destination.with_name(destination.name + ".native-link")
396
+ os.link(cached, temporary)
397
+ os.replace(temporary, destination)
398
+ self.events.append(
399
+ dict(
400
+ native_update_step=step,
401
+ logical_path=str(destination),
402
+ immutable_snapshot_path=str(cached),
403
+ native_serialization_performed=created,
404
+ storage_only_hardlink_alias=True,
405
+ )
406
+ )
407
+
408
+
409
+ @dataclass(frozen=True, slots=True)
410
+ class QRAGTrainedPolicyArtifact:
411
+ root: Path
412
+ artifact_id: str
413
+
414
+ @property
415
+ def checkpoint(self):
416
+ return self.root / "native-final.pt"
417
+
418
+ def runtime(self, **kwargs):
419
+ from .qrag_inference import QRAGTrainedPolicyRuntime
420
+
421
+ return QRAGTrainedPolicyRuntime(self, **kwargs)
422
+
423
+ @classmethod
424
+ def load(cls, root):
425
+ p = Path(root).expanduser()
426
+ if p.is_symlink() or not p.is_dir():
427
+ raise ValidationError("Q-RAG trained artifact must be a regular directory")
428
+ metadata = json.loads(_file(p / "artifact.json", "artifact metadata").read_text())
429
+ identity = metadata.pop("artifact_id")
430
+ if identity != content_hash(metadata) or metadata.get("protocol") != PROTOCOL:
431
+ raise ValidationError("Q-RAG trained artifact identity differs")
432
+ for name in ("fit-plan.json", "fit-terminal.json", "native-final.pt"):
433
+ if _sha(_file(p / name, "artifact file")) != metadata["files"][name]:
434
+ raise ValidationError("Q-RAG trained artifact file differs")
435
+ terminal = json.loads((p / "fit-terminal.json").read_text())
436
+ if terminal.get("status") != "trained_candidate" or terminal.get("optimizer_steps", 0) < 1:
437
+ raise ValidationError("Q-RAG artifact is not a closed trained candidate")
438
+ return cls(p.resolve(), identity)
439
+
440
+
441
+ @contextmanager
442
+ def _observe_native(root, source, initial, audit, controls, observed):
443
+ import hydra
444
+ from omegaconf import OmegaConf
445
+ from rl.agents.pqn import PQN
446
+ from rl.bert_predictor import BertPredictor
447
+
448
+ compose, initialize, update, native_save = hydra.compose, PQN.__init__, PQN.update, PQN.save
449
+ embedding_forward = BertPredictor.forward
450
+ store = _NativeCheckpointStore(root, native_save, observed["checkpoint_storage_events"])
451
+
452
+ def composed(*args, **kwargs):
453
+ cfg = compose(*args, **kwargs)
454
+ cfg.algo.model.model_name = str(initial)
455
+ cfg.algo.model.revision = None
456
+ for section, split in (("env", "train"), ("test_env", "dev")):
457
+ cfg.envs[section].dataset = OmegaConf.create(
458
+ dict(
459
+ _target_="agentinputlab.recipes.qrag.NativeQRAGDataset",
460
+ path=audit["files"][split]["path"],
461
+ task=controls.task,
462
+ expected_sha256=audit["files"][split]["sha256"],
463
+ )
464
+ )
465
+ cfg.envs.task = controls.task
466
+ OmegaConf.resolve(cfg)
467
+ _save(root / "native-composed-config.json", OmegaConf.to_container(cfg, resolve=True))
468
+ return cfg
469
+
470
+ def initialized(agent, *args, **kwargs):
471
+ observed["native_policy_initialization_started"] = True
472
+ initialize(agent, *args, **kwargs)
473
+ observed["agent"] = agent
474
+ observed["native_policy_initialized"] = True
475
+ observed["initial_critic_parameter_sha256"] = _parameter_hashes(agent.critic)
476
+
477
+ def stepped(optimizer, args, kwargs):
478
+ observed["optimizer_steps"] += 1
479
+
480
+ observed["step_hook"] = agent.critic_optim.register_step_post_hook(stepped)
481
+
482
+ def updated(agent, state, action, next_state, values, reward, not_done):
483
+ value = update(agent, state, action, next_state, values, reward, not_done)
484
+ observed["updates"].append(
485
+ dict(
486
+ loss=float(value),
487
+ native_rewards=reward.detach().cpu().tolist(),
488
+ native_not_done=not_done.detach().cpu().tolist(),
489
+ native_update_step=agent._update_step,
490
+ current_learning_rates=[float(g["lr"]) for g in agent.critic_optim.param_groups],
491
+ alpha=float(agent.alpha),
492
+ )
493
+ )
494
+ return value
495
+
496
+ def saved(agent, checkpoint_path, verbose=False):
497
+ return store(agent, checkpoint_path, verbose=verbose)
498
+
499
+ hydra.compose, PQN.__init__, PQN.update, PQN.save = composed, initialized, updated, saved
500
+ BertPredictor.forward = _counted_embedding_forward(embedding_forward, observed)
501
+ try:
502
+ yield
503
+ finally:
504
+ hydra.compose, PQN.__init__, PQN.update, PQN.save = compose, initialize, update, native_save
505
+ BertPredictor.forward = embedding_forward
506
+ if "step_hook" in observed:
507
+ observed.pop("step_hook").remove()
508
+
509
+
510
+ class QRAGValuePolicyTraining:
511
+ release_id = RELEASE
512
+
513
+ def __init__(self, controls=None):
514
+ self.controls = (
515
+ QRAGFitControls(**controls)
516
+ if isinstance(controls, Mapping)
517
+ else controls or QRAGFitControls()
518
+ )
519
+ if not isinstance(self.controls, QRAGFitControls):
520
+ raise ValidationError("Q-RAG fit requires typed controls")
521
+
522
+ def fit(
523
+ self,
524
+ *,
525
+ checkout,
526
+ initial_checkpoint,
527
+ initial_manifest,
528
+ initial_manifest_sha256,
529
+ train_file,
530
+ dev_file,
531
+ output_root,
532
+ source_and_asset_acknowledged=False,
533
+ ):
534
+ if source_and_asset_acknowledged is not True:
535
+ raise ValidationError(
536
+ "Q-RAG fit requires explicit mounted-source/model/data acknowledgement"
537
+ )
538
+ c = self.controls
539
+ source = validate_qrag_training_source(checkout)
540
+ initial, _ = validate_qrag_initial_model(
541
+ initial_checkpoint, initial_manifest, initial_manifest_sha256
542
+ )
543
+ audit = audit_qrag_training_data(train_file, dev_file, c)
544
+ root = Path(output_root).expanduser().absolute()
545
+ if root.exists() or root.is_symlink():
546
+ raise ValidationError("Q-RAG fit output must be create-only; no consumed-attempt retry")
547
+ if root.resolve().is_relative_to(source) or root.resolve().is_relative_to(initial):
548
+ raise ValidationError("Q-RAG fit output must not mutate mounted source or assets")
549
+ parent = root.parent
550
+ while not parent.exists():
551
+ parent = parent.parent
552
+ if shutil.disk_usage(parent).free < c.min_free_output_bytes:
553
+ raise ValidationError(
554
+ "Q-RAG native checkpoints exceed the declared free-output-space guard"
555
+ )
556
+ versions = {
557
+ n: importlib.metadata.version(n)
558
+ for n in (
559
+ "torch",
560
+ "transformers",
561
+ "numpy",
562
+ "hydra-core",
563
+ "omegaconf",
564
+ "safetensors",
565
+ "tensorboard",
566
+ )
567
+ }
568
+ root.mkdir(parents=True)
569
+ argv = [
570
+ str(source / "train_q_rag.py"),
571
+ "envs=hotpotqa",
572
+ "algo=pqn_e5_hotpotqa",
573
+ f"seed={c.seed}",
574
+ f"device={c.device}",
575
+ f"steps_count={c.steps_count}",
576
+ f"batch_size={c.batch_size}",
577
+ f"accumulate_grads={c.accumulate_grads}",
578
+ f"envs_parallel={c.environments}",
579
+ f"learning_start={c.learning_start}",
580
+ f"eval_interval={c.eval_interval}",
581
+ f"eval_episodes={c.eval_episodes}",
582
+ f"algo.pqn.scheduler.warmup={c.warmup_steps}",
583
+ f"logger.log_dir={json.dumps(str(root / 'native'))}",
584
+ ]
585
+ plan = dict(
586
+ protocol=PROTOCOL,
587
+ release_id=RELEASE,
588
+ controls=asdict(c),
589
+ split_audit=audit,
590
+ source_commit=QRAG_UPSTREAM_COMMIT,
591
+ source_files=SOURCE_FILES,
592
+ initial_manifest_sha256=initial_manifest_sha256,
593
+ dependency_versions=versions,
594
+ native_argv=argv,
595
+ native_reward="GroundTruthFeedback",
596
+ dataset_transport_only=True,
597
+ hyperparameters_are_explicit_configuration_not_paper_parity=True,
598
+ source_load_unsafe_checkpoint_method_not_used=True,
599
+ checkpoint_storage="native serialization once per unchanged update; hardlinked best/last/final paths",
600
+ automatic_retry=False,
601
+ )
602
+ _save(root / "fit-plan.json", plan)
603
+ observed = dict(
604
+ optimizer_steps=0,
605
+ updates=[],
606
+ native_policy_initialization_started=False,
607
+ native_policy_initialized=False,
608
+ embedding_forward_attempts=0,
609
+ embedding_forward_responses=0,
610
+ checkpoint_storage_events=[],
611
+ )
612
+ start, cpu = time.monotonic(), time.process_time()
613
+ try:
614
+ with (
615
+ _LOCK,
616
+ _scope(root, c.seed),
617
+ _source_import(source),
618
+ _unused_vllm_import_compatibility(),
619
+ ):
620
+ import torch
621
+
622
+ with _observe_native(root, source, initial, audit, c, observed):
623
+ sys.argv[:] = argv
624
+ with (
625
+ (root / "native-training.log").open("x") as log,
626
+ redirect_stdout(log),
627
+ redirect_stderr(log),
628
+ ):
629
+ native = runpy.run_path(str(source / "train_q_rag.py"), run_name="__main__")
630
+ agent = native["agent"]
631
+ if (
632
+ observed["optimizer_steps"] != c.steps_count
633
+ or len(observed["updates"]) != audit["native_updates"]
634
+ ):
635
+ raise ValidationError(
636
+ "Q-RAG actual native updates differ from the bounded plan"
637
+ )
638
+ if not all(
639
+ math.isfinite(x["loss"]) and math.isfinite(x["alpha"])
640
+ for x in observed["updates"]
641
+ ):
642
+ raise ValidationError("Q-RAG native loss/temperature is non-finite")
643
+ final = _parameter_hashes(agent.critic)
644
+ changed = sum(
645
+ v != observed["initial_critic_parameter_sha256"][k] for k, v in final.items()
646
+ )
647
+ if not changed:
648
+ raise ValidationError("Q-RAG native fit produced no changed critic parameter")
649
+ # The context restored PQN.save; reuse the already immutable
650
+ # final native snapshot when evaluation saved this update.
651
+ store = _NativeCheckpointStore(
652
+ root, type(agent).save, observed["checkpoint_storage_events"]
653
+ )
654
+ for event in observed["checkpoint_storage_events"]:
655
+ store.snapshots[event["native_update_step"]] = Path(
656
+ event["immutable_snapshot_path"]
657
+ )
658
+ store(agent, str(root / "native-final.pt"))
659
+ _save(
660
+ root / "parameter-proof.json",
661
+ dict(
662
+ initial=observed["initial_critic_parameter_sha256"],
663
+ final=final,
664
+ changed_critic_parameter_tensors=changed,
665
+ new_neural_forwards=0,
666
+ ),
667
+ )
668
+ peak = torch.cuda.max_memory_allocated() if c.device == "cuda:0" else 0
669
+ terminal = dict(
670
+ status="trained_candidate",
671
+ optimizer_steps=observed["optimizer_steps"],
672
+ embedding_forward_attempts=observed["embedding_forward_attempts"],
673
+ embedding_forward_responses=observed["embedding_forward_responses"],
674
+ checkpoint_storage_events=observed["checkpoint_storage_events"],
675
+ updates=observed["updates"],
676
+ changed_critic_parameter_tensors=changed,
677
+ wall_seconds=time.monotonic() - start,
678
+ cpu_seconds=time.process_time() - cpu,
679
+ peak_cuda_allocated_bytes=peak,
680
+ new_generative_model_calls=0,
681
+ training_compute_is_separate_not_free=True,
682
+ official_native_ground_truth_feedback=True,
683
+ automatic_retry=False,
684
+ published_score_parity=False,
685
+ )
686
+ _save(root / "fit-terminal.json", terminal)
687
+ metadata = dict(
688
+ protocol=PROTOCOL,
689
+ release_id=RELEASE,
690
+ files={
691
+ n: _sha(root / n)
692
+ for n in ("fit-plan.json", "fit-terminal.json", "native-final.pt")
693
+ },
694
+ native_final_candidate_not_released_checkpoint=True,
695
+ paper_results_changed=False,
696
+ )
697
+ artifact_id = content_hash(metadata)
698
+ _save(root / "artifact.json", dict(metadata, artifact_id=artifact_id))
699
+ return QRAGTrainedPolicyArtifact(root.resolve(), artifact_id)
700
+ except Exception as exc:
701
+ if not (root / "fit-terminal.json").exists():
702
+ _save(
703
+ root / "fit-terminal.json",
704
+ dict(
705
+ status="failed_terminal",
706
+ optimizer_steps=observed["optimizer_steps"],
707
+ embedding_forward_attempts=observed["embedding_forward_attempts"],
708
+ embedding_forward_responses=observed["embedding_forward_responses"],
709
+ native_policy_initialization_started=observed[
710
+ "native_policy_initialization_started"
711
+ ],
712
+ native_policy_initialized=observed["native_policy_initialized"],
713
+ updates=observed["updates"],
714
+ error_type=type(exc).__name__,
715
+ error=str(exc),
716
+ wall_seconds=time.monotonic() - start,
717
+ cpu_seconds=time.process_time() - cpu,
718
+ automatic_retry=False,
719
+ ),
720
+ )
721
+ raise
722
+
723
+
724
+ __all__ = [
725
+ "QRAGFitControls",
726
+ "QRAGTrainedPolicyArtifact",
727
+ "QRAGValuePolicyTraining",
728
+ "audit_qrag_training_data",
729
+ ]