verifiers 0.3.2.dev71__tar.gz → 0.3.2.dev73__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.
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/PKG-INFO +2 -1
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/pyproject.toml +2 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/conftest.py +1 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/dashboard/eval.py +15 -7
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/eval/main.py +0 -4
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/eval/runner.py +69 -34
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/cli/eval.py +12 -2
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/runtimes/prime.py +9 -6
- verifiers-0.3.2.dev73/verifiers/v1/utils/platform.py +164 -0
- verifiers-0.3.2.dev71/verifiers/v1/utils/platform.py +0 -317
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/.gitignore +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/LICENSE +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/README.md +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/fixtures/counter_tool_v1.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/fixtures/duet_v1.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/fixtures/echo_acp_resume_v1.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/fixtures/echo_agentic_v1.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/fixtures/echo_tool_v1.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/fixtures/echo_user_sim_v1.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/fixtures/echo_v1.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/fixtures/pyproject.toml +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/fixtures/tool_response_image_v1.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/test_color_codeword_tasks.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/test_configs.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/test_e2e.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/test_envs.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/test_graph.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/test_judges.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/test_scoring.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/test_taskset.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/tests/v1/test_trace.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/cli/commands/init.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/acp/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/acp/runner.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/agent.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/dashboard/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/dashboard/base.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/dashboard/replay.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/dashboard/validate.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/debug.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/eval/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/eval/resume.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/gepa.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/init.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/output.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/replay.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/resolve.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/resume.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/cli/validate.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/clients/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/clients/base.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/clients/client.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/clients/eval.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/clients/train.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/agent.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/cli/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/cli/debug.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/cli/env.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/cli/init.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/cli/replay.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/cli/validate.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/client.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/env.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/judge.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/retries.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/runtime.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/serve.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/task.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/configs/taskset.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/dialects/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/dialects/anthropic.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/dialects/base.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/dialects/chat.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/dialects/responses.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/env.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/envs/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/envs/agentic_judge/env.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/envs/best_of_n/env.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/envs/isolated_verifier/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/envs/isolated_verifier/env.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/envs/shared_agentic_judge/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/envs/single_agent/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/envs/single_agent/env.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/envs/user_sim/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/envs/user_sim/env.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/episode.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/errors.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/gepa/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/gepa/adapter.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/gepa/config.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/gepa/dataset.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/gepa/reflection.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/gepa/runner.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/graph.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/bash/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/bash/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/browser_use/program.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/codex/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/codex/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/node.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/null/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/null/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/pi/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/pi/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/pool/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/pool/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/prime_agent/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/rlm/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/utils/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/utils/compaction.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/utils/core.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/utils/install.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/utils/launch.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/harnesses/utils/mcp.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/interception/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/interception/base.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/interception/pool.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/interception/server.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/interception/tool.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/interception/tunnel/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/interception/tunnel/base.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/interception/tunnel/custom.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/interception/tunnel/prime.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/judge.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/judges/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/judges/reference.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/judges/reference.txt +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/judges/rubric.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/judges/rubric.txt +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/mcp/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/mcp/launch.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/mcp/server.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/mcp/toolset.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/rollout.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/runtimes/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/runtimes/base.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/runtimes/docker/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/runtimes/docker/egress.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/runtimes/limiters.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/runtimes/modal.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/runtimes/subprocess.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/semantic.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/serve/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/serve/client.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/serve/encoding.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/serve/pool.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/serve/server.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/serve/types.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/session.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/state.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/task.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/taskset.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/harbor/env.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/lean/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/lean/scoring.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/lean/taskset.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/nemo_gym/taskset.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/trace.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/types.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/__init__.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/aio.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/artifacts.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/compile.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/decorators.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/format.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/generic.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/git.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/image.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/interrupt.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/loaders.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/logging.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/memory.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/paths.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/prime.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/retries.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/verifiers/v1/utils/score.py +0 -0
- {verifiers-0.3.2.dev71 → verifiers-0.3.2.dev73}/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.
|
|
3
|
+
Version: 0.3.2.dev73
|
|
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
|
|
@@ -35,6 +35,7 @@ Requires-Dist: msgpack>=1.1.2
|
|
|
35
35
|
Requires-Dist: numpy>=2.1.0
|
|
36
36
|
Requires-Dist: openai<3.0.0,>=2.54.0
|
|
37
37
|
Requires-Dist: prime-pydantic-config[toml]>=0.4.3
|
|
38
|
+
Requires-Dist: prime-runs>=0.1.1
|
|
38
39
|
Requires-Dist: prime-sandboxes>=0.2.39
|
|
39
40
|
Requires-Dist: prime-tunnel>=0.1.8
|
|
40
41
|
Requires-Dist: pydantic>=2.12.3
|
|
@@ -34,6 +34,7 @@ dependencies = [
|
|
|
34
34
|
"openai>=2.54.0,<3.0.0",
|
|
35
35
|
"prime-tunnel>=0.1.8",
|
|
36
36
|
"prime-sandboxes>=0.2.39",
|
|
37
|
+
"prime-runs>=0.1.1",
|
|
37
38
|
"pydantic>=2.12.3",
|
|
38
39
|
"rich>=11.0.0",
|
|
39
40
|
"tenacity>=8.5.0",
|
|
@@ -146,6 +147,7 @@ ty = "2026-07-28T00:00:00Z"
|
|
|
146
147
|
# PrimeIntellect-published on PyPI (trusted publisher)
|
|
147
148
|
prime-tunnel = false
|
|
148
149
|
prime-sandboxes = false
|
|
150
|
+
prime-runs = false
|
|
149
151
|
prime-pydantic-config = false
|
|
150
152
|
renderers = false
|
|
151
153
|
|
|
@@ -281,17 +281,25 @@ def Overview(config: EvalConfig) -> Table:
|
|
|
281
281
|
|
|
282
282
|
|
|
283
283
|
def _push_footer(push: "PushState | None") -> Group | None:
|
|
284
|
-
"""The `--push`
|
|
285
|
-
|
|
286
|
-
|
|
284
|
+
"""The `--push` line under the rollouts: dim with the run's URL while it streams,
|
|
285
|
+
white once pushed, red when it failed. `None` when `--push` is off or the run stayed
|
|
286
|
+
local."""
|
|
287
287
|
if push is None or not push.started:
|
|
288
288
|
return None
|
|
289
|
-
if
|
|
290
|
-
|
|
291
|
-
elif push.url:
|
|
289
|
+
if push.error and push.url:
|
|
290
|
+
# The run exists and holds what streamed up; only closing it out failed.
|
|
292
291
|
line = Text(f"Traces pushed ({push.url})", style="white", overflow="fold")
|
|
293
|
-
|
|
292
|
+
line.append(f" not closed out: {push.error}", style="red")
|
|
293
|
+
elif push.error:
|
|
294
294
|
line = Text(f"Trace push failed ({push.error})", style="red", overflow="fold")
|
|
295
|
+
elif push.incomplete and push.url:
|
|
296
|
+
# Closed out, but the uploader lost records: what landed is there, say what didn't.
|
|
297
|
+
line = Text(f"Traces pushed ({push.url})", style="white", overflow="fold")
|
|
298
|
+
line.append(f" incomplete: {push.incomplete}", style="red")
|
|
299
|
+
elif not push.finished:
|
|
300
|
+
line = Text(f"Pushing traces ({push.url})", style="dim", overflow="fold")
|
|
301
|
+
else:
|
|
302
|
+
line = Text(f"Traces pushed ({push.url})", style="white", overflow="fold")
|
|
295
303
|
return Group(Rule(style="dim"), line)
|
|
296
304
|
|
|
297
305
|
|
|
@@ -134,10 +134,6 @@ def main(argv: list[str] | None = None) -> None:
|
|
|
134
134
|
# Graceful cleanup has already run (each rollout's `finally`); partial results are on
|
|
135
135
|
# disk. Exit on the conventional Ctrl-C code without a traceback.
|
|
136
136
|
raise SystemExit(130)
|
|
137
|
-
if config.push and config.rich is None:
|
|
138
|
-
from verifiers.v1.utils.platform import push_traces
|
|
139
|
-
|
|
140
|
-
push_traces(episodes, config)
|
|
141
137
|
if (
|
|
142
138
|
config.rich is None
|
|
143
139
|
): # --rich is the whole output; otherwise dump each trace as JSON
|
|
@@ -13,8 +13,8 @@ import asyncio
|
|
|
13
13
|
import contextlib
|
|
14
14
|
import logging
|
|
15
15
|
import time
|
|
16
|
-
from collections.abc import AsyncIterator, Awaitable, Callable
|
|
17
|
-
from typing import cast
|
|
16
|
+
from collections.abc import AsyncIterator, Awaitable, Callable, Iterable
|
|
17
|
+
from typing import TypeVar, cast
|
|
18
18
|
|
|
19
19
|
from verifiers.v1.cli.dashboard import dashboard
|
|
20
20
|
from verifiers.v1.cli.eval import resume
|
|
@@ -30,9 +30,36 @@ from verifiers.v1.configs.cli.eval import EvalConfig
|
|
|
30
30
|
from verifiers.v1.configs.serve import ServeConfig
|
|
31
31
|
from verifiers.v1.env import Env, RunSlot
|
|
32
32
|
from verifiers.v1.episode import Episode, EvalRunInfo
|
|
33
|
+
from verifiers.v1.utils.aio import run_shielded
|
|
34
|
+
from verifiers.v1.utils.platform import (
|
|
35
|
+
PushState,
|
|
36
|
+
abort_run,
|
|
37
|
+
finish_run,
|
|
38
|
+
log_episodes,
|
|
39
|
+
open_run,
|
|
40
|
+
)
|
|
33
41
|
|
|
34
42
|
logger = logging.getLogger(__name__)
|
|
35
43
|
|
|
44
|
+
T = TypeVar("T")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
async def gather_rollouts(rollouts: Iterable[Awaitable[T]]) -> list[T]:
|
|
48
|
+
"""`asyncio.gather`, but one rollout failing cancels the rest and waits for them
|
|
49
|
+
to unwind, so nothing keeps uploading into a run the caller is already closing.
|
|
50
|
+
Not a `TaskGroup`: that wraps errors in an `ExceptionGroup`, and `main` would no
|
|
51
|
+
longer see a `KeyboardInterrupt` as Ctrl-C."""
|
|
52
|
+
tasks = [asyncio.ensure_future(rollout) for rollout in rollouts]
|
|
53
|
+
try:
|
|
54
|
+
return await asyncio.gather(*tasks)
|
|
55
|
+
except BaseException:
|
|
56
|
+
for task in tasks:
|
|
57
|
+
task.cancel()
|
|
58
|
+
# return_exceptions: wait for every task, not just the first to cancel.
|
|
59
|
+
await asyncio.gather(*tasks, return_exceptions=True)
|
|
60
|
+
raise
|
|
61
|
+
|
|
62
|
+
|
|
36
63
|
RunSlotFn = Callable[[RunSlot], Awaitable[Episode]]
|
|
37
64
|
OnComplete = Callable[[Episode], Awaitable[None]]
|
|
38
65
|
|
|
@@ -203,47 +230,55 @@ async def run_eval(config: EvalConfig) -> list[Episode]:
|
|
|
203
230
|
asyncio.Semaphore(config.max_concurrent) if config.max_concurrent else None
|
|
204
231
|
)
|
|
205
232
|
write_lock = asyncio.Lock()
|
|
233
|
+
push_state = PushState()
|
|
234
|
+
|
|
235
|
+
# Opened before the first rollout so every episode streams as it lands.
|
|
236
|
+
run = open_run(config, push_state, num_examples=len(tasks))
|
|
237
|
+
# Resumed rollouts are part of this run too.
|
|
238
|
+
log_episodes(run, finished)
|
|
206
239
|
|
|
207
240
|
async def on_complete(episode: Episode) -> None:
|
|
208
241
|
episode.record_run(EvalRunInfo(id=config.run.id, name=config.run.name))
|
|
209
242
|
await append_episode(out, episode, write_lock)
|
|
243
|
+
await asyncio.to_thread(log_episodes, run, [episode])
|
|
210
244
|
|
|
211
245
|
backend = (
|
|
212
246
|
_in_process(env, config, semaphore, on_complete)
|
|
213
247
|
if env is not None
|
|
214
248
|
else _server(config, config.serve, semaphore, on_complete)
|
|
215
249
|
)
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
250
|
+
# The run is closed out whatever breaks, backend setup and teardown included.
|
|
251
|
+
try:
|
|
252
|
+
async with backend as run_slot:
|
|
253
|
+
# The display slots: in-process ones are the env's own (it fills their live
|
|
254
|
+
# traces); a served rollout's is a client-side stand-in its worker never sees.
|
|
255
|
+
planned = [
|
|
256
|
+
slot
|
|
257
|
+
for task, n in plan
|
|
258
|
+
for slot in (
|
|
259
|
+
env.slots(task, n)
|
|
260
|
+
if env is not None
|
|
261
|
+
else [RunSlot(task) for _ in range(n)]
|
|
262
|
+
)
|
|
263
|
+
]
|
|
264
|
+
slots = [RunSlot.finished(episode) for episode in finished] + planned
|
|
265
|
+
display = (
|
|
266
|
+
dashboard(slots, config, start, push=push_state)
|
|
267
|
+
if config.rich is not None
|
|
268
|
+
else contextlib.nullcontext()
|
|
226
269
|
)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
episodes = finished + list(results)
|
|
242
|
-
if (
|
|
243
|
-
push_state is not None
|
|
244
|
-
): # upload off the event loop so the view keeps refreshing
|
|
245
|
-
from verifiers.v1.utils.platform import push_traces
|
|
246
|
-
|
|
247
|
-
push_state.started = True
|
|
248
|
-
await asyncio.to_thread(push_traces, episodes, config, push_state)
|
|
270
|
+
async with display:
|
|
271
|
+
results = await gather_rollouts(run_slot(slot) for slot in planned)
|
|
272
|
+
episodes = finished + list(results)
|
|
273
|
+
# Drain and close out off the event loop so the view keeps refreshing.
|
|
274
|
+
# Shielded: a Ctrl-C here must not cancel the close-out before the
|
|
275
|
+
# worker picks it up (a cancelled executor item never runs), so it
|
|
276
|
+
# runs to completion first and the interrupt is re-raised after —
|
|
277
|
+
# by which point the run is finished and `abort_run` has nothing to do.
|
|
278
|
+
await run_shielded(
|
|
279
|
+
asyncio.to_thread(finish_run, run, episodes, push_state)
|
|
280
|
+
)
|
|
281
|
+
except BaseException as e:
|
|
282
|
+
await asyncio.to_thread(abort_run, run, e, push_state)
|
|
283
|
+
raise
|
|
249
284
|
return episodes
|
|
@@ -48,13 +48,23 @@ class RunConfig(BaseConfig):
|
|
|
48
48
|
"""Run directory name — the run writes to `output_dir / dir`. Defaults to `run.name`;
|
|
49
49
|
set it only when the directory should differ from the display name."""
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
_id: str = PrivateAttr(default_factory=lambda: str(uuid4()))
|
|
51
|
+
_id: str | None = PrivateAttr(default=None)
|
|
53
52
|
|
|
54
53
|
@property
|
|
55
54
|
def id(self) -> str:
|
|
55
|
+
"""The run's one id, assigned by `open_run` from the prime-runs handle: the
|
|
56
|
+
platform's evaluation id online, the SDK's local id otherwise. The run mints
|
|
57
|
+
none of its own, so the run dir, every trace and the dashboard agree."""
|
|
58
|
+
if self._id is None:
|
|
59
|
+
raise RuntimeError("the run has no id until `open_run` has opened it")
|
|
56
60
|
return self._id
|
|
57
61
|
|
|
62
|
+
def assign_id(self, run_id: str) -> None:
|
|
63
|
+
"""Called once by `open_run`, before the first rollout."""
|
|
64
|
+
if self._id is not None and self._id != run_id:
|
|
65
|
+
raise RuntimeError(f"the run already has id {self._id!r}")
|
|
66
|
+
self._id = run_id
|
|
67
|
+
|
|
58
68
|
|
|
59
69
|
class EvalConfig(BaseConfig):
|
|
60
70
|
env: SerializeAsAny[EnvConfig] = SingleAgentEnvConfig()
|
|
@@ -295,17 +295,20 @@ class PrimeRuntime(Runtime):
|
|
|
295
295
|
|
|
296
296
|
async def run(self, argv: list[str], env: dict[str, str]) -> ProgramResult:
|
|
297
297
|
try:
|
|
298
|
-
#
|
|
299
|
-
|
|
300
|
-
# long SDK deadline is only a final safety bound.
|
|
301
|
-
result = await self._client.run_background_job(
|
|
298
|
+
# Poll directly so rollout cancellation owns the execution timeout.
|
|
299
|
+
job = await self._client.start_background_job(
|
|
302
300
|
self.info.id,
|
|
303
301
|
shlex.join(argv),
|
|
304
|
-
timeout=EFFECTIVELY_UNBOUNDED_SECONDS,
|
|
305
302
|
working_dir=self.config.workdir,
|
|
306
303
|
env=self.process_env(env),
|
|
307
|
-
poll_interval=1,
|
|
308
304
|
)
|
|
305
|
+
delay = 0.1
|
|
306
|
+
while True:
|
|
307
|
+
result = await self._client.get_background_job(self.info.id, job)
|
|
308
|
+
if result.completed:
|
|
309
|
+
break
|
|
310
|
+
await asyncio.sleep(delay)
|
|
311
|
+
delay = min(delay * 2, 3)
|
|
309
312
|
except (
|
|
310
313
|
Exception
|
|
311
314
|
) as e: # a sandbox/API failure is one rollout's problem, not the eval's
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"""The eval's run on the Prime Intellect platform (`--no-push` to keep it local)."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import logging
|
|
5
|
+
import os
|
|
6
|
+
from collections.abc import Mapping
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
import prime_runs as pr
|
|
11
|
+
from prime_runs.projection import (
|
|
12
|
+
build_samples, # noqa: F401 - prime-rl imports it from here
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
from verifiers.v1.configs.cli.eval import EvalConfig
|
|
16
|
+
from verifiers.v1.episode import Episode
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class PushState:
|
|
23
|
+
"""The dashboard's view of the run: reads through to it, owns no I/O."""
|
|
24
|
+
|
|
25
|
+
run: pr.Run | None = None
|
|
26
|
+
error: str | None = None
|
|
27
|
+
incomplete: str | None = None
|
|
28
|
+
"""Set when the run closed out but the uploader lost records on the way: the run
|
|
29
|
+
exists and holds what did land, so the footer says so rather than "failed"."""
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def url(self) -> str | None:
|
|
33
|
+
return self.run.url if self.run is not None else None
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def finished(self) -> bool:
|
|
37
|
+
return self.run is not None and self.run.finished
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def started(self) -> bool:
|
|
41
|
+
"""A live run, or a reason there isn't one."""
|
|
42
|
+
return self.error is not None or self.url is not None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def open_run(config: EvalConfig, state: PushState, *, num_examples: int) -> pr.Run:
|
|
46
|
+
"""Open the run this eval streams into, before the first rollout, and give the
|
|
47
|
+
config the run's id. A run that cannot be opened is logged and replaced by a
|
|
48
|
+
disabled one; the eval goes on."""
|
|
49
|
+
identity: dict[str, Any] = {
|
|
50
|
+
"name": config.run.name,
|
|
51
|
+
# Resolved by name via the hub's get-or-create; no taskset, nothing to attach to.
|
|
52
|
+
"environments": [config.env.taskset.id] if config.env.taskset.id else [],
|
|
53
|
+
"model": config.model,
|
|
54
|
+
"framework": "verifiers",
|
|
55
|
+
# The v0 keys the dashboard's lists read. The config itself is a follow-up:
|
|
56
|
+
# a dump or the launched file can carry credentials and needs masking first.
|
|
57
|
+
"config": {
|
|
58
|
+
"model": config.model,
|
|
59
|
+
"num_examples": num_examples,
|
|
60
|
+
"rollouts_per_example": config.num_rollouts,
|
|
61
|
+
},
|
|
62
|
+
}
|
|
63
|
+
if config.push and os.getenv(pr.MODE_ENV, "").strip().lower() == "disabled":
|
|
64
|
+
# The SDK's own kill switch; the explicit `mode="online"` below would override it.
|
|
65
|
+
logger.info("--push: %s=disabled; running without a platform run", pr.MODE_ENV)
|
|
66
|
+
elif config.push:
|
|
67
|
+
try:
|
|
68
|
+
state.run = pr.init(mode="online", **identity)
|
|
69
|
+
except Exception as e: # noqa: BLE001 - a failed upload must not fail the eval
|
|
70
|
+
logger.warning(
|
|
71
|
+
"--push: could not open the run (%s: %s); running without it",
|
|
72
|
+
type(e).__name__,
|
|
73
|
+
e,
|
|
74
|
+
)
|
|
75
|
+
state.error = f"{type(e).__name__}: {e}"
|
|
76
|
+
if state.run is None:
|
|
77
|
+
state.run = pr.init(mode="disabled", **identity)
|
|
78
|
+
# The run's one id: the platform's when online, the SDK's local one otherwise.
|
|
79
|
+
# The SDK keys every upload to it regardless; this is for the local records.
|
|
80
|
+
config.run.assign_id(state.run.id)
|
|
81
|
+
return state.run
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def log_episodes(run: pr.Run, episodes: list[Episode]) -> None:
|
|
85
|
+
"""Hand finished episodes to the run, best effort: the SDK already keeps upload
|
|
86
|
+
failures on its own thread, so this only guards the hand-off itself. A problem
|
|
87
|
+
here is the platform's, never the eval's."""
|
|
88
|
+
if not episodes:
|
|
89
|
+
return
|
|
90
|
+
try:
|
|
91
|
+
run.log_episodes(episodes)
|
|
92
|
+
except Exception as e: # noqa: BLE001 - the rollouts are on disk; report, don't raise
|
|
93
|
+
logger.warning(
|
|
94
|
+
"--push: could not queue %d episode(s) (%s: %s)",
|
|
95
|
+
len(episodes),
|
|
96
|
+
type(e).__name__,
|
|
97
|
+
e,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def finish_run(run: pr.Run, episodes: list[Episode], state: PushState) -> None:
|
|
102
|
+
"""Drain, write the run's aggregates, close it out. Blocking: call it off the loop."""
|
|
103
|
+
try:
|
|
104
|
+
summary = pr.metrics.from_episodes(episodes)
|
|
105
|
+
except Exception as e: # noqa: BLE001 - close the run even without its headline
|
|
106
|
+
logger.warning(
|
|
107
|
+
"--push: could not aggregate the run's metrics (%s: %s)",
|
|
108
|
+
type(e).__name__,
|
|
109
|
+
e,
|
|
110
|
+
)
|
|
111
|
+
summary = None
|
|
112
|
+
_close(run, state, summary=summary)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def abort_run(run: pr.Run, error: BaseException, state: PushState) -> None:
|
|
116
|
+
"""Close the run out after the eval broke, so it doesn't sit at running. Not
|
|
117
|
+
for a break during `finish_run`: that close-out completes on its own thread
|
|
118
|
+
and the SDK lets the first `finish()` decide the status — it sets `run.status`
|
|
119
|
+
as it starts, so an in-flight one is visible here before it is `finished`."""
|
|
120
|
+
if run.finished or run.status is not pr.RunStatus.RUNNING:
|
|
121
|
+
return
|
|
122
|
+
if isinstance(error, (KeyboardInterrupt, asyncio.CancelledError)):
|
|
123
|
+
status, message = pr.RunStatus.CANCELLED, "interrupted"
|
|
124
|
+
else:
|
|
125
|
+
status, message = pr.RunStatus.FAILED, f"{type(error).__name__}: {error}"
|
|
126
|
+
_close(run, state, status=status, error=message)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _close(
|
|
130
|
+
run: pr.Run,
|
|
131
|
+
state: PushState,
|
|
132
|
+
summary: Mapping[str, Any] | None = None,
|
|
133
|
+
status: pr.RunStatus = pr.RunStatus.COMPLETED,
|
|
134
|
+
error: str | None = None,
|
|
135
|
+
) -> None:
|
|
136
|
+
"""`run.finish()`, best effort: the results are on disk, so nothing here may raise."""
|
|
137
|
+
try:
|
|
138
|
+
run.finish(summary, status=status, error=error)
|
|
139
|
+
except Exception as e: # noqa: BLE001 - the run is over; report, don't raise
|
|
140
|
+
logger.warning(
|
|
141
|
+
"--push: could not close out the run (%s: %s)", type(e).__name__, e
|
|
142
|
+
)
|
|
143
|
+
if state.error is None:
|
|
144
|
+
state.error = f"{type(e).__name__}: {e}"
|
|
145
|
+
else:
|
|
146
|
+
state.incomplete = _losses(run)
|
|
147
|
+
if state.incomplete:
|
|
148
|
+
logger.warning("--push: %s, but %s", status.value, state.incomplete)
|
|
149
|
+
if run.url:
|
|
150
|
+
# The run's own status: `finish()` is a no-op once another caller closed it.
|
|
151
|
+
logger.info("--push: %s -> %s", run.status.value, run.url)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _losses(run: pr.Run) -> str | None:
|
|
155
|
+
"""What the uploader could not store, or `None`. A sink that switched itself off
|
|
156
|
+
quietly (Prime Traces outside the beta) is not a loss and is not counted here."""
|
|
157
|
+
parts = [
|
|
158
|
+
f"{count} record(s) not stored by the {sink} sink"
|
|
159
|
+
for sink, count in sorted(run.failed_records.items())
|
|
160
|
+
if count
|
|
161
|
+
]
|
|
162
|
+
if run.dropped_records:
|
|
163
|
+
parts.append(f"{run.dropped_records} record(s) never queued (uploader overrun)")
|
|
164
|
+
return "; ".join(parts) or None
|