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,360 @@
1
+ """Live, context-bound callbacks for the isolated pinned LLMCompiler worker.
2
+
3
+ The worker process has no provider credential or request-selected network tool.
4
+ A per-call authenticated loopback endpoint exposes only the already bound model
5
+ and read-only ToolConnector. The ordinary supervisor still bounds its process
6
+ and pipes. Caller backends/tools remain responsible for their own I/O timeouts.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import hmac
11
+ import json
12
+ import math
13
+ import os
14
+ import secrets
15
+ import threading
16
+ from collections.abc import Mapping
17
+ from contextlib import suppress
18
+ from dataclasses import dataclass, field
19
+ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
20
+ from pathlib import Path
21
+ from typing import Any
22
+
23
+ from agentinputlab.backends import GenerationRequest, LLMBackend
24
+ from agentinputlab.connectors.tools import ToolCall, ToolConnector
25
+ from agentinputlab.connectors.tools.openapi import validate_json_value
26
+ from agentinputlab.contracts import ExecutionBudget, ValidationError
27
+ from agentinputlab.contracts.serialization import content_hash, to_jsonable
28
+
29
+ from .base import JsonLineSubprocessWorker
30
+ from .supervisor import SupervisedWorkerError
31
+
32
+ _KEY_ENV = "AGENTINPUTLAB_LLMC_CALLBACK_KEY"
33
+
34
+
35
+ def _strict_json(raw):
36
+ def unique(pairs):
37
+ result = {}
38
+ for key, value in pairs:
39
+ if key in result:
40
+ raise ValueError("duplicate JSON key")
41
+ result[key] = value
42
+ return result
43
+ return json.loads(raw, object_pairs_hook=unique,
44
+ parse_constant=lambda value: (_ for _ in ()).throw(ValueError("nonfinite JSON")))
45
+
46
+
47
+ class _Callbacks:
48
+ def __init__(self, owner, request):
49
+ self.owner, self.request = owner, request
50
+ budget = request["payload"].get("execution_budget")
51
+ if not isinstance(budget, Mapping):
52
+ raise ValidationError("live LLMCompiler requires the state execution_budget")
53
+ self.budget = ExecutionBudget(**budget)
54
+ if self.budget.max_context_tokens is not None or self.budget.max_cost_usd is not None:
55
+ raise ValidationError("live callbacks do not yet attest pre-call input-token or priced-cost ceilings")
56
+ self.specs = {s.name: s for s in owner.tools.list_tools()}
57
+ self.argument_order = {name: tuple(keys) for name, keys in owner.argument_order.items()}
58
+ if to_jsonable(owner.argument_order) != request["payload"].get("tool_argument_order", {}):
59
+ raise ValidationError("tool positional argument order differs from the request")
60
+ if not self.specs or any(not s.read_only or s.network for s in self.specs.values()):
61
+ raise ValidationError("live LLMCompiler tools must be read-only and no-network")
62
+ if to_jsonable(tuple(self.specs.values())) != request["payload"]["tool_specs"]:
63
+ raise ValidationError("live tool schemas differ from the request")
64
+ deps = request["dependency_fingerprints"]
65
+ if (content_hash(deps["backend"]) != content_hash(owner.backend.fingerprint())
66
+ or content_hash(deps["tools"]) != content_hash(owner.tools.fingerprint())):
67
+ raise ValidationError("live dependencies differ from the request")
68
+ self.lock = threading.RLock()
69
+ self.model_calls = self.tool_calls = self.input_tokens = self.output_tokens = 0
70
+ self.reserved_output = self.inflight = self.unknown_usage_calls = 0
71
+ self.cost = 0.0
72
+ self.unpriced = 0
73
+ self.closed = self.fatal = False
74
+ self.attested = False
75
+ self.expected_attestation = owner.fingerprint()["worker_attestation"]
76
+ self.seen = set()
77
+ self.events = []
78
+
79
+ def usage(self):
80
+ with self.lock:
81
+ result = {"model_calls": self.model_calls, "tool_calls": self.tool_calls,
82
+ "retrieval_calls": 0, "input_tokens": self.input_tokens,
83
+ "output_tokens": self.output_tokens,
84
+ "unpriced_model_calls": self.model_calls if self.unpriced else 0}
85
+ if self.unpriced == 0:
86
+ result["cost_usd"] = self.cost
87
+ return result
88
+
89
+ def dispatch(self, value):
90
+ if (not isinstance(value, dict) or set(value) != {"request_id", "call_id", "kind", "payload"}
91
+ or value["request_id"] != self.request["request_id"]
92
+ or not isinstance(value["call_id"], str) or not value["call_id"]):
93
+ raise ValueError("invalid callback envelope")
94
+ with self.lock:
95
+ if self.closed or self.fatal or value["call_id"] in self.seen:
96
+ raise ValueError("closed, failed, or duplicate callback")
97
+ self.seen.add(value["call_id"])
98
+ if value["kind"] == "attest":
99
+ if self.attested or value["payload"] != self.expected_attestation:
100
+ raise ValueError("worker source/version attestation differs")
101
+ self.attested = True
102
+ self.events.append({"kind": "attestation", "matched": True})
103
+ return {"attested": True}
104
+ if not self.attested:
105
+ raise ValueError("native worker must attest before model/tool dispatch")
106
+ if value["kind"] == "model":
107
+ return self.model(value["payload"])
108
+ if value["kind"] == "tool":
109
+ return self.tool(value["payload"])
110
+ raise ValueError("unknown callback kind")
111
+
112
+ def model(self, value):
113
+ if (not isinstance(value, dict) or set(value) != {"prompt", "channel", "stop", "seed"}
114
+ or value["channel"] not in {"planner", "join"}
115
+ or value["seed"] != self.request["payload"]["seed"]
116
+ or not isinstance(value["prompt"], str) or not value["prompt"]
117
+ or not isinstance(value["stop"], list)
118
+ or not all(isinstance(s, str) and s for s in value["stop"])):
119
+ raise ValueError("invalid live model request")
120
+ cap = self.owner.per_call_output_cap
121
+ request = GenerationRequest(prompt=value["prompt"], seed=value["seed"],
122
+ stop=tuple(value["stop"]), max_tokens=cap, temperature=0.0,
123
+ metadata={"method_id": "llm_compiler", "stage": value["channel"],
124
+ "transport_profile": "controlled_host_callback_v1"})
125
+ with self.lock:
126
+ if (self.fatal or self.closed or self.model_calls >= self.budget.max_model_calls
127
+ or self.output_tokens + self.reserved_output + cap > self.budget.max_output_tokens):
128
+ raise ValueError("live model budget exhausted before dispatch")
129
+ self.model_calls += 1
130
+ self.unpriced += 1
131
+ self.reserved_output += cap
132
+ self.inflight += 1
133
+ event = {"kind": "model", "request": to_jsonable(request)}
134
+ self.events.append(event)
135
+ try:
136
+ response = self.owner.backend.generate(request)
137
+ usage = response.usage
138
+ with self.lock:
139
+ self.input_tokens += usage.input_tokens
140
+ self.output_tokens += usage.output_tokens
141
+ self.reserved_output -= cap
142
+ if usage.cost_usd is not None:
143
+ self.unpriced -= 1
144
+ self.cost += usage.cost_usd
145
+ if usage.output_tokens > cap:
146
+ self.fatal = True
147
+ event["response"] = to_jsonable(response)
148
+ if usage.output_tokens > cap:
149
+ raise RuntimeError("provider exceeded the requested output cap")
150
+ return {"text": response.text, "input_tokens": usage.input_tokens,
151
+ "output_tokens": usage.output_tokens, "finish_reason": response.finish_reason}
152
+ except Exception as exc:
153
+ with self.lock:
154
+ self.fatal = True
155
+ if "response" not in event:
156
+ self.unknown_usage_calls += 1
157
+ # Keep the full output reservation when actual usage is unknown.
158
+ event["error_type"] = type(exc).__name__
159
+ raise RuntimeError("bound model callback failed; no retry") from None
160
+ finally:
161
+ with self.lock:
162
+ self.inflight -= 1
163
+
164
+ def tool(self, value):
165
+ if (not isinstance(value, dict) or set(value) != {"name", "arguments"}
166
+ or value["name"] not in self.specs):
167
+ raise ValueError("invalid bound tool request")
168
+ spec = self.specs[value["name"]]
169
+ properties = spec.input_schema.get("properties", {})
170
+ arguments = value["arguments"]
171
+ if isinstance(arguments, list):
172
+ if len(arguments) == 1 and isinstance(arguments[0], dict):
173
+ arguments = arguments[0]
174
+ else:
175
+ order = self.argument_order.get(spec.name)
176
+ if order is None:
177
+ if len(properties) > 1:
178
+ raise ValueError("multi-argument tools require explicit positional argument_order")
179
+ order = tuple(properties)
180
+ if len(arguments) > len(order):
181
+ raise ValueError("positional argument count differs from its explicit binding")
182
+ arguments = dict(zip(order[:len(arguments)], arguments, strict=True))
183
+ if not isinstance(arguments, dict):
184
+ raise ValueError("tool arguments must be a JSON object or positional list")
185
+ validate_json_value(arguments, spec.input_schema)
186
+ with self.lock:
187
+ if self.fatal or self.closed or self.tool_calls >= self.budget.max_tool_calls:
188
+ raise ValueError("live tool budget exhausted before dispatch")
189
+ self.tool_calls += 1
190
+ self.inflight += 1
191
+ call = ToolCall(value["name"], arguments, call_id=secrets.token_hex(16))
192
+ event = {"kind": "tool", "request": to_jsonable(call)}
193
+ self.events.append(event)
194
+ try:
195
+ result = self.owner.tools.call(call)
196
+ event["response"] = to_jsonable(result)
197
+ if result.error:
198
+ raise RuntimeError("bound tool returned an error")
199
+ return {"output": to_jsonable(result.output)}
200
+ except Exception as exc:
201
+ self.fatal = True
202
+ event["error_type"] = type(exc).__name__
203
+ raise RuntimeError("bound read-only tool failed; no synthetic observation") from None
204
+ finally:
205
+ with self.lock:
206
+ self.inflight -= 1
207
+
208
+
209
+ def _server(callbacks, key, limit):
210
+ class Handler(BaseHTTPRequestHandler):
211
+ def log_message(self, *args):
212
+ pass
213
+
214
+ def do_POST(self):
215
+ try:
216
+ self.connection.settimeout(10)
217
+ if (self.path != "/callback" or not hmac.compare_digest(
218
+ self.headers.get("Authorization", ""), "Bearer " + key)):
219
+ self.send_error(403)
220
+ return
221
+ size = int(self.headers.get("Content-Length", "0"))
222
+ if size < 1 or size > limit:
223
+ raise ValueError("callback byte limit exceeded")
224
+ raw = self.rfile.read(size)
225
+ if len(raw) != size:
226
+ raise ValueError("truncated callback")
227
+ result = {"ok": True, "payload": callbacks.dispatch(_strict_json(raw))}
228
+ except Exception as exc:
229
+ result = {"ok": False, "failure_code": "HOST_CALLBACK_FAILED",
230
+ "error_type": type(exc).__name__}
231
+ body = json.dumps(result, allow_nan=False).encode()
232
+ if len(body) > limit:
233
+ body = b'{"ok":false,"failure_code":"CALLBACK_RESPONSE_TOO_LARGE"}'
234
+ self.send_response(200)
235
+ self.send_header("Content-Type", "application/json")
236
+ self.send_header("Content-Length", str(len(body)))
237
+ self.end_headers()
238
+ with suppress(BrokenPipeError, ConnectionResetError):
239
+ self.wfile.write(body)
240
+
241
+ server = ThreadingHTTPServer(("127.0.0.1", 0), Handler)
242
+ server.daemon_threads = True
243
+ server.block_on_close = False
244
+ return server
245
+
246
+
247
+ @dataclass
248
+ class LLMCompilerLiveWorker:
249
+ """Execute pinned Planner/TFU/join with caller-owned live dependencies.
250
+
251
+ Keep the legacy worker environment separate from the host package. Tools
252
+ must be read-only/no-network, and backends/tools must set their own bounded
253
+ I/O timeouts. Streaming controls use buffered callback delivery, not provider
254
+ streaming latency/parity. Priced/input-token ceilings fail before dispatch.
255
+ """
256
+
257
+ python_executable: str
258
+ checkout: Path
259
+ prompt_bundle: Path
260
+ backend: LLMBackend
261
+ tools: ToolConnector
262
+ per_call_output_cap: int = 512
263
+ timeout_seconds: float = 400
264
+ argument_order: Mapping[str, tuple[str, ...]] = field(default_factory=dict)
265
+ worker_id: str = "agentinputlab.llmcompiler.controlled-live.v1"
266
+ _last_resource_receipt: Any = field(default=None, init=False, repr=False)
267
+ callback_events: list = field(default_factory=list, init=False, repr=False)
268
+
269
+ def __post_init__(self):
270
+ if (isinstance(self.per_call_output_cap, bool) or not isinstance(self.per_call_output_cap, int)
271
+ or self.per_call_output_cap < 1):
272
+ raise ValidationError("per_call_output_cap must be positive")
273
+ if (not isinstance(self.python_executable, str) or not self.python_executable
274
+ or isinstance(self.timeout_seconds, bool)
275
+ or not isinstance(self.timeout_seconds, (int, float))
276
+ or not math.isfinite(self.timeout_seconds) or self.timeout_seconds <= 0):
277
+ raise ValidationError("worker interpreter and finite positive timeout required")
278
+ if any(not isinstance(name, str) or not isinstance(order, (list, tuple))
279
+ or not all(isinstance(key, str) and key for key in order)
280
+ or len(set(order)) != len(order) for name, order in self.argument_order.items()):
281
+ raise ValidationError("argument_order must map tool names to unique parameter names")
282
+ self.checkout, self.prompt_bundle = Path(self.checkout), Path(self.prompt_bundle)
283
+
284
+ @property
285
+ def last_resource_receipt(self):
286
+ return self._last_resource_receipt
287
+
288
+ def fingerprint(self):
289
+ import hashlib
290
+ from importlib import resources
291
+
292
+ package = resources.files("workers").joinpath("llmcompiler")
293
+ driver_sha = hashlib.sha256(package.joinpath("driver.py").read_bytes()).hexdigest()
294
+ live_sha = hashlib.sha256(package.joinpath("live.py").read_bytes()).hexdigest()
295
+ manifest = package.joinpath("compatibility_manifest.json").read_bytes()
296
+ manifest_sha = hashlib.sha256(manifest).hexdigest()
297
+ attestation = {"schema": "agentinputlab.llmcompiler.live-attestation.v1",
298
+ "driver_sha256": driver_sha, "live_driver_sha256": live_sha,
299
+ "compatibility_manifest_sha256": manifest_sha,
300
+ "required_versions": json.loads(manifest)["legacy_dependencies"]["required_versions"],
301
+ "source_files_verified": True, "required_versions_verified": True, "import_origins_verified": True}
302
+ return {"worker_id": self.worker_id,
303
+ "upstream_commit": "a00c9d35507507da70e8c637eee64efc8c1857ae",
304
+ "driver_sha256": driver_sha, "live_driver_sha256": live_sha,
305
+ "compatibility_manifest_sha256": manifest_sha, "worker_attestation": attestation,
306
+ "prompt_bundle_sha256": hashlib.sha256(self.prompt_bundle.read_bytes()).hexdigest(),
307
+ "model": dict(self.backend.fingerprint()), "tools": dict(self.tools.fingerprint()),
308
+ "model_transport": "context_bound_host_callback", "tool_transport": "context_bound_readonly_callback",
309
+ "streaming_delivery": "buffered_completion_callbacks_not_native_streaming",
310
+ "positional_argument_order": to_jsonable(self.argument_order),
311
+ "per_call_output_cap": self.per_call_output_cap, "timeout_seconds": self.timeout_seconds}
312
+
313
+ def call(self, payload):
314
+ if not isinstance(payload, Mapping):
315
+ raise ValidationError("live LLMCompiler requires a typed request mapping")
316
+ callbacks = _Callbacks(self, payload)
317
+ identity = self.fingerprint()
318
+ self.callback_events = callbacks.events
319
+ self._last_resource_receipt = None
320
+ key = secrets.token_urlsafe(32)
321
+ server = _server(callbacks, key, 4 * 1024 * 1024)
322
+ thread = threading.Thread(target=server.serve_forever, daemon=True)
323
+ thread.start()
324
+ worker = JsonLineSubprocessWorker(
325
+ command=(self.python_executable, "-m", "workers.llmcompiler.live",
326
+ "--checkout", str(self.checkout), "--prompt-bundle", str(self.prompt_bundle),
327
+ "--callback-url", f"http://127.0.0.1:{server.server_port}/callback",
328
+ "--callback-key-env", _KEY_ENV), worker_id=self.worker_id,
329
+ identity=identity, timeout_seconds=self.timeout_seconds,
330
+ environment={"PATH": os.environ.get("PATH", ""), "PYTHONDONTWRITEBYTECODE": "1",
331
+ "CUDA_VISIBLE_DEVICES": "", _KEY_ENV: key})
332
+ try:
333
+ try:
334
+ response = dict(worker.call(payload))
335
+ except SupervisedWorkerError:
336
+ response = {"status": "error", "request_id": payload["request_id"],
337
+ "failure_code": "LIVE_WORKER_EXECUTION_FAILED", "message": "supervised native worker failed"}
338
+ with callbacks.lock:
339
+ callbacks.closed = True
340
+ usage = callbacks.usage()
341
+ incomplete = callbacks.inflight > 0
342
+ if incomplete:
343
+ response = {"status": "error", "request_id": payload["request_id"],
344
+ "failure_code": "CALLBACK_USAGE_INCOMPLETE", "message": "bound callback still in flight at worker exit"}
345
+ elif response.get("status") == "ok" and any(
346
+ response.get("usage", {}).get(k) != usage[k]
347
+ for k in ("model_calls", "tool_calls", "input_tokens", "output_tokens")):
348
+ response = {"status": "error", "request_id": payload["request_id"],
349
+ "failure_code": "CALLBACK_USAGE_MISMATCH", "message": "worker and host usage differ"}
350
+ response["usage"] = usage
351
+ response["consumed"] = bool(usage["model_calls"] or usage["tool_calls"])
352
+ response["callback_diagnostics"] = {"unknown_usage_calls": callbacks.unknown_usage_calls,
353
+ "usage_incomplete": incomplete, "automatic_retry": False}
354
+ return response
355
+ finally:
356
+ self._last_resource_receipt = worker.last_resource_receipt
357
+ callbacks.closed = True
358
+ server.shutdown()
359
+ server.server_close()
360
+ thread.join(timeout=2)
@@ -0,0 +1,162 @@
1
+ """Pinned local LLMLingua runtime; executable objects stay in the context."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import importlib.metadata
6
+ import json
7
+ import re
8
+ import threading
9
+ import time
10
+ from collections.abc import Mapping
11
+ from dataclasses import replace
12
+ from functools import lru_cache
13
+ from pathlib import Path, PurePosixPath
14
+ from typing import Any
15
+
16
+ from agentinputlab.algorithms.curate.llmlingua import (
17
+ LongLLMLinguaOfficialAdapter,
18
+ )
19
+ from agentinputlab.algorithms.curate.llmlingua.controlled import LongLLMLinguaCompressionRequest
20
+ from agentinputlab.artifacts import sha256_file
21
+ from agentinputlab.contracts import (
22
+ ExternalDependencyError,
23
+ InterventionContext,
24
+ TraceEvent,
25
+ TracePhase,
26
+ ValidationError,
27
+ )
28
+ from agentinputlab.contracts.serialization import freeze_mapping
29
+
30
+ _SOURCE_FILES = {
31
+ "prompt_compressor.py": "472fde8f6f55f273fe94eee40c25c73508f1ed3a7f5d61788636c20fc4be5068",
32
+ "utils.py": "1ed3eb0734354ea0136a0d98a9366233a872d22ff350fab107e53de45c954e33",
33
+ }
34
+ _SHA = re.compile(r"[0-9a-f]{64}")
35
+
36
+
37
+ @lru_cache(maxsize=4)
38
+ def _verify_files(snapshot: str, pins: tuple[tuple[str, str], ...],
39
+ identities: tuple[tuple[str, int, int], ...]) -> None:
40
+ del identities
41
+ for name, expected in pins:
42
+ if sha256_file(Path(snapshot) / name) != expected:
43
+ raise ExternalDependencyError(f"LongLLMLingua snapshot checksum differs: {name}")
44
+
45
+
46
+ class LongLLMLinguaNativeRuntime:
47
+ """Use a caller-mounted safetensors snapshot, never an implicit alternative.
48
+
49
+ The supplied checksums are operator trust. Live calls verify every file
50
+ before loading. Injected factories are explicit caller code; their identity
51
+ is recorded and they do not certify model execution or verify model weights.
52
+ """
53
+
54
+ def __init__(self, snapshot: str | Path, *, model_id: str, revision: str,
55
+ file_sha256: Mapping[str, str], device_map: str = "cpu",
56
+ torch_dtype: str = "float16", compressor_factory: Any = None):
57
+ self.snapshot = Path(snapshot).resolve()
58
+ if not self.snapshot.is_dir() or not model_id or re.fullmatch(r"[0-9a-f]{40}", revision) is None:
59
+ raise ValidationError("LongLLMLingua needs a local snapshot and pinned model identity")
60
+ if device_map not in {"cpu", "cuda:0", "mps"} or torch_dtype not in {"float16", "bfloat16", "float32"}:
61
+ raise ValidationError("LongLLMLingua requires an explicit device and floating dtype")
62
+ pins = dict(file_sha256)
63
+ for name, value in pins.items():
64
+ path = PurePosixPath(name)
65
+ if (not name or path.is_absolute() or ".." in path.parts or "\\" in name
66
+ or not isinstance(value, str) or _SHA.fullmatch(value) is None):
67
+ raise ValidationError("LongLLMLingua snapshot pins must be safe paths and SHA-256")
68
+ if (not {"config.json", "tokenizer_config.json", "special_tokens_map.json"}.issubset(pins)
69
+ or not any(n.endswith(".safetensors") for n in pins)
70
+ or not any(n in pins for n in ("tokenizer.json", "tokenizer.model"))):
71
+ raise ValidationError("LongLLMLingua snapshot closure lacks model/tokenizer files")
72
+ self._pins = tuple(sorted(pins.items()))
73
+ self._model_id, self._revision = model_id, revision
74
+ self._device, self._dtype = device_map, torch_dtype
75
+ self._factory = compressor_factory
76
+ self._lock = threading.RLock()
77
+
78
+ @staticmethod
79
+ def _source() -> Mapping[str, Any]:
80
+ try:
81
+ distribution = importlib.metadata.distribution("llmlingua")
82
+ if distribution.version != "0.2.2":
83
+ raise ExternalDependencyError("LongLLMLingua requires llmlingua==0.2.2")
84
+ for name, expected in _SOURCE_FILES.items():
85
+ if sha256_file(distribution.locate_file("llmlingua/" + name)) != expected:
86
+ raise ExternalDependencyError("LongLLMLingua upstream source differs from its lock")
87
+ except (importlib.metadata.PackageNotFoundError, OSError) as exc:
88
+ raise ExternalDependencyError("install agentinputlab[compression] and mount the pinned assets") from exc
89
+ return {"package": "llmlingua", "version": "0.2.2", "file_sha256": _SOURCE_FILES}
90
+
91
+ def fingerprint(self) -> Mapping[str, Any]:
92
+ return freeze_mapping({
93
+ "runtime_id": "agentinputlab.longllmlingua.native.v1", "source": self._source(),
94
+ "model": {"id": self._model_id, "locator": str(self.snapshot),
95
+ "revision": self._revision, "file_sha256": dict(self._pins)},
96
+ "tokenizer": {"revision": self._revision, "file_sha256": {
97
+ name: sha for name, sha in self._pins if "tokenizer" in name or "special_tokens" in name}},
98
+ "load": {"device_map": self._device, "torch_dtype": self._dtype,
99
+ "local_files_only": True, "trust_remote_code": False},
100
+ "injected_factory": self._factory is not None,
101
+ "file_verification": "caller_runtime" if self._factory is not None else "full_sha256_before_live_load",
102
+ })
103
+
104
+ def _require_loader_closure(self) -> None:
105
+ """Reject undeclared sidecars/shards that native auto-loading could use."""
106
+ pins = dict(self._pins)
107
+ for name in ("generation_config.json", "model.safetensors.index.json", "tokenizer.json",
108
+ "tokenizer.model", "added_tokens.json", "chat_template.jinja"):
109
+ if (self.snapshot/name).exists() and name not in pins:
110
+ raise ExternalDependencyError(f"LongLLMLingua loader file is not pinned: {name}")
111
+ if (self.snapshot/'adapter_config.json').exists():
112
+ raise ExternalDependencyError("LongLLMLingua does not implicitly load PEFT adapters")
113
+ try:
114
+ config = json.loads((self.snapshot/'config.json').read_text())
115
+ if not any(str(name).endswith('ForCausalLM') for name in config.get('architectures', [])):
116
+ raise ExternalDependencyError("LongLLMLingua perplexity scoring requires a causal LM")
117
+ index = self.snapshot/'model.safetensors.index.json'
118
+ if index.exists():
119
+ if (self.snapshot/'model.safetensors').exists():
120
+ raise ExternalDependencyError("LongLLMLingua snapshot has ambiguous weight layouts")
121
+ shards = set(json.loads(index.read_text())['weight_map'].values())
122
+ if not shards or any(not isinstance(n, str) or n not in pins for n in shards):
123
+ raise ExternalDependencyError("LongLLMLingua weight index references unpinned shards")
124
+ elif 'model.safetensors' not in pins:
125
+ raise ExternalDependencyError("LongLLMLingua needs pinned single or indexed safetensors")
126
+ except (ValueError, KeyError, AttributeError, TypeError) as exc:
127
+ raise ExternalDependencyError("LongLLMLingua loader config/index is malformed") from exc
128
+
129
+ def run(self, request: LongLLMLinguaCompressionRequest) -> Mapping[str, Any]:
130
+ if not isinstance(request, LongLLMLinguaCompressionRequest):
131
+ raise ValidationError("LongLLMLingua runtime requires a typed compression request")
132
+ state, config, seed = request.state, request.config, request.seed
133
+ with self._lock:
134
+ self._source()
135
+ started = time.monotonic()
136
+ cpu_started = time.process_time()
137
+ if self._factory is None:
138
+ try:
139
+ self._require_loader_closure()
140
+ identities = tuple((name, (self.snapshot/name).stat().st_size,
141
+ (self.snapshot/name).stat().st_mtime_ns) for name, _ in self._pins)
142
+ _verify_files(str(self.snapshot), self._pins, identities)
143
+ except OSError as exc:
144
+ raise ExternalDependencyError("LongLLMLingua snapshot closure is incomplete") from exc
145
+ adapter = LongLLMLinguaOfficialAdapter(model_name=str(self.snapshot), model_revision=self._revision,
146
+ device_map=self._device, model_config={"local_files_only": True, "torch_dtype": self._dtype},
147
+ config=config, compressor_factory=self._factory)
148
+ native = adapter.propose(state, InterventionContext(seed=seed))
149
+ native = replace(native, trace=replace(native.trace, events=(*native.trace.events,
150
+ TraceEvent(TracePhase.FINALIZE, "native_helper_execution", {
151
+ "wall_seconds": time.monotonic()-started,
152
+ "injected_factory": self._factory is not None,
153
+ "compression_invocations": 1,
154
+ "internal_forward_count": "not_metered_native_perplexity_passes",
155
+ "helper_sampled_output_tokens": 0,
156
+ "helper_compute_free": False}))))
157
+ return {"patch": native, "usage": {"model_calls": 0, "retrieval_calls": 0,
158
+ "input_tokens": 0, "output_tokens": 0, "cpu_seconds": time.process_time()-cpu_started},
159
+ "usage_scope": "zero sampled generation; helper forward passes and wall time are separate"}
160
+
161
+
162
+ __all__ = ["LongLLMLinguaNativeRuntime"]