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,226 @@
1
+ """Versioned, checksum-pinned benchmark smoke assets.
2
+
3
+ The benchmark inventory describes experimental coverage. This module
4
+ is intentionally separate: it lists only source files that have been fetched,
5
+ byte-verified, and assigned a deterministic preprocessing recipe. A registry
6
+ cell therefore does not imply that its full data is already materializable.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import json
12
+ import re
13
+ import urllib.parse
14
+ from collections.abc import Mapping
15
+ from dataclasses import dataclass
16
+ from importlib import resources
17
+ from types import MappingProxyType
18
+ from typing import Any
19
+
20
+ from agentinputlab.artifacts import AcquisitionPolicy, ArtifactKind, ArtifactManifest
21
+ from agentinputlab.contracts.errors import RegistryError
22
+
23
+ _SHA256 = re.compile(r"^[0-9a-f]{64}$")
24
+ _SAFE_SEGMENT = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]*$")
25
+ _KNOWN_STATUSES = {"verified_smoke", "license_review_required"}
26
+ _KNOWN_REDISTRIBUTION = {"downloader_only", "not_redistributed"}
27
+ _KNOWN_PROCESSORS = {
28
+ "beir_zip_v1",
29
+ "bfcl_v3_simple_tar_v1",
30
+ "bright_corpus_parquet_v1",
31
+ "bright_examples_parquet_v1",
32
+ "clariq_tsv_v1",
33
+ "hotpotqa_parquet_v1",
34
+ "musique_zip_v1",
35
+ "qasper_tgz_v1",
36
+ "tau3_banking_tar_v1",
37
+ "two_wiki_zip_v1",
38
+ }
39
+
40
+
41
+ def _string_mapping(value: Any, *, label: str) -> Mapping[str, str]:
42
+ if not isinstance(value, Mapping):
43
+ raise RegistryError(f"{label} must be a mapping")
44
+ converted: dict[str, str] = {}
45
+ for key, item in value.items():
46
+ if not isinstance(key, str) or not isinstance(item, str):
47
+ raise RegistryError(f"{label} keys and values must be strings")
48
+ converted[key] = item
49
+ return converted
50
+
51
+
52
+ def _count_mapping(value: Any, *, label: str) -> Mapping[str, int]:
53
+ if not isinstance(value, Mapping):
54
+ raise RegistryError(f"{label} must be a mapping")
55
+ converted: dict[str, int] = {}
56
+ for key, item in value.items():
57
+ if not isinstance(key, str) or not isinstance(item, int) or isinstance(item, bool):
58
+ raise RegistryError(f"{label} keys must be strings and values must be integers")
59
+ if item < 0:
60
+ raise RegistryError(f"{label} values must be non-negative")
61
+ converted[key] = item
62
+ return converted
63
+
64
+
65
+ @dataclass(frozen=True, slots=True)
66
+ class BenchmarkSmokeAsset:
67
+ asset_id: str
68
+ cell_id: str
69
+ source_url: str
70
+ source_revision: str
71
+ sha256: str
72
+ size_bytes: int
73
+ license_id: str
74
+ redistribution: str
75
+ status: str
76
+ processor: str
77
+ expected_counts: Mapping[str, int]
78
+ prepared_sha256: Mapping[str, str]
79
+ allowed_hosts: tuple[str, ...]
80
+ provenance: Mapping[str, str]
81
+ note: str = ""
82
+
83
+ def __post_init__(self) -> None:
84
+ object.__setattr__(
85
+ self,
86
+ "allowed_hosts",
87
+ tuple(sorted({host.strip().lower() for host in self.allowed_hosts if host.strip()})),
88
+ )
89
+ object.__setattr__(self, "expected_counts", MappingProxyType(dict(self.expected_counts)))
90
+ object.__setattr__(self, "prepared_sha256", MappingProxyType(dict(self.prepared_sha256)))
91
+ object.__setattr__(self, "provenance", MappingProxyType(dict(self.provenance)))
92
+ parsed = urllib.parse.urlsplit(self.source_url)
93
+ if not _SAFE_SEGMENT.fullmatch(self.asset_id) or ".." in self.asset_id:
94
+ raise RegistryError("benchmark asset_id must be a flat safe identifier")
95
+ if not _SAFE_SEGMENT.fullmatch(self.source_revision) or ".." in self.source_revision:
96
+ raise RegistryError("benchmark source_revision must be a flat safe identifier")
97
+ if parsed.scheme != "https" or not parsed.hostname:
98
+ raise RegistryError(f"benchmark asset {self.asset_id!r} requires an HTTPS source")
99
+ if parsed.username is not None or parsed.password is not None:
100
+ raise RegistryError("benchmark asset URLs must not contain user information")
101
+ if not _SHA256.fullmatch(self.sha256):
102
+ raise RegistryError(f"benchmark asset {self.asset_id!r} has an invalid SHA-256")
103
+ if isinstance(self.size_bytes, bool) or not isinstance(self.size_bytes, int):
104
+ raise RegistryError(f"benchmark asset {self.asset_id!r} size must be an integer")
105
+ if self.size_bytes < 1:
106
+ raise RegistryError(f"benchmark asset {self.asset_id!r} has an invalid size")
107
+ if self.status not in _KNOWN_STATUSES:
108
+ raise RegistryError(f"benchmark asset {self.asset_id!r} has an unknown status")
109
+ if self.redistribution not in _KNOWN_REDISTRIBUTION:
110
+ raise RegistryError(
111
+ f"benchmark asset {self.asset_id!r} has an unknown redistribution policy"
112
+ )
113
+ if self.processor not in _KNOWN_PROCESSORS:
114
+ raise RegistryError(f"benchmark asset {self.asset_id!r} has an unknown processor")
115
+ if any(not _SHA256.fullmatch(digest) for digest in self.prepared_sha256.values()):
116
+ raise RegistryError(
117
+ f"benchmark asset {self.asset_id!r} has an invalid prepared SHA-256"
118
+ )
119
+ if not set(self.prepared_sha256) <= {
120
+ "audit.jsonl",
121
+ "inputs.jsonl",
122
+ "gold.jsonl",
123
+ "corpus.jsonl",
124
+ }:
125
+ raise RegistryError(f"benchmark asset {self.asset_id!r} has unknown prepared files")
126
+ if not self.allowed_hosts or parsed.hostname.lower() not in self.allowed_hosts:
127
+ raise RegistryError(
128
+ f"benchmark asset {self.asset_id!r} must allowlist its source hostname"
129
+ )
130
+ if self.license_id == "NOASSERTION" and self.status != "license_review_required":
131
+ raise RegistryError("NOASSERTION benchmark assets must remain license-review gated")
132
+
133
+ @classmethod
134
+ def from_mapping(cls, value: Mapping[str, Any]) -> BenchmarkSmokeAsset:
135
+ try:
136
+ hosts = value["allowed_hosts"]
137
+ if not isinstance(hosts, list) or not all(isinstance(item, str) for item in hosts):
138
+ raise RegistryError("benchmark asset allowed_hosts must be a string list")
139
+ expected_counts = _count_mapping(
140
+ value["expected_counts"], label="benchmark asset expected_counts"
141
+ )
142
+ provenance = _string_mapping(
143
+ value.get("provenance", {}), label="benchmark asset provenance"
144
+ )
145
+ prepared_sha256 = _string_mapping(
146
+ value.get("prepared_sha256", {}), label="benchmark asset prepared_sha256"
147
+ )
148
+ return cls(
149
+ asset_id=str(value["asset_id"]),
150
+ cell_id=str(value["cell_id"]),
151
+ source_url=str(value["source_url"]),
152
+ source_revision=str(value["source_revision"]),
153
+ sha256=str(value["sha256"]),
154
+ size_bytes=int(value["size_bytes"]),
155
+ license_id=str(value["license_id"]),
156
+ redistribution=str(value["redistribution"]),
157
+ status=str(value["status"]),
158
+ processor=str(value["processor"]),
159
+ expected_counts=expected_counts,
160
+ prepared_sha256=prepared_sha256,
161
+ allowed_hosts=tuple(sorted({item.lower() for item in hosts})),
162
+ provenance=provenance,
163
+ note=str(value.get("note", "")),
164
+ )
165
+ except (KeyError, TypeError, ValueError) as exc:
166
+ raise RegistryError(f"invalid benchmark smoke asset: {value!r}") from exc
167
+
168
+ def artifact_manifest(self) -> ArtifactManifest:
169
+ """Project the source lock into the shared artifact-store contract."""
170
+
171
+ return ArtifactManifest(
172
+ artifact_id=self.asset_id,
173
+ kind=ArtifactKind.DATASET,
174
+ revision=self.source_revision,
175
+ sha256=self.sha256,
176
+ acquisition=AcquisitionPolicy.DOWNLOAD,
177
+ license_id=self.license_id,
178
+ source_uri=self.source_url,
179
+ size_bytes=self.size_bytes,
180
+ lineage={"benchmark_cell": self.cell_id, "processor": self.processor},
181
+ metadata={
182
+ "redistribution": self.redistribution,
183
+ "status": self.status,
184
+ "provenance": dict(self.provenance),
185
+ "prepared_sha256": dict(self.prepared_sha256),
186
+ },
187
+ )
188
+
189
+
190
+ class BenchmarkSmokeAssetRegistry:
191
+ def __init__(self, assets: tuple[BenchmarkSmokeAsset, ...]) -> None:
192
+ if not assets:
193
+ raise RegistryError("benchmark smoke asset registry must not be empty")
194
+ if len({asset.asset_id for asset in assets}) != len(assets):
195
+ raise RegistryError("benchmark smoke asset IDs must be unique")
196
+ self._assets = assets
197
+ self._by_id = {asset.asset_id: asset for asset in assets}
198
+
199
+ @classmethod
200
+ def default(cls) -> BenchmarkSmokeAssetRegistry:
201
+ resource = resources.files("agentinputlab.benchmarks").joinpath("data", "smoke_assets.json")
202
+ payload = json.loads(resource.read_text(encoding="utf-8"))
203
+ if payload.get("schema_version") != 1:
204
+ raise RegistryError("unsupported benchmark smoke asset registry snapshot")
205
+ raw_assets = payload.get("assets")
206
+ if not isinstance(raw_assets, list) or payload.get("asset_count") != len(raw_assets):
207
+ raise RegistryError("benchmark smoke asset count does not match its payload")
208
+ return cls(tuple(BenchmarkSmokeAsset.from_mapping(item) for item in raw_assets))
209
+
210
+ def get(self, asset_id: str) -> BenchmarkSmokeAsset:
211
+ try:
212
+ return self._by_id[asset_id]
213
+ except KeyError as exc:
214
+ raise RegistryError(f"unknown benchmark smoke asset: {asset_id}") from exc
215
+
216
+ def list(
217
+ self,
218
+ *,
219
+ include_license_review: bool = False,
220
+ ) -> tuple[BenchmarkSmokeAsset, ...]:
221
+ if include_license_review:
222
+ return self._assets
223
+ return tuple(asset for asset in self._assets if asset.status == "verified_smoke")
224
+
225
+ def __len__(self) -> int:
226
+ return len(self._assets)
@@ -0,0 +1,68 @@
1
+ """Benchmark adapter contracts that physically isolate evaluator gold."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Mapping
6
+ from dataclasses import dataclass, field
7
+ from typing import Any, Protocol, runtime_checkable
8
+
9
+ from agentinputlab.contracts.serialization import content_hash
10
+ from agentinputlab.contracts.state import (
11
+ ContextBlock,
12
+ ExecutionBudget,
13
+ FrozenAgentState,
14
+ Message,
15
+ )
16
+
17
+
18
+ @dataclass(frozen=True, slots=True)
19
+ class BenchmarkExample:
20
+ example_id: str
21
+ query: str
22
+ instruction: str = ""
23
+ visible_context: tuple[ContextBlock, ...] = ()
24
+ visible_messages: tuple[Message, ...] = ()
25
+ visible_metadata: Mapping[str, Any] = field(default_factory=dict)
26
+ evaluator_gold: Mapping[str, Any] = field(default_factory=dict, repr=False)
27
+ visible_tool_names: tuple[str, ...] = ()
28
+ optimizer_visible_id: str | None = None
29
+
30
+ def visible_state(self, *, budget: ExecutionBudget | None = None) -> FrozenAgentState:
31
+ """Create a state with no reference to evaluator-only fields."""
32
+
33
+ return FrozenAgentState(
34
+ task_id=self.optimizer_visible_id or self.example_id,
35
+ query=self.query,
36
+ instruction=self.instruction,
37
+ context=self.visible_context,
38
+ messages=self.visible_messages,
39
+ tool_names=self.visible_tool_names,
40
+ metadata=dict(self.visible_metadata),
41
+ budget=budget or ExecutionBudget(),
42
+ )
43
+
44
+
45
+ def opaque_checkpoint_state_id(
46
+ benchmark_id: str,
47
+ checkpoint_id: str,
48
+ replay_identity: str,
49
+ ) -> str:
50
+ """Derive a stable predictor-visible ID without exposing protected labels."""
51
+
52
+ return "ailcp_" + content_hash(
53
+ {
54
+ "benchmark_id": benchmark_id,
55
+ "checkpoint_id": checkpoint_id,
56
+ "replay_identity": replay_identity,
57
+ }
58
+ )
59
+
60
+
61
+ @runtime_checkable
62
+ class BenchmarkAdapter(Protocol):
63
+ benchmark_id: str
64
+ pairing_mode: str
65
+
66
+ def examples(self, split: str) -> tuple[BenchmarkExample, ...]: ...
67
+
68
+ def score(self, example: BenchmarkExample, prediction: Any) -> Mapping[str, float]: ...
@@ -0,0 +1,235 @@
1
+ """Checksum-pinned BEIR archives with streamed corpus access and held-out qrels.
2
+
3
+ No dataset is bundled. This loader preserves the complete corpus and official
4
+ test judgments, including queries whose IDs overlap corpus IDs. CQADupstack
5
+ uses explicit forum namespaces and never merges equal IDs from different forums.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import csv
11
+ import io
12
+ import json
13
+ import stat
14
+ import zipfile
15
+ from pathlib import Path, PurePosixPath
16
+ from types import MappingProxyType
17
+
18
+ from agentinputlab.artifacts import sha256_file
19
+ from agentinputlab.backends import Document
20
+ from agentinputlab.contracts import ArtifactError, ValidationError
21
+
22
+ from .base import BenchmarkExample
23
+ from .retrieval import PreparedRetrievalBenchmarkAdapter
24
+
25
+ # Raw source hashes independently match the upstream BEIR download table's MD5.
26
+ BEIR_ARCHIVE_LOCKS = {
27
+ "beir.fiqa_2018": {
28
+ "dataset": "fiqa",
29
+ "size_bytes": 17948027,
30
+ "sha256": "32c7df99ed21252fdfb2cf3f5673502a8d245ee0c44c4a133570d92ce2b3ad02",
31
+ "upstream_md5": "17918ed23cd04fb15047f73e6c3bd9d9",
32
+ },
33
+ "beir.quora": {
34
+ "dataset": "quora",
35
+ "size_bytes": 15853968,
36
+ "sha256": "56aacd9dcc4d9c093b63f175afdda0e21cbc8442ecf6c717d09de7b358d77531",
37
+ "upstream_md5": "18fb154900ba42a600f84b839c173167",
38
+ },
39
+ "beir.dbpedia_entity": {
40
+ "dataset": "dbpedia-entity",
41
+ "size_bytes": 639285131,
42
+ "sha256": "e4c13080b5399a19e02b04c908c485f8997ac9e265a06ef5f9f28c3f1134c472",
43
+ "upstream_md5": "c2a39eb420a3164af735795df012ac2c",
44
+ },
45
+ "beir.fever": {
46
+ "dataset": "fever",
47
+ "size_bytes": 1236988269,
48
+ "sha256": "58b3faee0c152158b27970380f778ea56e4e34482034404226c10e11eadc7b72",
49
+ "upstream_md5": "5a818580227bfb4b35bb6fa46d9b6c03",
50
+ },
51
+ }
52
+ _FORUMS = (
53
+ "android",
54
+ "english",
55
+ "gaming",
56
+ "gis",
57
+ "mathematica",
58
+ "physics",
59
+ "programmers",
60
+ "stats",
61
+ "tex",
62
+ "unix",
63
+ "webmasters",
64
+ "wordpress",
65
+ )
66
+
67
+
68
+ class BEIRArchiveAdapter(PreparedRetrievalBenchmarkAdapter):
69
+ """Official test cases, native IR measures, and a streaming complete corpus."""
70
+
71
+ def __init__(
72
+ self, *, benchmark_id: str, source_archive: str | Path, license_acknowledged: bool = False
73
+ ):
74
+ if not license_acknowledged:
75
+ raise ValidationError(
76
+ "mounted BEIR dataset requires license_acknowledged=True; data licenses are separate from code"
77
+ )
78
+ if benchmark_id not in BEIR_ARCHIVE_LOCKS:
79
+ raise ValidationError("BEIR archive cell has no verified source lock")
80
+ self.lock = dict(BEIR_ARCHIVE_LOCKS[benchmark_id])
81
+ self.path = Path(source_archive)
82
+ if not self.path.is_file() or self.path.stat().st_size != self.lock["size_bytes"]:
83
+ raise ArtifactError("BEIR archive size differs")
84
+ sha = sha256_file(self.path)
85
+ if sha != self.lock["sha256"]:
86
+ raise ArtifactError("BEIR archive checksum differs")
87
+ self.benchmark_id = benchmark_id
88
+ self.split = "test"
89
+ self._ignore_identical_ids = True
90
+ with zipfile.ZipFile(self.path) as archive:
91
+ self.groups = self._validate(archive)
92
+ examples = []
93
+ for group, prefix in self.groups:
94
+ qrels = {}
95
+ with archive.open(prefix + "qrels/test.tsv") as raw:
96
+ reader = csv.DictReader(io.TextIOWrapper(raw, encoding="utf-8"), delimiter="\t")
97
+ if reader.fieldnames != ["query-id", "corpus-id", "score"]:
98
+ raise ArtifactError("BEIR qrels schema differs")
99
+ for row in reader:
100
+ qid = self._id(group, row["query-id"])
101
+ did = self._id(group, row["corpus-id"])
102
+ score = int(row["score"])
103
+ if score < 0 or did in qrels.setdefault(qid, {}):
104
+ raise ArtifactError("BEIR invalid or duplicate judgment")
105
+ qrels[qid][did] = score
106
+ queries = {}
107
+ for row in self._rows(archive, prefix + "queries.jsonl"):
108
+ qid = self._id(group, row["_id"])
109
+ if qid in queries:
110
+ raise ArtifactError("BEIR duplicate query ID")
111
+ if not isinstance(row["text"], str) or not row["text"].strip():
112
+ raise ArtifactError("BEIR query text is empty")
113
+ queries[qid] = row["text"]
114
+ if set(qrels) - set(queries):
115
+ raise ArtifactError("BEIR qrels refer to absent queries")
116
+ for qid in sorted(qrels):
117
+ if not any(s > 0 for s in qrels[qid].values()):
118
+ raise ArtifactError("BEIR test query lacks positive judgment")
119
+ examples.append(
120
+ BenchmarkExample(
121
+ example_id=qid,
122
+ query=queries[qid],
123
+ instruction="Retrieve the most relevant "
124
+ + (
125
+ "duplicate questions."
126
+ if self.lock["dataset"] in ("quora", "cqadupstack")
127
+ else "documents."
128
+ ),
129
+ visible_metadata=MappingProxyType(
130
+ {
131
+ "benchmark_cell": benchmark_id,
132
+ "source_split": "test",
133
+ "forum": group,
134
+ }
135
+ ),
136
+ evaluator_gold=MappingProxyType(
137
+ {"relevance": MappingProxyType(qrels[qid])}
138
+ ),
139
+ )
140
+ )
141
+ self._examples = tuple(examples)
142
+ self._examples_by_id = {e.example_id: e for e in examples}
143
+
144
+ def _validate(self, archive):
145
+ infos = archive.infolist()
146
+ names = set()
147
+ total = 0
148
+ if len(infos) > 256:
149
+ raise ArtifactError("BEIR archive has too many members")
150
+ for info in infos:
151
+ path = PurePosixPath(info.filename)
152
+ if (
153
+ path.is_absolute()
154
+ or ".." in path.parts
155
+ or "\\" in info.filename
156
+ or info.filename in names
157
+ or stat.S_ISLNK(info.external_attr >> 16)
158
+ ):
159
+ raise ArtifactError("BEIR archive contains unsafe/duplicate members")
160
+ names.add(info.filename)
161
+ total += info.file_size
162
+ if info.file_size > 12 * 1024**3 or info.file_size / max(info.compress_size, 1) > 400:
163
+ raise ArtifactError("BEIR archive member is oversized")
164
+ if total > 24 * 1024**3:
165
+ raise ArtifactError("BEIR archive is oversized")
166
+ dataset = self.lock["dataset"]
167
+ if dataset == "cqadupstack":
168
+ groups = tuple((f, "cqadupstack/" + f + "/") for f in _FORUMS)
169
+ else:
170
+ groups = (("", dataset + "/"),)
171
+ for _, prefix in groups:
172
+ if (
173
+ not {prefix + "corpus.jsonl", prefix + "queries.jsonl", prefix + "qrels/test.tsv"}
174
+ <= names
175
+ ):
176
+ raise ArtifactError("BEIR required corpus/query/test members missing")
177
+ return groups
178
+
179
+ @staticmethod
180
+ def _id(group, value):
181
+ if not isinstance(value, str) or not value:
182
+ raise ArtifactError("BEIR source ID must be nonempty text")
183
+ return group + "::" + value if group else value
184
+
185
+ @staticmethod
186
+ def _rows(archive, name):
187
+ with archive.open(name) as raw:
188
+ for line in io.TextIOWrapper(raw, encoding="utf-8"):
189
+ row = json.loads(line)
190
+ if not isinstance(row, dict):
191
+ raise ArtifactError("BEIR JSONL record must be object")
192
+ yield row
193
+
194
+ def iter_documents(self, *, forum: str | None = None):
195
+ """Yield all source documents, without loading full corpora into RAM."""
196
+ if forum is not None and forum not in {g for g, _ in self.groups}:
197
+ raise ValidationError("unknown BEIR forum")
198
+ with zipfile.ZipFile(self.path) as archive:
199
+ for group, prefix in self.groups:
200
+ if forum is not None and group != forum:
201
+ continue
202
+ for row in self._rows(archive, prefix + "corpus.jsonl"):
203
+ text = row["text"]
204
+ title = row.get("title", "")
205
+ if not isinstance(text, str) or not isinstance(title, str):
206
+ raise ArtifactError("BEIR corpus title/text must be strings")
207
+ yield Document(
208
+ doc_id=self._id(group, row["_id"]),
209
+ text=text,
210
+ title=title,
211
+ corpus_revision=self.lock["sha256"],
212
+ metadata={"forum": group},
213
+ )
214
+
215
+ def fingerprint(self):
216
+ return {
217
+ "benchmark_id": self.benchmark_id,
218
+ "source_archive_sha256": self.lock["sha256"],
219
+ "source_size_bytes": self.lock["size_bytes"],
220
+ "upstream_md5": self.lock["upstream_md5"],
221
+ "source_url": "https://public.ukp.informatik.tu-darmstadt.de/thakur/BEIR/datasets/"
222
+ + self.lock["dataset"]
223
+ + ".zip",
224
+ "split": "test",
225
+ "test_queries": len(self._examples),
226
+ "ignore_identical_ids": True,
227
+ "corpus_scope": "complete_source",
228
+ "scorer": "ir_measures:nDCG@10,R@100",
229
+ "cqadupstack_query_corpus": "same_forum_only",
230
+ "aggregate_leaderboard_claimed": False,
231
+ "licenses_bundled": False,
232
+ }
233
+
234
+
235
+ __all__ = ["BEIR_ARCHIVE_LOCKS", "BEIRArchiveAdapter"]