verifiers 0.4.1.dev64__tar.gz → 0.4.1.dev67__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.4.1.dev64 → verifiers-0.4.1.dev67}/PKG-INFO +1 -1
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/counter_tool.py +8 -1
- verifiers-0.4.1.dev67/tests/integration/test_limits.py +116 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/test_task.py +31 -2
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/test_trace.py +27 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/__init__.py +3 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/agent.py +1 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/agent.py +10 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/scoring.py +6 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/task.py +10 -2
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/rollout.py +22 -1
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/session.py +16 -1
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/trace.py +1 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/decorators.py +11 -5
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/loaders.py +10 -1
- verifiers-0.4.1.dev64/tests/integration/test_limits.py +0 -56
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/.gitignore +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/LICENSE +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/README.md +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/pyproject.toml +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/conftest.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/agent_user.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/agent_user_harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/duet.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/echo.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/echo_acp_resume.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/echo_agentic.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/echo_tool.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/echo_tool_compose/docker-compose.yaml +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/echo_user_sim.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/fetch_tool.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/network_policy.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/parallel.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/pyproject.toml +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/skill_codeword.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/skills/project-codeword/SKILL.md +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/tool_response_image.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/grid.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_agent_user.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_agentic_judge.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_compose_scoring.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_examples.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_multi_agent.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_multi_turn.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_multi_turn_tool.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_multimodal_tool.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_network_policy.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_parallel.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_resume_tool.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_rubric_judge.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_sampling.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_scoring_network.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_shared_tool.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_single_turn.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_skills.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_stateful_tool.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_tool_vms.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_user_echo.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/test_user_sim.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/cli/test_replay.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/conftest.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/harnesses/test_core.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/harnesses/test_rlm.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/interception/test_tunnel.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/judges/conftest.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/judges/test_judge.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/judges/test_reference.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/judges/test_rubric.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/runtimes/test_private_network.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/serve/test_client.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/serve/test_delta.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/serve/test_pool.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/test_agent.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/test_api.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/test_dialects.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/test_graph.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/test_harbor_grading_network.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/test_runtimes.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/test_scoring_network.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/test_semantic.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/test_taskset.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/utils/test_compile.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/utils/test_loaders.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/utils/test_platform.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/unit/utils/test_score.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/acp/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/acp/runner.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/dashboard/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/dashboard/base.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/dashboard/eval.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/dashboard/replay.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/dashboard/validate.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/debug.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/eval/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/eval/hint.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/eval/main.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/eval/resume.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/eval/runner.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/gepa.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/output.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/replay.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/resolve.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/resume.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/cli/validate.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/clients/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/clients/base.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/clients/client.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/clients/eval.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/clients/train.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/cli/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/cli/debug.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/cli/env.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/cli/eval.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/cli/replay.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/cli/validate.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/client.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/deployment.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/env.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/interception.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/judge.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/retries.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/runtime.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/select.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/serve.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/configs/taskset.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/dialects/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/dialects/anthropic.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/dialects/base.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/dialects/chat.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/dialects/responses.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/env.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/envs/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/envs/agentic_judge/env.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/envs/best_of_n/env.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/envs/single_agent/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/envs/single_agent/env.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/envs/user_sim/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/envs/user_sim/env.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/episode.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/errors.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/gepa/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/gepa/adapter.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/gepa/config.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/gepa/dataset.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/gepa/reflection.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/gepa/runner.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/grading.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/graph.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/bash/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/bash/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/browser_use/program.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/codex/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/codex/gate.mjs +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/codex/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/deepseek/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/deepseek/gate.mjs +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/deepseek/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/deepseek/usage.mjs +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/node.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/null/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/null/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/opencode/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/opencode/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/opencode/mcp-ready.js +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/pi/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/pi/gate.mjs +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/pi/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/prime_agent/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/rlm/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/utils/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/utils/compaction.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/utils/core.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/utils/install.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/utils/launch.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/utils/mcp.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/harnesses/utils/replay.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/interception/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/interception/base.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/interception/pool.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/interception/server.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/interception/tunnel/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/interception/tunnel/base.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/interception/tunnel/custom.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/interception/tunnel/prime.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/judge.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/judges/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/judges/decision.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/judges/reference.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/judges/reference.txt +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/judges/rubric.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/judges/rubric.txt +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/mcp/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/mcp/launch.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/mcp/server.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/mcp/toolset.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/runtimes/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/runtimes/backends/custom.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/runtimes/backends/docker.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/runtimes/backends/prime.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/runtimes/backends/subprocess.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/runtimes/base.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/runtimes/compose.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/runtimes/deployment.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/runtimes/egress.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/runtimes/limiters.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/runtimes/private_network.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/runtimes/runtime.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/runtimes/strategies.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/semantic.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/serve/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/serve/client.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/serve/delta.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/serve/encoding.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/serve/pool.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/serve/server.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/serve/types.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/state.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/task.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/taskset.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/tasksets/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/tasksets/harbor/toolset.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/tasksets/nemo_gym/taskset.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/types.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/__init__.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/aio.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/artifacts.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/compile.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/env.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/eval.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/format.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/generic.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/git.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/image.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/interrupt.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/logging.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/memory.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/paths.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/platform.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/prime.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/retries.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/scope.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/score.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/trace_store.py +0 -0
- {verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/verifiers/v1/utils/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: verifiers
|
|
3
|
-
Version: 0.4.1.
|
|
3
|
+
Version: 0.4.1.dev67
|
|
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
|
|
@@ -21,6 +21,8 @@ class CounterToolset(vf.Toolset[vf.ToolsetConfig, CounterState]):
|
|
|
21
21
|
|
|
22
22
|
class CounterTaskConfig(vf.TaskConfig):
|
|
23
23
|
tools: vf.ToolsetConfig = vf.ToolsetConfig()
|
|
24
|
+
constant_reward: bool = False
|
|
25
|
+
"""Score every rollout 1, so a skipped score (reward 0) stands out."""
|
|
24
26
|
|
|
25
27
|
|
|
26
28
|
class CounterTask(vf.Task[vf.TaskData, CounterState, CounterTaskConfig]):
|
|
@@ -30,7 +32,12 @@ class CounterTask(vf.Task[vf.TaskData, CounterState, CounterTaskConfig]):
|
|
|
30
32
|
|
|
31
33
|
@vf.reward(weight=1.0)
|
|
32
34
|
async def counted(self, trace: vf.Trace) -> float:
|
|
33
|
-
return float(trace.state.count >= 2)
|
|
35
|
+
return float(self.config.constant_reward or trace.state.count >= 2)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def any_response(response: vf.Response) -> bool:
|
|
39
|
+
"""A plugged stop that ends the run on its first model response."""
|
|
40
|
+
return True
|
|
34
41
|
|
|
35
42
|
|
|
36
43
|
class CounterConfig(vf.TasksetConfig):
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""The seat's caps stop a rollout that would run on: the counter task wants three tool
|
|
2
|
+
turns (counter-tool), and each cap ends it after the first with its own stop
|
|
3
|
+
condition. The turn cap also runs across the harness x runtime grid, since each program
|
|
4
|
+
handles a refused request in its own way."""
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
from grid import grid
|
|
8
|
+
|
|
9
|
+
CAPS = [
|
|
10
|
+
pytest.param({"max_turns": 1}, "max_turns", id="max-turns"),
|
|
11
|
+
pytest.param({"max_input_tokens": 1}, "max_input_tokens", id="max-input-tokens"),
|
|
12
|
+
pytest.param({"max_output_tokens": 1}, "max_output_tokens", id="max-output-tokens"),
|
|
13
|
+
pytest.param({"max_total_tokens": 1}, "max_total_tokens", id="max-total-tokens"),
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.mark.parametrize("cap,stop_condition", CAPS)
|
|
18
|
+
async def test_cap(run, cap, stop_condition):
|
|
19
|
+
(episode,) = await run(
|
|
20
|
+
"counter-tool",
|
|
21
|
+
harness="null",
|
|
22
|
+
runtime={"type": "prime"},
|
|
23
|
+
env={"agent": cap},
|
|
24
|
+
)
|
|
25
|
+
(trace,) = episode.traces
|
|
26
|
+
assert trace.num_branches == 1
|
|
27
|
+
assert trace.stop_condition == stop_condition
|
|
28
|
+
assert trace.is_truncated
|
|
29
|
+
assert trace.num_turns == 1
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
async def test_rollout_timeout(run):
|
|
33
|
+
(episode,) = await run(
|
|
34
|
+
"counter-tool",
|
|
35
|
+
harness="null",
|
|
36
|
+
runtime={"type": "prime"},
|
|
37
|
+
rollout_timeout=1,
|
|
38
|
+
)
|
|
39
|
+
(trace,) = episode.traces
|
|
40
|
+
assert trace.is_timeout
|
|
41
|
+
assert trace.stop_condition == "agent_timeout"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@pytest.mark.parametrize("skip", [False, True], ids=["scored", "skipped"])
|
|
45
|
+
async def test_skip_scoring_on_truncated(run, skip):
|
|
46
|
+
(episode,) = await run(
|
|
47
|
+
"counter-tool",
|
|
48
|
+
harness="null",
|
|
49
|
+
runtime={"type": "prime"},
|
|
50
|
+
taskset_overrides={"task": {"constant_reward": True}},
|
|
51
|
+
env={"agent": {"max_turns": 1, "scoring": {"skip_on_truncated": skip}}},
|
|
52
|
+
)
|
|
53
|
+
(trace,) = episode.traces
|
|
54
|
+
assert trace.is_truncated and trace.ok
|
|
55
|
+
if skip:
|
|
56
|
+
assert trace.reward == 0 and trace.rewards == {}
|
|
57
|
+
assert trace.info["scoring_skipped"] == "truncated"
|
|
58
|
+
else:
|
|
59
|
+
assert trace.reward == 1
|
|
60
|
+
assert "scoring_skipped" not in trace.info
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@pytest.mark.parametrize("skip", [False, True], ids=["scored", "skipped"])
|
|
64
|
+
async def test_skip_scoring_on_timeout(run, skip):
|
|
65
|
+
(episode,) = await run(
|
|
66
|
+
"counter-tool",
|
|
67
|
+
harness="null",
|
|
68
|
+
runtime={"type": "prime"},
|
|
69
|
+
rollout_timeout=1,
|
|
70
|
+
taskset_overrides={"task": {"constant_reward": True}},
|
|
71
|
+
env={"agent": {"scoring": {"skip_on_timeout": skip}}},
|
|
72
|
+
)
|
|
73
|
+
(trace,) = episode.traces
|
|
74
|
+
assert trace.is_timeout and trace.ok
|
|
75
|
+
if skip:
|
|
76
|
+
assert trace.reward == 0 and trace.rewards == {}
|
|
77
|
+
assert trace.info["scoring_skipped"] == "timeout"
|
|
78
|
+
else:
|
|
79
|
+
assert trace.reward == 1
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@pytest.mark.parametrize("harness,harness_runtime", grid(needs=("mcp",)), indirect=True)
|
|
83
|
+
async def test_max_turns(run, harness, harness_runtime):
|
|
84
|
+
(episode,) = await run(
|
|
85
|
+
"counter-tool",
|
|
86
|
+
harness=harness,
|
|
87
|
+
runtime=harness_runtime,
|
|
88
|
+
max_turns=1,
|
|
89
|
+
max_tokens=8192,
|
|
90
|
+
)
|
|
91
|
+
(trace,) = episode.traces
|
|
92
|
+
assert trace.num_branches == 1
|
|
93
|
+
assert trace.stop_condition == "max_turns", [e.message for e in trace.errors]
|
|
94
|
+
assert trace.num_turns == 1
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@pytest.mark.parametrize("skip", [False, True], ids=["scored", "skipped"])
|
|
98
|
+
async def test_skip_scoring_on_stop(run, scripted_model, skip):
|
|
99
|
+
stop = {"fn": "counter_tool:any_response", "skip_scoring": skip}
|
|
100
|
+
(episode,) = await run(
|
|
101
|
+
"counter-tool",
|
|
102
|
+
harness="null",
|
|
103
|
+
runtime={"type": "subprocess"},
|
|
104
|
+
client=scripted_model,
|
|
105
|
+
taskset_overrides={
|
|
106
|
+
"task": {"constant_reward": True, "stops": {"any_response": stop}}
|
|
107
|
+
},
|
|
108
|
+
)
|
|
109
|
+
(trace,) = episode.traces
|
|
110
|
+
assert trace.stop_condition == "any_response" and trace.ok
|
|
111
|
+
if skip:
|
|
112
|
+
assert trace.reward == 0 and trace.rewards == {}
|
|
113
|
+
assert trace.info["scoring_skipped"] == "any_response"
|
|
114
|
+
else:
|
|
115
|
+
assert trace.reward == 1
|
|
116
|
+
assert "scoring_skipped" not in trace.info
|
|
@@ -36,6 +36,10 @@ class HookTask(vf.Task[HookData]):
|
|
|
36
36
|
async def single_turn(self, trace: vf.Trace) -> bool:
|
|
37
37
|
return trace.num_turns >= 1
|
|
38
38
|
|
|
39
|
+
@vf.stop(skip_scoring=True)
|
|
40
|
+
async def no_reply(self, trace: vf.Trace) -> bool:
|
|
41
|
+
return trace.last_reply is None
|
|
42
|
+
|
|
39
43
|
@vf.reward
|
|
40
44
|
async def lcs(self, trace: vf.Trace) -> float:
|
|
41
45
|
return 0.5
|
|
@@ -49,7 +53,7 @@ async def test_config_plugged_fns_merge_and_override(tmp_path) -> None:
|
|
|
49
53
|
fns = tmp_path / "fns.py"
|
|
50
54
|
fns.write_text(PLUGGED_FNS_PY)
|
|
51
55
|
config = vf.TaskConfig(
|
|
52
|
-
stops={"single_turn": vf.
|
|
56
|
+
stops={"single_turn": vf.StopFunctionConfig(fn=f"{fns}:two_turns")},
|
|
53
57
|
metrics={"reply_length": vf.DecoratedFunctionConfig(fn=f"{fns}:reply_length")},
|
|
54
58
|
rewards={
|
|
55
59
|
"exact_match": vf.RewardFunctionConfig(fn=f"{fns}:exact_match", weight=0.5),
|
|
@@ -70,9 +74,10 @@ async def test_config_plugged_fns_merge_and_override(tmp_path) -> None:
|
|
|
70
74
|
)
|
|
71
75
|
|
|
72
76
|
# the plugged `single_turn` replaces the decorated one: no stop after one turn
|
|
73
|
-
|
|
77
|
+
no_reply, stop = task.hooks("stop")
|
|
74
78
|
assert stop.__name__ == "single_turn"
|
|
75
79
|
assert not await stop(trace)
|
|
80
|
+
assert no_reply.stop_skip_scoring and not stop.stop_skip_scoring
|
|
76
81
|
|
|
77
82
|
await task.score(trace)
|
|
78
83
|
# `lcs` scored by the plugged marker (config wins the name clash), config weight
|
|
@@ -102,3 +107,27 @@ async def test_defer_scoring_defers_only_task_scoring() -> None:
|
|
|
102
107
|
assert trace.rewards == {}
|
|
103
108
|
await task.score(trace)
|
|
104
109
|
assert set(trace.rewards) == {"fmt", "lcs"}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def test_plugged_stops_set_skip_scoring(tmp_path) -> None:
|
|
113
|
+
fns = tmp_path / "fns.py"
|
|
114
|
+
fns.write_text(PLUGGED_FNS_PY)
|
|
115
|
+
data = HookData(idx=0, prompt="abc")
|
|
116
|
+
|
|
117
|
+
def skips(stops: dict) -> dict[str, bool]:
|
|
118
|
+
config = vf.TaskConfig(stops=stops)
|
|
119
|
+
return {
|
|
120
|
+
fn.__name__: fn.stop_skip_scoring
|
|
121
|
+
for fn in HookTask(data, config).hooks("stop")
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
# a fresh plugged stop scores by default; a fn-less entry keeps or overrides the decorator's
|
|
125
|
+
assert skips({"two": vf.StopFunctionConfig(fn=f"{fns}:two_turns")})["two"] is False
|
|
126
|
+
assert skips(
|
|
127
|
+
{"two": vf.StopFunctionConfig(fn=f"{fns}:two_turns", skip_scoring=True)}
|
|
128
|
+
)["two"]
|
|
129
|
+
assert skips({"no_reply": vf.StopFunctionConfig()})["no_reply"] is True
|
|
130
|
+
assert (
|
|
131
|
+
skips({"no_reply": vf.StopFunctionConfig(skip_scoring=False)})["no_reply"]
|
|
132
|
+
is False
|
|
133
|
+
)
|
|
@@ -9,6 +9,7 @@ from verifiers.v1.configs.agent import resolve_agent
|
|
|
9
9
|
from verifiers.v1.dialects.chat import ChatDialect
|
|
10
10
|
from verifiers.v1.dialects.responses import ResponsesDialect, fold_assistant
|
|
11
11
|
from verifiers.v1.graph import MessageNode, prepare_turn
|
|
12
|
+
from verifiers.v1.session import RolloutLimits
|
|
12
13
|
from verifiers.v1.types import AssistantMessage, UserMessage
|
|
13
14
|
from verifiers.v1.utils.trace_store import write_episode
|
|
14
15
|
|
|
@@ -266,3 +267,29 @@ def test_sampling_mask_from_packed_matches_lists():
|
|
|
266
267
|
):
|
|
267
268
|
np.testing.assert_array_equal(mask.ids, ids)
|
|
268
269
|
np.testing.assert_array_equal(mask.counts, counts)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def test_max_turn_tokens_limit():
|
|
273
|
+
limits = RolloutLimits(max_turn_tokens=16)
|
|
274
|
+
trace = vf.Trace(
|
|
275
|
+
agent=vf.AgentInfo(config=vf.AgentConfig()),
|
|
276
|
+
task=vf.TraceTask(type="Task", data=vf.TaskData(idx=0, prompt=None)),
|
|
277
|
+
)
|
|
278
|
+
trace.calls.append(vf.ModelCall(finish_reason="stop"))
|
|
279
|
+
assert limits.reached(trace) is None
|
|
280
|
+
# A length finish below the cap ran out of context: not this limit.
|
|
281
|
+
usage = vf.Usage(prompt_tokens=100, completion_tokens=8)
|
|
282
|
+
trace.calls.append(vf.ModelCall(finish_reason="length", usage=usage))
|
|
283
|
+
assert limits.reached(trace) is None
|
|
284
|
+
usage = vf.Usage(prompt_tokens=100, completion_tokens=16)
|
|
285
|
+
trace.calls.append(vf.ModelCall(finish_reason="length", usage=usage))
|
|
286
|
+
assert limits.reached(trace) == "max_turn_tokens"
|
|
287
|
+
trace.stop("max_turn_tokens")
|
|
288
|
+
assert trace.is_truncated
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
@pytest.mark.parametrize("max_tokens,expected", [(None, 16), (8, 8), (64, 16)])
|
|
292
|
+
def test_max_turn_tokens_caps_sampling(max_tokens, expected):
|
|
293
|
+
spec = vf.AgentConfig(max_turn_tokens=16)
|
|
294
|
+
sampling = vf.SamplingConfig(max_tokens=max_tokens)
|
|
295
|
+
assert resolve_agent(spec, sampling=sampling).sampling.max_tokens == expected
|
|
@@ -56,6 +56,7 @@ if TYPE_CHECKING:
|
|
|
56
56
|
from verifiers.v1.configs.task import (
|
|
57
57
|
DecoratedFunctionConfig,
|
|
58
58
|
RewardFunctionConfig,
|
|
59
|
+
StopFunctionConfig,
|
|
59
60
|
TaskConfig,
|
|
60
61
|
)
|
|
61
62
|
from verifiers.v1.configs.taskset import SharedTasksetConfig, TasksetConfig
|
|
@@ -301,6 +302,7 @@ _NAME_TO_MODULE = {
|
|
|
301
302
|
"State": "verifiers.v1.state",
|
|
302
303
|
"StateT": "verifiers.v1.state",
|
|
303
304
|
"StaticPoolConfig": "verifiers.v1.configs.serve",
|
|
305
|
+
"StopFunctionConfig": "verifiers.v1.configs.task",
|
|
304
306
|
"SubprocessConfig": "verifiers.v1.configs.runtime",
|
|
305
307
|
"SystemMessage": "verifiers.v1.types",
|
|
306
308
|
"TRACE_VERSION": "verifiers.v1.trace",
|
|
@@ -480,6 +482,7 @@ __all__ = [ # noqa: RUF022 - grouped by public API area
|
|
|
480
482
|
"SharedTasksetConfig",
|
|
481
483
|
"DecoratedFunctionConfig",
|
|
482
484
|
"RewardFunctionConfig",
|
|
485
|
+
"StopFunctionConfig",
|
|
483
486
|
"BaseConfig",
|
|
484
487
|
"Harness",
|
|
485
488
|
"HarnessSession",
|
|
@@ -575,6 +575,7 @@ class Agent:
|
|
|
575
575
|
max_input_tokens=config.max_input_tokens,
|
|
576
576
|
max_output_tokens=config.max_output_tokens,
|
|
577
577
|
max_total_tokens=config.max_total_tokens,
|
|
578
|
+
max_turn_tokens=config.max_turn_tokens,
|
|
578
579
|
)
|
|
579
580
|
self.timeout = config.timeout
|
|
580
581
|
# Env episode agents replace this with the episode's agent semaphore
|
|
@@ -66,6 +66,11 @@ class AgentConfig(BaseConfig):
|
|
|
66
66
|
"""Max output tokens per run (None = no limit)."""
|
|
67
67
|
max_total_tokens: int | None = None
|
|
68
68
|
"""Max total tokens per run (None = no limit)."""
|
|
69
|
+
max_turn_tokens: int | None = Field(None, gt=0)
|
|
70
|
+
"""Max output tokens per model response (None = no limit). Caps the sampling
|
|
71
|
+
`max_tokens` the framework sets on every request, whatever the harness asks for,
|
|
72
|
+
and stops the run once a response hits it. `sampling.max_tokens` alone caps each
|
|
73
|
+
response without stopping the run."""
|
|
69
74
|
|
|
70
75
|
timeout: TimeoutConfig = TimeoutConfig()
|
|
71
76
|
retries: RetryConfig = RetryConfig()
|
|
@@ -147,6 +152,11 @@ def resolve_agent(
|
|
|
147
152
|
defaults = sampling or SamplingConfig()
|
|
148
153
|
overrides = (spec.sampling or SamplingConfig()).model_dump(exclude_unset=True)
|
|
149
154
|
merged = {**defaults.model_dump(), **merge_defaults(defaults, overrides)}
|
|
155
|
+
if spec.max_turn_tokens is not None:
|
|
156
|
+
max_tokens = merged.get("max_tokens")
|
|
157
|
+
merged["max_tokens"] = min(
|
|
158
|
+
max_tokens or spec.max_turn_tokens, spec.max_turn_tokens
|
|
159
|
+
)
|
|
150
160
|
return spec.model_copy(
|
|
151
161
|
update={
|
|
152
162
|
"harness": spec.harness if spec.harness is not None else harness,
|
|
@@ -24,6 +24,12 @@ class ScoringConfig(BaseConfig):
|
|
|
24
24
|
combined with the runtime's own rules the same way. None keeps the default: isolated
|
|
25
25
|
scoring runs under `TaskData.network`, shared scoring keeps the agent phase's network,
|
|
26
26
|
and Harbor's shared grading lifts the policy."""
|
|
27
|
+
skip_on_truncated: bool = False
|
|
28
|
+
"""Skip task scoring for a truncated trace (`Trace.is_truncated`): it keeps no
|
|
29
|
+
rewards, so its reward is 0."""
|
|
30
|
+
skip_on_timeout: bool = False
|
|
31
|
+
"""Skip task scoring for a trace whose stage deadline expired before scoring
|
|
32
|
+
(`Trace.is_timeout`): it keeps no rewards, so its reward is 0."""
|
|
27
33
|
|
|
28
34
|
@field_serializer("runtime")
|
|
29
35
|
def serialize_runtime(
|
|
@@ -14,13 +14,21 @@ class DecoratedFunctionConfig(BaseConfig):
|
|
|
14
14
|
fn: str | None = None
|
|
15
15
|
"""Import path to the function: `pkg.module.function`, `pkg.module:function`,
|
|
16
16
|
or `path/to/file.py:function`. Unset keeps the task's decorated method with the
|
|
17
|
-
entry's name and only overrides its metadata (priority, weight)."""
|
|
17
|
+
entry's name and only overrides its metadata (priority, weight, skip_scoring)."""
|
|
18
18
|
|
|
19
19
|
priority: int | None = None
|
|
20
20
|
"""Execution order, like the decorator's — higher runs first, ties break by name.
|
|
21
21
|
Unset keeps the replaced method's priority (0 for a fresh function)."""
|
|
22
22
|
|
|
23
23
|
|
|
24
|
+
class StopFunctionConfig(DecoratedFunctionConfig):
|
|
25
|
+
"""A plugged function standing in for a `@vf.stop` task method."""
|
|
26
|
+
|
|
27
|
+
skip_scoring: bool | None = None
|
|
28
|
+
"""Skip task scoring for a trace this stop ends: it keeps no rewards, so its reward
|
|
29
|
+
is 0. Unset keeps the replaced method's setting (false for a fresh function)."""
|
|
30
|
+
|
|
31
|
+
|
|
24
32
|
class RewardFunctionConfig(DecoratedFunctionConfig):
|
|
25
33
|
"""A plugged function standing in for a `@vf.reward` task method."""
|
|
26
34
|
|
|
@@ -39,7 +47,7 @@ class TaskConfig(BaseConfig):
|
|
|
39
47
|
judges: Judges = Field(default_factory=list)
|
|
40
48
|
"""Judge plugins run after task rewards, set through `--env.taskset.task.judges`."""
|
|
41
49
|
|
|
42
|
-
stops: dict[str,
|
|
50
|
+
stops: dict[str, StopFunctionConfig] = Field(default_factory=dict)
|
|
43
51
|
"""Typed `Request`, `Response`, or `Trace` stop predicates plugged by name and
|
|
44
52
|
merged with the task's `@vf.stop` methods (a plugged function replaces a
|
|
45
53
|
decorated one with the same name)."""
|
|
@@ -157,6 +157,9 @@ class Rollout:
|
|
|
157
157
|
for fn in discover_decorated(task, "intercept")
|
|
158
158
|
]
|
|
159
159
|
stops = [(hook_boundary(fn, allow_trace=True), fn) for fn in task.hooks("stop")]
|
|
160
|
+
self._skip_scoring_stops = {
|
|
161
|
+
fn.__name__ for _, fn in stops if getattr(fn, "stop_skip_scoring", False)
|
|
162
|
+
}
|
|
160
163
|
execution_policy = runtime_config
|
|
161
164
|
self._session = RolloutSession(
|
|
162
165
|
ctx=ctx,
|
|
@@ -721,6 +724,17 @@ class Rollout:
|
|
|
721
724
|
"agent_completed",
|
|
722
725
|
)
|
|
723
726
|
|
|
727
|
+
def _scoring_skip_reason(self) -> str | None:
|
|
728
|
+
"""Why the resolved scoring policy, or the `skip_scoring` stop that ended this trace,
|
|
729
|
+
skips task scoring for it, if either does."""
|
|
730
|
+
if self._scoring_policy.skip_on_truncated and self.trace.is_truncated:
|
|
731
|
+
return "truncated"
|
|
732
|
+
if self._scoring_policy.skip_on_timeout and self.trace.is_timeout:
|
|
733
|
+
return "timeout"
|
|
734
|
+
if self.trace.stop_condition in self._skip_scoring_stops:
|
|
735
|
+
return self.trace.stop_condition
|
|
736
|
+
return None
|
|
737
|
+
|
|
724
738
|
def _metrics_deadline(self) -> float:
|
|
725
739
|
"""Best-effort metrics get at most 30 seconds, and a tenth of a finite scoring budget."""
|
|
726
740
|
budget = (
|
|
@@ -848,7 +862,14 @@ class Rollout:
|
|
|
848
862
|
boundary(TaskError, "scoring"),
|
|
849
863
|
):
|
|
850
864
|
# Cross-trace judgement runs later, after the runtime is gone.
|
|
851
|
-
if
|
|
865
|
+
if skip_reason := self._scoring_skip_reason():
|
|
866
|
+
logger.info(
|
|
867
|
+
"rollout %s: scoring skipped (%s)",
|
|
868
|
+
trace.id,
|
|
869
|
+
skip_reason,
|
|
870
|
+
)
|
|
871
|
+
trace.info["scoring_skipped"] = skip_reason
|
|
872
|
+
elif grader is not None:
|
|
852
873
|
try:
|
|
853
874
|
await grade_task(
|
|
854
875
|
grader,
|
|
@@ -87,12 +87,15 @@ class RolloutLimits:
|
|
|
87
87
|
a @stop — and becomes the trace's stop condition. Each caps a trace computed property:
|
|
88
88
|
`max_turns` -> num_turns, `max_input_tokens` -> num_input_tokens, `max_output_tokens` ->
|
|
89
89
|
num_output_tokens, `max_total_tokens` -> num_total_tokens. Token caps are soft by one turn:
|
|
90
|
-
they're checked between turns, so the turn that crosses a cap still completes.
|
|
90
|
+
they're checked between turns, so the turn that crosses a cap still completes.
|
|
91
|
+
`max_turn_tokens` caps each response (applied through sampling) and refuses the turn
|
|
92
|
+
after a response that hit it."""
|
|
91
93
|
|
|
92
94
|
max_turns: int | None = None
|
|
93
95
|
max_input_tokens: int | None = None
|
|
94
96
|
max_output_tokens: int | None = None
|
|
95
97
|
max_total_tokens: int | None = None
|
|
98
|
+
max_turn_tokens: int | None = None
|
|
96
99
|
|
|
97
100
|
def reached(self, trace: Trace) -> str | None:
|
|
98
101
|
"""The name of the first limit `trace` has reached, or None if within all caps."""
|
|
@@ -113,6 +116,18 @@ class RolloutLimits:
|
|
|
113
116
|
and trace.num_total_tokens >= self.max_total_tokens
|
|
114
117
|
):
|
|
115
118
|
return "max_total_tokens"
|
|
119
|
+
if self.max_turn_tokens is not None:
|
|
120
|
+
last = next((c for c in reversed(trace.calls) if c.error is None), None)
|
|
121
|
+
# A length finish below the cap ran out of context, not turn tokens.
|
|
122
|
+
if (
|
|
123
|
+
last is not None
|
|
124
|
+
and last.finish_reason == "length"
|
|
125
|
+
and (
|
|
126
|
+
last.usage is None
|
|
127
|
+
or last.usage.completion_tokens >= self.max_turn_tokens
|
|
128
|
+
)
|
|
129
|
+
):
|
|
130
|
+
return "max_turn_tokens"
|
|
116
131
|
return None
|
|
117
132
|
|
|
118
133
|
|
|
@@ -83,12 +83,18 @@ def tool(func: F | None = None, name: str | None = None) -> F | Callable[[F], F]
|
|
|
83
83
|
|
|
84
84
|
|
|
85
85
|
@overload
|
|
86
|
-
def stop(func: F, priority: int = 0) -> F: ...
|
|
86
|
+
def stop(func: F, priority: int = 0, skip_scoring: bool = False) -> F: ...
|
|
87
87
|
@overload
|
|
88
|
-
def stop(
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
def stop(
|
|
89
|
+
func: None = None, priority: int = 0, skip_scoring: bool = False
|
|
90
|
+
) -> Callable[[F], F]: ...
|
|
91
|
+
def stop(
|
|
92
|
+
func: F | None = None, priority: int = 0, skip_scoring: bool = False
|
|
93
|
+
) -> F | Callable[[F], F]:
|
|
94
|
+
"""Stop when a typed `Request`, `Response`, or `Trace` predicate returns true. With
|
|
95
|
+
`skip_scoring`, a trace this stop ends skips task scoring: it keeps no rewards, so
|
|
96
|
+
its reward is 0."""
|
|
97
|
+
decorator = mark("stop", stop_priority=priority, stop_skip_scoring=skip_scoring)
|
|
92
98
|
return decorator if func is None else decorator(func)
|
|
93
99
|
|
|
94
100
|
|
|
@@ -15,7 +15,11 @@ from pydantic_config import BaseConfig
|
|
|
15
15
|
from verifiers.v1.configs.env import EnvConfig
|
|
16
16
|
from verifiers.v1.configs.harness import HarnessConfig
|
|
17
17
|
from verifiers.v1.configs.judge import JudgeConfig
|
|
18
|
-
from verifiers.v1.configs.task import
|
|
18
|
+
from verifiers.v1.configs.task import (
|
|
19
|
+
DecoratedFunctionConfig,
|
|
20
|
+
RewardFunctionConfig,
|
|
21
|
+
StopFunctionConfig,
|
|
22
|
+
)
|
|
19
23
|
from verifiers.v1.configs.taskset import TasksetConfig
|
|
20
24
|
from verifiers.v1.env import Env
|
|
21
25
|
from verifiers.v1.envs.single_agent import SingleAgentEnv
|
|
@@ -279,6 +283,11 @@ def load_plugged_fn(
|
|
|
279
283
|
if weight is None:
|
|
280
284
|
weight = getattr(fn, "_vf_weight", 1.0)
|
|
281
285
|
plugged._vf_weight = weight
|
|
286
|
+
if isinstance(config, StopFunctionConfig):
|
|
287
|
+
skip_scoring = config.skip_scoring
|
|
288
|
+
if skip_scoring is None:
|
|
289
|
+
skip_scoring = getattr(fn, "stop_skip_scoring", False)
|
|
290
|
+
plugged.stop_skip_scoring = skip_scoring
|
|
282
291
|
return plugged
|
|
283
292
|
|
|
284
293
|
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
"""The seat's caps stop a rollout that would run on: the counter task wants three tool
|
|
2
|
-
turns (counter-tool), and each cap ends it after the first with its own stop
|
|
3
|
-
condition. The turn cap also runs across the harness x runtime grid, since each program
|
|
4
|
-
handles a refused request in its own way."""
|
|
5
|
-
|
|
6
|
-
import pytest
|
|
7
|
-
from grid import grid
|
|
8
|
-
|
|
9
|
-
CAPS = [
|
|
10
|
-
pytest.param({"max_turns": 1}, "max_turns", id="max-turns"),
|
|
11
|
-
pytest.param({"max_input_tokens": 1}, "max_input_tokens", id="max-input-tokens"),
|
|
12
|
-
pytest.param({"max_output_tokens": 1}, "max_output_tokens", id="max-output-tokens"),
|
|
13
|
-
pytest.param({"max_total_tokens": 1}, "max_total_tokens", id="max-total-tokens"),
|
|
14
|
-
]
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@pytest.mark.parametrize("cap,stop_condition", CAPS)
|
|
18
|
-
async def test_cap(run, cap, stop_condition):
|
|
19
|
-
(episode,) = await run(
|
|
20
|
-
"counter-tool",
|
|
21
|
-
harness="null",
|
|
22
|
-
runtime={"type": "prime"},
|
|
23
|
-
env={"agent": cap},
|
|
24
|
-
)
|
|
25
|
-
(trace,) = episode.traces
|
|
26
|
-
assert trace.num_branches == 1
|
|
27
|
-
assert trace.stop_condition == stop_condition
|
|
28
|
-
assert trace.is_truncated
|
|
29
|
-
assert trace.num_turns == 1
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
async def test_rollout_timeout(run):
|
|
33
|
-
(episode,) = await run(
|
|
34
|
-
"counter-tool",
|
|
35
|
-
harness="null",
|
|
36
|
-
runtime={"type": "prime"},
|
|
37
|
-
rollout_timeout=1,
|
|
38
|
-
)
|
|
39
|
-
(trace,) = episode.traces
|
|
40
|
-
assert trace.is_timeout
|
|
41
|
-
assert trace.stop_condition == "agent_timeout"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
@pytest.mark.parametrize("harness,harness_runtime", grid(needs=("mcp",)), indirect=True)
|
|
45
|
-
async def test_max_turns(run, harness, harness_runtime):
|
|
46
|
-
(episode,) = await run(
|
|
47
|
-
"counter-tool",
|
|
48
|
-
harness=harness,
|
|
49
|
-
runtime=harness_runtime,
|
|
50
|
-
max_turns=1,
|
|
51
|
-
max_tokens=8192,
|
|
52
|
-
)
|
|
53
|
-
(trace,) = episode.traces
|
|
54
|
-
assert trace.num_branches == 1
|
|
55
|
-
assert trace.stop_condition == "max_turns", [e.message for e in trace.errors]
|
|
56
|
-
assert trace.num_turns == 1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/agent_user_harness.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/echo_acp_resume.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/network_policy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/skill_codeword.py
RENAMED
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev64 → verifiers-0.4.1.dev67}/tests/integration/fixtures/tool_response_image.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|