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,1029 @@
1
+ """R²AG hidden-state conditioning adapted to the shared agent arenas.
2
+
3
+ The upstream-compatible worker remains the strict paper-shaped composite path.
4
+ This module defines a separate common-support intervention. It preserves the
5
+ three retrieval features, R²-Former, learned projection, and marker-only input
6
+ embedding replacement. The custom reader's answer is exposed to the
7
+ downstream agent only as a non-authoritative generated anchor beside the real
8
+ retrieved documents. That final placement is an explicit agent-arena
9
+ adaptation and is never reported as upstream checkpoint or paper-result parity.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import hashlib
15
+ import importlib.util
16
+ import json
17
+ import math
18
+ import re
19
+ from collections.abc import Mapping, Sequence
20
+ from dataclasses import dataclass, field
21
+ from pathlib import Path
22
+ from types import ModuleType
23
+ from typing import Any, Protocol, runtime_checkable
24
+
25
+ from agentinputlab.backends.retrieval import RetrievalResult, Retriever
26
+ from agentinputlab.contracts import (
27
+ AlgorithmOutputError,
28
+ BudgetExceededError,
29
+ CapabilityError,
30
+ ContextBlock,
31
+ ExecutionTrace,
32
+ ExternalDependencyError,
33
+ FrozenAgentState,
34
+ InputPatch,
35
+ InterventionContext,
36
+ PatchOp,
37
+ PatchOperation,
38
+ SemanticFamily,
39
+ TraceEvent,
40
+ TracePhase,
41
+ ValidationError,
42
+ )
43
+ from agentinputlab.contracts.serialization import content_hash, freeze_mapping
44
+
45
+ from .bridge import R2AG_UPSTREAM_COMMIT, compute_r2ag_retrieval_features
46
+
47
+ _SHA256 = re.compile(r"^[0-9a-f]{64}$")
48
+ _MANIFEST_NAME = "artifact-manifest.json"
49
+ _MANIFEST_SCHEMA = "agentinputlab.r2ag-common-support-artifact.v1"
50
+ _MARKER = "<R>"
51
+ _QWEN38_FP8_BACKBONE = "Qwen3.8-27B-FP8"
52
+
53
+
54
+ def _qwen38_fp8_min_new_tokens(*, backbone: str, max_new_tokens: int) -> int | None:
55
+ """Prevent an EOS-only anchor for the exact Qwen3.8 FP8 reader.
56
+
57
+ ``generate(inputs_embeds=...)`` can otherwise terminate immediately with
58
+ EOS for a subset of prompts. R2AG requires a non-empty, explicitly
59
+ non-authoritative anchor, so require one generated token for this exact
60
+ backbone while leaving every other reader unchanged.
61
+ """
62
+
63
+ if backbone != _QWEN38_FP8_BACKBONE:
64
+ return None
65
+ return min(1, max_new_tokens)
66
+
67
+
68
+ def _sha256_file(path: Path) -> str:
69
+ digest = hashlib.sha256()
70
+ with path.open("rb") as handle:
71
+ for chunk in iter(lambda: handle.read(1024 * 1024), b""):
72
+ digest.update(chunk)
73
+ return digest.hexdigest()
74
+
75
+
76
+ def r2ag_reader_backbone_identity(model_root: Path) -> str:
77
+ """Return the portable local-snapshot identity recorded in the artifact."""
78
+
79
+ identity = model_root.expanduser().resolve().name
80
+ if not identity:
81
+ raise ValidationError("R²AG base-model snapshot identity is empty")
82
+ return identity
83
+
84
+
85
+ def _repair_qwen38_fp8_model_config(model_config: Any, *, backbone: str) -> int:
86
+ """Remove stale dense-layer exclusions from the official Qwen3.8 FP8 config.
87
+
88
+ The checkpoint contains FP8 weights and inverse scales for every language
89
+ MLP gate projection, but its generated ``modules_to_not_convert`` list also
90
+ names those gates. Transformers would therefore build a dense Linear for
91
+ an FP8 tensor and fail at the first forward pass. Keep this repair scoped
92
+ to the exact local backbone used by the campaign.
93
+ """
94
+
95
+ if backbone != _QWEN38_FP8_BACKBONE:
96
+ return 0
97
+ quantization_config = getattr(model_config, "quantization_config", None)
98
+ if not isinstance(quantization_config, Mapping):
99
+ return 0
100
+ normalized = dict(quantization_config)
101
+ if normalized.get("quant_method") != "fp8":
102
+ return 0
103
+ exclusions = list(normalized.get("modules_to_not_convert", ()))
104
+ retained = [name for name in exclusions if not str(name).endswith(".mlp.gate")]
105
+ repaired = len(exclusions) - len(retained)
106
+ if repaired:
107
+ normalized["modules_to_not_convert"] = retained
108
+ model_config.quantization_config = normalized
109
+ return repaired
110
+
111
+
112
+ @dataclass(frozen=True, slots=True)
113
+ class R2AGReaderResult:
114
+ anchor: str
115
+ input_tokens: int
116
+ output_tokens: int
117
+ marker_positions: tuple[int, ...]
118
+ rformer_output_sha256: str
119
+ projection_output_sha256: str
120
+
121
+ def __post_init__(self) -> None:
122
+ if not self.anchor.strip():
123
+ raise ValidationError("R²AG common-support reader returned an empty anchor")
124
+ for name, value in (
125
+ ("input_tokens", self.input_tokens),
126
+ ("output_tokens", self.output_tokens),
127
+ ):
128
+ if isinstance(value, bool) or not isinstance(value, int) or value < 1:
129
+ raise ValidationError(f"R²AG reader {name} must be positive")
130
+ positions = tuple(self.marker_positions)
131
+ if not positions or positions != tuple(sorted(set(positions))):
132
+ raise ValidationError("R²AG marker positions must be ordered and unique")
133
+ if any(
134
+ _SHA256.fullmatch(value) is None
135
+ for value in (
136
+ self.rformer_output_sha256,
137
+ self.projection_output_sha256,
138
+ )
139
+ ):
140
+ raise ValidationError("R²AG tensor identities must be lowercase SHA-256")
141
+ object.__setattr__(self, "marker_positions", positions)
142
+
143
+
144
+ @runtime_checkable
145
+ class R2AGCommonSupportReader(Protocol):
146
+ def run(
147
+ self,
148
+ *,
149
+ query: str,
150
+ documents: Sequence[RetrievalResult],
151
+ features: Sequence[Mapping[str, float]],
152
+ max_new_tokens: int,
153
+ seed: int,
154
+ ) -> R2AGReaderResult:
155
+ """Run R²-Former, projection, marker replacement, and generation."""
156
+
157
+ def fingerprint(self) -> Mapping[str, Any]:
158
+ """Return the closed source/model/training identity."""
159
+
160
+
161
+ @runtime_checkable
162
+ class R2AGFeatureEncoder(Protocol):
163
+ def encode(
164
+ self,
165
+ *,
166
+ query: str,
167
+ documents: Sequence[RetrievalResult],
168
+ ) -> tuple[Sequence[float], tuple[Sequence[float], ...]]:
169
+ """Encode one query and ordered documents with role-correct prefixes."""
170
+
171
+ def fingerprint(self) -> Mapping[str, Any]:
172
+ """Return the checksum-closed encoder identity."""
173
+
174
+
175
+ @dataclass(frozen=True, slots=True)
176
+ class R2AGRuntimeRequest:
177
+ query: str
178
+ documents: tuple[RetrievalResult, ...]
179
+ max_new_tokens: int
180
+ seed: int
181
+
182
+ def __post_init__(self) -> None:
183
+ if not self.query.strip() or not self.documents:
184
+ raise ValidationError("R²AG runtime request requires query and documents")
185
+ if self.max_new_tokens < 1 or self.seed < 0:
186
+ raise ValidationError("R²AG runtime request controls are invalid")
187
+ object.__setattr__(self, "documents", tuple(self.documents))
188
+
189
+ def external_reservation(self) -> Mapping[str, int]:
190
+ return {"model_calls": 1, "embedding_calls": 1}
191
+
192
+
193
+ @runtime_checkable
194
+ class R2AGCommonSupportRuntime(Protocol):
195
+ def run(self, request: R2AGRuntimeRequest) -> Mapping[str, Any]:
196
+ """Encode features and execute the local hidden-state-conditioned reader."""
197
+
198
+ def fingerprint(self) -> Mapping[str, Any]:
199
+ """Return both reader and feature-encoder identities."""
200
+
201
+
202
+ @dataclass(slots=True)
203
+ class LocalSentenceTransformerR2AGFeatureEncoder: # pragma: no cover - L20 GPU acceptance
204
+ """Role-correct local E5 encoder used only for R²AG retrieval features."""
205
+
206
+ model_root: Path
207
+ model_load_set_sha256: str
208
+ device: str = "cuda"
209
+ batch_size: int = 16
210
+ query_prefix: str = "query: "
211
+ document_prefix: str = "passage: "
212
+ _model: Any | None = field(init=False, default=None, repr=False)
213
+
214
+ def __post_init__(self) -> None:
215
+ root = self.model_root.expanduser().resolve()
216
+ if not root.is_dir() or root.is_symlink():
217
+ raise ValidationError("R²AG feature model_root must be a real directory")
218
+ if _SHA256.fullmatch(self.model_load_set_sha256) is None:
219
+ raise ValidationError("R²AG feature model load-set identity is invalid")
220
+ if r2ag_model_tree_sha256(root) != self.model_load_set_sha256:
221
+ raise ValidationError("R²AG feature model load-set checksum mismatch")
222
+ if isinstance(self.batch_size, bool) or not isinstance(self.batch_size, int):
223
+ raise ValidationError("R²AG feature batch_size must be an integer")
224
+ if self.batch_size < 1:
225
+ raise ValidationError("R²AG feature batch_size must be positive")
226
+ if not self.query_prefix or not self.document_prefix:
227
+ raise ValidationError("R²AG feature prefixes must be non-empty")
228
+ object.__setattr__(self, "model_root", root)
229
+
230
+ def _load(self) -> Any:
231
+ if self._model is not None:
232
+ return self._model
233
+ try:
234
+ from sentence_transformers import SentenceTransformer
235
+ except ImportError as exc:
236
+ raise ExternalDependencyError(
237
+ "R²AG feature encoding requires sentence-transformers"
238
+ ) from exc
239
+ try:
240
+ model = SentenceTransformer(
241
+ str(self.model_root),
242
+ device=self.device,
243
+ local_files_only=True,
244
+ )
245
+ except TypeError:
246
+ model = SentenceTransformer(str(self.model_root), device=self.device)
247
+ self._model = model
248
+ return model
249
+
250
+ def encode(
251
+ self,
252
+ *,
253
+ query: str,
254
+ documents: Sequence[RetrievalResult],
255
+ ) -> tuple[Sequence[float], tuple[Sequence[float], ...]]:
256
+ if not query.strip() or not documents:
257
+ raise ValidationError("R²AG feature encoding requires query and documents")
258
+ texts = [
259
+ f"{self.query_prefix}{query.strip()}",
260
+ *(
261
+ f"{self.document_prefix}Title: {item.document.title}\n{item.document.text}"
262
+ for item in documents
263
+ ),
264
+ ]
265
+ vectors = self._load().encode(
266
+ texts,
267
+ batch_size=self.batch_size,
268
+ convert_to_numpy=True,
269
+ normalize_embeddings=True,
270
+ show_progress_bar=False,
271
+ )
272
+ rows = tuple(tuple(float(value) for value in row) for row in vectors)
273
+ if len(rows) != len(texts):
274
+ raise AlgorithmOutputError("R²AG feature encoder returned an invalid vector count")
275
+ if not rows[0] or any(len(row) != len(rows[0]) for row in rows):
276
+ raise AlgorithmOutputError("R²AG feature encoder returned ragged vectors")
277
+ return rows[0], rows[1:]
278
+
279
+ def fingerprint(self) -> Mapping[str, Any]:
280
+ return freeze_mapping(
281
+ {
282
+ "runtime": "sentence_transformers_role_correct.v1",
283
+ "model_root": str(self.model_root),
284
+ "model_load_set_sha256": self.model_load_set_sha256,
285
+ "query_prefix": self.query_prefix,
286
+ "document_prefix": self.document_prefix,
287
+ "normalize_embeddings": True,
288
+ }
289
+ )
290
+
291
+
292
+ @dataclass(slots=True)
293
+ class LocalR2AGCommonSupportRuntime:
294
+ """Monitored context runtime bundling the reader and role-correct encoder."""
295
+
296
+ reader: R2AGCommonSupportReader
297
+ feature_encoder: R2AGFeatureEncoder
298
+ worker_id: str = "r2ag-common-support-local"
299
+
300
+ def __post_init__(self) -> None:
301
+ if not isinstance(self.reader, R2AGCommonSupportReader):
302
+ raise CapabilityError("R²AG runtime reader does not implement its protocol")
303
+ if not isinstance(self.feature_encoder, R2AGFeatureEncoder):
304
+ raise CapabilityError("R²AG runtime feature encoder does not implement its protocol")
305
+
306
+ def run(self, request: R2AGRuntimeRequest) -> Mapping[str, Any]:
307
+ if not isinstance(request, R2AGRuntimeRequest):
308
+ raise TypeError("R²AG runtime requires R2AGRuntimeRequest")
309
+ query_vector, document_vectors = self.feature_encoder.encode(
310
+ query=request.query,
311
+ documents=request.documents,
312
+ )
313
+ features = compute_r2ag_retrieval_features(query_vector, document_vectors)
314
+ reader = self.reader.run(
315
+ query=request.query,
316
+ documents=request.documents,
317
+ features=features,
318
+ max_new_tokens=request.max_new_tokens,
319
+ seed=request.seed,
320
+ )
321
+ return {
322
+ "status": "ok",
323
+ "features": [dict(row) for row in features],
324
+ "reader": {
325
+ "anchor": reader.anchor,
326
+ "input_tokens": reader.input_tokens,
327
+ "output_tokens": reader.output_tokens,
328
+ "marker_positions": list(reader.marker_positions),
329
+ "rformer_output_sha256": reader.rformer_output_sha256,
330
+ "projection_output_sha256": reader.projection_output_sha256,
331
+ },
332
+ "usage": {
333
+ "model_calls": 1,
334
+ "retrieval_calls": 0,
335
+ "tool_calls": 0,
336
+ "embedding_calls": 1,
337
+ "input_tokens": reader.input_tokens,
338
+ "output_tokens": reader.output_tokens,
339
+ },
340
+ }
341
+
342
+ def fingerprint(self) -> Mapping[str, Any]:
343
+ return freeze_mapping(
344
+ {
345
+ "runtime": "r2ag_common_support_context_runtime.v1",
346
+ "reader": dict(self.reader.fingerprint()),
347
+ "feature_encoder": dict(self.feature_encoder.fingerprint()),
348
+ }
349
+ )
350
+
351
+
352
+ @dataclass(slots=True)
353
+ class LocalR2AGCommonSupportReader: # pragma: no cover - L20 GPU acceptance
354
+ """Lazy local Qwen reader backed by a checksum-closed retrained artifact."""
355
+
356
+ artifact_root: Path
357
+ manifest_sha256: str
358
+ source_root: Path
359
+ base_model_root: Path
360
+ base_model_load_set_sha256: str
361
+ device: str = "cuda"
362
+ _manifest: Mapping[str, Any] = field(init=False, repr=False)
363
+ _runtime: tuple[Any, Any, Any, Any, Any] | None = field(
364
+ init=False,
365
+ default=None,
366
+ repr=False,
367
+ )
368
+
369
+ def __post_init__(self) -> None:
370
+ artifact = self.artifact_root.expanduser().resolve()
371
+ source = self.source_root.expanduser().resolve()
372
+ base_model = self.base_model_root.expanduser().resolve()
373
+ for label, path in (
374
+ ("artifact_root", artifact),
375
+ ("source_root", source),
376
+ ("base_model_root", base_model),
377
+ ):
378
+ if not path.is_dir() or path.is_symlink():
379
+ raise ValidationError(f"R²AG {label} must be a real directory")
380
+ if _SHA256.fullmatch(self.manifest_sha256) is None:
381
+ raise ValidationError("R²AG manifest_sha256 must be lowercase SHA-256")
382
+ if _SHA256.fullmatch(self.base_model_load_set_sha256) is None:
383
+ raise ValidationError("R²AG base model load-set identity is invalid")
384
+ manifest_path = artifact / _MANIFEST_NAME
385
+ if (
386
+ not manifest_path.is_file()
387
+ or manifest_path.is_symlink()
388
+ or _sha256_file(manifest_path) != self.manifest_sha256
389
+ ):
390
+ raise ValidationError("R²AG artifact manifest checksum mismatch")
391
+ try:
392
+ manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
393
+ except (OSError, json.JSONDecodeError) as exc:
394
+ raise ValidationError("R²AG artifact manifest is invalid") from exc
395
+ if not isinstance(manifest, Mapping) or manifest.get("schema_version") != _MANIFEST_SCHEMA:
396
+ raise ValidationError("R²AG artifact manifest schema mismatch")
397
+ expected = {
398
+ "upstream_commit": R2AG_UPSTREAM_COMMIT,
399
+ "marker_token": _MARKER,
400
+ "feature_names": ["rerank", "neighbor", "precedent"],
401
+ "reader_backbone": r2ag_reader_backbone_identity(base_model),
402
+ "base_model_load_set_sha256": self.base_model_load_set_sha256,
403
+ "upstream_checkpoint_parity_claimed": False,
404
+ "paper_result_parity_claimed": False,
405
+ "generated_anchor_is_evidence": False,
406
+ }
407
+ for name, value in expected.items():
408
+ if manifest.get(name) != value:
409
+ raise ValidationError(f"R²AG artifact manifest drifted at {name}")
410
+ for name in (
411
+ "num_documents",
412
+ "marker_token_id",
413
+ "rformer_hidden_size",
414
+ "rformer_heads",
415
+ "rformer_layers",
416
+ "reader_hidden_size",
417
+ "max_sequence_length",
418
+ "max_document_chars",
419
+ ):
420
+ value = manifest.get(name)
421
+ if isinstance(value, bool) or not isinstance(value, int) or value < 1:
422
+ raise ValidationError(f"R²AG artifact manifest has invalid {name}")
423
+ model_source = source / "RRAG/models/modeling_rrag.py"
424
+ if (
425
+ not model_source.is_file()
426
+ or model_source.is_symlink()
427
+ or _sha256_file(model_source) != manifest.get("modeling_source_sha256")
428
+ ):
429
+ raise ValidationError("R²AG pinned modeling source checksum mismatch")
430
+ files = manifest.get("artifact_files")
431
+ if not isinstance(files, Mapping) or not files:
432
+ raise ValidationError("R²AG artifact closure is empty")
433
+ observed: set[str] = set()
434
+ for raw_name, raw_digest in files.items():
435
+ if (
436
+ not isinstance(raw_name, str)
437
+ or not raw_name
438
+ or Path(raw_name).is_absolute()
439
+ or ".." in Path(raw_name).parts
440
+ or not isinstance(raw_digest, str)
441
+ or _SHA256.fullmatch(raw_digest) is None
442
+ ):
443
+ raise ValidationError("R²AG artifact closure entry is invalid")
444
+ target = artifact / raw_name
445
+ if not target.is_file() or target.is_symlink() or _sha256_file(target) != raw_digest:
446
+ raise ValidationError(f"R²AG artifact closure mismatch: {raw_name}")
447
+ observed.add(raw_name)
448
+ actual = {
449
+ str(path.relative_to(artifact))
450
+ for path in artifact.rglob("*")
451
+ if path.is_file() and path.name != _MANIFEST_NAME
452
+ }
453
+ if observed != actual or "checkpoint.pt" not in observed:
454
+ raise ValidationError("R²AG artifact closure has missing or extra files")
455
+ tokenizer_files = {name for name in observed if name.startswith("tokenizer/")}
456
+ if not tokenizer_files:
457
+ raise ValidationError("R²AG artifact has no closed tokenizer snapshot")
458
+ object.__setattr__(self, "artifact_root", artifact)
459
+ object.__setattr__(self, "source_root", source)
460
+ object.__setattr__(self, "base_model_root", base_model)
461
+ object.__setattr__(self, "_manifest", freeze_mapping(dict(manifest)))
462
+
463
+ def _load(self) -> tuple[Any, Any, Any, Any, Any]:
464
+ if self._runtime is not None:
465
+ return self._runtime
466
+ try:
467
+ import torch
468
+ from transformers import AutoConfig, AutoModelForCausalLM, AutoTokenizer
469
+ except ImportError as exc:
470
+ raise ExternalDependencyError(
471
+ "R²AG common-support runtime requires torch and transformers"
472
+ ) from exc
473
+ if self.device.startswith("cuda") and not torch.cuda.is_available():
474
+ raise ExternalDependencyError("R²AG requested unavailable CUDA")
475
+ module = _load_source_module(
476
+ self.source_root / "RRAG/models/modeling_rrag.py",
477
+ "agentinputlab_common_support_rrag_modeling",
478
+ )
479
+ rformer_type = getattr(module, "RFormer", None)
480
+ if not isinstance(rformer_type, type):
481
+ raise ExternalDependencyError("R²AG pinned source does not expose RFormer")
482
+ tokenizer = AutoTokenizer.from_pretrained(
483
+ self.artifact_root / "tokenizer",
484
+ local_files_only=True,
485
+ trust_remote_code=False,
486
+ )
487
+ marker_id = tokenizer.convert_tokens_to_ids(_MARKER)
488
+ if marker_id != self._manifest.get("marker_token_id"):
489
+ raise ValidationError("R²AG marker token ID differs from the training artifact")
490
+ dtype = torch.bfloat16 if self.device.startswith("cuda") else torch.float32
491
+ model_config = AutoConfig.from_pretrained(
492
+ self.base_model_root,
493
+ local_files_only=True,
494
+ trust_remote_code=False,
495
+ )
496
+ _repair_qwen38_fp8_model_config(
497
+ model_config,
498
+ backbone=str(self._manifest["reader_backbone"]),
499
+ )
500
+ model = AutoModelForCausalLM.from_pretrained(
501
+ self.base_model_root,
502
+ config=model_config,
503
+ local_files_only=True,
504
+ trust_remote_code=False,
505
+ dtype=dtype,
506
+ ).to(self.device)
507
+ model.resize_token_embeddings(len(tokenizer))
508
+ model.eval()
509
+ for parameter in model.parameters():
510
+ parameter.requires_grad_(False)
511
+ num_k = int(self._manifest["num_documents"])
512
+ d_model = int(self._manifest["rformer_hidden_size"])
513
+ rformer = rformer_type(
514
+ input_dim=3,
515
+ num_k=num_k,
516
+ d_model=d_model,
517
+ n_head=int(self._manifest["rformer_heads"]),
518
+ num_layers=int(self._manifest["rformer_layers"]),
519
+ dropout=float(self._manifest["rformer_dropout"]),
520
+ ).to(self.device)
521
+ projection = torch.nn.Linear(
522
+ d_model,
523
+ int(self._manifest["reader_hidden_size"]),
524
+ device=self.device,
525
+ )
526
+ try:
527
+ checkpoint = torch.load(
528
+ self.artifact_root / "checkpoint.pt",
529
+ map_location="cpu",
530
+ weights_only=True,
531
+ )
532
+ except TypeError as exc:
533
+ raise ExternalDependencyError("R²AG requires safe weights-only loading") from exc
534
+ if not isinstance(checkpoint, Mapping) or set(checkpoint) != {"r_former", "llama_proj"}:
535
+ raise ValidationError("R²AG checkpoint component schema mismatch")
536
+ rformer.load_state_dict(checkpoint["r_former"], strict=True)
537
+ projection.load_state_dict(checkpoint["llama_proj"], strict=True)
538
+ rformer.eval()
539
+ projection.eval()
540
+ for component in (rformer, projection):
541
+ for parameter in component.parameters():
542
+ parameter.requires_grad_(False)
543
+ self._runtime = (torch, tokenizer, model, rformer, projection)
544
+ return self._runtime
545
+
546
+ def run(
547
+ self,
548
+ *,
549
+ query: str,
550
+ documents: Sequence[RetrievalResult],
551
+ features: Sequence[Mapping[str, float]],
552
+ max_new_tokens: int,
553
+ seed: int,
554
+ ) -> R2AGReaderResult:
555
+ if not query.strip():
556
+ raise ValidationError("R²AG reader requires a non-empty query")
557
+ if len(documents) != int(self._manifest["num_documents"]):
558
+ raise ValidationError("R²AG document count differs from its trained checkpoint")
559
+ if len(features) != len(documents):
560
+ raise ValidationError("R²AG feature count differs from its documents")
561
+ if (
562
+ isinstance(max_new_tokens, bool)
563
+ or not isinstance(max_new_tokens, int)
564
+ or max_new_tokens < 1
565
+ ):
566
+ raise ValidationError("R²AG max_new_tokens must be positive")
567
+ torch, tokenizer, model, rformer, projection = self._load()
568
+ prompt = r2ag_reader_prompt(
569
+ query,
570
+ documents,
571
+ max_document_chars=int(self._manifest["max_document_chars"]),
572
+ )
573
+ encoded = tokenizer(
574
+ prompt,
575
+ return_tensors="pt",
576
+ add_special_tokens=False,
577
+ truncation=False,
578
+ ).to(self.device)
579
+ input_tokens = int(encoded.attention_mask.sum().detach().cpu())
580
+ if input_tokens > int(self._manifest["max_sequence_length"]):
581
+ raise BudgetExceededError("R²AG reader input exceeds its trained sequence length")
582
+ marker_id = int(self._manifest["marker_token_id"])
583
+ marker_rows = torch.nonzero(encoded.input_ids == marker_id, as_tuple=False)
584
+ marker_positions = tuple(int(row[1].item()) for row in marker_rows)
585
+ if len(marker_positions) != len(documents):
586
+ raise AlgorithmOutputError("R²AG tokenizer did not preserve one marker per document")
587
+ values = [
588
+ [float(row[name]) for name in ("rerank", "neighbor", "precedent")] for row in features
589
+ ]
590
+ feature_tensor = torch.tensor(values, dtype=torch.float32, device=self.device)
591
+ with torch.inference_mode():
592
+ rformer_output, loss = rformer(feature_tensor)
593
+ if loss is not None:
594
+ raise AlgorithmOutputError("R²AG inference RFormer returned training loss")
595
+ projected = projection(rformer_output)
596
+ input_embeddings = model.get_input_embeddings()(encoded.input_ids)
597
+ updated = input_embeddings.clone()
598
+ flattened = projected.reshape(-1, projected.shape[-1])
599
+ for index, position in enumerate(marker_positions):
600
+ updated[0, position] = flattened[index].to(updated.dtype)
601
+ before = input_embeddings.clone()
602
+ untouched = [
603
+ index for index in range(updated.shape[1]) if index not in marker_positions
604
+ ]
605
+ if untouched:
606
+ selector = torch.tensor(untouched, dtype=torch.long, device=self.device)
607
+ if not torch.equal(updated[:, selector], before[:, selector]):
608
+ raise AlgorithmOutputError("R²AG modified a non-marker embedding")
609
+ torch.manual_seed(seed)
610
+ if torch.cuda.is_available():
611
+ torch.cuda.manual_seed_all(seed)
612
+ generation_compatibility: dict[str, int] = {}
613
+ min_new_tokens = _qwen38_fp8_min_new_tokens(
614
+ backbone=str(self._manifest["reader_backbone"]),
615
+ max_new_tokens=max_new_tokens,
616
+ )
617
+ if min_new_tokens is not None:
618
+ generation_compatibility["min_new_tokens"] = min_new_tokens
619
+ output = model.generate(
620
+ inputs_embeds=updated.contiguous(),
621
+ attention_mask=encoded.attention_mask,
622
+ max_new_tokens=max_new_tokens,
623
+ do_sample=False,
624
+ num_beams=1,
625
+ repetition_penalty=1.0,
626
+ length_penalty=1.0,
627
+ **generation_compatibility,
628
+ )
629
+ if output.ndim != 2 or output.shape[0] != 1:
630
+ raise AlgorithmOutputError("R²AG reader output must be one token sequence")
631
+ output_tokens = int(output.shape[1])
632
+ if not 1 <= output_tokens <= max_new_tokens:
633
+ raise AlgorithmOutputError("R²AG reader output exceeds its generation budget")
634
+ anchor = tokenizer.decode(output[0], skip_special_tokens=True).strip()
635
+ if not anchor:
636
+ raise AlgorithmOutputError("R²AG reader returned an empty generated anchor")
637
+ return R2AGReaderResult(
638
+ anchor=anchor,
639
+ input_tokens=input_tokens,
640
+ output_tokens=output_tokens,
641
+ marker_positions=marker_positions,
642
+ rformer_output_sha256=_tensor_sha256(rformer_output, torch),
643
+ projection_output_sha256=_tensor_sha256(projected, torch),
644
+ )
645
+
646
+ def fingerprint(self) -> Mapping[str, Any]:
647
+ return freeze_mapping(
648
+ {
649
+ "runtime": "r2ag_marker_only_hidden_state_conditioning.v1",
650
+ "upstream_commit": R2AG_UPSTREAM_COMMIT,
651
+ "manifest_sha256": self.manifest_sha256,
652
+ "artifact_closure_sha256": self._manifest.get("artifact_closure_sha256"),
653
+ "base_model_load_set_sha256": self.base_model_load_set_sha256,
654
+ "training_data_sha256": self._manifest.get("training_data_sha256"),
655
+ "reader_backbone": self._manifest.get("reader_backbone"),
656
+ "fp8_model_config_compatibility": (
657
+ "qwen3.8_fp8_mlp_gate_exclusion.v1"
658
+ if self._manifest.get("reader_backbone") == _QWEN38_FP8_BACKBONE
659
+ else None
660
+ ),
661
+ "fp8_generation_compatibility": (
662
+ "qwen3.8_fp8_min_new_tokens_1.v1"
663
+ if self._manifest.get("reader_backbone") == _QWEN38_FP8_BACKBONE
664
+ else None
665
+ ),
666
+ "num_documents": self._manifest.get("num_documents"),
667
+ "marker_token_id": self._manifest.get("marker_token_id"),
668
+ "upstream_checkpoint_parity_claimed": False,
669
+ "paper_result_parity_claimed": False,
670
+ }
671
+ )
672
+
673
+
674
+ @dataclass(frozen=True, slots=True)
675
+ class R2AGCommonSupportConfig:
676
+ retrieval_top_k: int = 6
677
+ max_new_tokens: int = 96
678
+
679
+ def __post_init__(self) -> None:
680
+ for name, value in (
681
+ ("retrieval_top_k", self.retrieval_top_k),
682
+ ("max_new_tokens", self.max_new_tokens),
683
+ ):
684
+ if isinstance(value, bool) or not isinstance(value, int) or value < 1:
685
+ raise ValidationError(f"R²AG {name} must be positive")
686
+ if self.retrieval_top_k < 2:
687
+ raise ValidationError("R²AG requires at least two documents")
688
+
689
+
690
+ @dataclass(slots=True)
691
+ class R2AGCommonSupport:
692
+ """Expose a retrieval-conditioned anchor and its real documents to an agent."""
693
+
694
+ config: R2AGCommonSupportConfig = R2AGCommonSupportConfig()
695
+ method_id: str = "r2ag"
696
+ release_id: str = "acquire.r2ag.common_support"
697
+ family: SemanticFamily = SemanticFamily.ACQUIRE
698
+
699
+ def propose(self, state: FrozenAgentState, context: InterventionContext) -> InputPatch:
700
+ if not state.query.strip():
701
+ raise ValidationError("R²AG requires a non-empty query")
702
+ runtime = _runtime(context.external_runtime)
703
+ retriever = _retriever(context.retriever)
704
+ if state.budget.max_model_calls < 1:
705
+ raise BudgetExceededError("R²AG has no reader model-call budget")
706
+ if state.budget.max_retrieval_calls < 1:
707
+ raise BudgetExceededError("R²AG has no retrieval budget")
708
+ if state.budget.max_output_tokens < 1:
709
+ raise BudgetExceededError("R²AG has no output-token budget")
710
+ results = _validated_results(
711
+ retriever.retrieve(state.query, top_k=self.config.retrieval_top_k),
712
+ top_k=self.config.retrieval_top_k,
713
+ )
714
+ if len(results) != self.config.retrieval_top_k:
715
+ raise AlgorithmOutputError("R²AG requires its exact checkpoint document count")
716
+ runtime_response = runtime.run(
717
+ R2AGRuntimeRequest(
718
+ query=state.query,
719
+ documents=results,
720
+ max_new_tokens=min(self.config.max_new_tokens, state.budget.max_output_tokens),
721
+ seed=context.seed,
722
+ )
723
+ )
724
+ features, reader_result = _validated_runtime_response(runtime_response, len(results))
725
+ if (
726
+ state.budget.max_context_tokens is not None
727
+ and reader_result.input_tokens > state.budget.max_context_tokens
728
+ ):
729
+ raise BudgetExceededError("R²AG reader exceeded max_context_tokens")
730
+ real_blocks = tuple(
731
+ _real_context(result, feature)
732
+ for result, feature in zip(results, features, strict=True)
733
+ )
734
+ anchor_hash = content_hash(
735
+ {
736
+ "anchor": reader_result.anchor,
737
+ "rformer": reader_result.rformer_output_sha256,
738
+ "projection": reader_result.projection_output_sha256,
739
+ }
740
+ )
741
+ anchor_block = ContextBlock(
742
+ block_id=f"r2ag-generated-anchor:{anchor_hash[:16]}",
743
+ text=(
744
+ "R²AG retrieval-conditioned hypothesis (non-authoritative; verify against the "
745
+ f"retrieved documents): {reader_result.anchor}"
746
+ ),
747
+ source="r2ag_common_support_generated_anchor",
748
+ metadata={
749
+ "evidence_kind": "model_generated_non_authoritative_anchor",
750
+ "generated_anchor_is_evidence": False,
751
+ "anchor_sha256": anchor_hash,
752
+ "rformer_output_sha256": reader_result.rformer_output_sha256,
753
+ "projection_output_sha256": reader_result.projection_output_sha256,
754
+ },
755
+ )
756
+ runtime_identity = dict(runtime.fingerprint())
757
+ reader_identity = runtime_identity.get("reader", {})
758
+ feature_encoder_identity = runtime_identity.get("feature_encoder", {})
759
+ if not isinstance(reader_identity, Mapping) or not isinstance(
760
+ feature_encoder_identity, Mapping
761
+ ):
762
+ raise AlgorithmOutputError("R²AG runtime fingerprint lacks component identities")
763
+ trace = ExecutionTrace(
764
+ method_id=self.method_id,
765
+ release_id=self.release_id,
766
+ events=(
767
+ TraceEvent(
768
+ TracePhase.PREPARE,
769
+ "r2ag_common_support_configuration",
770
+ {
771
+ "upstream_commit": R2AG_UPSTREAM_COMMIT,
772
+ "reader": reader_identity,
773
+ "retriever": dict(retriever.fingerprint()),
774
+ "feature_encoder": feature_encoder_identity,
775
+ "external_runtime": runtime_identity,
776
+ "candidate_document_ids": tuple(item.document.doc_id for item in results),
777
+ "upstream_checkpoint_parity_claimed": False,
778
+ "paper_result_parity_claimed": False,
779
+ },
780
+ ),
781
+ TraceEvent(
782
+ TracePhase.OBSERVE,
783
+ "r2ag_retrieval_feature_tensor",
784
+ {
785
+ "feature_names": ("rerank", "neighbor", "precedent"),
786
+ "features": tuple(dict(row) for row in features),
787
+ "feature_tensor_sha256": content_hash(features),
788
+ },
789
+ ),
790
+ TraceEvent(
791
+ TracePhase.FINALIZE,
792
+ "r2ag_marker_conditioned_anchor",
793
+ {
794
+ "marker_positions": reader_result.marker_positions,
795
+ "rformer_output_sha256": reader_result.rformer_output_sha256,
796
+ "projection_output_sha256": reader_result.projection_output_sha256,
797
+ "anchor_sha256": anchor_hash,
798
+ "generated_anchor_visible_to_downstream": True,
799
+ "generated_anchor_is_evidence": False,
800
+ },
801
+ ),
802
+ ),
803
+ counters={
804
+ "model_calls": 1,
805
+ "retrieval_calls": 1,
806
+ "embedding_calls": 1,
807
+ "input_tokens": reader_result.input_tokens,
808
+ "output_tokens": reader_result.output_tokens,
809
+ "conditioned_documents": len(results),
810
+ "retrieval_feature_values": len(results) * 3,
811
+ },
812
+ )
813
+ return InputPatch(
814
+ method_id=self.method_id,
815
+ release_id=self.release_id,
816
+ source_state_hash=state.state_hash,
817
+ operations=(
818
+ PatchOperation(
819
+ PatchOp.ADD_CONTEXT,
820
+ (*real_blocks, anchor_block),
821
+ target="retrieved_evidence_and_generated_anchor",
822
+ rationale=(
823
+ "preserve R²AG hidden-state conditioning as a non-authoritative "
824
+ "agent input anchor beside real retrieved documents"
825
+ ),
826
+ ),
827
+ ),
828
+ trace=trace,
829
+ implementation_identity=(
830
+ f"controlled_marker_conditioned_reader:yefd/RRAG@{R2AG_UPSTREAM_COMMIT}"
831
+ ),
832
+ profile_kind="controlled_adapter",
833
+ metadata={
834
+ "common_support_adaptation": (
835
+ "custom_reader_answer_as_non_authoritative_downstream_context"
836
+ ),
837
+ "generated_anchor_visible_to_downstream": True,
838
+ "generated_anchor_is_evidence": False,
839
+ "real_documents_are_evidence": True,
840
+ "marker_only_embedding_replacement": True,
841
+ "upstream_checkpoint_parity_claimed": False,
842
+ "paper_result_parity_claimed": False,
843
+ "reader_manifest_sha256": reader_identity.get("manifest_sha256"),
844
+ "reader_backbone": reader_identity.get("reader_backbone"),
845
+ "feature_encoder_load_set_sha256": feature_encoder_identity.get(
846
+ "model_load_set_sha256"
847
+ ),
848
+ },
849
+ )
850
+
851
+
852
+ def _retriever(value: object) -> Retriever:
853
+ if value is None or not hasattr(value, "retrieve") or not hasattr(value, "fingerprint"):
854
+ raise ExternalDependencyError("R²AG common-support requires a Retriever")
855
+ return value # type: ignore[return-value]
856
+
857
+
858
+ def _runtime(value: object) -> R2AGCommonSupportRuntime:
859
+ if not isinstance(value, R2AGCommonSupportRuntime):
860
+ raise ExternalDependencyError(
861
+ "R²AG common-support requires InterventionContext.external_runtime"
862
+ )
863
+ return value
864
+
865
+
866
+ def _validated_runtime_response(
867
+ value: Mapping[str, Any],
868
+ expected_documents: int,
869
+ ) -> tuple[tuple[Mapping[str, float], ...], R2AGReaderResult]:
870
+ if not isinstance(value, Mapping) or value.get("status") != "ok":
871
+ raise AlgorithmOutputError("R²AG external runtime returned a failed response")
872
+ raw_features = value.get("features")
873
+ raw_reader = value.get("reader")
874
+ if (
875
+ isinstance(raw_features, (str, bytes))
876
+ or not isinstance(raw_features, Sequence)
877
+ or len(raw_features) != expected_documents
878
+ or not isinstance(raw_reader, Mapping)
879
+ ):
880
+ raise AlgorithmOutputError("R²AG external runtime response schema is invalid")
881
+ features: list[Mapping[str, float]] = []
882
+ for row in raw_features:
883
+ if not isinstance(row, Mapping) or set(row) != {"rerank", "neighbor", "precedent"}:
884
+ raise AlgorithmOutputError("R²AG external runtime feature schema is invalid")
885
+ try:
886
+ parsed = {name: float(row[name]) for name in ("rerank", "neighbor", "precedent")}
887
+ except (TypeError, ValueError, OverflowError) as exc:
888
+ raise AlgorithmOutputError("R²AG external runtime features are non-numeric") from exc
889
+ if not all(math.isfinite(item) for item in parsed.values()):
890
+ raise AlgorithmOutputError("R²AG external runtime features are non-finite")
891
+ features.append(freeze_mapping(parsed))
892
+ try:
893
+ result = R2AGReaderResult(
894
+ anchor=raw_reader["anchor"],
895
+ input_tokens=raw_reader["input_tokens"],
896
+ output_tokens=raw_reader["output_tokens"],
897
+ marker_positions=tuple(raw_reader["marker_positions"]),
898
+ rformer_output_sha256=raw_reader["rformer_output_sha256"],
899
+ projection_output_sha256=raw_reader["projection_output_sha256"],
900
+ )
901
+ except (KeyError, TypeError, ValidationError) as exc:
902
+ raise AlgorithmOutputError("R²AG external runtime reader receipt is invalid") from exc
903
+ usage = value.get("usage")
904
+ if (
905
+ not isinstance(usage, Mapping)
906
+ or usage.get("model_calls") != 1
907
+ or usage.get("embedding_calls") != 1
908
+ or usage.get("input_tokens") != result.input_tokens
909
+ or usage.get("output_tokens") != result.output_tokens
910
+ ):
911
+ raise AlgorithmOutputError("R²AG external runtime usage receipt is invalid")
912
+ return tuple(features), result
913
+
914
+
915
+ def _validated_results(
916
+ values: Sequence[RetrievalResult], *, top_k: int
917
+ ) -> tuple[RetrievalResult, ...]:
918
+ try:
919
+ results = tuple(values)
920
+ except TypeError as exc:
921
+ raise AlgorithmOutputError("R²AG retriever returned a non-sequence") from exc
922
+ if not all(isinstance(item, RetrievalResult) for item in results) or len(results) > top_k:
923
+ raise AlgorithmOutputError("R²AG retriever returned invalid results")
924
+ ids = tuple(item.document.doc_id for item in results)
925
+ if any(not value for value in ids) or len(ids) != len(set(ids)):
926
+ raise AlgorithmOutputError("R²AG retrieval IDs must be non-empty and unique")
927
+ if tuple(item.rank for item in results) != tuple(range(1, len(results) + 1)):
928
+ raise AlgorithmOutputError("R²AG retrieval ranks must be contiguous and one-based")
929
+ return results
930
+
931
+
932
+ def _real_context(
933
+ result: RetrievalResult,
934
+ feature: Mapping[str, float],
935
+ ) -> ContextBlock:
936
+ document = result.document
937
+ if not document.corpus_revision:
938
+ raise AlgorithmOutputError("R²AG evidence requires a corpus revision")
939
+ reserved = {
940
+ "corpus_revision",
941
+ "document_id",
942
+ "evidence_kind",
943
+ "rank",
944
+ "r2ag_features",
945
+ "title",
946
+ }
947
+ if reserved & set(document.metadata):
948
+ raise AlgorithmOutputError("R²AG document metadata uses reserved provenance keys")
949
+ return ContextBlock(
950
+ block_id=document.doc_id,
951
+ text=document.text,
952
+ source=document.corpus_revision,
953
+ score=result.score,
954
+ metadata={
955
+ **dict(document.metadata),
956
+ "document_id": document.doc_id,
957
+ "title": document.title,
958
+ "corpus_revision": document.corpus_revision,
959
+ "rank": result.rank,
960
+ "r2ag_features": dict(feature),
961
+ "evidence_kind": "real_corpus_document",
962
+ },
963
+ )
964
+
965
+
966
+ def r2ag_reader_prompt(
967
+ query: str,
968
+ documents: Sequence[RetrievalResult],
969
+ *,
970
+ max_document_chars: int,
971
+ ) -> str:
972
+ rows = [
973
+ "Use the retrieval signals and documents to propose a concise answer. The answer is a "
974
+ "hypothesis and must not invent facts absent from the documents.",
975
+ f"Question: {query.strip()}",
976
+ "Documents:",
977
+ ]
978
+ for index, item in enumerate(documents, start=1):
979
+ title = item.document.title.strip() or item.document.doc_id
980
+ text = item.document.text.strip()[:max_document_chars]
981
+ rows.append(f"[{index}] relevance: {_MARKER} Title: {title}\n{text}")
982
+ rows.append("Answer:")
983
+ return "\n".join(rows)
984
+
985
+
986
+ def _tensor_sha256(value: Any, torch: Any) -> str:
987
+ tensor = value.detach().cpu().contiguous()
988
+ digest = hashlib.sha256()
989
+ digest.update(str(tensor.dtype).encode("ascii"))
990
+ digest.update(json.dumps(tuple(tensor.shape)).encode("ascii"))
991
+ digest.update(tensor.view(torch.uint8).numpy().tobytes())
992
+ return digest.hexdigest()
993
+
994
+
995
+ def r2ag_model_tree_sha256(root: Path) -> str:
996
+ records: list[tuple[str, str]] = []
997
+ for path in sorted(root.rglob("*")):
998
+ if path.is_symlink():
999
+ raise ValidationError("R²AG feature model load set may not contain symlinks")
1000
+ if path.is_file():
1001
+ records.append((str(path.relative_to(root)), _sha256_file(path)))
1002
+ if not records:
1003
+ raise ValidationError("R²AG feature model load set is empty")
1004
+ return content_hash(records)
1005
+
1006
+
1007
+ def _load_source_module(path: Path, name: str) -> ModuleType:
1008
+ spec = importlib.util.spec_from_file_location(name, path)
1009
+ if spec is None or spec.loader is None:
1010
+ raise ExternalDependencyError("unable to import pinned R²AG source")
1011
+ module = importlib.util.module_from_spec(spec)
1012
+ spec.loader.exec_module(module)
1013
+ return module
1014
+
1015
+
1016
+ __all__ = [
1017
+ "LocalR2AGCommonSupportReader",
1018
+ "LocalR2AGCommonSupportRuntime",
1019
+ "LocalSentenceTransformerR2AGFeatureEncoder",
1020
+ "R2AGCommonSupport",
1021
+ "R2AGCommonSupportConfig",
1022
+ "R2AGCommonSupportReader",
1023
+ "R2AGCommonSupportRuntime",
1024
+ "R2AGFeatureEncoder",
1025
+ "R2AGReaderResult",
1026
+ "R2AGRuntimeRequest",
1027
+ "r2ag_model_tree_sha256",
1028
+ "r2ag_reader_prompt",
1029
+ ]