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,796 @@
1
+ """Native LLMLingua-2 word alignment, filtering and token-classifier training.
2
+
3
+ Only mounted teacher-compressed records are accepted: this recipe does not
4
+ silently buy GPT-4 calls, invent retained-word labels, or increase inference
5
+ budgets. Native label/fit scripts run in a dedicated, offline process. Original
6
+ Adam, loss, padding labels, clipping order and random 80/20 split are retained.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import hashlib
12
+ import importlib.metadata
13
+ import importlib.util
14
+ import inspect
15
+ import json
16
+ import math
17
+ import os
18
+ import random
19
+ import runpy
20
+ import sys
21
+ import time
22
+ from collections.abc import Mapping
23
+ from contextlib import contextmanager, redirect_stderr, redirect_stdout
24
+ from dataclasses import asdict, dataclass
25
+ from pathlib import Path
26
+ from types import ModuleType
27
+
28
+ from agentinputlab.artifacts import load_pinned_json_mapping
29
+ from agentinputlab.contracts import ExternalDependencyError, ValidationError
30
+ from agentinputlab.contracts.serialization import content_hash
31
+
32
+ from .recomp_extractive import _LOCK, _save, _scope
33
+
34
+ RELEASE = "training.llmlingua2.distillation"
35
+ PROTOCOL = "agentinputlab.llmlingua2.native_token_fit.v1"
36
+ COMMIT = "e0e9d99beb94098bbd924aa53c2c112eac41c758"
37
+ BASE = "experiments/llmlingua2/"
38
+ TRAIN_SCRIPT = BASE + "model_training/train_roberta.py"
39
+ SOURCE_BLOBS = {
40
+ TRAIN_SCRIPT: "a5ae084d4882a9c50de76b2db3428a17bf8de39c",
41
+ BASE + "model_training/utils.py": "87877f6b4d59b5e7fb926d1da512b8e299f75875",
42
+ BASE + "data_collection/label_word.py": "25e82a6171e29c1a2e93bb0f9e3a4e6ac5467ecd",
43
+ BASE + "data_collection/filter.py": "5b314177a87d4bd0f4eeaac72430b0c07940ed76",
44
+ }
45
+
46
+
47
+ def _sha(path):
48
+ digest = hashlib.sha256()
49
+ with Path(path).open("rb") as stream:
50
+ for chunk in iter(lambda: stream.read(1024 * 1024), b""):
51
+ digest.update(chunk)
52
+ return digest.hexdigest()
53
+
54
+
55
+ def _regular(path, label):
56
+ supplied = Path(path).expanduser()
57
+ if supplied.is_symlink() or not supplied.is_file():
58
+ raise ValidationError(f"LLMLingua-2 {label} requires a regular non-symlink file")
59
+ return supplied.resolve()
60
+
61
+
62
+ def _new_root(path, *protected):
63
+ root = Path(path).expanduser().absolute()
64
+ if root.exists() or root.is_symlink():
65
+ raise ValidationError("LLMLingua-2 output must be create-only; no automatic retry")
66
+ if any(root.resolve().is_relative_to(Path(p).resolve()) for p in protected):
67
+ raise ValidationError("LLMLingua-2 output must not mutate mounted source or assets")
68
+ root.mkdir(parents=True)
69
+ return root
70
+
71
+
72
+ def validate_llmlingua_training_checkout(checkout):
73
+ from workers.adaptive_rag.driver import _git, _safe_file
74
+
75
+ supplied = Path(checkout).expanduser()
76
+ if supplied.is_symlink() or not supplied.is_dir():
77
+ raise ValidationError("LLMLingua-2 requires a regular pinned source checkout")
78
+ root = supplied.resolve()
79
+ if _git(root, "rev-parse", "HEAD") != COMMIT or _git(
80
+ root, "status", "--porcelain=v1", "--untracked-files=all"
81
+ ):
82
+ raise ExternalDependencyError("LLMLingua-2 training source must be exact and clean")
83
+ evidence = {}
84
+ for name, expected in SOURCE_BLOBS.items():
85
+ raw = _safe_file(root, name).read_bytes()
86
+ blob = hashlib.sha1(b"blob " + str(len(raw)).encode() + b"\0" + raw).hexdigest()
87
+ if blob != expected or _git(root, "rev-parse", COMMIT + ":" + name) != expected:
88
+ raise ExternalDependencyError("LLMLingua-2 native script differs from pinned source")
89
+ evidence[name] = hashlib.sha256(raw).hexdigest()
90
+ return root, dict(commit=COMMIT, source_files=evidence)
91
+
92
+
93
+ def _closed_files(folder, manifest, digest, schema):
94
+ data = load_pinned_json_mapping(manifest, expected_sha256=digest)
95
+ root = Path(folder).expanduser()
96
+ if root.is_symlink() or not root.is_dir() or data.get("schema") != schema:
97
+ raise ValidationError("LLMLingua-2 mounted asset/manifest is invalid")
98
+ root = root.resolve()
99
+ files = data.get("files")
100
+ if not isinstance(files, dict) or not files:
101
+ raise ValidationError("LLMLingua-2 requires a complete mounted file closure")
102
+ actual = set()
103
+ for p in root.rglob("*"):
104
+ if p.is_symlink():
105
+ raise ValidationError("LLMLingua-2 asset symlinks are not permitted")
106
+ if p.is_file():
107
+ actual.add(p.relative_to(root).as_posix())
108
+ if actual != set(files):
109
+ raise ValidationError("LLMLingua-2 asset closure has extra or missing files")
110
+ for relative, expected in files.items():
111
+ path = Path(relative)
112
+ if path.is_absolute() or ".." in path.parts or path.as_posix() != relative:
113
+ raise ValidationError("LLMLingua-2 asset relative path is unsafe")
114
+ if _sha(_regular(root / path, "asset")) != expected:
115
+ raise ValidationError("LLMLingua-2 mounted asset hash differs")
116
+ return root, data
117
+
118
+
119
+ def validate_llmlingua_initial_checkpoint(root, manifest, digest):
120
+ folder, data = _closed_files(
121
+ root, manifest, digest, "agentinputlab.llmlingua2.token_checkpoint.v1"
122
+ )
123
+ if not {"model.safetensors", "config.json", "tokenizer.json"} <= data["files"].keys():
124
+ raise ValidationError("LLMLingua-2 requires a safe model and tokenizer closure")
125
+ if any(name.endswith((".bin", ".pkl", ".pickle", ".py")) for name in data["files"]):
126
+ raise ValidationError("LLMLingua-2 unsafe model payload is not accepted")
127
+ config = json.loads((folder / "config.json").read_text())
128
+ tokenizer = json.loads((folder / "tokenizer_config.json").read_text())
129
+ if not isinstance(config, dict) or not isinstance(tokenizer, dict):
130
+ raise ValidationError("LLMLingua-2 model/tokenizer configuration must be objects")
131
+ kind = config.get("model_type")
132
+ marker = {"bert": "bert-base-multilingual-cased", "xlm-roberta": "xlm-roberta-large"}
133
+ # Standard HF configs omit the default two-label mapping on serialization.
134
+ # A local strict from_pretrained below still rejects a mismatched tensor head.
135
+ labels = config.get("id2label")
136
+ label_count = len(labels) if isinstance(labels, dict) else config.get("num_labels", 2)
137
+ if (
138
+ kind not in marker
139
+ or config.get("auto_map")
140
+ or tokenizer.get("auto_map")
141
+ or (labels is not None and not isinstance(labels, dict))
142
+ or type(label_count) is not int
143
+ or label_count != 2
144
+ ):
145
+ raise ValidationError("LLMLingua-2 native path requires standard two-label BERT/XLM-R")
146
+ return folder, data
147
+
148
+
149
+ def _validate_nlp(root, manifest, digest):
150
+ folder, data = _closed_files(root, manifest, digest, "agentinputlab.llmlingua2.spacy_model.v1")
151
+ meta = json.loads((folder / "meta.json").read_text())
152
+ if meta.get("lang") != "en" or meta.get("name") != "core_web_sm":
153
+ raise ValidationError("LLMLingua-2 requires the declared English small spaCy model")
154
+ if any(name.endswith(".py") for name in data["files"]):
155
+ raise ValidationError("LLMLingua-2 NLP asset must not contain executable Python")
156
+ return folder, data
157
+
158
+
159
+ @contextmanager
160
+ def _nlp_mount(path):
161
+ import spacy
162
+
163
+ original = spacy.load
164
+
165
+ def load(name, *args, **kwargs):
166
+ if name != "en_core_web_sm" or args or kwargs:
167
+ raise ValidationError("LLMLingua-2 unexpected NLP load")
168
+ return original(str(path))
169
+
170
+ spacy.load = load
171
+ try:
172
+ yield
173
+ finally:
174
+ spacy.load = original
175
+
176
+
177
+ def label_llmlingua_compressed_records(
178
+ *,
179
+ checkout,
180
+ records_file,
181
+ data_provenance,
182
+ data_provenance_sha256,
183
+ nlp_root,
184
+ nlp_manifest,
185
+ nlp_manifest_sha256,
186
+ output_root,
187
+ window_size=400,
188
+ filter_native=True,
189
+ max_data_bytes=32 * 1024 * 1024,
190
+ source_and_asset_acknowledged=False,
191
+ ):
192
+ """Run native alignment/filter over caller-mounted real teacher outputs.
193
+
194
+ JSON only at the public boundary. The upstream PT intermediary is created
195
+ locally from those checked records and loaded with weights_only=True. The
196
+ native alignment loop and filtering percentiles are not replaced.
197
+ """
198
+ if source_and_asset_acknowledged is not True:
199
+ raise ValidationError("LLMLingua-2 requires explicit source/data acknowledgement")
200
+ if type(window_size) is not int or window_size < 1 or type(filter_native) is not bool:
201
+ raise ValidationError("LLMLingua-2 alignment controls are invalid")
202
+ if type(max_data_bytes) is not int or max_data_bytes < 1:
203
+ raise ValidationError("LLMLingua-2 data byte cap must be positive")
204
+ source, binding = validate_llmlingua_training_checkout(checkout)
205
+ path = _regular(records_file, "teacher records")
206
+ if path.suffix != ".json" or path.stat().st_size > max_data_bytes:
207
+ raise ValidationError("LLMLingua-2 teacher JSON exceeds byte cap")
208
+ records = json.loads(path.read_text())
209
+ if not isinstance(records, list) or not records:
210
+ raise ValidationError("LLMLingua-2 requires nonempty real compression records")
211
+ seen = set()
212
+ for row in records:
213
+ if (
214
+ not isinstance(row, dict)
215
+ or not all(
216
+ isinstance(row.get(k), list)
217
+ and row[k]
218
+ and all(isinstance(t, str) and t.strip() and "\0" not in t for t in row[k])
219
+ for k in ("prompt_list", "compressed_prompt_list")
220
+ )
221
+ or len(row["prompt_list"]) != len(row["compressed_prompt_list"])
222
+ ):
223
+ raise ValidationError("LLMLingua-2 requires paired nonempty original/teacher chunks")
224
+ for text in row["prompt_list"]:
225
+ identity = " ".join(text.casefold().split())
226
+ if identity in seen:
227
+ raise ValidationError("LLMLingua-2 duplicated original chunks are not permitted")
228
+ seen.add(identity)
229
+ provenance = load_pinned_json_mapping(data_provenance, expected_sha256=data_provenance_sha256)
230
+ if (
231
+ provenance.get("records_sha256") != _sha(path)
232
+ or not isinstance(provenance.get("teacher_revision"), str)
233
+ or not provenance["teacher_revision"].strip()
234
+ ):
235
+ raise ValidationError("LLMLingua-2 data provenance must bind real teacher outputs")
236
+ nlp, _ = _validate_nlp(nlp_root, nlp_manifest, nlp_manifest_sha256)
237
+ root = _new_root(output_root, source, nlp, path.parent)
238
+ import torch
239
+
240
+ original_load, original_save = torch.load, torch.save
241
+ previous_datasets = sys.modules.get("datasets")
242
+ mounted = ModuleType("datasets")
243
+
244
+ def load_dataset(name, *, split):
245
+ if name != str(path) or split != "train":
246
+ raise ValidationError("LLMLingua-2 unexpected native dataset access")
247
+ return records
248
+
249
+ mounted.load_dataset = load_dataset
250
+
251
+ def save_plain(value, target, *args, **kwargs):
252
+ # defaultdict -> ordinary dict changes serialization only, not values.
253
+ return original_save(
254
+ dict(value) if isinstance(value, Mapping) else value, target, *args, **kwargs
255
+ )
256
+
257
+ def load_safe(target, *args, **kwargs):
258
+ if args or kwargs or Path(target).resolve() != root / "alignment.pt":
259
+ raise ValidationError("LLMLingua-2 unexpected native PT input")
260
+ return original_load(target, map_location="cpu", weights_only=True)
261
+
262
+ plan = dict(
263
+ source=binding,
264
+ records_sha256=_sha(path),
265
+ data_provenance=provenance,
266
+ source_chunks=len(seen),
267
+ window_size=window_size,
268
+ native_filter=filter_native,
269
+ new_teacher_calls=0,
270
+ nlp_manifest_sha256=nlp_manifest_sha256,
271
+ )
272
+ _save(root / "label-plan.json", plan)
273
+ try:
274
+ with _LOCK, _scope(root, 17), _nlp_mount(nlp), (root / "native.log").open("x") as log:
275
+ sys.modules["datasets"] = mounted
276
+ torch.load, torch.save = load_safe, save_plain
277
+ with redirect_stdout(log), redirect_stderr(log):
278
+ sys.argv = [
279
+ str(source / (BASE + "data_collection/label_word.py")),
280
+ "--load_prompt_from",
281
+ str(path),
282
+ "--save_path",
283
+ str(root / "alignment.json"),
284
+ "--window_size",
285
+ str(window_size),
286
+ ]
287
+ runpy.run_path(sys.argv[0], run_name="__main__")
288
+ if filter_native:
289
+ sys.argv = [
290
+ str(source / (BASE + "data_collection/filter.py")),
291
+ "--load_path",
292
+ str(root / "alignment.pt"),
293
+ "--save_path",
294
+ str(root / "filtered.pt"),
295
+ ]
296
+ runpy.run_path(sys.argv[0], run_name="__main__")
297
+ selected = original_load(
298
+ root / ("filtered.pt" if filter_native else "alignment.pt"),
299
+ map_location="cpu",
300
+ weights_only=True,
301
+ )
302
+ _save(root / "training-data.json", selected)
303
+ except Exception as exc:
304
+ _save(
305
+ root / "label-failed.json",
306
+ dict(
307
+ error_type=type(exc).__name__,
308
+ error=str(exc),
309
+ new_teacher_calls=0,
310
+ automatic_retry=False,
311
+ ),
312
+ )
313
+ raise
314
+ finally:
315
+ torch.load, torch.save = original_load, original_save
316
+ if previous_datasets is None:
317
+ sys.modules.pop("datasets", None)
318
+ else:
319
+ sys.modules["datasets"] = previous_datasets
320
+ _save(
321
+ root / "label-terminal.json",
322
+ dict(
323
+ rows=len(selected["origin"]),
324
+ new_teacher_calls=0,
325
+ native_alignment=True,
326
+ native_filter=filter_native,
327
+ output_sha256=_sha(root / "training-data.json"),
328
+ plan_sha256=_sha(root / "label-plan.json"),
329
+ ),
330
+ )
331
+ return root / "training-data.json"
332
+
333
+
334
+ @dataclass(frozen=True, slots=True)
335
+ class LLMLingua2FitControls:
336
+ epochs: int = 10
337
+ batch_size: int = 10
338
+ learning_rate: float = 1e-5
339
+ seed: int = 17
340
+ max_optimizer_steps: int = 10000
341
+ max_data_bytes: int = 32 * 1024 * 1024
342
+ device: str = "cpu"
343
+
344
+ def __post_init__(self):
345
+ for name in ("epochs", "batch_size", "seed", "max_optimizer_steps", "max_data_bytes"):
346
+ value = getattr(self, name)
347
+ if type(value) is not int or value < (0 if name == "seed" else 1):
348
+ raise ValidationError(f"LLMLingua-2 {name} must be an integer in range")
349
+ if (
350
+ type(self.learning_rate) not in (int, float)
351
+ or not math.isfinite(self.learning_rate)
352
+ or self.learning_rate <= 0
353
+ or self.device not in {"cpu", "cuda"}
354
+ ):
355
+ raise ValidationError("LLMLingua-2 learning rate or device is invalid")
356
+
357
+
358
+ def audit_llmlingua_training_data(path, controls):
359
+ path = _regular(path, "training JSON")
360
+ if path.suffix != ".json" or path.stat().st_size > controls.max_data_bytes:
361
+ raise ValidationError("LLMLingua-2 native JSON exceeds byte cap")
362
+ data = json.loads(path.read_text())
363
+ if (
364
+ not isinstance(data, dict)
365
+ or not isinstance(data.get("origin"), list)
366
+ or not isinstance(data.get("labels"), list)
367
+ or len(data["origin"]) != len(data["labels"])
368
+ or len(data["origin"]) < 5
369
+ ):
370
+ raise ValidationError("LLMLingua-2 requires at least five paired original/label rows")
371
+ keys = []
372
+ for text, labels in zip(data["origin"], data["labels"], strict=True):
373
+ if (
374
+ not isinstance(text, str)
375
+ or not text.strip()
376
+ or "\0" in text
377
+ or not isinstance(labels, list)
378
+ or not labels
379
+ or any(type(value) is not bool for value in labels)
380
+ ):
381
+ raise ValidationError("LLMLingua-2 labels must be native retained-word booleans")
382
+ keys.append(" ".join(text.casefold().split()))
383
+ if len(set(keys)) != len(keys):
384
+ raise ValidationError("LLMLingua-2 split cannot include duplicated original text")
385
+ order = list(range(len(keys)))
386
+ random.Random(controls.seed).shuffle(order)
387
+ cut = int(len(keys) * 0.8)
388
+ planned = math.ceil(cut / controls.batch_size) * controls.epochs
389
+ if planned > controls.max_optimizer_steps:
390
+ raise ValidationError("LLMLingua-2 native optimizer plan exceeds step cap; not truncated")
391
+ return data, dict(
392
+ path=str(path),
393
+ sha256=_sha(path),
394
+ rows=len(keys),
395
+ native_train_indices=order[:cut],
396
+ native_validation_indices=order[cut:],
397
+ planned_optimizer_steps=planned,
398
+ split_policy="native_random_shuffle_80_20",
399
+ source_query_overlap=False,
400
+ token_label_alignment_checked_by_native_dataset=True,
401
+ )
402
+
403
+
404
+ def _tensor_hash(tensor, torch):
405
+ raw = tensor.detach().cpu().contiguous().view(torch.uint8).numpy().tobytes()
406
+ return hashlib.sha256(raw).hexdigest()
407
+
408
+
409
+ @dataclass(frozen=True, slots=True)
410
+ class LLMLingua2TrainedArtifact:
411
+ root: Path
412
+ artifact_id: str
413
+
414
+ @property
415
+ def checkpoint(self):
416
+ return self.root / "checkpoint"
417
+
418
+ def intervention(self, *, config=None, device_map="cpu"):
419
+ """Deploy this fitted candidate without impersonating a released model."""
420
+ from .llmlingua2_inference import LLMLingua2TrainedCompressor
421
+
422
+ return LLMLingua2TrainedCompressor(self, config=config, device_map=device_map)
423
+
424
+ @classmethod
425
+ def load(cls, root):
426
+ supplied = Path(root).expanduser()
427
+ if supplied.is_symlink() or not supplied.is_dir():
428
+ raise ValidationError("LLMLingua-2 trained artifact directory is invalid")
429
+ folder = supplied.resolve()
430
+ metadata = json.loads(_regular(folder / "artifact.json", "artifact").read_text())
431
+ identity = metadata.pop("artifact_id", None)
432
+ if (
433
+ identity != content_hash(metadata)
434
+ or metadata.get("protocol") != PROTOCOL
435
+ or metadata.get("release_id") != RELEASE
436
+ ):
437
+ raise ValidationError("LLMLingua-2 trained artifact identity differs")
438
+ for name in ("fit-plan.json", "fit-terminal.json"):
439
+ if _sha(_regular(folder / name, name)) != metadata.get(name + "_sha256"):
440
+ raise ValidationError("LLMLingua-2 trained evidence hash differs")
441
+ terminal = json.loads((folder / "fit-terminal.json").read_text())
442
+ if (
443
+ terminal.get("status") != "trained_candidate"
444
+ or terminal.get("optimizer_steps", 0) < 1
445
+ or terminal.get("changed_parameter_tensors", 0) < 1
446
+ ):
447
+ raise ValidationError("LLMLingua-2 native training did not complete")
448
+ validate_llmlingua_initial_checkpoint(
449
+ folder / "checkpoint",
450
+ folder / "checkpoint-manifest.json",
451
+ metadata["checkpoint_manifest_sha256"],
452
+ )
453
+ native_files = metadata.get("native_files")
454
+ native_name = metadata.get("native_directory")
455
+ if (
456
+ not isinstance(native_name, str)
457
+ or Path(native_name).name != native_name
458
+ or native_name
459
+ not in {"native-bert-base-multilingual-cased", "native-xlm-roberta-large"}
460
+ or not isinstance(native_files, dict)
461
+ ):
462
+ raise ValidationError("LLMLingua-2 native output evidence is incomplete")
463
+ native = folder / native_name
464
+ if (
465
+ native.is_symlink()
466
+ or not native.is_dir()
467
+ or any(p.is_symlink() for p in native.rglob("*"))
468
+ ):
469
+ raise ValidationError("LLMLingua-2 native output closure is invalid")
470
+ if {p.relative_to(native).as_posix() for p in native.rglob("*") if p.is_file()} != set(
471
+ native_files
472
+ ):
473
+ raise ValidationError("LLMLingua-2 native output files differ")
474
+ for name, digest in native_files.items():
475
+ if (
476
+ Path(name).is_absolute()
477
+ or ".." in Path(name).parts
478
+ or Path(name).as_posix() != name
479
+ ):
480
+ raise ValidationError("LLMLingua-2 native path is invalid")
481
+ if _sha(_regular(native / name, "native output")) != digest:
482
+ raise ValidationError("LLMLingua-2 native output hash differs")
483
+ return cls(folder, identity)
484
+
485
+
486
+ class LLMLingua2DistillationTraining:
487
+ release_id = RELEASE
488
+
489
+ def __init__(self, controls=None):
490
+ self.controls = (
491
+ LLMLingua2FitControls(**controls)
492
+ if isinstance(controls, Mapping)
493
+ else (controls or LLMLingua2FitControls())
494
+ )
495
+ if not isinstance(self.controls, LLMLingua2FitControls):
496
+ raise ValidationError("LLMLingua-2 fit requires typed controls")
497
+
498
+ def fit(
499
+ self,
500
+ *,
501
+ checkout,
502
+ initial_checkpoint,
503
+ initial_checkpoint_manifest,
504
+ initial_manifest_sha256,
505
+ training_file,
506
+ data_provenance,
507
+ data_provenance_sha256,
508
+ nlp_root,
509
+ nlp_manifest,
510
+ nlp_manifest_sha256,
511
+ output_root,
512
+ source_and_asset_acknowledged=False,
513
+ ):
514
+ if source_and_asset_acknowledged is not True:
515
+ raise ValidationError(
516
+ "LLMLingua-2 fit requires explicit source/model/data acknowledgement"
517
+ )
518
+ source, binding = validate_llmlingua_training_checkout(checkout)
519
+ initial, _ = validate_llmlingua_initial_checkpoint(
520
+ initial_checkpoint, initial_checkpoint_manifest, initial_manifest_sha256
521
+ )
522
+ model_kind = json.loads((initial / "config.json").read_text())["model_type"]
523
+ native_marker = {
524
+ "bert": "bert-base-multilingual-cased",
525
+ "xlm-roberta": "xlm-roberta-large",
526
+ }[model_kind]
527
+ if native_marker not in str(initial):
528
+ raise ValidationError(
529
+ "LLMLingua-2 initial path must retain native model-family substring"
530
+ )
531
+ nlp, _ = _validate_nlp(nlp_root, nlp_manifest, nlp_manifest_sha256)
532
+ c = self.controls
533
+ data, audit = audit_llmlingua_training_data(training_file, c)
534
+ provenance = load_pinned_json_mapping(
535
+ data_provenance, expected_sha256=data_provenance_sha256
536
+ )
537
+ if (
538
+ provenance.get("training_sha256") != audit["sha256"]
539
+ or not isinstance(provenance.get("teacher_revision"), str)
540
+ or not provenance["teacher_revision"].strip()
541
+ ):
542
+ raise ValidationError("LLMLingua-2 provenance must bind real teacher labels")
543
+ import torch
544
+ import transformers
545
+
546
+ if (
547
+ (c.device == "cpu" and torch.cuda.is_available())
548
+ or (
549
+ c.device == "cuda"
550
+ and (not torch.cuda.is_available() or torch.cuda.device_count() != 1)
551
+ )
552
+ or os.environ.get("WORLD_SIZE", "1") != "1"
553
+ ):
554
+ raise ValidationError(
555
+ "LLMLingua-2 fit requires one process and declared CUDA visibility"
556
+ )
557
+ root = _new_root(output_root, source, initial, nlp, Path(audit["path"]).parent)
558
+ # Keep native model-family substring branch without rewriting source.
559
+ checkpoint_name = (
560
+ "bert-base-multilingual-cased"
561
+ if "bert-base-multilingual-cased" in str(initial)
562
+ else "xlm-roberta-large"
563
+ )
564
+ checkpoint = root / "checkpoint"
565
+ native = root / ("native-" + checkpoint_name)
566
+ native.mkdir()
567
+ command = [
568
+ str(source / TRAIN_SCRIPT),
569
+ "--model_name",
570
+ str(initial),
571
+ "--data_path",
572
+ audit["path"],
573
+ "--save_path",
574
+ str(native),
575
+ "--num_epoch",
576
+ str(c.epochs),
577
+ "--batch_size",
578
+ str(c.batch_size),
579
+ "--lr",
580
+ str(c.learning_rate),
581
+ ]
582
+ plan = dict(
583
+ protocol=PROTOCOL,
584
+ release_id=RELEASE,
585
+ source=binding,
586
+ controls=asdict(c),
587
+ data_audit=audit,
588
+ data_provenance=provenance,
589
+ initial_manifest_sha256=initial_manifest_sha256,
590
+ nlp_manifest_sha256=nlp_manifest_sha256,
591
+ native_argv=command,
592
+ dependencies={
593
+ name: importlib.metadata.version(name)
594
+ for name in (
595
+ "torch",
596
+ "transformers",
597
+ "spacy",
598
+ "numpy",
599
+ "scikit-learn",
600
+ "tensorboard",
601
+ "safetensors",
602
+ )
603
+ },
604
+ label_type_argument_unused_by_native=True,
605
+ native_pad_labels_and_clip_order_preserved=True,
606
+ new_teacher_calls=0,
607
+ automatic_retry=False,
608
+ paper_result_parity_claimed=False,
609
+ )
610
+ _save(root / "fit-plan.json", plan)
611
+ observed = dict(optimizer_steps=0, loss_events=[])
612
+ original_load, original_step = torch.load, torch.optim.Adam.step
613
+ original_model_loader = transformers.AutoModelForTokenClassification.from_pretrained
614
+ original_tokenizer_loader = transformers.AutoTokenizer.from_pretrained
615
+ original_model_descriptor = inspect.getattr_static(
616
+ transformers.AutoModelForTokenClassification, "from_pretrained"
617
+ )
618
+ original_tokenizer_descriptor = inspect.getattr_static(
619
+ transformers.AutoTokenizer, "from_pretrained"
620
+ )
621
+ previous_utils = sys.modules.get("utils")
622
+ spec = importlib.util.spec_from_file_location(
623
+ "utils", source / (BASE + "model_training/utils.py")
624
+ )
625
+ utils = importlib.util.module_from_spec(spec)
626
+
627
+ def load_data(path, *args, **kwargs):
628
+ if args or kwargs or str(path) != audit["path"]:
629
+ raise ValidationError("LLMLingua-2 unexpected native serialized input")
630
+ return data
631
+
632
+ def load_model(name, *args, **kwargs):
633
+ if (
634
+ name != str(initial)
635
+ or args
636
+ or kwargs != dict(num_labels=2, ignore_mismatched_sizes=True)
637
+ ):
638
+ raise ValidationError("LLMLingua-2 unexpected native model load")
639
+ # No random replacement head or remote code: initial two-label shape
640
+ # must already match. The observed model/loss/train loop is native.
641
+ model, loading = original_model_loader(
642
+ name,
643
+ num_labels=2,
644
+ ignore_mismatched_sizes=False,
645
+ local_files_only=True,
646
+ trust_remote_code=False,
647
+ use_safetensors=True,
648
+ output_loading_info=True,
649
+ )
650
+ if any(
651
+ loading.get(key)
652
+ for key in ("missing_keys", "unexpected_keys", "mismatched_keys", "error_msgs")
653
+ ):
654
+ raise ValidationError(
655
+ "LLMLingua-2 initialization has missing or incompatible weights"
656
+ )
657
+ observed["model"] = model
658
+ observed["initial_tensors"] = {
659
+ k: _tensor_hash(v, torch) for k, v in model.state_dict().items()
660
+ }
661
+ forward = model.forward
662
+
663
+ def forwarding(*args, **kwargs):
664
+ result = forward(*args, **kwargs)
665
+ if result.loss is not None:
666
+ value = float(result.loss.detach().cpu())
667
+ if not math.isfinite(value):
668
+ raise ValidationError("LLMLingua-2 native loss is not finite")
669
+ observed["loss_events"].append(
670
+ dict(
671
+ loss=value,
672
+ training=bool(model.training),
673
+ examples=int(kwargs["labels"].shape[0]),
674
+ native_label_slots=int(kwargs["labels"].numel()),
675
+ )
676
+ )
677
+ return result
678
+
679
+ model.forward = forwarding
680
+ return model
681
+
682
+ def load_tokenizer(name, *args, **kwargs):
683
+ if name != str(initial) or args or kwargs:
684
+ raise ValidationError("LLMLingua-2 unexpected native tokenizer load")
685
+ return original_tokenizer_loader(name, local_files_only=True, trust_remote_code=False)
686
+
687
+ def step(optimizer, *args, **kwargs):
688
+ if observed["optimizer_steps"] >= audit["planned_optimizer_steps"]:
689
+ raise ValidationError("LLMLingua-2 native optimizer exceeded declared plan")
690
+ result = original_step(optimizer, *args, **kwargs)
691
+ observed["optimizer_steps"] += 1
692
+ return result
693
+
694
+ started, cpu = time.monotonic(), time.process_time()
695
+ try:
696
+ with (
697
+ _LOCK,
698
+ _scope(root, c.seed),
699
+ _nlp_mount(nlp),
700
+ (root / "native.log").open("x") as log,
701
+ ):
702
+ spec.loader.exec_module(utils)
703
+ sys.modules["utils"] = utils
704
+ torch.load, torch.optim.Adam.step = load_data, step
705
+ transformers.AutoModelForTokenClassification.from_pretrained = load_model
706
+ transformers.AutoTokenizer.from_pretrained = load_tokenizer
707
+ sys.argv = command
708
+ with redirect_stdout(log), redirect_stderr(log):
709
+ namespace = runpy.run_path(str(source / TRAIN_SCRIPT), run_name="__main__")
710
+ namespace["writer"].close()
711
+ if observed["optimizer_steps"] != audit["planned_optimizer_steps"]:
712
+ raise ValidationError("LLMLingua-2 native optimizer plan was not completed")
713
+ expected_train = [data["origin"][i] for i in audit["native_train_indices"]]
714
+ expected_val = [data["origin"][i] for i in audit["native_validation_indices"]]
715
+ if (
716
+ namespace["train_text"] != expected_train
717
+ or namespace["val_text"] != expected_val
718
+ ):
719
+ raise ValidationError(
720
+ "LLMLingua-2 actual native split differs from declared seeded split"
721
+ )
722
+ model = observed["model"]
723
+ actual = {k: _tensor_hash(v, torch) for k, v in model.state_dict().items()}
724
+ if set(actual) != set(observed["initial_tensors"]):
725
+ raise ValidationError(
726
+ "LLMLingua-2 parameter namespace changed during native fit"
727
+ )
728
+ changed = sum(actual[k] != observed["initial_tensors"][k] for k in actual)
729
+ if not changed:
730
+ raise ValidationError("LLMLingua-2 native fit changed no parameter tensors")
731
+ model.save_pretrained(checkpoint, safe_serialization=True)
732
+ namespace["tokenizer"].save_pretrained(checkpoint)
733
+ # The native source selects best only if validation accuracy>0;
734
+ # final export remains explicitly a candidate, not invented best.
735
+ terminal = dict(
736
+ status="trained_candidate",
737
+ optimizer_steps=observed["optimizer_steps"],
738
+ changed_parameter_tensors=changed,
739
+ loss_events=observed["loss_events"],
740
+ native_validation_accuracy=float(namespace["acc"]),
741
+ native_best_accuracy=float(namespace["best_acc"]),
742
+ native_best_checkpoint_selected=(native / "state_dict.pth").exists(),
743
+ checkpoint_selection="explicit_final_candidate_not_substituted_native_best",
744
+ new_teacher_calls=0,
745
+ wall_seconds=time.monotonic() - started,
746
+ cpu_seconds=time.process_time() - cpu,
747
+ peak_cuda_allocated_bytes=int(torch.cuda.max_memory_allocated())
748
+ if c.device == "cuda"
749
+ else 0,
750
+ )
751
+ _save(
752
+ root / "checkpoint-manifest.json",
753
+ dict(
754
+ schema="agentinputlab.llmlingua2.token_checkpoint.v1",
755
+ files={p.name: _sha(p) for p in checkpoint.iterdir() if p.is_file()},
756
+ ),
757
+ )
758
+ _save(root / "fit-terminal.json", terminal)
759
+ metadata = dict(
760
+ protocol=PROTOCOL,
761
+ release_id=RELEASE,
762
+ **{
763
+ name + "_sha256": _sha(root / name)
764
+ for name in ("fit-plan.json", "fit-terminal.json")
765
+ },
766
+ checkpoint_manifest_sha256=_sha(root / "checkpoint-manifest.json"),
767
+ native_directory=native.name,
768
+ native_files={
769
+ p.relative_to(native).as_posix(): _sha(p)
770
+ for p in native.rglob("*")
771
+ if p.is_file()
772
+ },
773
+ )
774
+ _save(root / "artifact.json", dict(metadata, artifact_id=content_hash(metadata)))
775
+ except Exception as exc:
776
+ _save(
777
+ root / "fit-failed.json",
778
+ dict(
779
+ error_type=type(exc).__name__,
780
+ error=str(exc),
781
+ consumed_optimizer_steps=observed["optimizer_steps"],
782
+ automatic_retry=False,
783
+ wall_seconds=time.monotonic() - started,
784
+ loss_events=observed["loss_events"],
785
+ ),
786
+ )
787
+ raise
788
+ finally:
789
+ torch.load, torch.optim.Adam.step = original_load, original_step
790
+ transformers.AutoModelForTokenClassification.from_pretrained = original_model_descriptor
791
+ transformers.AutoTokenizer.from_pretrained = original_tokenizer_descriptor
792
+ if previous_utils is None:
793
+ sys.modules.pop("utils", None)
794
+ else:
795
+ sys.modules["utils"] = previous_utils
796
+ return LLMLingua2TrainedArtifact.load(root)