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,149 @@
1
+ """Backend-neutral language-model request and response contracts."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ from collections.abc import Mapping
7
+ from dataclasses import dataclass, field
8
+ from typing import Any, Protocol, runtime_checkable
9
+
10
+ from agentinputlab.contracts.enums import StrEnum
11
+ from agentinputlab.contracts.errors import CapabilityError, ValidationError
12
+ from agentinputlab.contracts.serialization import content_hash, freeze_mapping
13
+ from agentinputlab.contracts.state import Message
14
+
15
+
16
+ def _is_finite_nonnegative_number(value: Any) -> bool:
17
+ if isinstance(value, bool) or not isinstance(value, (int, float)):
18
+ return False
19
+ try:
20
+ return math.isfinite(value) and value >= 0
21
+ except (OverflowError, TypeError, ValueError):
22
+ return False
23
+
24
+
25
+ class ModelCapability(StrEnum):
26
+ CHAT = "chat"
27
+ COMPLETION = "completion"
28
+ JSON_OBJECT = "json_object"
29
+ JSON_SCHEMA = "json_schema"
30
+ TOOL_CALLING = "tool_calling"
31
+ LOGPROBS = "logprobs"
32
+ SEED = "seed"
33
+ STREAMING = "streaming"
34
+
35
+
36
+ @dataclass(frozen=True, slots=True)
37
+ class GenerationRequest:
38
+ prompt: str = ""
39
+ messages: tuple[Message, ...] = ()
40
+ system: str = ""
41
+ temperature: float = 0.0
42
+ max_tokens: int = 512
43
+ seed: int | None = None
44
+ stop: tuple[str, ...] = ()
45
+ logprobs: bool = False
46
+ top_logprobs: int | None = None
47
+ response_format: Mapping[str, Any] | None = None
48
+ tools: tuple[Mapping[str, Any], ...] = ()
49
+ metadata: Mapping[str, Any] = field(default_factory=dict)
50
+
51
+ def __post_init__(self) -> None:
52
+ messages = tuple(self.messages)
53
+ stop = tuple(self.stop)
54
+ if not all(isinstance(message, Message) for message in messages):
55
+ raise ValidationError("generation messages must be Message instances")
56
+ if not all(isinstance(item, str) for item in stop):
57
+ raise ValidationError("generation stop entries must be strings")
58
+ if not isinstance(self.logprobs, bool):
59
+ raise ValidationError("logprobs must be boolean")
60
+ if self.top_logprobs is not None and (
61
+ isinstance(self.top_logprobs, bool)
62
+ or not isinstance(self.top_logprobs, int)
63
+ or not 1 <= self.top_logprobs <= 20
64
+ ):
65
+ raise ValidationError("top_logprobs must be an integer from 1 to 20 or None")
66
+ if self.top_logprobs is not None and not self.logprobs:
67
+ raise ValidationError("top_logprobs requires logprobs=True")
68
+ object.__setattr__(self, "messages", messages)
69
+ object.__setattr__(self, "stop", stop)
70
+ object.__setattr__(
71
+ self,
72
+ "tools",
73
+ tuple(freeze_mapping(tool) for tool in self.tools),
74
+ )
75
+ if self.response_format is not None:
76
+ object.__setattr__(
77
+ self,
78
+ "response_format",
79
+ freeze_mapping(self.response_format),
80
+ )
81
+ object.__setattr__(self, "metadata", freeze_mapping(self.metadata))
82
+ if not self.prompt and not self.messages:
83
+ raise ValidationError("generation request requires prompt or messages")
84
+ if (
85
+ isinstance(self.max_tokens, bool)
86
+ or not isinstance(self.max_tokens, int)
87
+ or self.max_tokens < 1
88
+ ):
89
+ raise ValidationError("max_tokens must be positive")
90
+ if not _is_finite_nonnegative_number(self.temperature):
91
+ raise ValidationError("temperature must be finite and non-negative")
92
+ if self.seed is not None and (
93
+ isinstance(self.seed, bool) or not isinstance(self.seed, int) or self.seed < 0
94
+ ):
95
+ raise ValidationError("seed must be a non-negative integer or None")
96
+
97
+ @property
98
+ def request_hash(self) -> str:
99
+ return content_hash(self)
100
+
101
+
102
+ @dataclass(frozen=True, slots=True)
103
+ class Usage:
104
+ input_tokens: int = 0
105
+ output_tokens: int = 0
106
+ cost_usd: float | None = None
107
+
108
+ def __post_init__(self) -> None:
109
+ if any(
110
+ isinstance(value, bool) or not isinstance(value, int) or value < 0
111
+ for value in (self.input_tokens, self.output_tokens)
112
+ ):
113
+ raise ValidationError("usage token counts must be non-negative integers")
114
+ if self.cost_usd is not None and not _is_finite_nonnegative_number(self.cost_usd):
115
+ raise ValidationError("usage cost_usd must be finite and non-negative or None")
116
+
117
+
118
+ @dataclass(frozen=True, slots=True)
119
+ class GenerationResponse:
120
+ text: str
121
+ model: str = ""
122
+ finish_reason: str = ""
123
+ usage: Usage = field(default_factory=Usage)
124
+ raw: Mapping[str, Any] = field(default_factory=dict)
125
+
126
+ def __post_init__(self) -> None:
127
+ object.__setattr__(self, "raw", freeze_mapping(self.raw))
128
+
129
+
130
+ @runtime_checkable
131
+ class LLMBackend(Protocol):
132
+ model_id: str
133
+ capabilities: frozenset[ModelCapability]
134
+
135
+ def generate(self, request: GenerationRequest) -> GenerationResponse:
136
+ """Generate one response or raise a typed backend error."""
137
+
138
+ def fingerprint(self) -> Mapping[str, Any]:
139
+ """Return serializable identity fields used by balance audits."""
140
+
141
+
142
+ def require_capabilities(
143
+ backend: LLMBackend,
144
+ required: set[ModelCapability] | frozenset[ModelCapability],
145
+ ) -> None:
146
+ missing = set(required) - set(backend.capabilities)
147
+ if missing:
148
+ names = ", ".join(sorted(item.value for item in missing))
149
+ raise CapabilityError(f"backend {backend.model_id!r} lacks capabilities: {names}")
@@ -0,0 +1,108 @@
1
+ """Dependency-free callable and deterministic replay backends."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections import deque
6
+ from collections.abc import Callable, Iterable, Mapping
7
+ from dataclasses import dataclass, field
8
+ from typing import Any
9
+
10
+ from agentinputlab.contracts.errors import ValidationError
11
+ from agentinputlab.contracts.serialization import content_hash
12
+
13
+ from .base import (
14
+ GenerationRequest,
15
+ GenerationResponse,
16
+ LLMBackend,
17
+ ModelCapability,
18
+ Usage,
19
+ )
20
+
21
+
22
+ @dataclass(slots=True)
23
+ class CallableBackend(LLMBackend):
24
+ fn: Callable[[GenerationRequest], GenerationResponse | str | Mapping[str, Any]]
25
+ model_id: str = "callable"
26
+ revision: str = "unversioned"
27
+ callable_id: str = ""
28
+ capabilities: frozenset[ModelCapability] = frozenset(
29
+ {ModelCapability.CHAT, ModelCapability.COMPLETION, ModelCapability.SEED}
30
+ )
31
+ calls: list[GenerationRequest] = field(default_factory=list, init=False)
32
+
33
+ def __post_init__(self) -> None:
34
+ if not self.revision or self.revision == "unversioned":
35
+ raise ValidationError("callable backend requires an explicit stable revision")
36
+ if not self.callable_id:
37
+ raise ValidationError("callable backend requires an explicit stable callable_id")
38
+
39
+ def generate(self, request: GenerationRequest) -> GenerationResponse:
40
+ self.calls.append(request)
41
+ value = self.fn(request)
42
+ if isinstance(value, GenerationResponse):
43
+ return value
44
+ if isinstance(value, str):
45
+ return GenerationResponse(text=value, model=self.model_id)
46
+ return GenerationResponse(
47
+ text=str(value.get("text", "")),
48
+ model=str(value.get("model", self.model_id)),
49
+ finish_reason=str(value.get("finish_reason", "")),
50
+ usage=Usage(**dict(value.get("usage", {}))),
51
+ raw=dict(value),
52
+ )
53
+
54
+ def fingerprint(self) -> Mapping[str, Any]:
55
+ return {
56
+ "backend": "callable",
57
+ "model_id": self.model_id,
58
+ "revision": self.revision,
59
+ "callable_id": self.callable_id,
60
+ "capabilities": sorted(item.value for item in self.capabilities),
61
+ }
62
+
63
+
64
+ @dataclass(slots=True)
65
+ class ReplayBackend(LLMBackend):
66
+ """Return recorded outputs in order and fail loudly if the cache is exhausted."""
67
+
68
+ responses: Iterable[str | GenerationResponse]
69
+ model_id: str = "replay"
70
+ capabilities: frozenset[ModelCapability] = frozenset(
71
+ {ModelCapability.CHAT, ModelCapability.COMPLETION, ModelCapability.SEED}
72
+ )
73
+ strict_request_hashes: tuple[str, ...] = ()
74
+ _queue: deque[str | GenerationResponse] = field(init=False, repr=False)
75
+ _calls: int = field(default=0, init=False, repr=False)
76
+ _fixture_hash: str = field(default="", init=False, repr=False)
77
+
78
+ def __post_init__(self) -> None:
79
+ values = tuple(self.responses)
80
+ self._queue = deque(values)
81
+ self._fixture_hash = content_hash(values)
82
+
83
+ def generate(self, request: GenerationRequest) -> GenerationResponse:
84
+ if self.strict_request_hashes:
85
+ if self._calls >= len(self.strict_request_hashes):
86
+ raise RuntimeError("replay request-hash fixture exhausted")
87
+ expected = self.strict_request_hashes[self._calls]
88
+ if request.request_hash != expected:
89
+ raise ValueError(
90
+ f"replay request mismatch at {self._calls}: "
91
+ f"expected {expected}, got {request.request_hash}"
92
+ )
93
+ if not self._queue:
94
+ raise RuntimeError("replay backend exhausted")
95
+ self._calls += 1
96
+ value = self._queue.popleft()
97
+ if isinstance(value, GenerationResponse):
98
+ return value
99
+ return GenerationResponse(text=value, model=self.model_id, finish_reason="replay")
100
+
101
+ def fingerprint(self) -> Mapping[str, Any]:
102
+ return {
103
+ "backend": "replay",
104
+ "model_id": self.model_id,
105
+ "strict": bool(self.strict_request_hashes),
106
+ "fixture_hash": self._fixture_hash,
107
+ "request_fixture_hash": content_hash(self.strict_request_hashes),
108
+ }
@@ -0,0 +1,88 @@
1
+ """Raw-completion transport for the pinned DecomP GPT3Generator seam."""
2
+ from __future__ import annotations
3
+
4
+ import math
5
+ import os
6
+ from collections.abc import Mapping
7
+ from dataclasses import dataclass
8
+
9
+ from agentinputlab.contracts import ValidationError
10
+ from agentinputlab.contracts.serialization import to_jsonable
11
+
12
+ from .openai_compatible import OpenAICompatibleBackend, _contains_exact_text
13
+
14
+ _FIELDS = frozenset({"prompt", "engine", "temperature", "max_tokens", "top_p",
15
+ "frequency_penalty", "presence_penalty", "stop", "n", "best_of", "logprobs"})
16
+
17
+
18
+ def validate_native_parameters(value: Mapping) -> dict:
19
+ """Validate the explicit single-choice native profile without rewriting it."""
20
+ if (not isinstance(value, Mapping) or set(value) - _FIELDS
21
+ or _FIELDS - {"best_of"} - set(value)
22
+ or not isinstance(value.get("prompt"), str) or not value["prompt"]
23
+ or not isinstance(value.get("engine"), str) or not value["engine"]):
24
+ raise ValidationError("invalid DecomP native completion fields")
25
+ if (type(value["n"]) is not int or value["n"] != 1
26
+ or (value.get("best_of") is not None and
27
+ (type(value["best_of"]) is not int or value["best_of"] != 1))):
28
+ raise ValidationError("DecomP live profile requires n=1 and best_of=1 or None")
29
+ if type(value["max_tokens"]) is not int or value["max_tokens"] < 1:
30
+ raise ValidationError("DecomP native max_tokens must be positive")
31
+ for name, lower, upper in (("temperature", 0, 2), ("top_p", 0, 1),
32
+ ("frequency_penalty", -2, 2), ("presence_penalty", -2, 2)):
33
+ number = value[name]
34
+ if (isinstance(number, bool) or not isinstance(number, (int, float))
35
+ or not math.isfinite(number) or not lower <= number <= upper):
36
+ raise ValidationError("invalid DecomP native sampling parameter")
37
+ if value["top_p"] == 0:
38
+ raise ValidationError("DecomP native top_p must be positive")
39
+ stop = value["stop"]
40
+ if not isinstance(stop, (list, tuple)) or not all(isinstance(s, str) and s for s in stop):
41
+ raise ValidationError("DecomP native stop must be a string sequence")
42
+ logs = value["logprobs"]
43
+ if logs is not None and (type(logs) is not int or not 0 <= logs <= 20):
44
+ raise ValidationError("invalid DecomP native logprobs")
45
+ return to_jsonable(value)
46
+
47
+
48
+ @dataclass(slots=True)
49
+ class DecompCompletionBackend(OpenAICompatibleBackend):
50
+ """Preserve original completion parameters and native branch-score inputs.
51
+
52
+ The caller-bound model replaces the legacy engine identity. The native
53
+ GPT3Generator still parses/sorts choices; no chat template, scoring rewrite,
54
+ response cache, fallback, or automatic retry is introduced here.
55
+ """
56
+
57
+ def __post_init__(self):
58
+ OpenAICompatibleBackend.__post_init__(self)
59
+ if self.extra_body:
60
+ raise ValidationError("DecomP native parameters cannot be overridden by extra_body")
61
+
62
+ def complete_native(self, parameters: Mapping, *, seed: int) -> Mapping:
63
+ value = validate_native_parameters(parameters)
64
+ if type(seed) is not int or seed < 0:
65
+ raise ValidationError("DecomP seed must be non-negative")
66
+ payload = {k: v for k, v in value.items() if k != "engine"}
67
+ payload.update(model=self.model_id, seed=seed)
68
+ key = self.api_key or os.environ.get(self.api_key_env, "")
69
+ headers = {"Content-Type": "application/json", **dict(self.extra_headers)}
70
+ if key:
71
+ headers["Authorization"] = "Bearer " + key
72
+ failed, response = False, None
73
+ try:
74
+ response = self.transport(self.base_url + "/completions", headers, payload, self.timeout_seconds)
75
+ except Exception:
76
+ failed = True
77
+ if failed:
78
+ raise RuntimeError("DecomP native completion transport failed; no retry")
79
+ if key and _contains_exact_text(response, key):
80
+ raise RuntimeError("DecomP completion response contains the configured credential")
81
+ if not isinstance(response, Mapping):
82
+ raise RuntimeError("DecomP native completion returned an invalid envelope")
83
+ return response
84
+
85
+ def fingerprint(self):
86
+ return {**dict(OpenAICompatibleBackend.fingerprint(self)),
87
+ "backend": "decomp_native_raw_completion.v1", "chat_template_applied": False,
88
+ "legacy_engine_binding": "explicit_caller_model_override", "automatic_retry": False}
@@ -0,0 +1,72 @@
1
+ """Explicit final-content stops for OpenAI-compatible reasoning responses.
2
+
3
+ The provider does not receive logical stop strings, so it cannot terminate
4
+ inside its separate reasoning channel. Apply stops only to the parsed final
5
+ text; keep ALL provider usage, even tokens generated past the logical stop.
6
+ This is opt-in and does not rewrite historical results or backend defaults.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ from collections.abc import Mapping
11
+ from dataclasses import dataclass, replace
12
+ from typing import Any
13
+
14
+ from agentinputlab.contracts import ValidationError
15
+
16
+ from .base import GenerationRequest, GenerationResponse, ModelCapability
17
+ from .openai_compatible import OpenAICompatibleBackend
18
+
19
+ FINAL_CONTENT_STOP_POLICY_ID = "openai-compatible.final-content-stop.v1"
20
+
21
+
22
+ @dataclass(slots=True)
23
+ class FinalContentStopBackend:
24
+ """Wrap a backend whose parser separates final content from raw reasoning.
25
+
26
+ No second generation is performed to recover truncated/empty content.
27
+ This wrapper exposes buffered ``generate`` only, not streaming. A generic
28
+ text decoder that merges reasoning into text cannot establish this contract.
29
+ """
30
+
31
+ inner: OpenAICompatibleBackend
32
+
33
+ def __post_init__(self) -> None:
34
+ if not isinstance(self.inner, OpenAICompatibleBackend):
35
+ raise ValidationError("final-content stops require an OpenAICompatibleBackend parser")
36
+ if "stop" in self.inner.extra_body:
37
+ raise ValidationError("configure logical stops on GenerationRequest, not extra_body")
38
+
39
+ @property
40
+ def model_id(self) -> str:
41
+ return self.inner.model_id
42
+
43
+ @property
44
+ def capabilities(self) -> frozenset[ModelCapability]:
45
+ return self.inner.capabilities - {ModelCapability.STREAMING}
46
+
47
+ def fingerprint(self) -> Mapping[str, Any]:
48
+ return {"backend": "final_content_stop", "policy_id": FINAL_CONTENT_STOP_POLICY_ID,
49
+ "inner": dict(self.inner.fingerprint()), "reasoning_is_final": False,
50
+ "charge_all_generated_tokens": True, "streaming": False}
51
+
52
+ def generate(self, request: GenerationRequest) -> GenerationResponse:
53
+ if "stop" in self.inner.extra_body:
54
+ raise ValidationError("configure logical stops on GenerationRequest, not extra_body")
55
+ if not request.stop:
56
+ return self.inner.generate(request)
57
+ if any(not value for value in request.stop):
58
+ raise ValidationError("final-content stop entries must be non-empty")
59
+ response = self.inner.generate(replace(request, stop=()))
60
+ matches = [(response.text.find(stop), index, stop) for index, stop in enumerate(request.stop)
61
+ if stop in response.text]
62
+ match = min(matches) if matches else None
63
+ return replace(response, text=response.text[:match[0]] if match else response.text,
64
+ finish_reason="stop" if match else response.finish_reason,
65
+ raw={**dict(response.raw), "agentinputlab_final_content_stop": {
66
+ "policy_id": FINAL_CONTENT_STOP_POLICY_ID, "requested_stop": list(request.stop),
67
+ "matched_stop": match[2] if match else None,
68
+ "provider_finish_reason": response.finish_reason,
69
+ "provider_usage_unchanged": True, "new_call_added_by_adapter": False}})
70
+
71
+
72
+ __all__ = ["FINAL_CONTENT_STOP_POLICY_ID", "FinalContentStopBackend"]
@@ -0,0 +1,84 @@
1
+ """Opt-in GPT-OSS stop compatibility for separately reported rerun variants.
2
+
3
+ Legacy completion-style stops can end a Harmony analysis message before the
4
+ model reaches its final channel. This adapter applies the same stops to final
5
+ content only. It does not promote reasoning to an answer or increase any token
6
+ cap. The server may generate past the logical final stop; *all* server-reported
7
+ tokens are retained and charged. Historical results must not be relabeled with
8
+ this adapter. It is intentionally not enabled by the production builder.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from collections.abc import Mapping
14
+ from dataclasses import dataclass, replace
15
+ from typing import Any
16
+
17
+ from agentinputlab.contracts.errors import ValidationError
18
+
19
+ from .base import GenerationRequest, GenerationResponse, ModelCapability
20
+ from .openai_compatible import OpenAICompatibleBackend
21
+
22
+ POLICY_ID = "gpt-oss.final-channel-stop.v1"
23
+
24
+
25
+ @dataclass(slots=True)
26
+ class GPTOSSFinalChannelStopBackend:
27
+ """Keep stop strings out of Harmony analysis, with no automatic new call."""
28
+
29
+ inner: OpenAICompatibleBackend
30
+
31
+ def __post_init__(self) -> None:
32
+ if (
33
+ self.inner.model_id.casefold() != "gpt-oss-20b"
34
+ or self.inner.deployment_identity.get("server") != "vllm"
35
+ ):
36
+ raise ValidationError("final-channel stop compatibility requires GPT-OSS/vLLM")
37
+
38
+ @property
39
+ def model_id(self) -> str:
40
+ return self.inner.model_id
41
+
42
+ @property
43
+ def capabilities(self) -> frozenset[ModelCapability]:
44
+ return self.inner.capabilities
45
+
46
+ def fingerprint(self) -> Mapping[str, Any]:
47
+ return {
48
+ "backend": "gpt_oss_final_channel_stop",
49
+ "policy_id": POLICY_ID,
50
+ "inner": dict(self.inner.fingerprint()),
51
+ "reasoning_is_final": False,
52
+ "charge_all_generated_tokens": True,
53
+ }
54
+
55
+ def generate(self, request: GenerationRequest) -> GenerationResponse:
56
+ if not request.stop:
57
+ return self.inner.generate(request)
58
+ if any(not value for value in request.stop):
59
+ raise ValidationError("final-channel stop entries must be non-empty")
60
+ # Only logical stop handling changes. In particular max_tokens, seed,
61
+ # messages, tools, temperature, and metadata are not regenerated.
62
+ response = self.inner.generate(replace(request, stop=()))
63
+ matches = [
64
+ (response.text.find(value), index, value)
65
+ for index, value in enumerate(request.stop)
66
+ if value in response.text
67
+ ]
68
+ match = min(matches) if matches else None
69
+ return replace(
70
+ response,
71
+ text=response.text[:match[0]] if match else response.text,
72
+ finish_reason="stop" if match else response.finish_reason,
73
+ raw={
74
+ **dict(response.raw),
75
+ "agentinputlab_final_channel_stop": {
76
+ "policy_id": POLICY_ID,
77
+ "requested_stop": list(request.stop),
78
+ "matched_stop": match[2] if match else None,
79
+ "provider_finish_reason": response.finish_reason,
80
+ "provider_usage_unchanged": True,
81
+ "new_call_added_by_adapter": False,
82
+ },
83
+ },
84
+ )