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.
- agentinputlab/__init__.py +28 -0
- agentinputlab/algorithms/__init__.py +6 -0
- agentinputlab/algorithms/acquire/__init__.py +145 -0
- agentinputlab/algorithms/acquire/adaptive_rag/__init__.py +43 -0
- agentinputlab/algorithms/acquire/adaptive_rag/replay.py +367 -0
- agentinputlab/algorithms/acquire/adaptive_rag/runtime.py +1202 -0
- agentinputlab/algorithms/acquire/adaptive_rag_common_support.py +542 -0
- agentinputlab/algorithms/acquire/hyde.py +296 -0
- agentinputlab/algorithms/acquire/hyde_controlled.py +200 -0
- agentinputlab/algorithms/acquire/hyde_external.py +148 -0
- agentinputlab/algorithms/acquire/ircot.py +28 -0
- agentinputlab/algorithms/acquire/ircot_common_support.py +478 -0
- agentinputlab/algorithms/acquire/ircot_native.py +355 -0
- agentinputlab/algorithms/acquire/ircot_replay.py +327 -0
- agentinputlab/algorithms/acquire/qrag/__init__.py +79 -0
- agentinputlab/algorithms/acquire/qrag/bridge.py +828 -0
- agentinputlab/algorithms/acquire/qrag/common_support.py +891 -0
- agentinputlab/algorithms/acquire/qrag/native_axis.py +71 -0
- agentinputlab/algorithms/acquire/qrag/reader_adapter.py +139 -0
- agentinputlab/algorithms/acquire/r2ag/__init__.py +57 -0
- agentinputlab/algorithms/acquire/r2ag/bridge.py +1312 -0
- agentinputlab/algorithms/acquire/r2ag/common_support.py +1029 -0
- agentinputlab/algorithms/acquire/r2ag/socket_runtime.py +255 -0
- agentinputlab/algorithms/clarify/__init__.py +61 -0
- agentinputlab/algorithms/clarify/_structured.py +64 -0
- agentinputlab/algorithms/clarify/active_task_disambiguation.py +371 -0
- agentinputlab/algorithms/clarify/ask_or_assume/__init__.py +17 -0
- agentinputlab/algorithms/clarify/ask_or_assume/monitor.py +410 -0
- agentinputlab/algorithms/clarify/future_turns.py +379 -0
- agentinputlab/algorithms/clarify/udcs.py +255 -0
- agentinputlab/algorithms/clarify/udcs_deterministic.py +196 -0
- agentinputlab/algorithms/curate/__init__.py +65 -0
- agentinputlab/algorithms/curate/acon/__init__.py +27 -0
- agentinputlab/algorithms/curate/acon/common.py +284 -0
- agentinputlab/algorithms/curate/acon/common_support.py +136 -0
- agentinputlab/algorithms/curate/acon/history_bridge.py +309 -0
- agentinputlab/algorithms/curate/acon/observation_bridge.py +290 -0
- agentinputlab/algorithms/curate/llmlingua/__init__.py +30 -0
- agentinputlab/algorithms/curate/llmlingua/adapters.py +537 -0
- agentinputlab/algorithms/curate/llmlingua/budget.py +48 -0
- agentinputlab/algorithms/curate/llmlingua/controlled.py +175 -0
- agentinputlab/algorithms/curate/llmlingua/multilingual.py +105 -0
- agentinputlab/algorithms/curate/llmlingua/span_map.py +167 -0
- agentinputlab/algorithms/curate/recomp/__init__.py +47 -0
- agentinputlab/algorithms/curate/recomp/external.py +1129 -0
- agentinputlab/algorithms/curate/recomp/selective.py +304 -0
- agentinputlab/algorithms/decompose/__init__.py +107 -0
- agentinputlab/algorithms/decompose/decomp/__init__.py +53 -0
- agentinputlab/algorithms/decompose/decomp/common_support.py +478 -0
- agentinputlab/algorithms/decompose/decomp/planner_component.py +199 -0
- agentinputlab/algorithms/decompose/decomp/worker_bridge.py +416 -0
- agentinputlab/algorithms/decompose/llm_compiler/__init__.py +35 -0
- agentinputlab/algorithms/decompose/llm_compiler/bridge.py +520 -0
- agentinputlab/algorithms/decompose/llm_compiler/common_support.py +504 -0
- agentinputlab/algorithms/decompose/plan_and_budget/__init__.py +43 -0
- agentinputlab/algorithms/decompose/plan_and_budget/cached_soft_budget.py +362 -0
- agentinputlab/algorithms/decompose/plan_and_budget/decomposer_component.py +107 -0
- agentinputlab/algorithms/decompose/plan_and_budget/full.py +205 -0
- agentinputlab/algorithms/decompose/plan_and_budget/hard_cap.py +246 -0
- agentinputlab/algorithms/decompose/plan_and_budget/regenerated_soft_budget.py +448 -0
- agentinputlab/algorithms/decompose/plan_and_solve/__init__.py +33 -0
- agentinputlab/algorithms/decompose/plan_and_solve/plan_component.py +192 -0
- agentinputlab/algorithms/decompose/plan_and_solve/ps_prompt.py +127 -0
- agentinputlab/algorithms/decompose/self_ask/__init__.py +27 -0
- agentinputlab/algorithms/decompose/self_ask/loop.py +362 -0
- agentinputlab/algorithms/decompose/self_ask/planner_component.py +117 -0
- agentinputlab/algorithms/reformulate/__init__.py +85 -0
- agentinputlab/algorithms/reformulate/infocqr/__init__.py +40 -0
- agentinputlab/algorithms/reformulate/infocqr/cache_replay.py +362 -0
- agentinputlab/algorithms/reformulate/infocqr/external.py +675 -0
- agentinputlab/algorithms/reformulate/infocqr/student.py +189 -0
- agentinputlab/algorithms/reformulate/query2doc/__init__.py +42 -0
- agentinputlab/algorithms/reformulate/query2doc/controlled_live.py +190 -0
- agentinputlab/algorithms/reformulate/query2doc/models.py +95 -0
- agentinputlab/algorithms/reformulate/query2doc/official_cached.py +335 -0
- agentinputlab/algorithms/reformulate/query2doc/querygym_bridge.py +223 -0
- agentinputlab/algorithms/reformulate/query2doc/querygym_runtime.py +326 -0
- agentinputlab/algorithms/reformulate/reformer/__init__.py +23 -0
- agentinputlab/algorithms/reformulate/reformer/external.py +417 -0
- agentinputlab/algorithms/reformulate/rrr.py +696 -0
- agentinputlab/annotation/__init__.py +5 -0
- agentinputlab/annotation/independent.py +428 -0
- agentinputlab/annotation/server.py +233 -0
- agentinputlab/annotation/static/app.js +121 -0
- agentinputlab/annotation/static/index.html +60 -0
- agentinputlab/annotation/static/review.css +2 -0
- agentinputlab/annotation/static/review.html +10 -0
- agentinputlab/annotation/static/review.js +11 -0
- agentinputlab/annotation/static/styles.css +55 -0
- agentinputlab/annotation/store.py +444 -0
- agentinputlab/api.py +368 -0
- agentinputlab/artifacts/__init__.py +15 -0
- agentinputlab/artifacts/json_file.py +104 -0
- agentinputlab/artifacts/manifest.py +98 -0
- agentinputlab/artifacts/store.py +157 -0
- agentinputlab/backends/__init__.py +98 -0
- agentinputlab/backends/embedding/__init__.py +25 -0
- agentinputlab/backends/embedding/base.py +145 -0
- agentinputlab/backends/embedding/callable.py +75 -0
- agentinputlab/backends/embedding/replay.py +129 -0
- agentinputlab/backends/llm/__init__.py +31 -0
- agentinputlab/backends/llm/base.py +149 -0
- agentinputlab/backends/llm/callable.py +108 -0
- agentinputlab/backends/llm/decomp_completion.py +88 -0
- agentinputlab/backends/llm/final_content_stop.py +72 -0
- agentinputlab/backends/llm/gpt_oss_final_channel.py +84 -0
- agentinputlab/backends/llm/openai_compatible.py +332 -0
- agentinputlab/backends/llm/transformers.py +171 -0
- agentinputlab/backends/retrieval/__init__.py +35 -0
- agentinputlab/backends/retrieval/base.py +50 -0
- agentinputlab/backends/retrieval/dense.py +777 -0
- agentinputlab/backends/retrieval/memory.py +119 -0
- agentinputlab/backends/retrieval/sqlite_fts.py +155 -0
- agentinputlab/backends/user/__init__.py +15 -0
- agentinputlab/backends/user/base.py +66 -0
- agentinputlab/backends/user/callable.py +54 -0
- agentinputlab/backends/user/replay.py +89 -0
- agentinputlab/backends/vector.py +38 -0
- agentinputlab/benchmarks/__init__.py +246 -0
- agentinputlab/benchmarks/acquisition.py +106 -0
- agentinputlab/benchmarks/ale.py +540 -0
- agentinputlab/benchmarks/appworld_ul.py +669 -0
- agentinputlab/benchmarks/assets.py +226 -0
- agentinputlab/benchmarks/base.py +68 -0
- agentinputlab/benchmarks/beir_archive.py +235 -0
- agentinputlab/benchmarks/beir_sample.py +269 -0
- agentinputlab/benchmarks/bfcl_native.py +245 -0
- agentinputlab/benchmarks/bfcl_v3.py +607 -0
- agentinputlab/benchmarks/cache.py +218 -0
- agentinputlab/benchmarks/clariq.py +203 -0
- agentinputlab/benchmarks/data/registry.json +321 -0
- agentinputlab/benchmarks/data/smoke_assets.json +511 -0
- agentinputlab/benchmarks/data/statebench_v0_8_1_task_ids.json +475 -0
- agentinputlab/benchmarks/data/toolsandbox_165848b_scenario_names.json +1 -0
- agentinputlab/benchmarks/execution.py +1111 -0
- agentinputlab/benchmarks/interactive.py +257 -0
- agentinputlab/benchmarks/ir_query.py +204 -0
- agentinputlab/benchmarks/longbench.py +203 -0
- agentinputlab/benchmarks/paired_replay.py +479 -0
- agentinputlab/benchmarks/preprocess.py +2313 -0
- agentinputlab/benchmarks/production.py +236 -0
- agentinputlab/benchmarks/qa.py +963 -0
- agentinputlab/benchmarks/registry.py +110 -0
- agentinputlab/benchmarks/retrieval.py +459 -0
- agentinputlab/benchmarks/runtime.py +509 -0
- agentinputlab/benchmarks/statebench.py +938 -0
- agentinputlab/benchmarks/tau3.py +725 -0
- agentinputlab/benchmarks/toolsandbox.py +626 -0
- agentinputlab/benchmarks/trec_dl_sample.py +263 -0
- agentinputlab/campaign.py +654 -0
- agentinputlab/campaign_runner.py +953 -0
- agentinputlab/cli/__init__.py +6 -0
- agentinputlab/cli/main.py +933 -0
- agentinputlab/connectors/__init__.py +46 -0
- agentinputlab/connectors/knowledge/__init__.py +4 -0
- agentinputlab/connectors/tools/__init__.py +30 -0
- agentinputlab/connectors/tools/base.py +57 -0
- agentinputlab/connectors/tools/mcp.py +222 -0
- agentinputlab/connectors/tools/memory.py +41 -0
- agentinputlab/connectors/tools/openapi.py +695 -0
- agentinputlab/connectors/tools/schema.py +102 -0
- agentinputlab/contracts/__init__.py +91 -0
- agentinputlab/contracts/availability.py +24 -0
- agentinputlab/contracts/dependency.py +58 -0
- agentinputlab/contracts/enums.py +82 -0
- agentinputlab/contracts/errors.py +63 -0
- agentinputlab/contracts/evidence.py +43 -0
- agentinputlab/contracts/intent.py +110 -0
- agentinputlab/contracts/lifecycle.py +164 -0
- agentinputlab/contracts/patch.py +167 -0
- agentinputlab/contracts/serialization.py +93 -0
- agentinputlab/contracts/state.py +127 -0
- agentinputlab/contracts/trace.py +59 -0
- agentinputlab/contracts/worker.py +42 -0
- agentinputlab/core/__init__.py +7 -0
- agentinputlab/data/__init__.py +32 -0
- agentinputlab/data/checksums.py +9 -0
- agentinputlab/data/downloader.py +235 -0
- agentinputlab/data/http.py +171 -0
- agentinputlab/data/index.py +21 -0
- agentinputlab/data/overlap.py +28 -0
- agentinputlab/data/preprocess.py +32 -0
- agentinputlab/data/storage.py +57 -0
- agentinputlab/data/trec_sample.py +427 -0
- agentinputlab/evaluation/__init__.py +5 -0
- agentinputlab/evaluation/outcomes.py +32 -0
- agentinputlab/experiments/__init__.py +278 -0
- agentinputlab/experiments/analysis.py +981 -0
- agentinputlab/experiments/artifacts.py +687 -0
- agentinputlab/experiments/automatic_measurement.py +678 -0
- agentinputlab/experiments/auxiliary_matrix.py +203 -0
- agentinputlab/experiments/bindings.py +430 -0
- agentinputlab/experiments/blueprints.py +147 -0
- agentinputlab/experiments/builders/__init__.py +45 -0
- agentinputlab/experiments/builders/executable_external_payload.py +423 -0
- agentinputlab/experiments/builders/external_process_arena.py +1018 -0
- agentinputlab/experiments/builders/registry_intervention.py +463 -0
- agentinputlab/experiments/cli.py +158 -0
- agentinputlab/experiments/controls.py +340 -0
- agentinputlab/experiments/driver_guard.py +205 -0
- agentinputlab/experiments/drivers/__init__.py +89 -0
- agentinputlab/experiments/drivers/external_arena.py +2908 -0
- agentinputlab/experiments/drivers/method_process.py +662 -0
- agentinputlab/experiments/drivers/parity_process.py +1484 -0
- agentinputlab/experiments/drivers/static_production.py +1574 -0
- agentinputlab/experiments/executor.py +448 -0
- agentinputlab/experiments/loader.py +605 -0
- agentinputlab/experiments/measurement.py +675 -0
- agentinputlab/experiments/paper_analysis.py +1818 -0
- agentinputlab/experiments/parity_identity.py +605 -0
- agentinputlab/experiments/plan.py +277 -0
- agentinputlab/experiments/production_builders.py +3739 -0
- agentinputlab/experiments/readiness.py +432 -0
- agentinputlab/experiments/schema.py +514 -0
- agentinputlab/experiments/secrets.py +177 -0
- agentinputlab/experiments/stateful_analysis.py +1738 -0
- agentinputlab/experiments/transfer_analysis.py +1316 -0
- agentinputlab/experiments/unseen_analysis.py +1025 -0
- agentinputlab/integrations/__init__.py +1 -0
- agentinputlab/integrations/action_space/__init__.py +1 -0
- agentinputlab/integrations/external_workers/__init__.py +76 -0
- agentinputlab/integrations/external_workers/ace.py +431 -0
- agentinputlab/integrations/external_workers/base.py +181 -0
- agentinputlab/integrations/external_workers/decomp_live.py +249 -0
- agentinputlab/integrations/external_workers/decomp_planner.py +30 -0
- agentinputlab/integrations/external_workers/infocqr_student.py +280 -0
- agentinputlab/integrations/external_workers/ircot.py +576 -0
- agentinputlab/integrations/external_workers/llmcompiler_live.py +360 -0
- agentinputlab/integrations/external_workers/longllmlingua.py +162 -0
- agentinputlab/integrations/external_workers/method.py +314 -0
- agentinputlab/integrations/external_workers/process.py +678 -0
- agentinputlab/integrations/external_workers/supervisor.py +1071 -0
- agentinputlab/integrations/full_architecture/__init__.py +1 -0
- agentinputlab/integrations/full_architecture/hyde.py +212 -0
- agentinputlab/integrations/full_architecture/plan_and_budget.py +188 -0
- agentinputlab/integrations/live_history.py +222 -0
- agentinputlab/integrations/prompt_optimization/__init__.py +1 -0
- agentinputlab/integrations/training/__init__.py +1 -0
- agentinputlab/metrics/__init__.py +50 -0
- agentinputlab/metrics/catalog.py +313 -0
- agentinputlab/metrics/harm.py +95 -0
- agentinputlab/metrics/paired.py +40 -0
- agentinputlab/metrics/qa.py +76 -0
- agentinputlab/metrics/text.py +33 -0
- agentinputlab/metrics/third_party.py +161 -0
- agentinputlab/models/__init__.py +4 -0
- agentinputlab/observability/__init__.py +56 -0
- agentinputlab/observability/budget.py +316 -0
- agentinputlab/observability/instrumentation.py +754 -0
- agentinputlab/observability/models.py +403 -0
- agentinputlab/observability/monitor.py +380 -0
- agentinputlab/optimizers/__init__.py +1 -0
- agentinputlab/optimizers/clarify/__init__.py +12 -0
- agentinputlab/optimizers/context/__init__.py +22 -0
- agentinputlab/optimizers/decompose/__init__.py +64 -0
- agentinputlab/optimizers/evidence/__init__.py +22 -0
- agentinputlab/optimizers/rewrite/__init__.py +30 -0
- agentinputlab/parity/__init__.py +5 -0
- agentinputlab/parity/base.py +206 -0
- agentinputlab/production_campaign.py +763 -0
- agentinputlab/py.typed +1 -0
- agentinputlab/recipes/__init__.py +333 -0
- agentinputlab/recipes/ace.py +418 -0
- agentinputlab/recipes/ace_bfcl.py +273 -0
- agentinputlab/recipes/ace_common_support.py +169 -0
- agentinputlab/recipes/ace_native_plan.py +322 -0
- agentinputlab/recipes/ace_online.py +711 -0
- agentinputlab/recipes/ace_retrieval.py +330 -0
- agentinputlab/recipes/ace_statebench.py +382 -0
- agentinputlab/recipes/ace_tau.py +463 -0
- agentinputlab/recipes/ace_toolsandbox.py +432 -0
- agentinputlab/recipes/acon_guideline.py +22 -0
- agentinputlab/recipes/adaptive_rag.py +822 -0
- agentinputlab/recipes/llmlingua2_inference.py +146 -0
- agentinputlab/recipes/llmlingua2_training.py +796 -0
- agentinputlab/recipes/mce.py +1486 -0
- agentinputlab/recipes/mce_final.py +335 -0
- agentinputlab/recipes/mce_text_fit.py +499 -0
- agentinputlab/recipes/mce_text_only.py +298 -0
- agentinputlab/recipes/qrag.py +729 -0
- agentinputlab/recipes/qrag_inference.py +364 -0
- agentinputlab/recipes/r2ag_features.py +236 -0
- agentinputlab/recipes/r2ag_inference.py +503 -0
- agentinputlab/recipes/r2ag_training.py +948 -0
- agentinputlab/recipes/recomp_abstractive.py +592 -0
- agentinputlab/recipes/recomp_extractive.py +525 -0
- agentinputlab/recipes/reformer.py +17 -0
- agentinputlab/recipes/rqrag.py +1516 -0
- agentinputlab/recipes/rqrag_common_support.py +193 -0
- agentinputlab/recipes/rqrag_completion.py +147 -0
- agentinputlab/recipes/skillopt.py +462 -0
- agentinputlab/recipes/skillopt_common_support.py +154 -0
- agentinputlab/recipes/skillopt_environment.py +165 -0
- agentinputlab/recipes/skillopt_environment_cli.py +5 -0
- agentinputlab/recipes/skillopt_retrieval.py +188 -0
- agentinputlab/recipes/smartsearch.py +897 -0
- agentinputlab/recipes/smartsearch_curriculum.py +283 -0
- agentinputlab/recipes/smartsearch_grpo_contracts.py +58 -0
- agentinputlab/recipes/smartsearch_grpo_data.py +314 -0
- agentinputlab/recipes/smartsearch_grpo_meter.py +324 -0
- agentinputlab/recipes/smartsearch_grpo_prefix.py +144 -0
- agentinputlab/recipes/smartsearch_grpo_rollout.py +119 -0
- agentinputlab/recipes/smartsearch_grpo_tools.py +364 -0
- agentinputlab/recipes/smartsearch_grpo_training.py +305 -0
- agentinputlab/recipes/smartsearch_grpo_transport.py +248 -0
- agentinputlab/recipes/smartsearch_grpo_worker.py +364 -0
- agentinputlab/recipes/smartsearch_inference.py +524 -0
- agentinputlab/recipes/smartsearch_native_data.py +172 -0
- agentinputlab/recipes/smartsearch_policy.py +616 -0
- agentinputlab/recipes/smartsearch_policy_worker.py +9 -0
- agentinputlab/recipes/smartsearch_sampling.py +232 -0
- agentinputlab/recipes/smartsearch_teacher.py +203 -0
- agentinputlab/recipes/smartsearch_training.py +265 -0
- agentinputlab/registry/__init__.py +46 -0
- agentinputlab/registry/beta.py +727 -0
- agentinputlab/registry/data/algorithms.json +1959 -0
- agentinputlab/registry/data/auxiliary_method_profiles.json +34 -0
- agentinputlab/registry/loader.py +100 -0
- agentinputlab/registry/result_manifest.py +184 -0
- agentinputlab/registry/runtime.py +195 -0
- agentinputlab/registry/schema.py +449 -0
- agentinputlab/runner/__init__.py +30 -0
- agentinputlab/runner/balance.py +248 -0
- agentinputlab/runner/cache.py +135 -0
- agentinputlab/runner/composite.py +130 -0
- agentinputlab/runner/engine.py +285 -0
- agentinputlab/runner/runtime_guard.py +268 -0
- agentinputlab/runner/worker.py +80 -0
- agentinputlab/runtime_bootstrap.py +288 -0
- agentinputlab/selectors/__init__.py +196 -0
- agentinputlab/selectors/advanced.py +1514 -0
- agentinputlab/selectors/artifacts.py +1087 -0
- agentinputlab/selectors/base.py +112 -0
- agentinputlab/selectors/campaigns.py +1893 -0
- agentinputlab/selectors/catalog.py +86 -0
- agentinputlab/selectors/discovery.py +1860 -0
- agentinputlab/selectors/evaluation.py +1348 -0
- agentinputlab/selectors/features.py +383 -0
- agentinputlab/selectors/learned.py +502 -0
- agentinputlab/selectors/no_op.py +28 -0
- agentinputlab/selectors/outcome_table.py +475 -0
- agentinputlab/selectors/producer.py +853 -0
- agentinputlab/selectors/rules.py +109 -0
- agentinputlab/selectors/runtime.py +420 -0
- agentinputlab/studies/__init__.py +16 -0
- agentinputlab/studies/design.py +165 -0
- agentinputlab/studies/paired.py +322 -0
- agentinputlab/studio/__init__.py +6 -0
- agentinputlab/studio/campaigns.py +819 -0
- agentinputlab/studio/engine.py +1408 -0
- agentinputlab/studio/model_backends.py +425 -0
- agentinputlab/studio/prepared.py +410 -0
- agentinputlab/studio/server.py +613 -0
- agentinputlab/studio/static/app.js +397 -0
- agentinputlab/studio/static/campaigns.html +175 -0
- agentinputlab/studio/static/campaigns.js +426 -0
- agentinputlab/studio/static/index.html +192 -0
- agentinputlab/studio/static/result.html +103 -0
- agentinputlab/studio/static/result.js +273 -0
- agentinputlab/studio/static/styles.css +467 -0
- agentinputlab-0.1.0a1.data/data/share/agentinputlab/CITATION.cff +22 -0
- agentinputlab-0.1.0a1.dist-info/METADATA +392 -0
- agentinputlab-0.1.0a1.dist-info/RECORD +469 -0
- agentinputlab-0.1.0a1.dist-info/WHEEL +5 -0
- agentinputlab-0.1.0a1.dist-info/entry_points.txt +6 -0
- agentinputlab-0.1.0a1.dist-info/licenses/LICENSE +21 -0
- agentinputlab-0.1.0a1.dist-info/licenses/NOTICE +31 -0
- agentinputlab-0.1.0a1.dist-info/licenses/THIRD_PARTY_NOTICES.md +94 -0
- agentinputlab-0.1.0a1.dist-info/top_level.txt +2 -0
- workers/README.md +94 -0
- workers/ace/README.md +261 -0
- workers/ace/__init__.py +1 -0
- workers/ace/compatibility_manifest.json +39 -0
- workers/ace/driver.py +1682 -0
- workers/acon/README.md +215 -0
- workers/acon/__init__.py +5 -0
- workers/acon/compatibility_manifest.json +93 -0
- workers/acon/driver.py +1859 -0
- workers/acon/fitted.py +395 -0
- workers/acon/guideline.py +470 -0
- workers/acon/guideline_source_manifest.json +20 -0
- workers/adaptive_rag/README.md +96 -0
- workers/adaptive_rag/__init__.py +15 -0
- workers/adaptive_rag/compatibility_manifest.json +61 -0
- workers/adaptive_rag/driver.py +1470 -0
- workers/adaptive_rag/fixture_runtime.py +163 -0
- workers/adaptive_rag/runtime.py +252 -0
- workers/ask_or_assume/README.md +124 -0
- workers/ask_or_assume/__init__.py +1 -0
- workers/ask_or_assume/compatibility_manifest.json +36 -0
- workers/ask_or_assume/driver.py +1227 -0
- workers/decomp/README.md +133 -0
- workers/decomp/UPSTREAM_LICENSE.Apache-2.0.txt +201 -0
- workers/decomp/__init__.py +5 -0
- workers/decomp/compatibility_manifest.json +205 -0
- workers/decomp/driver.py +1015 -0
- workers/decomp/live.py +137 -0
- workers/decomp/runtime.py +231 -0
- workers/infocqr/README.md +106 -0
- workers/infocqr/__init__.py +1 -0
- workers/infocqr/compatibility_manifest.json +84 -0
- workers/infocqr/driver.py +1766 -0
- workers/ircot/README.md +167 -0
- workers/ircot/__init__.py +7 -0
- workers/ircot/compatibility_manifest.json +121 -0
- workers/ircot/controlled.py +457 -0
- workers/ircot/driver.py +1373 -0
- workers/ircot/fixture_bindings.json +39 -0
- workers/ircot/fixture_config.json +48 -0
- workers/ircot/fixture_prompt.txt +2 -0
- workers/ircot/native_qa.py +398 -0
- workers/ircot/qa_compatibility_manifest.json +57 -0
- workers/ircot/runtime.py +97 -0
- workers/llmcompiler/README.md +160 -0
- workers/llmcompiler/__init__.py +1 -0
- workers/llmcompiler/compatibility_manifest.json +45 -0
- workers/llmcompiler/driver.py +1514 -0
- workers/llmcompiler/export_prompts.py +74 -0
- workers/llmcompiler/live.py +174 -0
- workers/llmcompiler/patch_manifest.json +147 -0
- workers/mce/README.md +198 -0
- workers/mce/__init__.py +29 -0
- workers/mce/compatibility_manifest.json +115 -0
- workers/mce/driver.py +2585 -0
- workers/mce/final_eval.py +173 -0
- workers/official_arenas/README.md +25 -0
- workers/official_arenas/__init__.py +1 -0
- workers/official_arenas/capture_records.py +110 -0
- workers/official_arenas/driver.py +619 -0
- workers/official_arenas/protocol.py +334 -0
- workers/official_arenas/providers/__init__.py +1 -0
- workers/official_arenas/providers/_live_history.py +228 -0
- workers/official_arenas/providers/_message_compat.py +77 -0
- workers/official_arenas/providers/appworld_ul.py +196 -0
- workers/official_arenas/providers/fixture.py +112 -0
- workers/official_arenas/providers/statebench.py +960 -0
- workers/official_arenas/providers/tau3.py +1672 -0
- workers/official_arenas/providers/tau_retail.py +586 -0
- workers/official_arenas/providers/toolsandbox.py +1321 -0
- workers/official_arenas/providers/tooltalk.py +699 -0
- workers/official_arenas/retail_capture.py +188 -0
- workers/official_arenas/retail_driver.py +275 -0
- workers/qrag/README.md +172 -0
- workers/qrag/__init__.py +1 -0
- workers/qrag/compatibility_manifest.json +64 -0
- workers/qrag/driver.py +673 -0
- workers/r2ag/README.md +154 -0
- workers/r2ag/__init__.py +5 -0
- workers/r2ag/compatibility_manifest.json +55 -0
- workers/r2ag/driver.py +1287 -0
- workers/r2ag/feature_schema.json +8 -0
- workers/r2ag/runtime.py +589 -0
- workers/recomp/README.md +120 -0
- workers/recomp/__init__.py +1 -0
- workers/recomp/compatibility_manifest.json +43 -0
- workers/recomp/driver.py +1653 -0
- workers/reformer/README.md +125 -0
- workers/reformer/__init__.py +1 -0
- workers/reformer/compatibility_manifest.json +68 -0
- workers/reformer/driver.py +1459 -0
- workers/reformer/induction.py +457 -0
- workers/rrr/README.md +126 -0
- workers/rrr/__init__.py +1 -0
- workers/rrr/compatibility_manifest.json +57 -0
- workers/rrr/driver.py +1133 -0
- workers/smartsearch/README.md +331 -0
- workers/smartsearch/__init__.py +1 -0
- workers/smartsearch/compatibility_manifest.json +41 -0
- workers/smartsearch/driver.py +1643 -0
|
@@ -0,0 +1,891 @@
|
|
|
1
|
+
"""Released Q-RAG value policy adapted to the shared agent arenas.
|
|
2
|
+
|
|
3
|
+
The upstream worker remains the paper-shaped selector/reader path. This module
|
|
4
|
+
provides a separate common-support intervention: the shared retriever builds an
|
|
5
|
+
ordered candidate pool, the released frozen PQN selects two documents with the
|
|
6
|
+
official QAEnv/PQN loop, and the unified downstream agent answers from those
|
|
7
|
+
real documents. No gold answer, supporting-fact label, reward, training step,
|
|
8
|
+
or upstream reader is available to the intervention.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import gc
|
|
14
|
+
import hashlib
|
|
15
|
+
import importlib.util
|
|
16
|
+
import json
|
|
17
|
+
import math
|
|
18
|
+
import os
|
|
19
|
+
import random
|
|
20
|
+
import re
|
|
21
|
+
import subprocess
|
|
22
|
+
import sys
|
|
23
|
+
import time
|
|
24
|
+
import types
|
|
25
|
+
from collections import defaultdict
|
|
26
|
+
from collections.abc import Mapping, Sequence
|
|
27
|
+
from contextlib import contextmanager, suppress
|
|
28
|
+
from dataclasses import dataclass, field
|
|
29
|
+
from pathlib import Path
|
|
30
|
+
from typing import Any, Protocol, runtime_checkable
|
|
31
|
+
|
|
32
|
+
from agentinputlab.backends.retrieval import RetrievalResult, Retriever
|
|
33
|
+
from agentinputlab.contracts import (
|
|
34
|
+
AlgorithmOutputError,
|
|
35
|
+
BudgetExceededError,
|
|
36
|
+
ContextBlock,
|
|
37
|
+
ExecutionTrace,
|
|
38
|
+
ExternalDependencyError,
|
|
39
|
+
FrozenAgentState,
|
|
40
|
+
InputPatch,
|
|
41
|
+
InterventionContext,
|
|
42
|
+
PatchOp,
|
|
43
|
+
PatchOperation,
|
|
44
|
+
SemanticFamily,
|
|
45
|
+
TraceEvent,
|
|
46
|
+
TracePhase,
|
|
47
|
+
ValidationError,
|
|
48
|
+
)
|
|
49
|
+
from agentinputlab.contracts.serialization import content_hash, freeze_mapping
|
|
50
|
+
|
|
51
|
+
from .bridge import (
|
|
52
|
+
QRAG_CHECKPOINT_CONFIG_SHA256,
|
|
53
|
+
QRAG_CHECKPOINT_FILE_SHA256,
|
|
54
|
+
QRAG_CHECKPOINT_REPOSITORY,
|
|
55
|
+
QRAG_CHECKPOINT_REVISION,
|
|
56
|
+
QRAG_EMBEDDER_MODEL_SHA256,
|
|
57
|
+
QRAG_EMBEDDER_REPOSITORY,
|
|
58
|
+
QRAG_EMBEDDER_REVISION,
|
|
59
|
+
QRAG_SOURCE_MANIFEST_SHA256,
|
|
60
|
+
QRAG_UPSTREAM_COMMIT,
|
|
61
|
+
)
|
|
62
|
+
from .native_axis import (
|
|
63
|
+
QRAG_SINGLE_CANDIDATE_AXIS_COMPAT,
|
|
64
|
+
install_single_candidate_axis_compat,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
_SHA256 = re.compile(r"^[0-9a-f]{64}$")
|
|
68
|
+
_SOURCE_RECEIPT = "agentinputlab-source-receipt.json"
|
|
69
|
+
_EMBEDDER_MANIFEST = "agentinputlab-manifest.json"
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _sha256_file(path: Path) -> str:
|
|
73
|
+
digest = hashlib.sha256()
|
|
74
|
+
with path.open("rb") as handle:
|
|
75
|
+
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
|
|
76
|
+
digest.update(chunk)
|
|
77
|
+
return digest.hexdigest()
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _json(path: Path) -> Mapping[str, Any]:
|
|
81
|
+
try:
|
|
82
|
+
value = json.loads(path.read_text(encoding="utf-8"))
|
|
83
|
+
except (OSError, UnicodeDecodeError, json.JSONDecodeError) as exc:
|
|
84
|
+
raise ExternalDependencyError(f"Q-RAG artifact JSON is invalid: {path}") from exc
|
|
85
|
+
if not isinstance(value, Mapping):
|
|
86
|
+
raise ExternalDependencyError(f"Q-RAG artifact JSON must be an object: {path}")
|
|
87
|
+
return value
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def _real_directory(value: Path, *, label: str) -> Path:
|
|
91
|
+
path = value.expanduser().resolve()
|
|
92
|
+
if not path.is_dir() or path.is_symlink():
|
|
93
|
+
raise ValidationError(f"Q-RAG {label} must be a real directory")
|
|
94
|
+
return path
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _real_file(value: Path, *, label: str) -> Path:
|
|
98
|
+
path = value.expanduser().resolve()
|
|
99
|
+
if not path.is_file() or path.is_symlink():
|
|
100
|
+
raise ValidationError(f"Q-RAG {label} must be a real file")
|
|
101
|
+
return path
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _safe_file(root: Path, relative: str) -> Path:
|
|
105
|
+
if not relative or Path(relative).is_absolute():
|
|
106
|
+
raise ExternalDependencyError("Q-RAG artifact path is invalid")
|
|
107
|
+
path = root / relative
|
|
108
|
+
if path.is_symlink():
|
|
109
|
+
raise ExternalDependencyError("Q-RAG artifact symlinks are forbidden")
|
|
110
|
+
try:
|
|
111
|
+
resolved = path.resolve(strict=True)
|
|
112
|
+
resolved.relative_to(root)
|
|
113
|
+
except (FileNotFoundError, ValueError) as exc:
|
|
114
|
+
raise ExternalDependencyError("Q-RAG artifact path escapes its root or is missing") from exc
|
|
115
|
+
if not resolved.is_file():
|
|
116
|
+
raise ExternalDependencyError("Q-RAG artifact path is not a file")
|
|
117
|
+
return resolved
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@contextmanager
|
|
121
|
+
def _source_import(root: Path):
|
|
122
|
+
value = str(root)
|
|
123
|
+
sys.path.insert(0, value)
|
|
124
|
+
try:
|
|
125
|
+
yield
|
|
126
|
+
finally:
|
|
127
|
+
if sys.path and sys.path[0] == value:
|
|
128
|
+
sys.path.pop(0)
|
|
129
|
+
else: # pragma: no cover - defensive against third-party path mutation
|
|
130
|
+
with suppress(ValueError):
|
|
131
|
+
sys.path.remove(value)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@contextmanager
|
|
135
|
+
def _unused_vllm_import_compatibility():
|
|
136
|
+
"""Allow the released dummy-feedback path without a worker-local vLLM.
|
|
137
|
+
|
|
138
|
+
Q-RAG's ``rl.feedback`` package imports its optional local reader at module
|
|
139
|
+
import time, even though the common-support runtime uses only the released
|
|
140
|
+
``DummyFeedbackModel``. Keep target serving isolated in the external vLLM
|
|
141
|
+
process and fail closed if this unused reader is ever constructed.
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
try:
|
|
145
|
+
available = importlib.util.find_spec("vllm") is not None
|
|
146
|
+
except (ImportError, ValueError):
|
|
147
|
+
available = "vllm" in sys.modules
|
|
148
|
+
if available:
|
|
149
|
+
yield
|
|
150
|
+
return
|
|
151
|
+
|
|
152
|
+
class _UnavailableVLLM:
|
|
153
|
+
def __init__(self, *_args: Any, **_kwargs: Any) -> None:
|
|
154
|
+
raise RuntimeError(
|
|
155
|
+
"Q-RAG common-support execution must not instantiate its unused vLLM reader"
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
module = types.ModuleType("vllm")
|
|
159
|
+
module.LLM = _UnavailableVLLM
|
|
160
|
+
module.SamplingParams = _UnavailableVLLM
|
|
161
|
+
sys.modules["vllm"] = module
|
|
162
|
+
try:
|
|
163
|
+
yield
|
|
164
|
+
finally:
|
|
165
|
+
if sys.modules.get("vllm") is module:
|
|
166
|
+
del sys.modules["vllm"]
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
@dataclass(frozen=True, slots=True)
|
|
170
|
+
class QRAGPolicyRequest:
|
|
171
|
+
question: str
|
|
172
|
+
candidates: tuple[RetrievalResult, ...]
|
|
173
|
+
seed: int
|
|
174
|
+
max_steps: int = 2
|
|
175
|
+
|
|
176
|
+
def __post_init__(self) -> None:
|
|
177
|
+
if not self.question.strip() or not self.candidates:
|
|
178
|
+
raise ValidationError("Q-RAG policy request requires question and candidates")
|
|
179
|
+
if isinstance(self.seed, bool) or not isinstance(self.seed, int) or self.seed < 0:
|
|
180
|
+
raise ValidationError("Q-RAG policy seed must be non-negative")
|
|
181
|
+
if self.max_steps != 2:
|
|
182
|
+
raise ValidationError("released Q-RAG policy requires exactly two selection steps")
|
|
183
|
+
object.__setattr__(self, "candidates", tuple(self.candidates))
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@runtime_checkable
|
|
187
|
+
class QRAGCommonSupportRuntime(Protocol):
|
|
188
|
+
def select(self, request: QRAGPolicyRequest) -> Mapping[str, Any]:
|
|
189
|
+
"""Select two candidate indices with the released value policy."""
|
|
190
|
+
|
|
191
|
+
def fingerprint(self) -> Mapping[str, Any]:
|
|
192
|
+
"""Return checksum-closed source, checkpoint, and embedder identity."""
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@dataclass(slots=True)
|
|
196
|
+
class LocalQRAGFrozenPolicyRuntime: # pragma: no cover - L20 GPU acceptance
|
|
197
|
+
"""Lazy inference-only runtime around the pinned upstream QAEnv and PQN."""
|
|
198
|
+
|
|
199
|
+
source_root: Path
|
|
200
|
+
checkpoint_root: Path
|
|
201
|
+
embedder_root: Path
|
|
202
|
+
compatibility_manifest_path: Path
|
|
203
|
+
compatibility_manifest_sha256: str
|
|
204
|
+
embedder_manifest_sha256: str
|
|
205
|
+
device: str = "cuda"
|
|
206
|
+
worker_id: str = "qrag-common-support-local"
|
|
207
|
+
single_candidate_axis_compat: bool = False
|
|
208
|
+
_runtime: tuple[Any, Any, Any] | None = field(init=False, default=None, repr=False)
|
|
209
|
+
_verified: bool = field(init=False, default=False, repr=False)
|
|
210
|
+
|
|
211
|
+
def __post_init__(self) -> None:
|
|
212
|
+
if not isinstance(self.single_candidate_axis_compat, bool):
|
|
213
|
+
raise ValidationError("Q-RAG single_candidate_axis_compat must be boolean")
|
|
214
|
+
self.source_root = _real_directory(self.source_root, label="source_root")
|
|
215
|
+
self.checkpoint_root = _real_directory(self.checkpoint_root, label="checkpoint_root")
|
|
216
|
+
self.embedder_root = _real_directory(self.embedder_root, label="embedder_root")
|
|
217
|
+
self.compatibility_manifest_path = _real_file(
|
|
218
|
+
self.compatibility_manifest_path,
|
|
219
|
+
label="compatibility_manifest_path",
|
|
220
|
+
)
|
|
221
|
+
for label, value in (
|
|
222
|
+
("compatibility_manifest_sha256", self.compatibility_manifest_sha256),
|
|
223
|
+
("embedder_manifest_sha256", self.embedder_manifest_sha256),
|
|
224
|
+
):
|
|
225
|
+
if not isinstance(value, str) or _SHA256.fullmatch(value) is None:
|
|
226
|
+
raise ValidationError(f"Q-RAG {label} must be a lowercase SHA-256")
|
|
227
|
+
if not isinstance(self.device, str) or not self.device.strip():
|
|
228
|
+
raise ValidationError("Q-RAG device must not be empty")
|
|
229
|
+
|
|
230
|
+
def _verify_artifacts(self) -> Mapping[str, Any]:
|
|
231
|
+
manifest = _json(self.compatibility_manifest_path)
|
|
232
|
+
if content_hash(manifest) != self.compatibility_manifest_sha256:
|
|
233
|
+
raise ExternalDependencyError("Q-RAG compatibility manifest checksum mismatch")
|
|
234
|
+
source = manifest.get("source")
|
|
235
|
+
checkpoint = manifest.get("checkpoint")
|
|
236
|
+
embedder = manifest.get("embedder")
|
|
237
|
+
if not all(isinstance(row, Mapping) for row in (source, checkpoint, embedder)):
|
|
238
|
+
raise ExternalDependencyError("Q-RAG compatibility manifest sections are invalid")
|
|
239
|
+
assert isinstance(source, Mapping)
|
|
240
|
+
assert isinstance(checkpoint, Mapping)
|
|
241
|
+
assert isinstance(embedder, Mapping)
|
|
242
|
+
if (
|
|
243
|
+
source.get("commit") != QRAG_UPSTREAM_COMMIT
|
|
244
|
+
or source.get("content_manifest_sha256") != QRAG_SOURCE_MANIFEST_SHA256
|
|
245
|
+
or checkpoint.get("repository") != QRAG_CHECKPOINT_REPOSITORY
|
|
246
|
+
or checkpoint.get("revision") != QRAG_CHECKPOINT_REVISION
|
|
247
|
+
or embedder.get("repository") != QRAG_EMBEDDER_REPOSITORY
|
|
248
|
+
or embedder.get("revision") != QRAG_EMBEDDER_REVISION
|
|
249
|
+
or embedder.get("model_safetensors_sha256") != QRAG_EMBEDDER_MODEL_SHA256
|
|
250
|
+
):
|
|
251
|
+
raise ExternalDependencyError("Q-RAG compatibility manifest identity drifted")
|
|
252
|
+
required = source.get("required_files")
|
|
253
|
+
if not isinstance(required, Mapping) or not required:
|
|
254
|
+
raise ExternalDependencyError("Q-RAG source required-file manifest is invalid")
|
|
255
|
+
for relative, expected in required.items():
|
|
256
|
+
if not isinstance(relative, str) or not isinstance(expected, str):
|
|
257
|
+
raise ExternalDependencyError("Q-RAG source required-file row is invalid")
|
|
258
|
+
if _sha256_file(_safe_file(self.source_root, relative)) != expected:
|
|
259
|
+
raise ExternalDependencyError(f"Q-RAG source hash mismatch: {relative}")
|
|
260
|
+
self._verify_source_transport(source)
|
|
261
|
+
|
|
262
|
+
model_path = _safe_file(self.checkpoint_root, "model_best.pt")
|
|
263
|
+
config_path = _safe_file(self.checkpoint_root, "config.yaml")
|
|
264
|
+
if model_path.stat().st_size != checkpoint.get("model_best_size"):
|
|
265
|
+
raise ExternalDependencyError("Q-RAG checkpoint size mismatch")
|
|
266
|
+
if _sha256_file(model_path) != QRAG_CHECKPOINT_FILE_SHA256:
|
|
267
|
+
raise ExternalDependencyError("Q-RAG checkpoint checksum mismatch")
|
|
268
|
+
if _sha256_file(config_path) != QRAG_CHECKPOINT_CONFIG_SHA256:
|
|
269
|
+
raise ExternalDependencyError("Q-RAG checkpoint configuration checksum mismatch")
|
|
270
|
+
self._verify_embedder_manifest()
|
|
271
|
+
self._verified = True
|
|
272
|
+
return manifest
|
|
273
|
+
|
|
274
|
+
def _verify_source_transport(self, source: Mapping[str, Any]) -> None:
|
|
275
|
+
git_dir = self.source_root / ".git"
|
|
276
|
+
if git_dir.exists():
|
|
277
|
+
completed = subprocess.run(
|
|
278
|
+
["git", "-C", str(self.source_root), "rev-parse", "HEAD"],
|
|
279
|
+
check=False,
|
|
280
|
+
capture_output=True,
|
|
281
|
+
text=True,
|
|
282
|
+
timeout=10,
|
|
283
|
+
)
|
|
284
|
+
if completed.returncode or completed.stdout.strip() != QRAG_UPSTREAM_COMMIT:
|
|
285
|
+
raise ExternalDependencyError("Q-RAG source checkout commit mismatch")
|
|
286
|
+
return
|
|
287
|
+
receipt = _json(_safe_file(self.source_root, _SOURCE_RECEIPT))
|
|
288
|
+
expected = {
|
|
289
|
+
"repository": source.get("repository"),
|
|
290
|
+
"commit": source.get("commit"),
|
|
291
|
+
"tree": source.get("tree"),
|
|
292
|
+
"transport": "jsdelivr_commit_snapshot",
|
|
293
|
+
}
|
|
294
|
+
if any(receipt.get(key) != value for key, value in expected.items()):
|
|
295
|
+
raise ExternalDependencyError("Q-RAG source snapshot identity mismatch")
|
|
296
|
+
self._verify_file_closure(
|
|
297
|
+
self.source_root,
|
|
298
|
+
receipt.get("files"),
|
|
299
|
+
excluded={_SOURCE_RECEIPT},
|
|
300
|
+
label="source snapshot",
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
def _verify_embedder_manifest(self) -> None:
|
|
304
|
+
path = _safe_file(self.embedder_root, _EMBEDDER_MANIFEST)
|
|
305
|
+
manifest = _json(path)
|
|
306
|
+
if content_hash(manifest) != self.embedder_manifest_sha256:
|
|
307
|
+
raise ExternalDependencyError("Q-RAG embedder manifest checksum mismatch")
|
|
308
|
+
if (
|
|
309
|
+
manifest.get("repository") != QRAG_EMBEDDER_REPOSITORY
|
|
310
|
+
or manifest.get("revision") != QRAG_EMBEDDER_REVISION
|
|
311
|
+
):
|
|
312
|
+
raise ExternalDependencyError("Q-RAG embedder repository/revision mismatch")
|
|
313
|
+
if _sha256_file(_safe_file(self.embedder_root, "model.safetensors")) != (
|
|
314
|
+
QRAG_EMBEDDER_MODEL_SHA256
|
|
315
|
+
):
|
|
316
|
+
raise ExternalDependencyError("Q-RAG embedder weights checksum mismatch")
|
|
317
|
+
self._verify_file_closure(
|
|
318
|
+
self.embedder_root,
|
|
319
|
+
manifest.get("files"),
|
|
320
|
+
excluded={_EMBEDDER_MANIFEST},
|
|
321
|
+
label="embedder snapshot",
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
@staticmethod
|
|
325
|
+
def _verify_file_closure(
|
|
326
|
+
root: Path,
|
|
327
|
+
rows: Any,
|
|
328
|
+
*,
|
|
329
|
+
excluded: set[str],
|
|
330
|
+
label: str,
|
|
331
|
+
) -> None:
|
|
332
|
+
if isinstance(rows, (str, bytes)) or not isinstance(rows, Sequence) or not rows:
|
|
333
|
+
raise ExternalDependencyError(f"Q-RAG {label} file receipt is invalid")
|
|
334
|
+
declared: set[str] = set()
|
|
335
|
+
for row in rows:
|
|
336
|
+
if not isinstance(row, Mapping) or set(row) != {"path", "sha256", "size"}:
|
|
337
|
+
raise ExternalDependencyError(f"Q-RAG {label} file row is invalid")
|
|
338
|
+
relative, digest, size = row.get("path"), row.get("sha256"), row.get("size")
|
|
339
|
+
if (
|
|
340
|
+
not isinstance(relative, str)
|
|
341
|
+
or relative in excluded
|
|
342
|
+
or relative in declared
|
|
343
|
+
or not isinstance(digest, str)
|
|
344
|
+
or _SHA256.fullmatch(digest) is None
|
|
345
|
+
or isinstance(size, bool)
|
|
346
|
+
or not isinstance(size, int)
|
|
347
|
+
or size < 0
|
|
348
|
+
):
|
|
349
|
+
raise ExternalDependencyError(f"Q-RAG {label} file row is invalid")
|
|
350
|
+
path = _safe_file(root, relative)
|
|
351
|
+
if path.stat().st_size != size or _sha256_file(path) != digest:
|
|
352
|
+
raise ExternalDependencyError(f"Q-RAG {label} file checksum mismatch: {relative}")
|
|
353
|
+
declared.add(relative)
|
|
354
|
+
actual = {
|
|
355
|
+
str(path.relative_to(root))
|
|
356
|
+
for path in root.rglob("*")
|
|
357
|
+
if path.is_file()
|
|
358
|
+
and str(path.relative_to(root)) not in excluded
|
|
359
|
+
and ".cache" not in path.parts
|
|
360
|
+
and "__pycache__" not in path.parts
|
|
361
|
+
and path.suffix not in {".pyc", ".lock", ".incomplete"}
|
|
362
|
+
}
|
|
363
|
+
if actual != declared:
|
|
364
|
+
raise ExternalDependencyError(f"Q-RAG {label} file closure mismatch")
|
|
365
|
+
|
|
366
|
+
def _load(self) -> tuple[Any, Any, Any]:
|
|
367
|
+
if self._runtime is not None:
|
|
368
|
+
return self._runtime
|
|
369
|
+
if not self._verified:
|
|
370
|
+
self._verify_artifacts()
|
|
371
|
+
os.environ.setdefault("TRANSFORMERS_OFFLINE", "1")
|
|
372
|
+
os.environ.setdefault("HF_DATASETS_OFFLINE", "1")
|
|
373
|
+
try:
|
|
374
|
+
import torch
|
|
375
|
+
from omegaconf import OmegaConf
|
|
376
|
+
from omegaconf.base import ContainerMetadata, Metadata
|
|
377
|
+
from omegaconf.listconfig import ListConfig
|
|
378
|
+
from omegaconf.nodes import AnyNode
|
|
379
|
+
except ImportError as exc:
|
|
380
|
+
raise ExternalDependencyError(
|
|
381
|
+
"Q-RAG local runtime requires torch, numpy, omegaconf, hydra-core, "
|
|
382
|
+
"rotary-embedding-torch, sortedcontainers, nltk, and transformers"
|
|
383
|
+
) from exc
|
|
384
|
+
with _unused_vllm_import_compatibility(), _source_import(self.source_root):
|
|
385
|
+
try:
|
|
386
|
+
from envs.qa_env import QAEnv
|
|
387
|
+
from envs.text_env import AbsolutePositionProcessor
|
|
388
|
+
from rl.agents.pqn import PQN
|
|
389
|
+
from rl.feedback.feedback import AFeedbackModel, DummyFeedbackModel
|
|
390
|
+
except ImportError as exc:
|
|
391
|
+
raise ExternalDependencyError("unable to import pinned Q-RAG source") from exc
|
|
392
|
+
|
|
393
|
+
class RunnableDummyFeedbackModel(DummyFeedbackModel):
|
|
394
|
+
"""Repair the upstream missing abstract reset without changing feedback semantics."""
|
|
395
|
+
|
|
396
|
+
def reset(self, obs: Any, info: Any) -> None:
|
|
397
|
+
AFeedbackModel.reset(self, obs, info)
|
|
398
|
+
|
|
399
|
+
cfg = OmegaConf.load(self.checkpoint_root / "config.yaml")
|
|
400
|
+
cfg.algo.model.model_name = str(self.embedder_root)
|
|
401
|
+
cfg.algo.model.revision = None
|
|
402
|
+
OmegaConf.resolve(cfg)
|
|
403
|
+
torch.set_default_device(self.device)
|
|
404
|
+
torch.set_float32_matmul_precision("high")
|
|
405
|
+
with _source_import(self.source_root):
|
|
406
|
+
agent = PQN(cfg.algo)
|
|
407
|
+
# The released checkpoint contains an OmegaConf ListConfig under its
|
|
408
|
+
# scheduler state. Keep weights-only loading and scope the smallest
|
|
409
|
+
# inert constructor allowlist needed to deserialize that container;
|
|
410
|
+
# arbitrary upstream Python globals remain rejected.
|
|
411
|
+
safe_checkpoint_globals = [
|
|
412
|
+
ListConfig,
|
|
413
|
+
ContainerMetadata,
|
|
414
|
+
Metadata,
|
|
415
|
+
Any,
|
|
416
|
+
list,
|
|
417
|
+
defaultdict,
|
|
418
|
+
dict,
|
|
419
|
+
int,
|
|
420
|
+
AnyNode,
|
|
421
|
+
]
|
|
422
|
+
with torch.serialization.safe_globals(safe_checkpoint_globals):
|
|
423
|
+
checkpoint = torch.load(
|
|
424
|
+
self.checkpoint_root / "model_best.pt",
|
|
425
|
+
map_location="cpu",
|
|
426
|
+
weights_only=True,
|
|
427
|
+
mmap=True,
|
|
428
|
+
)
|
|
429
|
+
required = {
|
|
430
|
+
"critic": agent.critic,
|
|
431
|
+
"policy": agent.policy,
|
|
432
|
+
"v_net_target": agent.v_net_target,
|
|
433
|
+
"action_embed_target": agent.action_embed_target,
|
|
434
|
+
}
|
|
435
|
+
if not isinstance(checkpoint, Mapping) or not set(required).issubset(checkpoint):
|
|
436
|
+
raise ExternalDependencyError("Q-RAG checkpoint lacks inference state dictionaries")
|
|
437
|
+
for name, module in required.items():
|
|
438
|
+
module.load_state_dict(checkpoint[name], strict=True)
|
|
439
|
+
module.eval()
|
|
440
|
+
agent.random_policy.eval()
|
|
441
|
+
if self.single_candidate_axis_compat:
|
|
442
|
+
install_single_candidate_axis_compat(agent.policy, self.source_root)
|
|
443
|
+
del checkpoint
|
|
444
|
+
gc.collect()
|
|
445
|
+
if str(self.device).startswith("cuda"):
|
|
446
|
+
torch.cuda.empty_cache()
|
|
447
|
+
env = QAEnv(
|
|
448
|
+
dataset=None,
|
|
449
|
+
max_steps=2,
|
|
450
|
+
positions_processor=AbsolutePositionProcessor(),
|
|
451
|
+
action_embed_length=int(cfg.max_action_length),
|
|
452
|
+
max_action_length_in_memory=int(cfg.algo.pqn.hyperparams.max_action_length_in_memory),
|
|
453
|
+
feedback_model=RunnableDummyFeedbackModel(),
|
|
454
|
+
separator=" [SEP] ",
|
|
455
|
+
sort_by_index=False,
|
|
456
|
+
)
|
|
457
|
+
self._runtime = (torch, agent, env)
|
|
458
|
+
return self._runtime
|
|
459
|
+
|
|
460
|
+
def select(self, request: QRAGPolicyRequest) -> Mapping[str, Any]:
|
|
461
|
+
if not isinstance(request, QRAGPolicyRequest):
|
|
462
|
+
raise TypeError("Q-RAG runtime requires QRAGPolicyRequest")
|
|
463
|
+
torch, agent, env = self._load()
|
|
464
|
+
try:
|
|
465
|
+
import numpy as np
|
|
466
|
+
except ImportError as exc: # pragma: no cover
|
|
467
|
+
raise ExternalDependencyError("Q-RAG runtime requires numpy") from exc
|
|
468
|
+
random.seed(request.seed)
|
|
469
|
+
np.random.seed(request.seed)
|
|
470
|
+
torch.manual_seed(request.seed)
|
|
471
|
+
if str(self.device).startswith("cuda"):
|
|
472
|
+
torch.cuda.manual_seed_all(request.seed)
|
|
473
|
+
torch.cuda.synchronize()
|
|
474
|
+
candidate_ids = tuple(row.document.doc_id for row in request.candidates)
|
|
475
|
+
chunks = tuple(_policy_candidate_text(row) for row in request.candidates)
|
|
476
|
+
sample = {
|
|
477
|
+
"id": content_hash({"question": request.question, "candidates": candidate_ids}),
|
|
478
|
+
"question": request.question,
|
|
479
|
+
"answer": "",
|
|
480
|
+
"chunks": chunks,
|
|
481
|
+
"sf_idx": [],
|
|
482
|
+
}
|
|
483
|
+
started = time.perf_counter()
|
|
484
|
+
state = env.reset(sample)
|
|
485
|
+
embeds, embeds_target = env.get_extra_embeds(
|
|
486
|
+
agent.action_tokenizer,
|
|
487
|
+
agent.critic.action_embed,
|
|
488
|
+
agent.action_embed_target,
|
|
489
|
+
)
|
|
490
|
+
steps: list[dict[str, Any]] = []
|
|
491
|
+
done = False
|
|
492
|
+
while not done and len(steps) < request.max_steps:
|
|
493
|
+
available = tuple(sorted(int(index) for index in state.available_ids))
|
|
494
|
+
embeds = env.update_embeds(embeds, agent.critic.action_embed)
|
|
495
|
+
embeds_target = env.update_embeds(embeds_target, agent.action_embed_target)
|
|
496
|
+
action, q_values, _ = agent.select_action(
|
|
497
|
+
state,
|
|
498
|
+
embeds["rope"],
|
|
499
|
+
embeds_target["rope"],
|
|
500
|
+
random=False,
|
|
501
|
+
evaluate=True,
|
|
502
|
+
)
|
|
503
|
+
q_row = q_values.detach().to(device="cpu", dtype=torch.float64).reshape(-1)
|
|
504
|
+
if q_row.numel() != len(candidate_ids) or action not in available:
|
|
505
|
+
raise AlgorithmOutputError("Q-RAG policy returned an invalid candidate action")
|
|
506
|
+
selected_q = float(q_row[action].item())
|
|
507
|
+
if not math.isfinite(selected_q):
|
|
508
|
+
raise AlgorithmOutputError("Q-RAG policy returned a non-finite selected value")
|
|
509
|
+
state, _, _, done = env.step(action)
|
|
510
|
+
selected = tuple(int(index) for index in state.item_ids)
|
|
511
|
+
steps.append(
|
|
512
|
+
{
|
|
513
|
+
"index": len(steps),
|
|
514
|
+
"available_indices": available,
|
|
515
|
+
"q_values": tuple(float(q_row[index].item()) for index in available),
|
|
516
|
+
"action_index": int(action),
|
|
517
|
+
"selected_q_value": selected_q,
|
|
518
|
+
"selected_indices": selected,
|
|
519
|
+
"selected_document_ids": tuple(candidate_ids[index] for index in selected),
|
|
520
|
+
}
|
|
521
|
+
)
|
|
522
|
+
if str(self.device).startswith("cuda"):
|
|
523
|
+
torch.cuda.synchronize()
|
|
524
|
+
elapsed = time.perf_counter() - started
|
|
525
|
+
selected = tuple(int(index) for index in state.item_ids)
|
|
526
|
+
expected_steps = min(2, len(candidate_ids))
|
|
527
|
+
if len(steps) != expected_steps or len(selected) != expected_steps:
|
|
528
|
+
raise AlgorithmOutputError("Q-RAG policy did not complete its fixed selection horizon")
|
|
529
|
+
return {
|
|
530
|
+
"status": "ok",
|
|
531
|
+
"trajectory": tuple(steps),
|
|
532
|
+
"trajectory_sha256": content_hash(steps),
|
|
533
|
+
"selected_indices": selected,
|
|
534
|
+
"selected_document_ids": tuple(candidate_ids[index] for index in selected),
|
|
535
|
+
"candidate_order_sha256": content_hash(candidate_ids),
|
|
536
|
+
"candidate_text_sha256": content_hash(chunks),
|
|
537
|
+
"usage": {
|
|
538
|
+
"model_calls": 0,
|
|
539
|
+
"retrieval_calls": 0,
|
|
540
|
+
"input_tokens": 0,
|
|
541
|
+
"output_tokens": 0,
|
|
542
|
+
"embedding_calls": 2 + 2 * len(steps),
|
|
543
|
+
"accelerator_seconds": elapsed,
|
|
544
|
+
},
|
|
545
|
+
"policy_steps": len(steps),
|
|
546
|
+
"attestation": {
|
|
547
|
+
"official_candidate_builder_called": True,
|
|
548
|
+
"official_pqn_select_action_called": True,
|
|
549
|
+
"official_qa_env_step_called": True,
|
|
550
|
+
"safe_weights_only_load": True,
|
|
551
|
+
"strict_state_dict_load": True,
|
|
552
|
+
"checkpoint_eval_mode": True,
|
|
553
|
+
"dummy_feedback_used": True,
|
|
554
|
+
"gold_answer_used": False,
|
|
555
|
+
"supporting_fact_labels_used": False,
|
|
556
|
+
"reward_used": False,
|
|
557
|
+
"training_called": False,
|
|
558
|
+
"stop_action_used": False,
|
|
559
|
+
"seed_applied": True,
|
|
560
|
+
},
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
def fingerprint(self) -> Mapping[str, Any]:
|
|
564
|
+
return freeze_mapping(
|
|
565
|
+
{
|
|
566
|
+
"runtime": "qrag_released_pqn_common_support.v1",
|
|
567
|
+
"source_repository": "griver/Q-RAG",
|
|
568
|
+
"source_commit": QRAG_UPSTREAM_COMMIT,
|
|
569
|
+
"source_manifest_sha256": QRAG_SOURCE_MANIFEST_SHA256,
|
|
570
|
+
"checkpoint_repository": QRAG_CHECKPOINT_REPOSITORY,
|
|
571
|
+
"checkpoint_revision": QRAG_CHECKPOINT_REVISION,
|
|
572
|
+
"checkpoint_file_sha256": QRAG_CHECKPOINT_FILE_SHA256,
|
|
573
|
+
"checkpoint_config_sha256": QRAG_CHECKPOINT_CONFIG_SHA256,
|
|
574
|
+
"embedder_repository": QRAG_EMBEDDER_REPOSITORY,
|
|
575
|
+
"embedder_revision": QRAG_EMBEDDER_REVISION,
|
|
576
|
+
"embedder_model_sha256": QRAG_EMBEDDER_MODEL_SHA256,
|
|
577
|
+
"embedder_manifest_sha256": self.embedder_manifest_sha256,
|
|
578
|
+
"compatibility_manifest_sha256": self.compatibility_manifest_sha256,
|
|
579
|
+
"safe_weights_only_load": True,
|
|
580
|
+
"strict_state_dict_load": True,
|
|
581
|
+
"optimizer_state_loaded": False,
|
|
582
|
+
"training_allowed": False,
|
|
583
|
+
"paper_result_parity_claimed": False,
|
|
584
|
+
**({"native_tensor_axis_adapter": QRAG_SINGLE_CANDIDATE_AXIS_COMPAT}
|
|
585
|
+
if self.single_candidate_axis_compat else {}),
|
|
586
|
+
}
|
|
587
|
+
)
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
@dataclass(frozen=True, slots=True)
|
|
591
|
+
class QRAGCommonSupportConfig:
|
|
592
|
+
candidate_top_k: int = 6
|
|
593
|
+
max_select_actions: int = 2
|
|
594
|
+
|
|
595
|
+
def __post_init__(self) -> None:
|
|
596
|
+
if self.candidate_top_k < 2:
|
|
597
|
+
raise ValidationError("Q-RAG common support requires at least two candidates")
|
|
598
|
+
if self.max_select_actions != 2:
|
|
599
|
+
raise ValidationError("released Q-RAG policy requires two selection actions")
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
@dataclass(slots=True)
|
|
603
|
+
class QRAGCommonSupport:
|
|
604
|
+
"""Select real shared-corpus documents with the released Q-RAG PQN."""
|
|
605
|
+
|
|
606
|
+
config: QRAGCommonSupportConfig = QRAGCommonSupportConfig()
|
|
607
|
+
method_id: str = "qrag"
|
|
608
|
+
release_id: str = "acquire.qrag.common_support"
|
|
609
|
+
family: SemanticFamily = SemanticFamily.ACQUIRE
|
|
610
|
+
|
|
611
|
+
def propose(self, state: FrozenAgentState, context: InterventionContext) -> InputPatch:
|
|
612
|
+
if not state.query.strip():
|
|
613
|
+
raise ValidationError("Q-RAG requires a non-empty query")
|
|
614
|
+
if state.budget.max_retrieval_calls < 1:
|
|
615
|
+
raise BudgetExceededError("Q-RAG has no retrieval budget")
|
|
616
|
+
retriever = _retriever(context.retriever)
|
|
617
|
+
runtime = _runtime(context.external_runtime)
|
|
618
|
+
results = _validated_results(
|
|
619
|
+
retriever.retrieve(state.query, top_k=self.config.candidate_top_k),
|
|
620
|
+
top_k=self.config.candidate_top_k,
|
|
621
|
+
)
|
|
622
|
+
if len(results) < 2:
|
|
623
|
+
raise AlgorithmOutputError("Q-RAG requires at least two retrieved candidates")
|
|
624
|
+
candidate_ids = tuple(row.document.doc_id for row in results)
|
|
625
|
+
response = runtime.select(
|
|
626
|
+
QRAGPolicyRequest(
|
|
627
|
+
question=state.query,
|
|
628
|
+
candidates=results,
|
|
629
|
+
seed=context.seed,
|
|
630
|
+
max_steps=self.config.max_select_actions,
|
|
631
|
+
)
|
|
632
|
+
)
|
|
633
|
+
trajectory, selected, usage, attestation = _validate_response(response, candidate_ids)
|
|
634
|
+
blocks = tuple(
|
|
635
|
+
_real_context(results[index], rank) for rank, index in enumerate(selected, 1)
|
|
636
|
+
)
|
|
637
|
+
runtime_identity = dict(runtime.fingerprint())
|
|
638
|
+
events = [
|
|
639
|
+
TraceEvent(
|
|
640
|
+
TracePhase.PREPARE,
|
|
641
|
+
"qrag_common_support_candidate_pool",
|
|
642
|
+
{
|
|
643
|
+
"candidate_document_ids": candidate_ids,
|
|
644
|
+
"candidate_order_sha256": content_hash(candidate_ids),
|
|
645
|
+
"retriever": dict(retriever.fingerprint()),
|
|
646
|
+
"runtime": runtime_identity,
|
|
647
|
+
"selection_budget": 2,
|
|
648
|
+
"upstream_reader_used": False,
|
|
649
|
+
"paper_result_parity_claimed": False,
|
|
650
|
+
},
|
|
651
|
+
)
|
|
652
|
+
]
|
|
653
|
+
events.extend(
|
|
654
|
+
TraceEvent(TracePhase.OBSERVE, "qrag_value_policy_step", dict(step))
|
|
655
|
+
for step in trajectory
|
|
656
|
+
)
|
|
657
|
+
events.append(
|
|
658
|
+
TraceEvent(
|
|
659
|
+
TracePhase.FINALIZE,
|
|
660
|
+
"qrag_selected_real_context",
|
|
661
|
+
{
|
|
662
|
+
"selected_indices": selected,
|
|
663
|
+
"selected_document_ids": tuple(candidate_ids[index] for index in selected),
|
|
664
|
+
"trajectory_sha256": content_hash(trajectory),
|
|
665
|
+
"gold_answer_used": False,
|
|
666
|
+
"supporting_fact_labels_used": False,
|
|
667
|
+
"reward_used": False,
|
|
668
|
+
},
|
|
669
|
+
)
|
|
670
|
+
)
|
|
671
|
+
return InputPatch(
|
|
672
|
+
method_id=self.method_id,
|
|
673
|
+
release_id=self.release_id,
|
|
674
|
+
source_state_hash=state.state_hash,
|
|
675
|
+
operations=(
|
|
676
|
+
PatchOperation(
|
|
677
|
+
PatchOp.ADD_CONTEXT,
|
|
678
|
+
blocks,
|
|
679
|
+
target="qrag_value_selected_real_documents",
|
|
680
|
+
rationale="select shared-corpus evidence with the released frozen Q-RAG PQN",
|
|
681
|
+
),
|
|
682
|
+
),
|
|
683
|
+
trace=ExecutionTrace(
|
|
684
|
+
method_id=self.method_id,
|
|
685
|
+
release_id=self.release_id,
|
|
686
|
+
events=tuple(events),
|
|
687
|
+
counters={
|
|
688
|
+
"retrieval_calls": 1,
|
|
689
|
+
"embedding_calls": usage["embedding_calls"],
|
|
690
|
+
"policy_steps": len(trajectory),
|
|
691
|
+
"selected_documents": len(blocks),
|
|
692
|
+
"accelerator_seconds": usage["accelerator_seconds"],
|
|
693
|
+
},
|
|
694
|
+
),
|
|
695
|
+
implementation_identity=f"thin_external_wrapper:griver/Q-RAG@{QRAG_UPSTREAM_COMMIT}",
|
|
696
|
+
profile_kind="controlled_adapter",
|
|
697
|
+
metadata={
|
|
698
|
+
"common_support_adaptation": "released_value_policy_over_shared_candidate_pool",
|
|
699
|
+
"selected_indices": selected,
|
|
700
|
+
"selected_document_ids": tuple(candidate_ids[index] for index in selected),
|
|
701
|
+
"runtime_attestation": attestation,
|
|
702
|
+
"upstream_reader_used": False,
|
|
703
|
+
"real_documents_are_evidence": True,
|
|
704
|
+
"gold_answer_used": False,
|
|
705
|
+
"supporting_fact_labels_used": False,
|
|
706
|
+
"reward_used": False,
|
|
707
|
+
"training_called": False,
|
|
708
|
+
"upstream_checkpoint_parity_claimed": False,
|
|
709
|
+
"paper_result_parity_claimed": False,
|
|
710
|
+
},
|
|
711
|
+
)
|
|
712
|
+
|
|
713
|
+
|
|
714
|
+
def _policy_candidate_text(result: RetrievalResult) -> str:
|
|
715
|
+
title = result.document.title.strip()
|
|
716
|
+
text = result.document.text.strip()
|
|
717
|
+
return f"Title: {title}\n{text}" if title else text
|
|
718
|
+
|
|
719
|
+
|
|
720
|
+
def _retriever(value: object) -> Retriever:
|
|
721
|
+
if value is None or not hasattr(value, "retrieve") or not hasattr(value, "fingerprint"):
|
|
722
|
+
raise ExternalDependencyError("Q-RAG common support requires a Retriever")
|
|
723
|
+
return value # type: ignore[return-value]
|
|
724
|
+
|
|
725
|
+
|
|
726
|
+
def _runtime(value: object) -> QRAGCommonSupportRuntime:
|
|
727
|
+
if not isinstance(value, QRAGCommonSupportRuntime):
|
|
728
|
+
raise ExternalDependencyError(
|
|
729
|
+
"Q-RAG common support requires InterventionContext.external_runtime"
|
|
730
|
+
)
|
|
731
|
+
return value
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
def _validated_results(
|
|
735
|
+
values: Sequence[RetrievalResult], *, top_k: int
|
|
736
|
+
) -> tuple[RetrievalResult, ...]:
|
|
737
|
+
try:
|
|
738
|
+
results = tuple(values)
|
|
739
|
+
except TypeError as exc:
|
|
740
|
+
raise AlgorithmOutputError("Q-RAG retriever returned a non-sequence") from exc
|
|
741
|
+
if not all(isinstance(row, RetrievalResult) for row in results) or len(results) > top_k:
|
|
742
|
+
raise AlgorithmOutputError("Q-RAG retriever returned invalid results")
|
|
743
|
+
ids = tuple(row.document.doc_id for row in results)
|
|
744
|
+
if any(not value for value in ids) or len(ids) != len(set(ids)):
|
|
745
|
+
raise AlgorithmOutputError("Q-RAG retrieval IDs must be non-empty and unique")
|
|
746
|
+
if tuple(row.rank for row in results) != tuple(range(1, len(results) + 1)):
|
|
747
|
+
raise AlgorithmOutputError("Q-RAG retrieval ranks must be contiguous and one-based")
|
|
748
|
+
return results
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
def _validate_response(
|
|
752
|
+
value: Mapping[str, Any],
|
|
753
|
+
candidate_ids: tuple[str, ...],
|
|
754
|
+
) -> tuple[
|
|
755
|
+
tuple[Mapping[str, Any], ...],
|
|
756
|
+
tuple[int, ...],
|
|
757
|
+
Mapping[str, Any],
|
|
758
|
+
Mapping[str, Any],
|
|
759
|
+
]:
|
|
760
|
+
if not isinstance(value, Mapping) or value.get("status") != "ok":
|
|
761
|
+
raise AlgorithmOutputError("Q-RAG policy runtime returned a failed response")
|
|
762
|
+
raw_steps = value.get("trajectory")
|
|
763
|
+
raw_selected = value.get("selected_indices")
|
|
764
|
+
usage = value.get("usage")
|
|
765
|
+
attestation = value.get("attestation")
|
|
766
|
+
if (
|
|
767
|
+
isinstance(raw_steps, (str, bytes))
|
|
768
|
+
or not isinstance(raw_steps, Sequence)
|
|
769
|
+
or isinstance(raw_selected, (str, bytes))
|
|
770
|
+
or not isinstance(raw_selected, Sequence)
|
|
771
|
+
or not isinstance(usage, Mapping)
|
|
772
|
+
or not isinstance(attestation, Mapping)
|
|
773
|
+
):
|
|
774
|
+
raise AlgorithmOutputError("Q-RAG policy response schema is invalid")
|
|
775
|
+
selected = tuple(raw_selected)
|
|
776
|
+
if (
|
|
777
|
+
len(selected) != min(2, len(candidate_ids))
|
|
778
|
+
or any(isinstance(index, bool) or not isinstance(index, int) for index in selected)
|
|
779
|
+
or len(selected) != len(set(selected))
|
|
780
|
+
or any(index < 0 or index >= len(candidate_ids) for index in selected)
|
|
781
|
+
):
|
|
782
|
+
raise AlgorithmOutputError("Q-RAG policy selected indices are invalid")
|
|
783
|
+
steps: list[Mapping[str, Any]] = []
|
|
784
|
+
history: tuple[int, ...] = ()
|
|
785
|
+
for step_index, row in enumerate(raw_steps):
|
|
786
|
+
if not isinstance(row, Mapping):
|
|
787
|
+
raise AlgorithmOutputError("Q-RAG policy trajectory row is invalid")
|
|
788
|
+
available = tuple(row.get("available_indices", ()))
|
|
789
|
+
q_values = tuple(row.get("q_values", ()))
|
|
790
|
+
action = row.get("action_index")
|
|
791
|
+
current = tuple(row.get("selected_indices", ()))
|
|
792
|
+
ids = tuple(row.get("selected_document_ids", ()))
|
|
793
|
+
expected_available = tuple(
|
|
794
|
+
index for index in range(len(candidate_ids)) if index not in history
|
|
795
|
+
)
|
|
796
|
+
if (
|
|
797
|
+
row.get("index") != step_index
|
|
798
|
+
or available != expected_available
|
|
799
|
+
or len(q_values) != len(available)
|
|
800
|
+
or not all(
|
|
801
|
+
isinstance(score, (int, float)) and math.isfinite(score) for score in q_values
|
|
802
|
+
)
|
|
803
|
+
or action not in available
|
|
804
|
+
or current != (*history, action)
|
|
805
|
+
or ids != tuple(candidate_ids[index] for index in current)
|
|
806
|
+
or row.get("selected_q_value") != q_values[available.index(action)]
|
|
807
|
+
):
|
|
808
|
+
raise AlgorithmOutputError("Q-RAG policy trajectory is inconsistent")
|
|
809
|
+
history = current
|
|
810
|
+
steps.append(freeze_mapping(dict(row)))
|
|
811
|
+
if tuple(history) != selected or tuple(raw_steps) == ():
|
|
812
|
+
raise AlgorithmOutputError("Q-RAG policy trajectory disagrees with final selection")
|
|
813
|
+
if value.get("selected_document_ids") != tuple(candidate_ids[index] for index in selected):
|
|
814
|
+
raise AlgorithmOutputError("Q-RAG selected document IDs mismatch")
|
|
815
|
+
if value.get("candidate_order_sha256") != content_hash(candidate_ids):
|
|
816
|
+
raise AlgorithmOutputError("Q-RAG candidate order checksum mismatch")
|
|
817
|
+
if value.get("trajectory_sha256") != content_hash(raw_steps):
|
|
818
|
+
raise AlgorithmOutputError("Q-RAG trajectory checksum mismatch")
|
|
819
|
+
if (
|
|
820
|
+
value.get("policy_steps") != len(steps)
|
|
821
|
+
or usage.get("embedding_calls") != 2 + 2 * len(steps)
|
|
822
|
+
or any(
|
|
823
|
+
usage.get(field) != 0
|
|
824
|
+
for field in ("model_calls", "retrieval_calls", "input_tokens", "output_tokens")
|
|
825
|
+
)
|
|
826
|
+
or not isinstance(usage.get("accelerator_seconds"), (int, float))
|
|
827
|
+
or usage["accelerator_seconds"] < 0
|
|
828
|
+
):
|
|
829
|
+
raise AlgorithmOutputError("Q-RAG usage receipt is invalid")
|
|
830
|
+
required_true = {
|
|
831
|
+
"official_candidate_builder_called",
|
|
832
|
+
"official_pqn_select_action_called",
|
|
833
|
+
"official_qa_env_step_called",
|
|
834
|
+
"safe_weights_only_load",
|
|
835
|
+
"strict_state_dict_load",
|
|
836
|
+
"checkpoint_eval_mode",
|
|
837
|
+
"dummy_feedback_used",
|
|
838
|
+
"seed_applied",
|
|
839
|
+
}
|
|
840
|
+
required_false = {
|
|
841
|
+
"gold_answer_used",
|
|
842
|
+
"supporting_fact_labels_used",
|
|
843
|
+
"reward_used",
|
|
844
|
+
"training_called",
|
|
845
|
+
"stop_action_used",
|
|
846
|
+
}
|
|
847
|
+
if any(attestation.get(key) is not True for key in required_true) or any(
|
|
848
|
+
attestation.get(key) is not False for key in required_false
|
|
849
|
+
):
|
|
850
|
+
raise AlgorithmOutputError("Q-RAG runtime attestation failed")
|
|
851
|
+
return tuple(steps), selected, freeze_mapping(dict(usage)), freeze_mapping(dict(attestation))
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
def _real_context(result: RetrievalResult, selected_rank: int) -> ContextBlock:
|
|
855
|
+
document = result.document
|
|
856
|
+
if not document.corpus_revision:
|
|
857
|
+
raise AlgorithmOutputError("Q-RAG evidence requires a corpus revision")
|
|
858
|
+
reserved = {
|
|
859
|
+
"corpus_revision",
|
|
860
|
+
"document_id",
|
|
861
|
+
"evidence_kind",
|
|
862
|
+
"qrag_candidate_rank",
|
|
863
|
+
"qrag_selected_rank",
|
|
864
|
+
"title",
|
|
865
|
+
}
|
|
866
|
+
if reserved & set(document.metadata):
|
|
867
|
+
raise AlgorithmOutputError("Q-RAG document metadata uses reserved provenance keys")
|
|
868
|
+
return ContextBlock(
|
|
869
|
+
block_id=document.doc_id,
|
|
870
|
+
text=document.text,
|
|
871
|
+
source=document.corpus_revision,
|
|
872
|
+
score=result.score,
|
|
873
|
+
metadata={
|
|
874
|
+
**dict(document.metadata),
|
|
875
|
+
"document_id": document.doc_id,
|
|
876
|
+
"title": document.title,
|
|
877
|
+
"corpus_revision": document.corpus_revision,
|
|
878
|
+
"qrag_candidate_rank": result.rank,
|
|
879
|
+
"qrag_selected_rank": selected_rank,
|
|
880
|
+
"evidence_kind": "real_corpus_document",
|
|
881
|
+
},
|
|
882
|
+
)
|
|
883
|
+
|
|
884
|
+
|
|
885
|
+
__all__ = [
|
|
886
|
+
"LocalQRAGFrozenPolicyRuntime",
|
|
887
|
+
"QRAGCommonSupport",
|
|
888
|
+
"QRAGCommonSupportConfig",
|
|
889
|
+
"QRAGCommonSupportRuntime",
|
|
890
|
+
"QRAGPolicyRequest",
|
|
891
|
+
]
|