verifiers 0.1.15.dev396__tar.gz → 0.1.15.dev398__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.1.15.dev396 → verifiers-0.1.15.dev398}/PKG-INFO +3 -1
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/pyproject.toml +4 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/GUIDE.md +54 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/README.md +6 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/__init__.py +6 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/cli/dashboard/eval.py +28 -4
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/clients/config.py +21 -9
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/dialects/chat.py +1 -19
- verifiers-0.1.15.dev398/verifiers/v1/judge.py +180 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/trace.py +19 -1
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/types.py +29 -9
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/.gitignore +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/LICENSE +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/README.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/AGENTS.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/README.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/conftest.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_browser_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_build_script.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_cli_agent_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_client_auth_errors.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_client_config.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_client_multimodal_types.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_composable_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_context_token_metrics.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_decorator_ranks.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_endpoint_registry.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_env_group.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_env_server.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_environment.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_environment_extra.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_envs.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_error_chain.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_eval_display.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_eval_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_gepa_cli.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_gepa_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_gym_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_harbor_env_mcp.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_imports.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_init_script.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_install_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_interception_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_lean_task.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_logging.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_math_rubric.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_maybe_think_parser.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_message_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_message_utils_multimodal.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_multiturn_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_nemorl_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_openai_chat_completions_token_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_openai_responses_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_opencode_rlm_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_openenv_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_parser.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_path_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_per_turn_timing.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_pricing_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_prime_plugin.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_renderer_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_renderer_e2e.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_rlm_composable_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_rubric.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_rubric_group.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_sandbox_debug_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_sandbox_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_sandbox_mixin.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_save_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_setup_script.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_singleturn_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_stateful_tool_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_think_parser.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_tool_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_tool_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_trajectory_processing.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_tui_info_formatting.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_types.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_wordle_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/test_xml_parser.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/conftest.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/fixtures/counter_tool_v1.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/fixtures/echo_agentic_v1.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/fixtures/echo_multi_v0.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/fixtures/echo_tool_v1.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/fixtures/echo_user_sim_v1.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/fixtures/echo_v0.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/fixtures/echo_v1.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/fixtures/pyproject.toml +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/fixtures/tool_response_image_v1.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/test_color_codeword_tasks.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/test_configs.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/test_e2e.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/test_envs.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/test_graph.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/test_legacy.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/tests/v1/test_trace.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/AGENTS.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/cli/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/cli/commands/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/cli/commands/build.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/cli/commands/eval.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/cli/commands/gepa.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/cli/commands/init.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/cli/commands/install.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/cli/commands/setup.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/cli/plugins/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/cli/plugins/prime.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/cli/tui.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/clients/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/clients/anthropic_messages_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/clients/client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/clients/nemorl_chat_completions_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/clients/openai_chat_completions_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/clients/openai_chat_completions_token_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/clients/openai_completions_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/clients/openai_responses_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/clients/renderer_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/decorators.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/AGENTS.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/env_group.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/environment.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/README.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/cli_agent_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/README.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/_filter.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/composable_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/harness.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/harnesses/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/harnesses/mini_swe_agent.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/harnesses/opencode.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/harnesses/prompt.txt +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/harnesses/rlm.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/sandbox_debug_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/swe_debug_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/task.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/cp/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/cp/cp_task.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/cp/test_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/harbor/cli_gym.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/harbor/harbor.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/harbor/terminal_lego.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/lean/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/lean/lean_task.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/math/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/math/math_task.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/README.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/openseeker/README.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/openseeker/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/openseeker/taskset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/README.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/api_tools/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/api_tools/tool_pdf.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/eval_toolkit.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/evaluator.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/llm_client/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/llm_client/base_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/prompts/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/prompts/cache_prompts.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/cache_filesys.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/load_eval_script.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/misc.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/tool_visit.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/url_tools.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/verification_tree.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/open_ended.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/quest/taskset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/redsearcher/README.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/redsearcher/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/redsearcher/taskset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/search/search_tasksets.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/README.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/extract_fix_patch.sh +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/taskset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/openswe/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/openswe/taskset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/log_parser.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/taskset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/scale_swe/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/scale_swe/taskset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/shared/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/shared/test_patch.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/swe_bench/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/swe_bench/taskset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/swe_lego/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/swe_lego/taskset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/log_parsers.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/taskset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/swe_smith/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/swe_smith/taskset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/composable/tasksets/swe/swe_tasksets.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/gym_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/harbor_env/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/harbor_env/env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/harbor_env/mcp.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/mcp_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/opencode_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/opencode_qa_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/opencode_rlm_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/sandbox_mixin.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/utils/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/utils/file_locks.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/experimental/utils/git_checkout_cache.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/integrations/README.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/integrations/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/integrations/browser_env/README.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/integrations/browser_env/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/integrations/browser_env/browser_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/integrations/browser_env/modes/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/integrations/browser_env/modes/base.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/integrations/browser_env/modes/cua_mode.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/integrations/browser_env/modes/dom_mode.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/integrations/openenv_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/integrations/reasoninggym_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/integrations/textarena_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/multiturn_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/python_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/sandbox_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/singleturn_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/stateful_tool_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/envs/tool_env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/errors.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/gepa/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/gepa/adapter.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/gepa/config.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/gepa/display.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/gepa/gepa_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/parsers/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/parsers/maybe_think_parser.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/parsers/parser.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/parsers/think_parser.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/parsers/xml_parser.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rl/README.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rl/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rl/inference/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rl/inference/client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rl/inference/server.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rl/trainer/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rl/trainer/config.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rl/trainer/orchestrator.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rl/trainer/trainer.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rl/trainer/utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rubrics/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rubrics/experimental/hybrid_math_rubric.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rubrics/judge_rubric.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rubrics/math_rubric.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rubrics/rubric.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/rubrics/rubric_group.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/scripts/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/scripts/build.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/scripts/eval.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/scripts/gepa.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/scripts/init.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/scripts/install.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/scripts/rl.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/scripts/setup.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/scripts/train.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/scripts/tui.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/scripts/vllm.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/serve/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/serve/client/env_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/serve/client/zmq_env_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/serve/server/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/serve/server/env_router.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/serve/server/env_server.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/serve/server/env_worker.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/serve/server/zmq_env_server.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/serve/types.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/types.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/async_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/client_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/config_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/data_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/display_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/env_config_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/env_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/error_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/eval_display.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/eval_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/heartbeat.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/import_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/install_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/interception_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/logging_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/message_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/metric_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/path_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/pricing_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/process_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/response_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/save_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/serve_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/thread_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/threaded_sandbox_client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/tool_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/usage_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/utils/version_utils.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/ARCHITECTURE.md +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/cli/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/cli/dashboard/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/cli/dashboard/base.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/cli/dashboard/validate.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/cli/eval/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/cli/eval/main.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/cli/eval/resume.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/cli/eval/runner.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/cli/init.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/cli/output.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/cli/resolve.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/cli/serve.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/cli/validate.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/clients/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/clients/client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/clients/eval.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/clients/train.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/configs/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/configs/eval.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/configs/init.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/configs/serve.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/configs/validate.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/decorators.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/dialects/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/dialects/anthropic.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/dialects/base.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/dialects/responses.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/env.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/episode.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/errors.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/graph.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harness.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/bash/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/bash/harness.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/bash/program.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/bash_edit/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/bash_edit/harness.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/bash_edit/program.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/codex/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/codex/harness.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/default/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/default/harness.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/default/program.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/rlm/harness.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/interception/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/interception/pool.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/interception/server.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/legacy.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/loaders.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/mcp/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/mcp/launch.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/mcp/multiplex.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/mcp/server.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/mcp/toolset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/mcp/user.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/retries.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/rollout.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/runtimes/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/runtimes/base.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/runtimes/docker.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/runtimes/limiters.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/runtimes/modal.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/runtimes/prime.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/runtimes/subprocess.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/serve/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/serve/client.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/serve/pool.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/serve/server.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/serve/types.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/state.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/task.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/taskset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/tasksets/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/utils/__init__.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/utils/format.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/utils/install.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/utils/logging.py +0 -0
- {verifiers-0.1.15.dev396 → verifiers-0.1.15.dev398}/verifiers/v1/utils/memory.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: verifiers
|
|
3
|
-
Version: 0.1.15.
|
|
3
|
+
Version: 0.1.15.dev398
|
|
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
|
|
@@ -51,6 +51,8 @@ Provides-Extra: browser
|
|
|
51
51
|
Requires-Dist: aiohttp>=3.9.0; extra == 'browser'
|
|
52
52
|
Requires-Dist: python-dotenv>=1.0.0; extra == 'browser'
|
|
53
53
|
Requires-Dist: stagehand>=3.0.0; extra == 'browser'
|
|
54
|
+
Provides-Extra: harbor
|
|
55
|
+
Requires-Dist: harbor==0.14.0; (python_version >= '3.12') and extra == 'harbor'
|
|
54
56
|
Provides-Extra: modal
|
|
55
57
|
Requires-Dist: modal>=1.4.0; extra == 'modal'
|
|
56
58
|
Provides-Extra: notebook
|
|
@@ -96,6 +96,10 @@ browser = [
|
|
|
96
96
|
"aiohttp>=3.9.0",
|
|
97
97
|
"python-dotenv>=1.0.0",
|
|
98
98
|
]
|
|
99
|
+
harbor = [
|
|
100
|
+
# Harbor currently publishes Python 3.12+ packages; keep core verifiers installable on 3.11.
|
|
101
|
+
"harbor==0.14.0; python_version >= '3.12'",
|
|
102
|
+
]
|
|
99
103
|
modal = [
|
|
100
104
|
"modal>=1.4.0",
|
|
101
105
|
]
|
|
@@ -254,6 +254,60 @@ async def verify(self, task, trace, runtime) -> float:
|
|
|
254
254
|
return float(r.stdout.strip() == "1.0")
|
|
255
255
|
```
|
|
256
256
|
|
|
257
|
+
### Judges
|
|
258
|
+
|
|
259
|
+
When grading can't be deterministic, `vf.Judge` is a reusable LLM judge: it owns the OpenAI client
|
|
260
|
+
(with the Prime key/team fallback), the call, and usage/cost capture, and leaves the two things that
|
|
261
|
+
differ as hooks — `build_messages` (prompt) and `parse` (verdict). Subclass it, build it once in the
|
|
262
|
+
taskset `__init__`, and call it from a `@reward`:
|
|
263
|
+
|
|
264
|
+
```python
|
|
265
|
+
import verifiers.v1 as vf
|
|
266
|
+
|
|
267
|
+
class CorrectnessJudge(vf.Judge[bool]): # Judge[ParsedT] — ParsedT is your verdict type
|
|
268
|
+
prompt = "Question: {question}\nAnswer: {answer}\nResponse: {response}\nCorrect? Reply yes or no."
|
|
269
|
+
|
|
270
|
+
def parse(self, response: vf.JudgeResponse[bool]) -> bool:
|
|
271
|
+
return response.text.strip().lower().startswith("yes")
|
|
272
|
+
|
|
273
|
+
class MyConfig(vf.TasksetConfig):
|
|
274
|
+
judge: vf.JudgeConfig = vf.JudgeConfig(model="openai/gpt-5-mini")
|
|
275
|
+
|
|
276
|
+
class MyTaskset(vf.Taskset[MyTask, MyConfig]):
|
|
277
|
+
def __init__(self, config: MyConfig) -> None:
|
|
278
|
+
super().__init__(config)
|
|
279
|
+
self.judge = CorrectnessJudge(config.judge)
|
|
280
|
+
|
|
281
|
+
@vf.reward()
|
|
282
|
+
async def correct(self, task, trace) -> float:
|
|
283
|
+
result = await self.judge.evaluate(trace=trace, question=task.question, answer=task.answer, response=...)
|
|
284
|
+
return 1.0 if result.parsed else 0.0
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
`evaluate(*, trace=None, **fields)` renders the prompt (`build_messages`), calls the model, and
|
|
288
|
+
parses the verdict (`parse`), returning a `JudgeResponse{text, parsed, usage}`. Passing `trace=`
|
|
289
|
+
**records the call onto it** — a typed record appended to `trace.info["judge"]` (for debugging) and
|
|
290
|
+
the call's tokens + cost added to `trace.extra_usage`, kept separate from the agent's `trace.usage`
|
|
291
|
+
and off the message graph (so the trainer's token math is unaffected); the eval dashboard shows the
|
|
292
|
+
agent's usage and `+judge` separately. The record lands even if the judge refuses, returns an empty
|
|
293
|
+
structured output, or `parse` raises (the request was already billed). Omit `trace` for a pure call
|
|
294
|
+
(e.g. in tests).
|
|
295
|
+
|
|
296
|
+
The two hooks:
|
|
297
|
+
|
|
298
|
+
| hook | default | override for |
|
|
299
|
+
| --- | --- | --- |
|
|
300
|
+
| `build_messages(**fields) -> str \| Messages` | formats the `prompt` template with the fields into one user message | a system+user / non-template prompt (return a `vf.Messages` list) |
|
|
301
|
+
| `parse(response) -> ParsedT` | the structured object if `schema` is set, else `response.text` | your verdict (`bool`, a grade `str`, a pydantic model, a `list[float]`, …) |
|
|
302
|
+
|
|
303
|
+
Good to know:
|
|
304
|
+
|
|
305
|
+
- **Per-task rubric** is just a field — `prompt = "{task.rubric}\n…"` with `evaluate(trace=trace, task=task, …)` (`str.format` does attribute access on a passed-in `task`). For per-task *parsing*, parse in the reward, where the task is in scope.
|
|
306
|
+
- **Structured outputs**: set `schema` to a pydantic model to use OpenAI structured outputs (where the provider supports it — most do); `JudgeResponse.parsed` is then the validated object. For an unsupported model, prompt for JSON and call `Model.model_validate_json(response.text)` in `parse`.
|
|
307
|
+
- **Multiple / dynamic calls per rollout** (e.g. one per table column): call the low-level `complete(messages, *, trace=, schema=, parse=)` directly with `vf.Messages` you build — it records each call when passed `trace`.
|
|
308
|
+
- **Config**: `JudgeConfig` adds `model` + `sampling` (a `JudgeSamplingConfig`) to `BaseClientConfig` (`base_url`/`api_key_var`/`headers`, Prime auto-config). CLI-overridable: `--taskset.judge.model …`, `--taskset.judge.sampling.max-tokens …`.
|
|
309
|
+
- **Errors propagate**: a judge API failure errors the rollout (recorded as a `TasksetError` on the trace); the OpenAI SDK already retries transient 429/5xx/connection errors.
|
|
310
|
+
|
|
257
311
|
## Stop conditions
|
|
258
312
|
|
|
259
313
|
A rollout ends when the harness finishes, a framework budget trips (`--max-turns`, token caps), or
|
|
@@ -30,6 +30,12 @@ tighter type contract. `import verifiers.v1 as vf`.
|
|
|
30
30
|
uv sync # core + the shipped packages + examples
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
Harbor's optional Python package and CLI require Python 3.12+:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
uv sync --python 3.12 --extra harbor
|
|
37
|
+
```
|
|
38
|
+
|
|
33
39
|
## Quickstart
|
|
34
40
|
|
|
35
41
|
```bash
|
|
@@ -38,6 +38,7 @@ from verifiers.v1.errors import (
|
|
|
38
38
|
UserError,
|
|
39
39
|
)
|
|
40
40
|
from verifiers.v1.harness import Harness, HarnessConfig
|
|
41
|
+
from verifiers.v1.judge import Judge, JudgeConfig, JudgeResponse, JudgeSamplingConfig
|
|
41
42
|
from verifiers.v1.loaders import (
|
|
42
43
|
default_harness_id,
|
|
43
44
|
harness_config_type,
|
|
@@ -189,6 +190,11 @@ __all__ = [
|
|
|
189
190
|
"taskset_config_type",
|
|
190
191
|
"harness_config_type",
|
|
191
192
|
"default_harness_id",
|
|
193
|
+
# judge
|
|
194
|
+
"Judge",
|
|
195
|
+
"JudgeConfig",
|
|
196
|
+
"JudgeSamplingConfig",
|
|
197
|
+
"JudgeResponse",
|
|
192
198
|
# mcp
|
|
193
199
|
"Toolset",
|
|
194
200
|
"ToolsetConfig",
|
|
@@ -25,6 +25,7 @@ from verifiers.v1.cli.output import output_path
|
|
|
25
25
|
from verifiers.v1.configs.eval import EvalConfig
|
|
26
26
|
from verifiers.v1.rollout import Phase, Rollout
|
|
27
27
|
from verifiers.v1.trace import Trace
|
|
28
|
+
from verifiers.v1.types import Usage
|
|
28
29
|
from verifiers.v1.utils.format import format_count, format_mean, format_time
|
|
29
30
|
from verifiers.utils.pricing_utils import format_cost_usd
|
|
30
31
|
|
|
@@ -199,8 +200,9 @@ def _breakdown(done: list[Trace]) -> Table | None:
|
|
|
199
200
|
# cost are summed; each timing phase is averaged over the rollouts that have it timed (averaged
|
|
200
201
|
# per phase rather than summed, since phases run concurrently across rollouts).
|
|
201
202
|
total_in = total_out = total_cached = total_reasoning = 0
|
|
202
|
-
|
|
203
|
-
|
|
203
|
+
total_judge_in = total_judge_out = 0
|
|
204
|
+
total_cost = total_judge_cost = 0.0
|
|
205
|
+
have_cost = have_cached = have_reasoning = have_judge = False
|
|
204
206
|
phase_secs: dict[str, float] = {}
|
|
205
207
|
phase_count: dict[str, int] = {}
|
|
206
208
|
for trace in done:
|
|
@@ -216,12 +218,27 @@ def _breakdown(done: list[Trace]) -> Table | None:
|
|
|
216
218
|
if trace.usage is not None and trace.usage.cost is not None:
|
|
217
219
|
total_cost += trace.usage.cost
|
|
218
220
|
have_cost = True
|
|
221
|
+
# Judge / auxiliary scoring calls (off the message graph) shown separately from the agent's.
|
|
222
|
+
judge = Usage.aggregate(trace.extra_usage)
|
|
223
|
+
if judge is not None:
|
|
224
|
+
total_judge_in += judge.input_tokens
|
|
225
|
+
total_judge_out += judge.completion_tokens
|
|
226
|
+
if judge.cost is not None:
|
|
227
|
+
total_judge_cost += judge.cost
|
|
228
|
+
have_judge = True
|
|
219
229
|
for phase in ("setup", "generation", "finalize", "scoring"):
|
|
220
230
|
span = getattr(trace.timing, phase)
|
|
221
231
|
if span.end: # phase was timed for this rollout
|
|
222
232
|
phase_secs[phase] = phase_secs.get(phase, 0.0) + span.duration
|
|
223
233
|
phase_count[phase] = phase_count.get(phase, 0) + 1
|
|
224
|
-
if
|
|
234
|
+
if (
|
|
235
|
+
total_in
|
|
236
|
+
or total_out
|
|
237
|
+
or have_cost
|
|
238
|
+
or have_cached
|
|
239
|
+
or have_reasoning
|
|
240
|
+
or have_judge
|
|
241
|
+
):
|
|
225
242
|
tokens = f"{format_count(total_in)}/{format_count(total_out)} tokens"
|
|
226
243
|
details = []
|
|
227
244
|
if have_cached:
|
|
@@ -231,8 +248,15 @@ def _breakdown(done: list[Trace]) -> Table | None:
|
|
|
231
248
|
if details:
|
|
232
249
|
tokens += f" ({', '.join(details)})"
|
|
233
250
|
usage = [tokens]
|
|
251
|
+
if have_judge:
|
|
252
|
+
usage.append(
|
|
253
|
+
f"+ {format_count(total_judge_in)}/{format_count(total_judge_out)} judge"
|
|
254
|
+
)
|
|
234
255
|
if have_cost:
|
|
235
|
-
|
|
256
|
+
cost = format_cost_usd(total_cost)
|
|
257
|
+
if total_judge_cost:
|
|
258
|
+
cost += f" + {format_cost_usd(total_judge_cost)} judge"
|
|
259
|
+
usage.append(cost)
|
|
236
260
|
grid.add_row("usage", " · ".join(usage))
|
|
237
261
|
time_segments = [
|
|
238
262
|
f"{phase} {format_time(phase_secs[phase] / phase_count[phase])}"
|
|
@@ -88,7 +88,9 @@ ClientConfig = Annotated[
|
|
|
88
88
|
]
|
|
89
89
|
|
|
90
90
|
|
|
91
|
-
def
|
|
91
|
+
def resolve_api_key(config: BaseClientConfig) -> str:
|
|
92
|
+
"""The API key for `config`: its env var, falling back to the Prime CLI config for a
|
|
93
|
+
`PRIME_API_KEY`-keyed pinference endpoint. `"EMPTY"` when unset."""
|
|
92
94
|
api_key = os.environ.get(config.api_key_var)
|
|
93
95
|
host = urlparse(config.base_url).hostname or ""
|
|
94
96
|
if (
|
|
@@ -97,19 +99,29 @@ def resolve_client(config: BaseClientConfig) -> Client:
|
|
|
97
99
|
and (host == PRIME_INFERENCE_HOST or host.endswith(f".{PRIME_INFERENCE_HOST}"))
|
|
98
100
|
):
|
|
99
101
|
api_key = load_prime_config().get("api_key")
|
|
100
|
-
|
|
102
|
+
return api_key or "EMPTY"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def build_async_openai(config: BaseClientConfig) -> AsyncOpenAI:
|
|
106
|
+
"""An `AsyncOpenAI` for `config` (resolved key + extra headers) — for in-env model calls
|
|
107
|
+
(e.g. a judge) and the training client's engine connection."""
|
|
108
|
+
return AsyncOpenAI(
|
|
109
|
+
base_url=config.base_url,
|
|
110
|
+
api_key=resolve_api_key(config),
|
|
111
|
+
default_headers=config.headers or None,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def resolve_client(config: BaseClientConfig) -> Client:
|
|
101
116
|
if isinstance(config, TrainClientConfig):
|
|
102
117
|
# The renderer calls a vLLM `/inference/v1/generate` engine through the OpenAI SDK.
|
|
103
|
-
openai = AsyncOpenAI(
|
|
104
|
-
base_url=config.base_url,
|
|
105
|
-
api_key=api_key,
|
|
106
|
-
default_headers=config.headers or None,
|
|
107
|
-
)
|
|
108
118
|
return TrainClient(
|
|
109
|
-
|
|
119
|
+
build_async_openai(config),
|
|
110
120
|
pool_size=config.pool_size,
|
|
111
121
|
config=config.renderer,
|
|
112
122
|
renderer_model_name=config.renderer_model_name,
|
|
113
123
|
)
|
|
114
124
|
# The proxy is a raw httpx forwarder; the dialect supplies the auth scheme + upstream path.
|
|
115
|
-
return EvalClient(
|
|
125
|
+
return EvalClient(
|
|
126
|
+
config.base_url, resolve_api_key(config), headers=config.headers or None
|
|
127
|
+
)
|
|
@@ -169,25 +169,7 @@ def response_from_wire(completion: ChatCompletion) -> Response:
|
|
|
169
169
|
finish: FinishReason = (
|
|
170
170
|
choice.finish_reason if choice.finish_reason in FINISH_REASONS else None
|
|
171
171
|
)
|
|
172
|
-
usage =
|
|
173
|
-
if completion.usage:
|
|
174
|
-
cached = (
|
|
175
|
-
completion.usage.prompt_tokens_details.cached_tokens
|
|
176
|
-
if completion.usage.prompt_tokens_details
|
|
177
|
-
else None
|
|
178
|
-
)
|
|
179
|
-
reasoning = (
|
|
180
|
-
completion.usage.completion_tokens_details.reasoning_tokens
|
|
181
|
-
if completion.usage.completion_tokens_details
|
|
182
|
-
else None
|
|
183
|
-
)
|
|
184
|
-
usage = Usage(
|
|
185
|
-
prompt_tokens=completion.usage.prompt_tokens - (cached or 0),
|
|
186
|
-
completion_tokens=completion.usage.completion_tokens,
|
|
187
|
-
cached_input_tokens=cached,
|
|
188
|
-
reasoning_tokens=reasoning,
|
|
189
|
-
cost=getattr(completion.usage, "cost", None),
|
|
190
|
-
)
|
|
172
|
+
usage = Usage.from_openai(completion.usage)
|
|
191
173
|
return Response(
|
|
192
174
|
id=completion.id,
|
|
193
175
|
created=completion.created,
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"""A reusable per-task LLM judge for v1 tasksets.
|
|
2
|
+
|
|
3
|
+
Most tasksets that can't grade deterministically reach for the same shape: an OpenAI-compatible
|
|
4
|
+
endpoint, a prompt built from `(question, answer, response)`, one chat call, and a verdict parsed
|
|
5
|
+
out of the reply. `Judge` centralizes that — the client construction (incl. the Prime key/team
|
|
6
|
+
fallback), the call, and usage/cost capture — and leaves the two things that actually differ as
|
|
7
|
+
hooks: `build_messages` (prompt setup) and `parse`
|
|
8
|
+
(verdict parsing). Set `schema` to use OpenAI structured outputs (where the provider supports it),
|
|
9
|
+
in which case `JudgeResponse.parsed` is the validated pydantic object.
|
|
10
|
+
|
|
11
|
+
class CorrectnessJudge(vf.Judge[bool]):
|
|
12
|
+
prompt = "Question: {question}\\nAnswer: {answer}\\nResponse: {response}\\nCorrect? yes/no"
|
|
13
|
+
|
|
14
|
+
def parse(self, response: vf.JudgeResponse[bool]) -> bool:
|
|
15
|
+
return response.text.strip().lower().startswith("yes")
|
|
16
|
+
|
|
17
|
+
self.judge = CorrectnessJudge(self.config.judge) # self.config.judge: vf.JudgeConfig
|
|
18
|
+
|
|
19
|
+
@vf.reward
|
|
20
|
+
async def correct(self, task, trace) -> float:
|
|
21
|
+
result = await self.judge.evaluate(
|
|
22
|
+
trace=trace, question=task.question, answer=task.answer, response=...
|
|
23
|
+
)
|
|
24
|
+
return float(result.parsed)
|
|
25
|
+
|
|
26
|
+
Passing `trace=` records the call onto it — a typed record appended to `trace.info["judge"]` and
|
|
27
|
+
the call's tokens + cost added to `trace.extra_usage` (kept separate from the agent's `trace.usage`),
|
|
28
|
+
so judge behaviour and spend are no longer invisible. The record lands even if the judge refuses, an
|
|
29
|
+
empty structured output comes back, or `parse` raises (the request was already billed). Omit `trace`
|
|
30
|
+
for a pure call (e.g. in tests).
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
from typing import TYPE_CHECKING, Any, Callable, Generic, TypeVar, cast
|
|
36
|
+
|
|
37
|
+
from openai import AsyncOpenAI
|
|
38
|
+
from pydantic import BaseModel
|
|
39
|
+
|
|
40
|
+
from verifiers.v1.clients.config import BaseClientConfig, build_async_openai
|
|
41
|
+
from verifiers.v1.dialects.chat import message_to_wire
|
|
42
|
+
from verifiers.v1.types import Messages, SamplingConfig, StrictBaseModel, Usage
|
|
43
|
+
|
|
44
|
+
if TYPE_CHECKING:
|
|
45
|
+
from verifiers.v1.trace import Trace
|
|
46
|
+
|
|
47
|
+
ParsedT = TypeVar("ParsedT")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class JudgeSamplingConfig(SamplingConfig):
|
|
51
|
+
"""Sampling knobs for a judge call (`temperature` / `top_p` / `reasoning_effort` /
|
|
52
|
+
`max_tokens`, plus provider-specific keys via `extra='allow'`). Same shape as the rollout's
|
|
53
|
+
`SamplingConfig` — set e.g. `judge.sampling.max_tokens`."""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class JudgeConfig(BaseClientConfig):
|
|
57
|
+
"""An LLM-judge endpoint. Inherits `base_url` / `api_key_var` / `headers` (with the Prime
|
|
58
|
+
auto-config) from `BaseClientConfig`; adds the model and sampling. Subclass to add
|
|
59
|
+
taskset-specific fields."""
|
|
60
|
+
|
|
61
|
+
model: str = "openai/gpt-5-mini"
|
|
62
|
+
sampling: JudgeSamplingConfig = JudgeSamplingConfig()
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class JudgeResponse(StrictBaseModel, Generic[ParsedT]):
|
|
66
|
+
"""One judge call's result — returned to the caller and (JSON-serialized) appended to
|
|
67
|
+
`trace.info["judge"]` for debugging, including the provider-reported `usage` (tokens + cost)."""
|
|
68
|
+
|
|
69
|
+
text: str
|
|
70
|
+
"""The judge's raw reply."""
|
|
71
|
+
parsed: ParsedT | None = None
|
|
72
|
+
"""The verdict the taskset acts on (`parse`'s output, or the structured object for `schema`)."""
|
|
73
|
+
usage: Usage | None = None
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class Judge(Generic[ParsedT]):
|
|
77
|
+
"""A per-task LLM judge over an OpenAI-compatible endpoint.
|
|
78
|
+
|
|
79
|
+
Override `build_messages` (prompt setup) and `parse` (verdict parsing) — or just set the
|
|
80
|
+
`prompt` template and use the defaults — then call `evaluate(**fields)`. Set `schema` to opt
|
|
81
|
+
into structured outputs.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
prompt: str | None = None
|
|
85
|
+
"""Default template for `build_messages`, formatted with the `evaluate` kwargs and sent as a
|
|
86
|
+
single user message. Override `build_messages` for system+user or non-template prompts."""
|
|
87
|
+
schema: type[BaseModel] | None = None
|
|
88
|
+
"""Pydantic schema for OpenAI structured outputs. When set, the call uses
|
|
89
|
+
`response_format=schema` and `JudgeResponse.parsed` is the validated object (provider must
|
|
90
|
+
support structured outputs)."""
|
|
91
|
+
|
|
92
|
+
def __init__(self, config: JudgeConfig | None = None) -> None:
|
|
93
|
+
self.config = config or JudgeConfig()
|
|
94
|
+
self.client: AsyncOpenAI = build_async_openai(self.config)
|
|
95
|
+
|
|
96
|
+
def build_messages(self, **fields: Any) -> str | Messages:
|
|
97
|
+
"""Prompt-setup hook: turn the `evaluate` fields into the messages to send (a single user
|
|
98
|
+
message as a plain `str`, or a `vf.Messages` list). The default formats the `prompt`
|
|
99
|
+
template with the fields; override it for a system+user / non-template prompt."""
|
|
100
|
+
if self.prompt is None:
|
|
101
|
+
raise ValueError(
|
|
102
|
+
f"{type(self).__name__} has no `prompt`; set it or override build_messages"
|
|
103
|
+
)
|
|
104
|
+
return self.prompt.format(**fields)
|
|
105
|
+
|
|
106
|
+
def parse(self, response: JudgeResponse[ParsedT]) -> ParsedT:
|
|
107
|
+
"""Parsing hook: turn a `JudgeResponse` into the verdict. The default returns the
|
|
108
|
+
structured object when `schema` is set, otherwise the raw reply text."""
|
|
109
|
+
if self.schema is not None:
|
|
110
|
+
return cast(ParsedT, response.parsed)
|
|
111
|
+
return cast(ParsedT, response.text)
|
|
112
|
+
|
|
113
|
+
async def complete(
|
|
114
|
+
self,
|
|
115
|
+
messages: str | Messages,
|
|
116
|
+
*,
|
|
117
|
+
trace: "Trace | None" = None,
|
|
118
|
+
schema: type[BaseModel] | None = None,
|
|
119
|
+
parse: Callable[[JudgeResponse[Any]], Any] | None = None,
|
|
120
|
+
**sampling: Any,
|
|
121
|
+
) -> JudgeResponse[Any]:
|
|
122
|
+
"""Call the judge once: send `messages`, build the `JudgeResponse`, and — when a `trace` is
|
|
123
|
+
given — record it (`Trace.record_judge`) in a `finally`, so the call's tokens + cost are
|
|
124
|
+
captured even when a refusal / empty structured output / `parse` hook raises after the
|
|
125
|
+
billed request. `schema` opts into structured outputs; `parse` sets `JudgeResponse.parsed`."""
|
|
126
|
+
wire = (
|
|
127
|
+
[{"role": "user", "content": messages}]
|
|
128
|
+
if isinstance(messages, str)
|
|
129
|
+
else [message_to_wire(m) for m in messages]
|
|
130
|
+
)
|
|
131
|
+
kwargs: dict[str, Any] = {"model": self.config.model, "messages": wire}
|
|
132
|
+
kwargs.update(self.config.sampling.model_dump(exclude_none=True))
|
|
133
|
+
kwargs.update(sampling)
|
|
134
|
+
|
|
135
|
+
response: JudgeResponse[Any] | None = None
|
|
136
|
+
try:
|
|
137
|
+
if schema is not None:
|
|
138
|
+
completion = await self.client.beta.chat.completions.parse(
|
|
139
|
+
response_format=schema, **kwargs
|
|
140
|
+
)
|
|
141
|
+
choice = completion.choices[0]
|
|
142
|
+
response = JudgeResponse(
|
|
143
|
+
text=choice.message.content or "",
|
|
144
|
+
parsed=choice.message.parsed,
|
|
145
|
+
usage=Usage.from_openai(completion.usage),
|
|
146
|
+
)
|
|
147
|
+
if choice.message.refusal is not None:
|
|
148
|
+
raise RuntimeError(
|
|
149
|
+
f"judge refused structured output: {choice.message.refusal}"
|
|
150
|
+
)
|
|
151
|
+
if response.parsed is None:
|
|
152
|
+
# No refusal but no object either — e.g. a truncated/malformed reply. Surface it
|
|
153
|
+
# rather than returning a None verdict callers read as a (falsy) failure.
|
|
154
|
+
raise RuntimeError(
|
|
155
|
+
f"judge returned no parseable structured output "
|
|
156
|
+
f"(finish_reason={choice.finish_reason})"
|
|
157
|
+
)
|
|
158
|
+
else:
|
|
159
|
+
completion = await self.client.chat.completions.create(**kwargs)
|
|
160
|
+
response = JudgeResponse(
|
|
161
|
+
text=completion.choices[0].message.content or "",
|
|
162
|
+
usage=Usage.from_openai(completion.usage),
|
|
163
|
+
)
|
|
164
|
+
if parse is not None:
|
|
165
|
+
response.parsed = parse(response)
|
|
166
|
+
return response
|
|
167
|
+
finally:
|
|
168
|
+
if trace is not None and response is not None:
|
|
169
|
+
trace.record_judge(response)
|
|
170
|
+
|
|
171
|
+
async def evaluate(
|
|
172
|
+
self, *, trace: "Trace | None" = None, **fields: Any
|
|
173
|
+
) -> JudgeResponse[ParsedT]:
|
|
174
|
+
"""Render the prompt (`build_messages(**fields)`), call the judge, and parse the verdict
|
|
175
|
+
(`parse`). When a `trace` is given the call is recorded onto it (`trace.info["judge"]` +
|
|
176
|
+
usage on `trace.extra_usage`), even if a refusal / empty output / parse raises."""
|
|
177
|
+
messages = self.build_messages(**fields)
|
|
178
|
+
return await self.complete(
|
|
179
|
+
messages, trace=trace, schema=self.schema, parse=self.parse
|
|
180
|
+
)
|
|
@@ -13,12 +13,15 @@ import time
|
|
|
13
13
|
import traceback
|
|
14
14
|
import uuid
|
|
15
15
|
from collections.abc import Mapping
|
|
16
|
-
from typing import Any, Generic, TypeVar
|
|
16
|
+
from typing import TYPE_CHECKING, Any, Generic, TypeVar
|
|
17
17
|
|
|
18
18
|
import numpy as np
|
|
19
19
|
from pydantic import Field, PrivateAttr
|
|
20
20
|
from renderers.base import MultiModalData
|
|
21
21
|
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from verifiers.v1.judge import JudgeResponse
|
|
24
|
+
|
|
22
25
|
from verifiers.v1 import graph
|
|
23
26
|
from verifiers.v1.errors import ProviderError
|
|
24
27
|
from verifiers.v1.graph import MessageNode
|
|
@@ -258,6 +261,13 @@ class Trace(StrictBaseModel, Generic[TaskT, StateT]):
|
|
|
258
261
|
/ `to_record`), unlike `info` which persists. Type it via `Taskset[Task, Config, MyState]`; defaults
|
|
259
262
|
to the base `State`."""
|
|
260
263
|
|
|
264
|
+
extra_usage: list[Usage] = Field(default_factory=list)
|
|
265
|
+
"""Token usage from model calls that aren't part of the message graph — LLM judges and other
|
|
266
|
+
auxiliary scoring calls (see `verifiers.v1.judge`). Kept separate from `usage` (the agent's own
|
|
267
|
+
spend) and off the graph, so branch/turn counts and the trainer's token math (`total_tokens`,
|
|
268
|
+
`branches`) see only sampled nodes; consumers that want a grand total add the two (e.g. the eval
|
|
269
|
+
dashboard shows the agent's usage and `+judge` separately)."""
|
|
270
|
+
|
|
261
271
|
is_completed: bool = False
|
|
262
272
|
stop_condition: str | None = None
|
|
263
273
|
errors: list[Error] = Field(default_factory=list)
|
|
@@ -396,6 +406,14 @@ class Trace(StrictBaseModel, Generic[TaskT, StateT]):
|
|
|
396
406
|
for name, value in values.items():
|
|
397
407
|
self.record_metric(name, value)
|
|
398
408
|
|
|
409
|
+
def record_judge(self, response: "JudgeResponse") -> None:
|
|
410
|
+
"""Persist a judge call (`Judge.evaluate` / `Judge.complete` is pure): append the typed
|
|
411
|
+
response to `info["judge"]` for debugging and fold its tokens + cost into `extra_usage`
|
|
412
|
+
(→ `usage`)."""
|
|
413
|
+
self.info.setdefault("judge", []).append(response.model_dump())
|
|
414
|
+
if response.usage is not None:
|
|
415
|
+
self.extra_usage.append(response.usage)
|
|
416
|
+
|
|
399
417
|
def record_reward(self, name: str, value: float, weight: float = 1.0) -> None:
|
|
400
418
|
"""Record a `@reward`/`@group_reward` contribution under `name` (weight
|
|
401
419
|
applied; summed into `reward`). Warns on override — a per-rollout reward and
|
|
@@ -160,27 +160,47 @@ class Usage(StrictBaseModel):
|
|
|
160
160
|
reasoning_tokens: int | None = None
|
|
161
161
|
cost: float | None = None
|
|
162
162
|
|
|
163
|
+
@classmethod
|
|
164
|
+
def from_openai(cls, usage: Any | None) -> "Usage | None":
|
|
165
|
+
"""Build from an OpenAI chat-completion `usage` object (the `.usage` on a
|
|
166
|
+
`ChatCompletion`), or `None` when the provider reported none. Splits cache-read tokens
|
|
167
|
+
out of `prompt_tokens` and carries the reasoning subset + provider-reported `cost`."""
|
|
168
|
+
if usage is None:
|
|
169
|
+
return None
|
|
170
|
+
prompt_details = getattr(usage, "prompt_tokens_details", None)
|
|
171
|
+
cached = prompt_details.cached_tokens if prompt_details else None
|
|
172
|
+
completion_details = getattr(usage, "completion_tokens_details", None)
|
|
173
|
+
reasoning = completion_details.reasoning_tokens if completion_details else None
|
|
174
|
+
return cls(
|
|
175
|
+
prompt_tokens=usage.prompt_tokens - (cached or 0),
|
|
176
|
+
completion_tokens=usage.completion_tokens,
|
|
177
|
+
cached_input_tokens=cached,
|
|
178
|
+
reasoning_tokens=reasoning,
|
|
179
|
+
cost=getattr(usage, "cost", None),
|
|
180
|
+
)
|
|
181
|
+
|
|
163
182
|
@classmethod
|
|
164
183
|
def aggregate(cls, usages: Iterable["Usage"]) -> "Usage | None":
|
|
165
184
|
"""Sum per-response usage while preserving whether cache usage was reported."""
|
|
166
185
|
values = list(usages)
|
|
167
186
|
if not values:
|
|
168
187
|
return None
|
|
188
|
+
# For the optional fields (cached / reasoning / cost), sum the responses that report them
|
|
189
|
+
# and yield None only when *no* response does — so one response omitting a field (e.g. a
|
|
190
|
+
# judge whose provider doesn't report reasoning or cost) doesn't null out the whole total.
|
|
169
191
|
cached = [
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
192
|
+
u.cached_input_tokens for u in values if u.cached_input_tokens is not None
|
|
193
|
+
]
|
|
194
|
+
reasoning = [
|
|
195
|
+
u.reasoning_tokens for u in values if u.reasoning_tokens is not None
|
|
173
196
|
]
|
|
174
|
-
|
|
175
|
-
costs = [usage.cost for usage in values]
|
|
197
|
+
costs = [u.cost for u in values if u.cost is not None]
|
|
176
198
|
return cls(
|
|
177
199
|
prompt_tokens=sum(usage.prompt_tokens for usage in values),
|
|
178
200
|
completion_tokens=sum(usage.completion_tokens for usage in values),
|
|
179
201
|
cached_input_tokens=sum(cached) if cached else None,
|
|
180
|
-
reasoning_tokens=sum(reasoning)
|
|
181
|
-
if
|
|
182
|
-
else None,
|
|
183
|
-
cost=sum(costs) if all(v is not None for v in costs) else None,
|
|
202
|
+
reasoning_tokens=sum(reasoning) if reasoning else None,
|
|
203
|
+
cost=sum(costs) if costs else None,
|
|
184
204
|
)
|
|
185
205
|
|
|
186
206
|
@property
|
|
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
|
|
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
|