verifiers 0.3.2.dev151__tar.gz → 0.3.2.dev152__tar.gz

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 (223) hide show
  1. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/PKG-INFO +1 -1
  2. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/conftest.py +2 -2
  3. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/test_color_codeword_tasks.py +1 -1
  4. verifiers-0.3.2.dev152/tests/v1/test_taskset.py +201 -0
  5. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/__init__.py +4 -0
  6. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/debug.py +3 -6
  7. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/eval/runner.py +3 -6
  8. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/init.py +1 -1
  9. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/validate.py +3 -6
  10. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/cli/debug.py +4 -8
  11. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/cli/eval.py +4 -8
  12. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/cli/validate.py +4 -8
  13. verifiers-0.3.2.dev152/verifiers/v1/configs/select.py +118 -0
  14. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/gepa/config.py +7 -6
  15. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/gepa/dataset.py +2 -2
  16. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/gepa/runner.py +2 -4
  17. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/task.py +9 -3
  18. verifiers-0.3.2.dev152/verifiers/v1/taskset.py +230 -0
  19. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/nemo_gym/taskset.py +0 -1
  20. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/openenv/taskset.py +0 -1
  21. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/textarena/taskset.py +0 -1
  22. verifiers-0.3.2.dev151/tests/v1/test_taskset.py +0 -91
  23. verifiers-0.3.2.dev151/verifiers/v1/taskset.py +0 -111
  24. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/.gitignore +0 -0
  25. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/LICENSE +0 -0
  26. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/README.md +0 -0
  27. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/pyproject.toml +0 -0
  28. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/fixtures/counter_tool_v1.py +0 -0
  29. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/fixtures/duet_v1.py +0 -0
  30. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/fixtures/echo_acp_resume_v1.py +0 -0
  31. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/fixtures/echo_agentic_v1.py +0 -0
  32. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/fixtures/echo_tool_v1.py +0 -0
  33. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/fixtures/echo_user_sim_v1.py +0 -0
  34. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/fixtures/echo_v1.py +0 -0
  35. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/fixtures/pyproject.toml +0 -0
  36. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/fixtures/tool_response_image_v1.py +0 -0
  37. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/test_configs.py +0 -0
  38. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/test_e2e.py +0 -0
  39. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/test_envs.py +0 -0
  40. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/test_graph.py +0 -0
  41. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/test_judges.py +0 -0
  42. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/test_platform_run.py +0 -0
  43. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/test_scoring.py +0 -0
  44. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/test_serve_delta.py +0 -0
  45. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/tests/v1/test_trace.py +0 -0
  46. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/__init__.py +0 -0
  47. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/acp/__init__.py +0 -0
  48. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/acp/runner.py +0 -0
  49. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/agent.py +0 -0
  50. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/__init__.py +0 -0
  51. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/dashboard/__init__.py +0 -0
  52. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/dashboard/base.py +0 -0
  53. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/dashboard/eval.py +0 -0
  54. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/dashboard/replay.py +0 -0
  55. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/dashboard/validate.py +0 -0
  56. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/eval/__init__.py +0 -0
  57. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/eval/hint.py +0 -0
  58. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/eval/main.py +0 -0
  59. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/eval/resume.py +0 -0
  60. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/gepa.py +0 -0
  61. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/output.py +0 -0
  62. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/replay.py +0 -0
  63. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/resolve.py +0 -0
  64. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/cli/resume.py +0 -0
  65. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/clients/__init__.py +0 -0
  66. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/clients/base.py +0 -0
  67. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/clients/client.py +0 -0
  68. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/clients/eval.py +0 -0
  69. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/clients/train.py +0 -0
  70. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/__init__.py +0 -0
  71. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/agent.py +0 -0
  72. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/cli/__init__.py +0 -0
  73. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/cli/env.py +0 -0
  74. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/cli/init.py +0 -0
  75. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/cli/replay.py +0 -0
  76. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/client.py +0 -0
  77. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/env.py +0 -0
  78. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/harness.py +0 -0
  79. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/judge.py +0 -0
  80. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/retries.py +0 -0
  81. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/runtime.py +0 -0
  82. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/serve.py +0 -0
  83. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/task.py +0 -0
  84. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/configs/taskset.py +0 -0
  85. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/dialects/__init__.py +0 -0
  86. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/dialects/anthropic.py +0 -0
  87. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/dialects/base.py +0 -0
  88. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/dialects/chat.py +0 -0
  89. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/dialects/responses.py +0 -0
  90. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/env.py +0 -0
  91. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/envs/__init__.py +0 -0
  92. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
  93. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/envs/agentic_judge/env.py +0 -0
  94. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
  95. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/envs/best_of_n/env.py +0 -0
  96. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/envs/isolated_verifier/__init__.py +0 -0
  97. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/envs/isolated_verifier/env.py +0 -0
  98. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/envs/shared_agentic_judge/__init__.py +0 -0
  99. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/envs/single_agent/__init__.py +0 -0
  100. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/envs/single_agent/env.py +0 -0
  101. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/envs/user_sim/__init__.py +0 -0
  102. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/envs/user_sim/env.py +0 -0
  103. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/episode.py +0 -0
  104. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/errors.py +0 -0
  105. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/gepa/__init__.py +0 -0
  106. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/gepa/adapter.py +0 -0
  107. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/gepa/reflection.py +0 -0
  108. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/graph.py +0 -0
  109. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harness.py +0 -0
  110. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/__init__.py +0 -0
  111. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/bash/__init__.py +0 -0
  112. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/bash/harness.py +0 -0
  113. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
  114. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
  115. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/browser_use/program.py +0 -0
  116. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
  117. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
  118. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/codex/__init__.py +0 -0
  119. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/codex/gate.mjs +0 -0
  120. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/codex/harness.py +0 -0
  121. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
  122. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
  123. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
  124. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
  125. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
  126. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
  127. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
  128. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
  129. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/node.py +0 -0
  130. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/null/__init__.py +0 -0
  131. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/null/harness.py +0 -0
  132. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
  133. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
  134. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/pi/__init__.py +0 -0
  135. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/pi/gate.mjs +0 -0
  136. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/pi/harness.py +0 -0
  137. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
  138. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/prime_agent/harness.py +0 -0
  139. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
  140. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/rlm/harness.py +0 -0
  141. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
  142. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
  143. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
  144. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/utils/__init__.py +0 -0
  145. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/utils/compaction.py +0 -0
  146. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/utils/core.py +0 -0
  147. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/utils/install.py +0 -0
  148. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/utils/launch.py +0 -0
  149. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/harnesses/utils/mcp.py +0 -0
  150. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/interception/__init__.py +0 -0
  151. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/interception/base.py +0 -0
  152. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/interception/pool.py +0 -0
  153. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/interception/server.py +0 -0
  154. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/interception/tunnel/__init__.py +0 -0
  155. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/interception/tunnel/base.py +0 -0
  156. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/interception/tunnel/custom.py +0 -0
  157. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/interception/tunnel/prime.py +0 -0
  158. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/judge.py +0 -0
  159. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/judges/__init__.py +0 -0
  160. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/judges/reference.py +0 -0
  161. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/judges/reference.txt +0 -0
  162. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/judges/rubric.py +0 -0
  163. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/judges/rubric.txt +0 -0
  164. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/mcp/__init__.py +0 -0
  165. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/mcp/launch.py +0 -0
  166. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/mcp/server.py +0 -0
  167. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/mcp/toolset.py +0 -0
  168. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/rollout.py +0 -0
  169. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/runtimes/__init__.py +0 -0
  170. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/runtimes/apptainer.py +0 -0
  171. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/runtimes/base.py +0 -0
  172. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/runtimes/container.py +0 -0
  173. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/runtimes/docker/__init__.py +0 -0
  174. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/runtimes/docker/egress.py +0 -0
  175. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/runtimes/limiters.py +0 -0
  176. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/runtimes/modal.py +0 -0
  177. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/runtimes/prime.py +0 -0
  178. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/runtimes/subprocess.py +0 -0
  179. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/semantic.py +0 -0
  180. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/serve/__init__.py +0 -0
  181. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/serve/client.py +0 -0
  182. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/serve/delta.py +0 -0
  183. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/serve/encoding.py +0 -0
  184. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/serve/pool.py +0 -0
  185. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/serve/server.py +0 -0
  186. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/serve/types.py +0 -0
  187. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/session.py +0 -0
  188. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/state.py +0 -0
  189. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/__init__.py +0 -0
  190. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
  191. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/harbor/compose.py +0 -0
  192. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/harbor/env.py +0 -0
  193. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
  194. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/harbor/toolset.py +0 -0
  195. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
  196. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
  197. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
  198. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
  199. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
  200. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
  201. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/trace.py +0 -0
  202. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/types.py +0 -0
  203. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/__init__.py +0 -0
  204. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/aio.py +0 -0
  205. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/artifacts.py +0 -0
  206. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/compile.py +0 -0
  207. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/decorators.py +0 -0
  208. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/format.py +0 -0
  209. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/generic.py +0 -0
  210. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/git.py +0 -0
  211. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/image.py +0 -0
  212. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/interrupt.py +0 -0
  213. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/loaders.py +0 -0
  214. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/logging.py +0 -0
  215. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/memory.py +0 -0
  216. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/paths.py +0 -0
  217. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/platform.py +0 -0
  218. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/prime.py +0 -0
  219. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/retries.py +0 -0
  220. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/scope.py +0 -0
  221. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/score.py +0 -0
  222. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/trace_store.py +0 -0
  223. {verifiers-0.3.2.dev151 → verifiers-0.3.2.dev152}/verifiers/v1/utils/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: verifiers
3
- Version: 0.3.2.dev151
3
+ Version: 0.3.2.dev152
4
4
  Summary: Verifiers: Environments for LLM Reinforcement Learning
5
5
  Project-URL: Homepage, https://github.com/primeintellect-ai/verifiers
6
6
  Project-URL: Documentation, https://github.com/primeintellect-ai/verifiers
@@ -177,7 +177,7 @@ def _eval_config(
177
177
  "taskset": taskset_cfg,
178
178
  **env_cfg,
179
179
  },
180
- num_tasks=num_tasks,
180
+ select={"limit": num_tasks},
181
181
  num_rollouts=n,
182
182
  sampling={
183
183
  "max_tokens": max_tokens,
@@ -218,7 +218,7 @@ def run_v1_server():
218
218
 
219
219
  async def _run(taskset: str, **kwargs) -> list[Trace]:
220
220
  config = _eval_config(taskset, **kwargs)
221
- tasks = list(load_taskset(config.env.taskset).head(config.num_tasks))
221
+ tasks = list(load_taskset(config.env.taskset).select(config.select))
222
222
  mpctx = mp.get_context("spawn")
223
223
  address_queue: mp.Queue = mpctx.Queue()
224
224
  proc = mpctx.Process(
@@ -10,7 +10,7 @@ def test_color_images_are_rendered_once(monkeypatch) -> None:
10
10
  return render(image)
11
11
 
12
12
  monkeypatch.setattr(taskset, "image_data_url", counted)
13
- tasks = list(taskset.ColorCodewordTaskset(taskset.ColorCodewordConfig()).head(100))
13
+ tasks = list(taskset.ColorCodewordTaskset(taskset.ColorCodewordConfig()).take(100))
14
14
 
15
15
  assert len(tasks) == 100
16
16
  assert calls == list(taskset.COLOR_RGB.values())
@@ -0,0 +1,201 @@
1
+ """`Taskset` iteration and selection: the framework-assigned `idx`, the lazy views
2
+ (`include`, `exclude`, `shuffle`, `skip`, `take`), and `select(SelectConfig)`."""
3
+
4
+ import itertools
5
+ import logging
6
+ import random
7
+
8
+ import pytest
9
+ from pydantic import ValidationError
10
+
11
+ import verifiers.v1 as vf
12
+
13
+
14
+ class CountTask(vf.Task[vf.TaskData]):
15
+ pass
16
+
17
+
18
+ def count_task(i: int) -> CountTask:
19
+ # A taskset-set idx (100 + i) that iteration must overwrite.
20
+ return CountTask(
21
+ vf.TaskData(idx=100 + i, id=f"id-{i}", name=f"t{i}", prompt=f"task {i}")
22
+ )
23
+
24
+
25
+ class FiniteTaskset(vf.Taskset[CountTask, vf.TasksetConfig]):
26
+ def load(self):
27
+ return [count_task(i) for i in range(10)]
28
+
29
+
30
+ class InfiniteTaskset(vf.Taskset[CountTask, vf.TasksetConfig]):
31
+ INFINITE = True
32
+
33
+ def load(self):
34
+ for i in itertools.count():
35
+ yield count_task(i)
36
+
37
+
38
+ def finite() -> FiniteTaskset:
39
+ return FiniteTaskset(vf.TasksetConfig())
40
+
41
+
42
+ def infinite() -> InfiniteTaskset:
43
+ return InfiniteTaskset(vf.TasksetConfig())
44
+
45
+
46
+ def idxs(tasks) -> list[int]:
47
+ return [task.data.idx for task in tasks]
48
+
49
+
50
+ def shuffled(xs, seed: int = 0) -> list[int]:
51
+ xs = list(xs)
52
+ random.Random(seed).shuffle(xs)
53
+ return xs
54
+
55
+
56
+ # Views
57
+
58
+
59
+ def test_iteration_sets_idx_to_the_load_position() -> None:
60
+ assert idxs(finite()) == list(range(10))
61
+
62
+
63
+ def test_include_keeps_tasks_that_any_list_names() -> None:
64
+ assert idxs(finite().include(idx=[3, "5:7", "8:"])) == [3, 5, 6, 8, 9]
65
+ assert idxs(finite().include(idx=":2")) == [0, 1]
66
+ assert idxs(finite().include(idx=["1:8:3", "::4"])) == [0, 1, 4, 7, 8]
67
+ assert idxs(finite().include(ids=["id-1"])) == [1]
68
+ assert idxs(finite().include(names=["t2"])) == [2]
69
+ key = list(finite())[4].key
70
+ assert idxs(finite().include(keys=[key])) == [4]
71
+ union = finite().include(idx=[0], ids=["id-1"], names=["t2"], keys=[key])
72
+ assert idxs(union) == [0, 1, 2, 4]
73
+
74
+
75
+ def test_keys_match_the_keys_traces_record(tmp_path) -> None:
76
+ prompt = tmp_path / "prompt.txt"
77
+ prompt.write_text("be brief")
78
+ taskset = FiniteTaskset(vf.TasksetConfig(system_prompt=prompt))
79
+ key = list(taskset)[4].key
80
+ assert idxs(taskset.include(keys=[key])) == [4]
81
+ assert 4 not in idxs(taskset.exclude(keys=[key]))
82
+
83
+
84
+ def test_exclude_drops_tasks_that_any_list_names() -> None:
85
+ assert idxs(finite().exclude(idx=":7", names=["t8"])) == [7, 9]
86
+
87
+
88
+ def test_unmatched_entries_warn(caplog) -> None:
89
+ with caplog.at_level(logging.WARNING):
90
+ assert idxs(finite().include(names=["t1", "typo"], idx=[42])) == [1]
91
+ assert "typo" in caplog.text and "42" in caplog.text
92
+
93
+
94
+ def test_shuffle_is_seeded_and_reproducible() -> None:
95
+ assert idxs(finite().shuffle()) == shuffled(range(10)) != list(range(10))
96
+ assert idxs(finite().shuffle(seed=7)) == shuffled(range(10), 7)
97
+
98
+
99
+ def test_skip_and_take_slice_the_stream() -> None:
100
+ assert idxs(finite().skip(7)) == [7, 8, 9]
101
+ assert idxs(finite().take(3)) == [0, 1, 2]
102
+ assert idxs(finite().skip(2).take(2)) == [2, 3]
103
+
104
+
105
+ def test_views_chain_in_call_order_and_leave_the_base_alone() -> None:
106
+ base = finite()
107
+ assert idxs(base.take(5).shuffle()) == shuffled(range(5))
108
+ assert idxs(base.shuffle().take(5)) == shuffled(range(10))[:5]
109
+ assert base.transform is None and idxs(base) == list(range(10))
110
+
111
+
112
+ def test_views_read_load_lazily() -> None:
113
+ built: list[int] = []
114
+
115
+ class RecordingTaskset(InfiniteTaskset):
116
+ def load(self):
117
+ for i in itertools.count():
118
+ built.append(i)
119
+ yield count_task(i)
120
+
121
+ base = RecordingTaskset(vf.TasksetConfig())
122
+ assert idxs(base.take(3)) == [0, 1, 2] and built == [0, 1, 2]
123
+ built.clear()
124
+ # An idx-only include stops reading after its last position.
125
+ assert idxs(base.include(idx=["2:4", 6])) == [2, 3, 6] and built == list(range(7))
126
+
127
+
128
+ def test_only_a_bounded_view_can_shuffle() -> None:
129
+ assert finite().bounded and not infinite().bounded
130
+ assert infinite().take(3).bounded
131
+ assert infinite().include(idx=["0:4", 9]).bounded
132
+ assert not infinite().include(idx="::2").bounded
133
+ assert not infinite().include(idx="5:").bounded
134
+ with pytest.raises(ValueError, match="may never end"):
135
+ infinite().include(idx=["0:4"], names=["t9"])
136
+ with pytest.raises(ValueError, match="open idx range"):
137
+ infinite().exclude(idx="5:")
138
+ assert idxs(infinite().exclude(idx="::2").take(2)) == [1, 3]
139
+ assert idxs(infinite().include(idx=":20").include(names=["t3"])) == [3]
140
+ with pytest.raises(ValueError, match="infinite"):
141
+ infinite().shuffle()
142
+ assert sorted(idxs(infinite().take(5).shuffle())) == [0, 1, 2, 3, 4]
143
+
144
+
145
+ # Config and select
146
+
147
+
148
+ def test_task_match_config_parses_idx() -> None:
149
+ assert vf.TaskMatchConfig(idx=["3", "0:2,4", "8:"]).idx == [3, "0:2", 4, "8:"]
150
+ assert vf.TaskMatchConfig(idx=5).idx == [5]
151
+ assert vf.TaskMatchConfig(idx="0:9:3").idx_stop == 9
152
+ for bad in [-1, "a", "5:5", "7:3", ":0", "1:2:0", "::00", "1:2:3:4"]:
153
+ with pytest.raises(ValidationError):
154
+ vf.TaskMatchConfig(idx=[bad])
155
+
156
+
157
+ def test_select_config_defaults_and_short_aliases() -> None:
158
+ config = vf.SelectConfig()
159
+ assert config.include.empty and config.exclude.empty
160
+ assert (config.shuffle, config.seed, config.skip, config.limit) == (
161
+ False,
162
+ 0,
163
+ 0,
164
+ None,
165
+ )
166
+ aliased = vf.SelectCLIConfig.model_validate({"n": 3, "s": True})
167
+ assert (aliased.limit, aliased.shuffle) == (3, True)
168
+ with pytest.raises(ValidationError):
169
+ vf.SelectConfig.model_validate({"n": 3})
170
+ with pytest.raises(ValidationError):
171
+ vf.SelectConfig(limit=0)
172
+
173
+
174
+ def test_default_select_yields_every_task() -> None:
175
+ assert idxs(finite().select(vf.SelectConfig())) == list(range(10))
176
+
177
+
178
+ def test_select_applies_its_steps_in_a_fixed_order() -> None:
179
+ config = vf.SelectConfig(
180
+ include={"idx": ["2:9"]},
181
+ exclude={"names": ["t5"]},
182
+ shuffle=True,
183
+ seed=3,
184
+ skip=1,
185
+ limit=2,
186
+ )
187
+ kept = [i for i in range(2, 9) if i != 5]
188
+ assert idxs(finite().select(config)) == shuffled(kept, 3)[1:3]
189
+ chained = (
190
+ finite().include(idx=["2:9"]).exclude(names=["t5"]).shuffle(3).skip(1).take(2)
191
+ )
192
+ assert idxs(finite().select(config)) == idxs(chained)
193
+
194
+
195
+ def test_select_bounds_an_infinite_taskset() -> None:
196
+ assert infinite().select(vf.SelectConfig(limit=4)).bounded
197
+ closed = vf.SelectConfig(include={"idx": "0:5"}, shuffle=True)
198
+ assert sorted(idxs(infinite().select(closed))) == [0, 1, 2, 3, 4]
199
+ # The shuffle comes before the limit, so the limit cannot bound it.
200
+ with pytest.raises(ValueError, match="infinite"):
201
+ infinite().select(vf.SelectConfig(shuffle=True, limit=5))
@@ -23,6 +23,7 @@ from verifiers.v1.configs.env import EnvConfig, SharedEnvConfig, default_agent_h
23
23
  from verifiers.v1.configs.harness import HarnessConfig
24
24
  from verifiers.v1.configs.judge import JudgeConfig, Judges
25
25
  from verifiers.v1.configs.retries import RetryConfig
26
+ from verifiers.v1.configs.select import SelectCLIConfig, SelectConfig, TaskMatchConfig
26
27
  from verifiers.v1.configs.serve import (
27
28
  ElasticPoolConfig,
28
29
  ServeConfig,
@@ -289,6 +290,9 @@ __all__ = [ # noqa: RUF022 - grouped by public API area
289
290
  # taskset / harness / runtime / environment
290
291
  "Taskset",
291
292
  "TaskConfig",
293
+ "SelectConfig",
294
+ "SelectCLIConfig",
295
+ "TaskMatchConfig",
292
296
  "TasksetConfig",
293
297
  "SharedTasksetConfig",
294
298
  "DecoratedFunctionConfig",
@@ -269,15 +269,12 @@ async def debug_task(task: Task, config: DebugConfig) -> tuple[Trace, bool]:
269
269
 
270
270
 
271
271
  async def run_debug(config: DebugConfig) -> list[Trace]:
272
- taskset = vf.load_taskset(config.taskset)
273
- if config.num_tasks is None and taskset.INFINITE:
272
+ taskset = vf.load_taskset(config.taskset).select(config.select)
273
+ if not taskset.bounded:
274
274
  raise ValueError(
275
275
  f"{type(taskset).__name__} is infinite - bound the run with -n"
276
276
  )
277
- selected = taskset.shuffle() if config.shuffle else taskset
278
- if config.num_tasks is not None:
279
- selected = selected.head(config.num_tasks)
280
- tasks = list(selected)
277
+ tasks = list(taskset)
281
278
  if isinstance(config.runtime, vf.SubprocessConfig) and any(
282
279
  type(t).NEEDS_CONTAINER or t.data.image for t in tasks
283
280
  ):
@@ -82,15 +82,12 @@ async def run_eval(config: EvalConfig) -> list[Episode]:
82
82
  from verifiers.v1.utils.loaders import load_environment
83
83
 
84
84
  env = load_environment(config.env)
85
- taskset = env.taskset
86
- if config.num_tasks is None and taskset.INFINITE:
85
+ taskset = env.taskset.select(config.select)
86
+ if not taskset.bounded:
87
87
  raise ValueError(
88
88
  f"{type(taskset).__name__} is infinite - bound the run with -n"
89
89
  )
90
- selected = taskset.shuffle() if config.shuffle else taskset
91
- if config.num_tasks is not None:
92
- selected = selected.head(config.num_tasks)
93
- tasks = list(selected)
90
+ tasks = list(taskset)
94
91
  out = output_path(config)
95
92
  # One (task, rollouts-to-run) pair per selected task; resume shrinks the counts.
96
93
  plan = [(task, config.num_rollouts) for task in tasks]
@@ -109,7 +109,7 @@ class {prefix}Taskset(vf.Taskset[{prefix}Task, {prefix}Config]):
109
109
  def load(self) -> list[{prefix}Task]:
110
110
  raise NotImplementedError(
111
111
  "Return this taskset's tasks, e.g. "
112
- "[{prefix}Task({prefix}Data(idx=i, prompt=...), self.config.task) "
112
+ "[{prefix}Task({prefix}Data(prompt=...), self.config.task) "
113
113
  "for i in range(self.config.num_tasks)]."
114
114
  )
115
115
  '''
@@ -325,15 +325,12 @@ async def _validate_task(task: Task, config: ValidateConfig) -> ResultRow:
325
325
 
326
326
 
327
327
  async def run_validate(config: ValidateConfig) -> list[dict]:
328
- taskset = vf.load_taskset(config.taskset)
329
- if config.num_tasks is None and taskset.INFINITE:
328
+ taskset = vf.load_taskset(config.taskset).select(config.select)
329
+ if not taskset.bounded:
330
330
  raise ValueError(
331
331
  f"{type(taskset).__name__} is infinite - bound the run with -n"
332
332
  )
333
- selected = taskset.shuffle() if config.shuffle else taskset
334
- if config.num_tasks is not None:
335
- selected = selected.head(config.num_tasks)
336
- tasks = list(selected)
333
+ tasks = list(taskset)
337
334
  if isinstance(config.runtime, vf.SubprocessConfig) and any(
338
335
  type(t).NEEDS_CONTAINER or t.data.image for t in tasks
339
336
  ):
@@ -7,6 +7,7 @@ from pydantic import AliasChoices, Field, SerializeAsAny, model_validator
7
7
  from pydantic_config import BaseConfig
8
8
 
9
9
  from verifiers.v1.configs.cli.validate import CheckTimeoutConfig
10
+ from verifiers.v1.configs.select import SelectCLIConfig
10
11
  from verifiers.v1.configs.taskset import TasksetConfig
11
12
  from verifiers.v1.runtimes import PrimeConfig, RuntimeConfig
12
13
 
@@ -15,6 +16,9 @@ class DebugConfig(BaseConfig):
15
16
  uuid: str = Field(default_factory=lambda: str(uuid4()), exclude=True)
16
17
  """Auto-generated run id, used as the default output directory leaf."""
17
18
  taskset: SerializeAsAny[TasksetConfig] = TasksetConfig()
19
+ select: SelectCLIConfig = SelectCLIConfig()
20
+ """Which of the taskset's tasks to debug, under `--select.*` (`-n` sets
21
+ `select.limit`, `-s` sets `select.shuffle`)."""
18
22
  runtime: RuntimeConfig = PrimeConfig()
19
23
  """Where each task's setup hook and debug action run."""
20
24
  command: str | None = None
@@ -26,14 +30,6 @@ class DebugConfig(BaseConfig):
26
30
  timeout: CheckTimeoutConfig = CheckTimeoutConfig()
27
31
  """Per-task stage timeouts: `--timeout.setup` for the `setup` hook, `--timeout.total`
28
32
  for the debug command/script."""
29
- num_tasks: int | None = Field(
30
- None,
31
- ge=1,
32
- validation_alias=AliasChoices("num_tasks", "n", "num_examples", "batch_size"),
33
- )
34
- """How many tasks to debug (None = all)."""
35
- shuffle: bool = Field(False, validation_alias=AliasChoices("shuffle", "s"))
36
- """Shuffle tasks before taking the first `num_tasks`."""
37
33
  max_concurrent: int | None = Field(
38
34
  128, validation_alias=AliasChoices("max_concurrent", "c")
39
35
  )
@@ -9,6 +9,7 @@ from pydantic_config import BaseConfig
9
9
  from verifiers.v1.clients import ClientConfig, EvalClientConfig
10
10
  from verifiers.v1.configs.cli.env import narrowed_env_annotation, resolve_env_field
11
11
  from verifiers.v1.configs.env import EnvConfig
12
+ from verifiers.v1.configs.select import SelectCLIConfig
12
13
  from verifiers.v1.envs.single_agent import SingleAgentEnvConfig
13
14
  from verifiers.v1.types import SamplingConfig
14
15
 
@@ -84,12 +85,9 @@ class EvalConfig(BaseConfig):
84
85
  """Model id."""
85
86
  client: ClientConfig = EvalClientConfig()
86
87
  sampling: SamplingConfig = SamplingConfig()
87
- num_tasks: int | None = Field(
88
- None,
89
- ge=1,
90
- validation_alias=AliasChoices("batch_size", "num_examples", "num_tasks", "n"),
91
- )
92
- """How many tasks to evaluate (None = all)."""
88
+ select: SelectCLIConfig = SelectCLIConfig()
89
+ """Which of the taskset's tasks to evaluate, under `--select.*` (`-n` sets
90
+ `select.limit`, `-s` sets `select.shuffle`)."""
93
91
  num_rollouts: int = Field(
94
92
  1,
95
93
  ge=1,
@@ -98,8 +96,6 @@ class EvalConfig(BaseConfig):
98
96
  ),
99
97
  )
100
98
  """Independent episodes per task — the trainer's group size."""
101
- shuffle: bool = Field(False, validation_alias=AliasChoices("shuffle", "s"))
102
- """Shuffle tasks before taking the first `num_tasks`."""
103
99
  max_concurrent: int | None = Field(
104
100
  128, ge=1, validation_alias=AliasChoices("max_concurrent", "c")
105
101
  )
@@ -7,6 +7,7 @@ from pydantic import AliasChoices, Field, SerializeAsAny, model_validator
7
7
  from pydantic_config import BaseConfig
8
8
 
9
9
  from verifiers.v1.configs.cli.eval import RunConfig
10
+ from verifiers.v1.configs.select import SelectCLIConfig
10
11
  from verifiers.v1.configs.taskset import TasksetConfig
11
12
  from verifiers.v1.runtimes import PrimeConfig, RuntimeConfig
12
13
 
@@ -24,6 +25,9 @@ class ValidateConfig(BaseConfig):
24
25
  """Run identity: `run.name` auto-generates as `<taskset>--validate--<short-id>` and
25
26
  names the run directory under `output_dir`."""
26
27
  taskset: SerializeAsAny[TasksetConfig] = TasksetConfig()
28
+ select: SelectCLIConfig = SelectCLIConfig()
29
+ """Which of the taskset's tasks to validate, under `--select.*` (`-n` sets
30
+ `select.limit`, `-s` sets `select.shuffle`)."""
27
31
  runtime: RuntimeConfig = PrimeConfig()
28
32
  """Where each task's validation hooks run."""
29
33
  timeout: CheckTimeoutConfig = CheckTimeoutConfig()
@@ -31,14 +35,6 @@ class ValidateConfig(BaseConfig):
31
35
  """Run only `Task.setup`."""
32
36
  only_gold: bool = False
33
37
  """Run only `Task.setup` and `Task.validate`."""
34
- num_tasks: int | None = Field(
35
- None,
36
- ge=1,
37
- validation_alias=AliasChoices("num_tasks", "n", "num_examples", "batch_size"),
38
- )
39
- """How many tasks to validate (None = all)."""
40
- shuffle: bool = Field(False, validation_alias=AliasChoices("shuffle", "s"))
41
- """Shuffle tasks before taking the first `num_tasks`."""
42
38
  max_concurrent: int | None = Field(
43
39
  128, validation_alias=AliasChoices("max_concurrent", "c")
44
40
  )
@@ -0,0 +1,118 @@
1
+ """Which of a taskset's tasks a run uses: `Taskset.select(SelectConfig)`, under
2
+ `--select.*` on the eval, debug, validate and GEPA CLIs (`SelectCLIConfig`)."""
3
+
4
+ import re
5
+ import sys
6
+
7
+ from pydantic import AliasChoices, Field, field_validator
8
+ from pydantic_config import BaseConfig
9
+
10
+ IDX_RANGE = re.compile(r"(\d*):(\d*)(?::(\d*))?")
11
+
12
+
13
+ class TaskMatchConfig(BaseConfig):
14
+ """Tasks named by position or identity; a task matches when any list names it."""
15
+
16
+ idx: list[int | str] = Field(default_factory=list)
17
+ """Positions in the taskset's `load()` stream (`TaskData.idx`): ints and Python
18
+ slices `start:stop:step`, each part optional (`"100:"`, `":50"`, `"::2"`).
19
+ Negative positions are not supported. A comma-separated string also works
20
+ (`"0:10,17"`)."""
21
+ ids: list[str] = Field(default_factory=list)
22
+ """`TaskData.id` values."""
23
+ keys: list[str] = Field(default_factory=list)
24
+ """`Task.key` values, as recorded on each trace (`task.key`)."""
25
+ names: list[str] = Field(default_factory=list)
26
+ """`TaskData.name` values."""
27
+
28
+ @field_validator("idx", mode="before")
29
+ @classmethod
30
+ def _parse_idx(cls, value):
31
+ if isinstance(value, (int, str)):
32
+ value = [value]
33
+ items: list[int | str] = []
34
+ for item in value:
35
+ parts = item.split(",") if isinstance(item, str) else [item]
36
+ items.extend(_parse_idx_item(part) for part in parts)
37
+ return items
38
+
39
+ @property
40
+ def empty(self) -> bool:
41
+ return not (self.idx or self.ids or self.keys or self.names)
42
+
43
+ def idx_ranges(self) -> list[range]:
44
+ """`idx` as ranges; an open-ended slice stops at `sys.maxsize`."""
45
+ ranges: list[range] = []
46
+ for item in self.idx:
47
+ if isinstance(item, int):
48
+ ranges.append(range(item, item + 1))
49
+ continue
50
+ start, stop, step = (item.split(":") + [""])[:3]
51
+ ranges.append(
52
+ range(int(start or 0), int(stop or sys.maxsize), int(step or 1))
53
+ )
54
+ return ranges
55
+
56
+ @property
57
+ def idx_tail(self) -> bool:
58
+ """Whether an `idx` slice names every position from some start on."""
59
+ return any(r.stop == sys.maxsize and r.step == 1 for r in self.idx_ranges())
60
+
61
+ @property
62
+ def idx_stop(self) -> int | None:
63
+ """One past the last position this can match, when it names only closed `idx`
64
+ ranges; None when a match could lie anywhere in the stream."""
65
+ ranges = self.idx_ranges()
66
+ if not ranges or self.ids or self.keys or self.names:
67
+ return None
68
+ stop = max(r.stop for r in ranges)
69
+ return None if stop == sys.maxsize else stop
70
+
71
+
72
+ def _parse_idx_item(item: int | str) -> int | str:
73
+ if isinstance(item, int):
74
+ if item < 0:
75
+ raise ValueError(f"idx {item} is negative")
76
+ return item
77
+ text = item.strip()
78
+ if text.isdigit():
79
+ return int(text)
80
+ match = IDX_RANGE.fullmatch(text)
81
+ if match is None:
82
+ raise ValueError(f"idx {item!r} is not an int or a 'start:stop:step' slice")
83
+ start, stop, step = match.groups()
84
+ if step and int(step) == 0:
85
+ raise ValueError(f"idx slice {item!r} has step 0")
86
+ if stop and int(start or 0) >= int(stop):
87
+ raise ValueError(f"idx range {item!r} is empty")
88
+ return text
89
+
90
+
91
+ class SelectConfig(BaseConfig):
92
+ """The steps apply in a fixed order: `include` keeps tasks, `exclude` drops them,
93
+ then `shuffle`, `skip` and `limit` pick from what is left."""
94
+
95
+ include: TaskMatchConfig = TaskMatchConfig()
96
+ """Keep only the tasks this names. Empty keeps all."""
97
+ exclude: TaskMatchConfig = TaskMatchConfig()
98
+ """Drop the tasks this names."""
99
+ shuffle: bool = False
100
+ """Shuffle the kept tasks under `seed`. Needs a finite stream: an infinite taskset
101
+ must be bounded by closed `include.idx` ranges first."""
102
+ seed: int = 0
103
+ """Seed for `shuffle`, fixed so runs select the same tasks."""
104
+ skip: int = Field(0, ge=0)
105
+ """Drop this many tasks after the shuffle."""
106
+ limit: int | None = Field(None, ge=1)
107
+ """Take at most this many tasks after `skip` (None = all)."""
108
+
109
+
110
+ class SelectCLIConfig(SelectConfig):
111
+ """`SelectConfig` with CLI short flags, for the one `select` block of an entrypoint:
112
+ `-n` sets `limit` and `-s` sets `shuffle`."""
113
+
114
+ shuffle: bool = Field(False, validation_alias=AliasChoices("shuffle", "s"))
115
+ """Shuffle the kept tasks under `seed` (`-s`). Needs a finite stream: an infinite
116
+ taskset must be bounded by closed `include.idx` ranges first."""
117
+ limit: int | None = Field(None, ge=1, validation_alias=AliasChoices("limit", "n"))
118
+ """Take at most this many tasks after `skip` (`-n`; None = all)."""
@@ -17,6 +17,7 @@ from verifiers.v1.clients import EvalClientConfig
17
17
  from verifiers.v1.configs.cli.env import narrowed_env_annotation, resolve_env_field
18
18
  from verifiers.v1.configs.cli.eval import RunConfig, default_run_name
19
19
  from verifiers.v1.configs.env import EnvConfig
20
+ from verifiers.v1.configs.select import SelectCLIConfig
20
21
  from verifiers.v1.envs.single_agent import SingleAgentEnvConfig
21
22
  from verifiers.v1.types import SamplingConfig
22
23
 
@@ -49,17 +50,17 @@ class GEPAConfig(BaseConfig):
49
50
  reflection_client: EvalClientConfig | None = None
50
51
  """Endpoint for `reflection_model`. None = reuse `client`."""
51
52
 
53
+ select: SelectCLIConfig = SelectCLIConfig()
54
+ """Which of the taskset's tasks GEPA splits into train/val, under `--select.*`
55
+ (`-n` sets `select.limit`, `-s` sets `select.shuffle`)."""
52
56
  num_train: int = Field(100, ge=1)
53
57
  """Tasks reserved for reflection minibatches (GEPA never scores the full trainset at once)."""
54
58
  num_val: int = Field(50, ge=1)
55
59
  """Tasks held out to score each candidate system prompt for the pareto frontier."""
56
- shuffle: bool = Field(True, validation_alias=AliasChoices("shuffle", "s"))
57
- """Shuffle tasks before splitting into train/val — v1 tasksets have no generic train/val
58
- split, so GEPA carves one out of `Taskset.select` the way `run_eval` samples (fixed
59
- seed, so the split is reproducible across runs)."""
60
60
  seed: int = 0
61
- """Seed for GEPA's optimizer (candidate selection / minibatch sampling). Task shuffling
62
- uses a fixed seed, matching eval — so this doesn't change the train/val split."""
61
+ """Seed for GEPA's optimizer (candidate selection / minibatch sampling). The train/val
62
+ split comes from `select` (`-s` shuffles it under `select.seed`), so this doesn't
63
+ change it."""
63
64
 
64
65
  max_total_rollouts: int = Field(500)
65
66
  """Total rollouts GEPA may spend across the whole optimization run."""
@@ -2,8 +2,8 @@
2
2
 
3
3
  v1 tasksets have no generic train/val split concept (`TasksetConfig` has no `split` field;
4
4
  individual tasksets define ad hoc ones inconsistently), so GEPA carves one out of the tasks
5
- `Taskset.select` hands it (the shared fixed-seed shuffle, reproducible across runs like every
6
- other entrypoint): two disjoint slices.
5
+ `select` yields (reproducible across runs like every other entrypoint): two
6
+ disjoint slices.
7
7
  """
8
8
 
9
9
  from verifiers.v1.task import Task
@@ -38,10 +38,8 @@ class _GEPALog:
38
38
 
39
39
  def run_gepa(env: Env, config: GEPAConfig) -> GEPAResult:
40
40
  logger.info("gepa config:\n%s", config.model_dump_json(indent=2))
41
- # Global shuffle: an infinite taskset raises here — run it with
42
- # shuffle=false (there is no whole set to sample from).
43
- taskset = env.taskset.shuffle() if config.shuffle else env.taskset
44
- all_tasks = list(taskset.head(config.num_train + config.num_val))
41
+ taskset = env.taskset.select(config.select)
42
+ all_tasks = list(taskset.take(config.num_train + config.num_val))
45
43
  train_tasks, val_tasks = split_tasks(all_tasks, config.num_train, config.num_val)
46
44
  selected_tasks = [*train_tasks, *val_tasks]
47
45
  # Seed from the tasks GEPA actually evaluates (train ∪ val), not the full pre-split pool —
@@ -82,7 +82,9 @@ class TaskData(BaseModel):
82
82
  model_config = ConfigDict(frozen=True)
83
83
 
84
84
  idx: int | None = None
85
- """Taskset-autogenerated index."""
85
+ """Task index in the taskset's `load()` stream - automatically set."""
86
+ id: str | None = None
87
+ """Optional durable id from the task's source, e.g. a dataset's instance id."""
86
88
  name: str | None = None
87
89
  """Optional human-readable task name."""
88
90
  description: str | None = None
@@ -163,11 +165,15 @@ class Task(Generic[DataT, StateT, ConfigT]):
163
165
  """
164
166
  return self.hash
165
167
 
166
- def with_system_prompt(self, system_prompt: str) -> Self:
168
+ def with_data(self, **update: Any) -> Self:
169
+ """A shallow copy whose data has `update` applied."""
167
170
  clone = copy.copy(self)
168
- clone.data = self.data.model_copy(update={"system_prompt": system_prompt})
171
+ clone.data = self.data.model_copy(update=update)
169
172
  return clone
170
173
 
174
+ def with_system_prompt(self, system_prompt: str) -> Self:
175
+ return self.with_data(system_prompt=system_prompt)
176
+
171
177
  def runtime_env(self) -> dict[str, str]:
172
178
  """Live-only process environment; unlike TaskData, it is not traced."""
173
179
  return {}