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,218 @@
1
+ """Cache-first benchmark preparation with bounded, opt-out network acquisition.
2
+
3
+ Only source-locked loaders are exposed here. Inventory entries without a locked
4
+ loader are not downloaded under a guessed URL. Large datasets require an explicit
5
+ larger byte limit; loading a small test sample never silently downloads a full
6
+ multi-GB corpus.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import os
12
+ from pathlib import Path
13
+
14
+ from agentinputlab.artifacts import AcquisitionPolicy, ArtifactKind, ArtifactManifest, ArtifactStore
15
+ from agentinputlab.contracts import ArtifactError, ValidationError
16
+ from agentinputlab.data import (
17
+ DownloadPolicy,
18
+ PinnedHTTPSDownloadTransport,
19
+ download_artifact_streamed,
20
+ )
21
+ from agentinputlab.data.storage import (
22
+ DEFAULT_PREPARED_LIMIT,
23
+ positive_byte_limit,
24
+ require_storage_capacity,
25
+ )
26
+
27
+ from .acquisition import materialize_benchmark_asset
28
+ from .assets import BenchmarkSmokeAssetRegistry
29
+ from .beir_archive import BEIR_ARCHIVE_LOCKS, BEIRArchiveAdapter
30
+ from .preprocess import _prepared_path, load_prepared_benchmark
31
+ from .production import load_production_benchmark_adapter, production_benchmark_specs
32
+
33
+ DEFAULT_DOWNLOAD_LIMIT = 512 * 1024 * 1024
34
+
35
+
36
+ def benchmark_cache_dir(cache_dir: str | Path | None = None) -> Path:
37
+ """Resolve a toolkit-owned cache, without changing HF or research caches."""
38
+ value = cache_dir or os.environ.get("AGENTINPUTLAB_CACHE")
39
+ return (
40
+ (Path(value) if value else Path.home() / ".cache" / "agentinputlab").expanduser().resolve()
41
+ )
42
+
43
+
44
+ def _source_manifest(cell_id: str) -> ArtifactManifest:
45
+ lock = BEIR_ARCHIVE_LOCKS[cell_id]
46
+ return ArtifactManifest(
47
+ artifact_id=cell_id,
48
+ kind=ArtifactKind.DATASET,
49
+ revision=lock["sha256"],
50
+ sha256=lock["sha256"],
51
+ acquisition=AcquisitionPolicy.DOWNLOAD,
52
+ license_id="NOASSERTION",
53
+ source_uri="https://public.ukp.informatik.tu-darmstadt.de/thakur/BEIR/datasets/"
54
+ + lock["dataset"]
55
+ + ".zip",
56
+ size_bytes=lock["size_bytes"],
57
+ )
58
+
59
+
60
+ def _require_download_capacity(root: Path, total_bytes: int, limit: int) -> None:
61
+ positive_byte_limit(limit, name="max_download_bytes")
62
+ if total_bytes > limit:
63
+ raise ArtifactError(
64
+ f"missing sources need {total_bytes:,} bytes, above max_download_bytes={limit:,}; "
65
+ "use a documented source-side sample or explicitly raise the limit for a full download"
66
+ )
67
+ require_storage_capacity([(root, total_bytes)])
68
+
69
+
70
+ def prepare_benchmark(
71
+ cell_id: str,
72
+ *,
73
+ cache_dir: str | Path | None = None,
74
+ offline: bool = False,
75
+ accept_license_review: bool = False,
76
+ max_download_bytes: int = DEFAULT_DOWNLOAD_LIMIT,
77
+ max_prepared_bytes: int = DEFAULT_PREPARED_LIMIT,
78
+ ) -> dict:
79
+ """Reuse a verified cache or download missing pinned sources automatically.
80
+
81
+ ``offline=True`` prohibits all network calls. The default download budget is
82
+ 512 MiB across missing source files, not an unbounded per-file allowance.
83
+ License-review sources require explicit acknowledgement, including cache use.
84
+ Corrupt caches raise an integrity error and are never silently overwritten.
85
+ """
86
+ root = benchmark_cache_dir(cache_dir)
87
+ positive_byte_limit(max_download_bytes, name="max_download_bytes")
88
+ positive_byte_limit(max_prepared_bytes, name="max_prepared_bytes")
89
+ specs = {s.cell_id: s for s in production_benchmark_specs()}
90
+ if cell_id in specs:
91
+ spec = specs[cell_id]
92
+ registry = BenchmarkSmokeAssetRegistry.default()
93
+ assets = [registry.get(x) for x in (spec.query_asset_id, spec.corpus_asset_id) if x]
94
+ if not accept_license_review and any(a.status == "license_review_required" for a in assets):
95
+ raise ArtifactError("review upstream dataset terms and pass accept_license_review=True")
96
+ prepared = root / "prepared"
97
+ missing = []
98
+ for asset in assets:
99
+ # A prepared cache remains usable after its raw download is cleaned.
100
+ if _prepared_path(asset, prepared).exists():
101
+ load_prepared_benchmark(asset, prepared)
102
+ else:
103
+ missing.append(asset)
104
+ store = ArtifactStore(root / "sources")
105
+ uncached = []
106
+ for asset in missing:
107
+ manifest = asset.artifact_manifest()
108
+ if store.path_for(manifest).exists():
109
+ store.verify(manifest)
110
+ else:
111
+ uncached.append(asset)
112
+ if uncached and offline:
113
+ raise ArtifactError(f"{cell_id} is not cached; offline mode prohibits downloads")
114
+ if uncached:
115
+ _require_download_capacity(
116
+ root, sum(a.size_bytes for a in uncached), max_download_bytes
117
+ )
118
+ if missing:
119
+ require_storage_capacity(
120
+ [
121
+ (root / "sources", sum(a.size_bytes for a in uncached)),
122
+ (prepared, len(missing) * max_prepared_bytes),
123
+ ]
124
+ )
125
+ reports = [
126
+ materialize_benchmark_asset(
127
+ a.asset_id,
128
+ store_root=root / "sources",
129
+ prepared_root=prepared,
130
+ allow_network=not offline,
131
+ accept_license_review=accept_license_review,
132
+ max_download_bytes=max_download_bytes,
133
+ max_prepared_bytes=max_prepared_bytes,
134
+ )
135
+ for a in missing
136
+ ]
137
+ return {
138
+ "cell_id": cell_id,
139
+ "cache_dir": str(root),
140
+ "kind": "production",
141
+ "prepared_root": str(prepared),
142
+ "acquisitions": reports,
143
+ }
144
+ if cell_id in BEIR_ARCHIVE_LOCKS:
145
+ if not accept_license_review:
146
+ raise ArtifactError("review upstream dataset terms and pass accept_license_review=True")
147
+ manifest = _source_manifest(cell_id)
148
+ store = ArtifactStore(root / "sources")
149
+ path = store.path_for(manifest)
150
+ acquired = "cache"
151
+ if path.exists():
152
+ store.verify(manifest)
153
+ else:
154
+ if offline:
155
+ raise ArtifactError(f"{cell_id} is not cached; offline mode prohibits downloads")
156
+ _require_download_capacity(root, manifest.size_bytes, max_download_bytes)
157
+ path = Path(
158
+ download_artifact_streamed(
159
+ manifest,
160
+ store,
161
+ policy=DownloadPolicy(
162
+ allow_network=True,
163
+ allowed_hosts=("public.ukp.informatik.tu-darmstadt.de",),
164
+ max_bytes=max_download_bytes,
165
+ ),
166
+ transport=PinnedHTTPSDownloadTransport(),
167
+ )
168
+ )
169
+ acquired = "network"
170
+ return {
171
+ "cell_id": cell_id,
172
+ "cache_dir": str(root),
173
+ "kind": "beir_archive",
174
+ "source_archive": str(path),
175
+ "source_sha256": manifest.sha256,
176
+ "acquired_from": acquired,
177
+ }
178
+ raise ValidationError(
179
+ f"{cell_id!r} has no automatic source-locked loader yet; use its documented native adapter"
180
+ )
181
+
182
+
183
+ def load_benchmark(
184
+ cell_id: str,
185
+ *,
186
+ cache_dir: str | Path | None = None,
187
+ offline: bool = False,
188
+ accept_license_review: bool = False,
189
+ max_download_bytes: int = DEFAULT_DOWNLOAD_LIMIT,
190
+ max_prepared_bytes: int = DEFAULT_PREPARED_LIMIT,
191
+ **runtime,
192
+ ):
193
+ """Prepare missing data and construct the corresponding official adapter."""
194
+ # Check dynamic-runtime requirements before spending bandwidth.
195
+ if cell_id == "tau3.banking_knowledge" and (
196
+ runtime.get("checkpoints") is None or runtime.get("evaluation_bridge") is None
197
+ ):
198
+ raise ValidationError(
199
+ "tau3 requires captured checkpoints and an evaluation_bridge before downloading"
200
+ )
201
+ report = prepare_benchmark(
202
+ cell_id,
203
+ cache_dir=cache_dir,
204
+ offline=offline,
205
+ accept_license_review=accept_license_review,
206
+ max_download_bytes=max_download_bytes,
207
+ max_prepared_bytes=max_prepared_bytes,
208
+ )
209
+ if report["kind"] == "beir_archive":
210
+ if runtime:
211
+ raise ValidationError("BEIR archive loader accepts no dynamic-runtime arguments")
212
+ return BEIRArchiveAdapter(
213
+ benchmark_id=cell_id, source_archive=report["source_archive"], license_acknowledged=True
214
+ )
215
+ return load_production_benchmark_adapter(cell_id, report["prepared_root"], **runtime)
216
+
217
+
218
+ __all__ = ["DEFAULT_DOWNLOAD_LIMIT", "benchmark_cache_dir", "load_benchmark", "prepare_benchmark"]
@@ -0,0 +1,203 @@
1
+ """Small source-verified ClariQ dev adapter and native RQ1/RQ2 scoring.
2
+
3
+ No upstream rows or unlicensed scoring code are redistributed. The caller mounts
4
+ the three pinned files and explicitly reviews their local-use terms. Document
5
+ utility (RQ3) needs a different bundle and is not approximated here.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import contextlib
11
+ import csv
12
+ import importlib.util
13
+ import io
14
+ import json
15
+ from collections.abc import Mapping, Sequence
16
+ from dataclasses import dataclass
17
+ from pathlib import Path
18
+ from types import MappingProxyType
19
+
20
+ from agentinputlab.artifacts import sha256_file
21
+ from agentinputlab.backends import Document, InMemoryBM25Retriever
22
+ from agentinputlab.contracts.errors import ArtifactError, ValidationError
23
+
24
+ from .base import BenchmarkExample
25
+
26
+ CLARIQ_REVISION = "46885a544581a0af8aff0681d29e4971807e2912"
27
+ CLARIQ_FILES = MappingProxyType({
28
+ "data/dev.tsv": "68d2a5f87eab73721979b5f45f64099a9b2f080db1d0ce4b979d9daa4249906e",
29
+ "data/question_bank.tsv": "266f501bdc31afbc8a763685ea0de82949137a2779241b325f5ee03026f42f1b",
30
+ "src/clariq_eval_tool.py": "6b3258c4d09ee9d0aa6901a0d3210a5535bc3f75049998b1a4b1d00be84ae210",
31
+ })
32
+
33
+
34
+ @dataclass(frozen=True, slots=True)
35
+ class ClariQPrediction:
36
+ clarification_need: int
37
+ ranked_question_ids: tuple[str, ...]
38
+
39
+ def __post_init__(self) -> None:
40
+ if type(self.clarification_need) is not int or self.clarification_need not in range(1, 5):
41
+ raise ValidationError("ClariQ clarification_need must be an integer in [1, 4]")
42
+ if isinstance(self.ranked_question_ids, (str, bytes)):
43
+ raise ValidationError("ClariQ ranked question IDs must be a sequence, not text")
44
+ ids = tuple(self.ranked_question_ids)
45
+ if not ids or any(not isinstance(value, str) or not value for value in ids):
46
+ raise ValidationError("ClariQ requires non-empty ranked question IDs")
47
+ if len(set(ids)) != len(ids):
48
+ raise ValidationError("ClariQ ranked question IDs must be unique")
49
+ object.__setattr__(self, "ranked_question_ids", ids)
50
+
51
+
52
+ def _read_tsv(path: Path) -> tuple[list[str], list[dict[str, str]]]:
53
+ with path.open(encoding="utf-8", newline="") as handle:
54
+ reader = csv.DictReader(handle, delimiter="\t")
55
+ rows = list(reader)
56
+ return list(reader.fieldnames or []), rows
57
+
58
+
59
+ def _topic_queries(rows: Sequence[Mapping[str, str]]) -> dict[str, str]:
60
+ topics: dict[str, str] = {}
61
+ labels: dict[str, str] = {}
62
+ for row in rows:
63
+ topic, query, label = row["topic_id"], row["initial_request"], row["clarification_need"]
64
+ if not topic.isdigit() or not query.strip() or label not in {"1", "2", "3", "4"}:
65
+ raise ArtifactError("invalid ClariQ topic, initial request or clarification label")
66
+ if topic in topics and (topics[topic] != query or labels[topic] != label):
67
+ raise ArtifactError("conflicting rows for the same ClariQ topic")
68
+ topics[topic], labels[topic] = query, label
69
+ return topics
70
+
71
+
72
+ class ClariQDevBundle:
73
+ """One initial request per topic; facet intent and reference answers stay private.
74
+
75
+ BM25 question ranking is an explicit toolkit baseline, not an upstream model.
76
+ The complete 3,941-question bank is small; no document corpus is loaded.
77
+ """
78
+
79
+ benchmark_id = "clariq.main"
80
+ pairing_mode = "stateless_score_twice"
81
+
82
+ def __init__(self, source_root: str | Path, *, accept_license_review: bool = False):
83
+ if accept_license_review is not True:
84
+ raise ArtifactError("ClariQ NOASSERTION source requires explicit local-use terms review")
85
+ self.source_root = Path(source_root).resolve()
86
+ self._verify()
87
+ self._fields, self._rows = _read_tsv(self.source_root / "data/dev.tsv")
88
+ self._topics = _topic_queries(self._rows)
89
+ _, bank = _read_tsv(self.source_root / "data/question_bank.tsv")
90
+ self._bank = {row["question_id"]: row["question"] for row in bank}
91
+ if len(self._rows) != 2313 or len(self._topics) != 50 or len(self._bank) != 3941:
92
+ raise ArtifactError("ClariQ pinned dev or question-bank counts differ")
93
+ self._retriever = InMemoryBM25Retriever(documents=tuple(
94
+ Document(doc_id=key, text=value, corpus_revision=CLARIQ_REVISION)
95
+ for key, value in sorted(self._bank.items())
96
+ ))
97
+
98
+ def _verify(self) -> None:
99
+ for name, expected in CLARIQ_FILES.items():
100
+ path = self.source_root / name
101
+ if path.is_symlink() or not path.is_file() or path.resolve().parent != path.parent:
102
+ raise ArtifactError(f"ClariQ source is missing or linked: {name}")
103
+ if sha256_file(path) != expected:
104
+ raise ArtifactError(f"ClariQ source checksum differs: {name}")
105
+
106
+ def examples(self, split: str = "dev") -> tuple[BenchmarkExample, ...]:
107
+ if split != "dev":
108
+ raise ValidationError("this pinned ClariQ bundle exposes only dev")
109
+ return tuple(BenchmarkExample(
110
+ example_id=topic,
111
+ query=query,
112
+ instruction=("Predict how much clarification this initial user request needs. "
113
+ "Return exactly one JSON object with key clarification_need: "
114
+ "1 means no clarification, 2/3/4 mean increasing need. "
115
+ "Do not answer the request or add any other keys."),
116
+ visible_metadata={"benchmark_cell": self.benchmark_id, "source_split": "dev",
117
+ "source_revision": CLARIQ_REVISION},
118
+ ) for topic, query in sorted(self._topics.items()))
119
+
120
+ def rank_questions(self, query: str, *, top_k: int = 30) -> tuple[str, ...]:
121
+ if not isinstance(query, str) or not query.strip():
122
+ raise ValidationError("ClariQ question ranking requires a non-empty query")
123
+ if type(top_k) is not int or not 1 <= top_k <= len(self._bank):
124
+ raise ValidationError("ClariQ top_k must be a positive bank-bounded integer")
125
+ return tuple(result.document.doc_id for result in self._retriever.retrieve(query, top_k=top_k))
126
+
127
+ @property
128
+ def question_retriever(self) -> InMemoryBM25Retriever:
129
+ """Visible question-bank-only retriever; never facet descriptions or answers."""
130
+ return self._retriever
131
+
132
+ def fingerprint(self) -> dict:
133
+ return {"benchmark": self.benchmark_id, "revision": CLARIQ_REVISION,
134
+ "source_sha256": dict(CLARIQ_FILES), "question_ranker": self._retriever.fingerprint(),
135
+ "scoring": "native_RQ1_weighted_PRF_and_RQ2_Recall5_10_20_30",
136
+ "document_retrieval_utility_evaluated": False,
137
+ "license_id": "NOASSERTION", "source_redistributed": False}
138
+
139
+ def evaluate(
140
+ self, predictions: Mapping[str, ClariQPrediction], *, topic_ids: Sequence[str],
141
+ output: str | Path,
142
+ ) -> dict:
143
+ """Run unmodified native metrics on all rows of a declared topic subset.
144
+
145
+ Missing predictions remain in the selected denominator and use native
146
+ missing-run semantics. A partial subset is never reported as full dev.
147
+ All run files, stdout and per-topic scores are retained under ``output``.
148
+ This method is sequential because the upstream scorer prints to stdout.
149
+ """
150
+ selected = tuple(topic_ids)
151
+ if not selected or len(set(selected)) != len(selected) or set(selected) - self._topics.keys():
152
+ raise ValidationError("ClariQ topic_ids must be a unique non-empty known subset")
153
+ if set(predictions) - set(selected):
154
+ raise ValidationError("ClariQ prediction is outside the declared topic subset")
155
+ for prediction in predictions.values():
156
+ if not isinstance(prediction, ClariQPrediction):
157
+ raise ValidationError("ClariQ predictions must be typed ClariQPrediction objects")
158
+ if set(prediction.ranked_question_ids) - self._bank.keys():
159
+ raise ValidationError("ClariQ prediction contains a question outside the source bank")
160
+ self._verify()
161
+ directory = Path(output)
162
+ directory.mkdir(parents=True, exist_ok=False)
163
+ with (directory / "dev.tsv").open("x", encoding="utf-8", newline="") as handle:
164
+ writer = csv.DictWriter(handle, fieldnames=self._fields, delimiter="\t")
165
+ writer.writeheader()
166
+ writer.writerows(row for row in self._rows if row["topic_id"] in selected)
167
+ # The native scorer uses an empty-file pandas parser that raises. Sentinels
168
+ # are deliberately outside the declared source topics, so native lookup
169
+ # gives every missing prediction its original label 0 / recall 0 semantics.
170
+ need_lines, question_lines = ["-1 0\n"], ["-1 Q0 Q00001 1 1 missing\n"]
171
+ for topic, prediction in sorted(predictions.items()):
172
+ need_lines.append(f"{topic} {prediction.clarification_need}\n")
173
+ for rank, question in enumerate(prediction.ranked_question_ids, 1):
174
+ question_lines.append(f"{topic} Q0 {question} {rank} {1.0 / rank:.17g} toolkit\n")
175
+ for name, lines in (("need.run", need_lines), ("questions.run", question_lines)):
176
+ with (directory / name).open("x", encoding="utf-8") as handle:
177
+ handle.writelines(lines)
178
+ scorer = self.source_root / "src/clariq_eval_tool.py"
179
+ spec = importlib.util.spec_from_file_location("_ail_pinned_clariq_evaluator", scorer)
180
+ module = importlib.util.module_from_spec(spec)
181
+ spec.loader.exec_module(module)
182
+ stdout = io.StringIO()
183
+ with contextlib.redirect_stdout(stdout):
184
+ module.evaluate_clarification_need("dev", str(directory), str(directory / "need.run"), "", False)
185
+ module.evaluate_question_relevance("dev", str(directory), str(directory / "questions.run"),
186
+ str(directory / "question_scores.json"), False)
187
+ metrics = {}
188
+ names = {"Precision": "weighted_precision", "Recall": "weighted_recall", "F1": "weighted_f1"}
189
+ for line in stdout.getvalue().splitlines():
190
+ name, _, value = line.partition(":")
191
+ if name.strip() in names or name.strip() in {"Recall5", "Recall10", "Recall20", "Recall30"}:
192
+ metrics[names.get(name.strip(), name.strip())] = float(value.strip())
193
+ if len(metrics) != 7:
194
+ raise ArtifactError("ClariQ native evaluator did not emit the seven expected metrics")
195
+ result = {"metrics": metrics, "native_stdout": stdout.getvalue(),
196
+ "topic_ids": list(selected), "predicted_topics": len(predictions),
197
+ "missing_predictions": sorted(set(selected) - predictions.keys()),
198
+ "evaluation_scope": "full_dev" if len(selected) == 50 else "fixed_dev_compatibility_subset",
199
+ "native_scorer_sha256": CLARIQ_FILES["src/clariq_eval_tool.py"],
200
+ "document_retrieval_utility_evaluated": False, "source_fingerprint": self.fingerprint()}
201
+ with (directory / "native-evaluation.json").open("x", encoding="utf-8") as handle:
202
+ json.dump(result, handle, indent=2, sort_keys=True)
203
+ return result