verifiers 0.1.15.dev427__tar.gz → 0.1.15.dev428__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.dev427 → verifiers-0.1.15.dev428}/PKG-INFO +1 -1
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_judges.py +78 -13
- verifiers-0.1.15.dev428/verifiers/v1/judges/rubric.py +330 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/judges/rubric.txt +2 -2
- verifiers-0.1.15.dev427/verifiers/v1/judges/rubric.py +0 -165
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/.gitignore +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/LICENSE +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/README.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/pyproject.toml +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/AGENTS.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/README.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/conftest.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_browser_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_build_script.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_cli_agent_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_client_auth_errors.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_client_config.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_client_multimodal_types.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_composable_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_context_token_metrics.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_decorator_ranks.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_endpoint_registry.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_env_group.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_env_server.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_environment.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_environment_extra.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_envs.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_error_chain.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_eval_display.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_eval_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_gepa_cli.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_gepa_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_gym_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_harbor_env_mcp.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_imports.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_init_script.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_install_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_interception_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_logging.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_math_rubric.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_maybe_think_parser.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_message_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_message_utils_multimodal.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_multiturn_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_nemorl_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_openai_chat_completions_token_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_openai_responses_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_opencode_rlm_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_openenv_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_parser.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_path_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_per_turn_timing.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_pricing_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_prime_plugin.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_renderer_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_renderer_e2e.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_rlm_composable_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_rubric.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_rubric_group.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_sandbox_debug_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_sandbox_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_sandbox_mixin.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_save_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_setup_script.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_singleturn_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_stateful_tool_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_think_parser.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_tool_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_tool_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_trajectory_processing.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_tui_info_formatting.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_types.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_wordle_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_xml_parser.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/conftest.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/counter_tool_v1.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/echo_agentic_v1.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/echo_multi_v0.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/echo_tool_v1.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/echo_user_sim_v1.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/echo_v0.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/echo_v1.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/pyproject.toml +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/tool_response_image_v1.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_color_codeword_tasks.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_configs.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_e2e.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_envs.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_graph.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_legacy.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_scoring.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_trace.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/AGENTS.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/commands/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/commands/build.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/commands/eval.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/commands/gepa.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/commands/init.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/commands/install.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/commands/setup.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/plugins/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/plugins/prime.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/tui.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/anthropic_messages_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/nemorl_chat_completions_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/openai_chat_completions_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/openai_chat_completions_token_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/openai_completions_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/openai_responses_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/renderer_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/decorators.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/AGENTS.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/env_group.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/environment.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/README.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/cli_agent_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/README.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/_filter.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/composable_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/harness.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/harnesses/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/harnesses/mini_swe_agent.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/harnesses/opencode.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/harnesses/prompt.txt +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/harnesses/rlm.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/sandbox_debug_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/swe_debug_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/task.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/cp/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/cp/cp_task.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/cp/test_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/harbor/cli_gym.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/harbor/harbor.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/harbor/terminal_lego.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/math/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/math/math_task.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/README.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/openseeker/README.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/openseeker/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/openseeker/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/README.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/api_tools/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/api_tools/tool_pdf.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/eval_toolkit.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/evaluator.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/llm_client/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/llm_client/base_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/prompts/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/prompts/cache_prompts.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/cache_filesys.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/load_eval_script.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/misc.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/tool_visit.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/url_tools.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/verification_tree.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/open_ended.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/redsearcher/README.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/redsearcher/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/redsearcher/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/search_tasksets.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/README.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/extract_fix_patch.sh +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/openswe/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/openswe/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/log_parser.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/scale_swe/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/scale_swe/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/shared/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/shared/test_patch.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_bench/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_bench/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_lego/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_lego/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/log_parsers.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_smith/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_smith/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_tasksets.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/gym_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/harbor_env/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/harbor_env/env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/harbor_env/mcp.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/mcp_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/opencode_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/opencode_qa_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/opencode_rlm_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/sandbox_mixin.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/utils/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/utils/file_locks.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/utils/git_checkout_cache.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/README.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/browser_env/README.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/browser_env/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/browser_env/browser_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/browser_env/modes/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/browser_env/modes/base.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/browser_env/modes/cua_mode.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/browser_env/modes/dom_mode.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/openenv_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/reasoninggym_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/textarena_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/multiturn_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/python_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/sandbox_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/singleturn_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/stateful_tool_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/tool_env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/errors.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/gepa/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/gepa/adapter.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/gepa/config.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/gepa/display.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/gepa/gepa_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/parsers/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/parsers/maybe_think_parser.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/parsers/parser.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/parsers/think_parser.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/parsers/xml_parser.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/README.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/inference/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/inference/client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/inference/server.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/trainer/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/trainer/config.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/trainer/orchestrator.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/trainer/trainer.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/trainer/utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rubrics/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rubrics/experimental/hybrid_math_rubric.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rubrics/judge_rubric.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rubrics/math_rubric.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rubrics/rubric.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rubrics/rubric_group.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/build.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/eval.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/gepa.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/init.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/install.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/rl.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/setup.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/train.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/tui.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/vllm.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/client/env_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/client/zmq_env_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/server/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/server/env_router.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/server/env_server.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/server/env_worker.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/server/zmq_env_server.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/types.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/types.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/async_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/client_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/config_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/data_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/display_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/env_config_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/env_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/error_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/eval_display.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/eval_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/heartbeat.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/import_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/install_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/interception_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/logging_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/message_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/metric_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/path_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/pricing_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/process_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/response_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/save_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/serve_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/thread_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/threaded_sandbox_client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/tool_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/usage_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/version_utils.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/ARCHITECTURE.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/GUIDE.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/README.md +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/dashboard/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/dashboard/base.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/dashboard/eval.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/dashboard/replay.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/dashboard/validate.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/debug.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/eval/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/eval/main.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/eval/resume.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/eval/runner.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/init.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/output.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/replay.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/resolve.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/serve.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/validate.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/clients/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/clients/client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/clients/config.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/clients/eval.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/clients/train.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/configs/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/configs/debug.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/configs/eval.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/configs/init.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/configs/replay.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/configs/serve.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/configs/validate.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/decorators.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/dialects/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/dialects/anthropic.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/dialects/base.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/dialects/chat.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/dialects/responses.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/env.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/episode.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/errors.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/graph.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harness.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/codex/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/codex/harness.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/default/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/default/harness.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/default/program.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/null/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/null/harness.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/null/program.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/rlm/harness.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/interception/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/interception/pool.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/interception/server.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/judge.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/judges/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/judges/reference.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/judges/reference.txt +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/legacy.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/loaders.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/mcp/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/mcp/launch.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/mcp/server.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/mcp/toolset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/mcp/user.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/retries.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/rollout.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/runtimes/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/runtimes/base.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/runtimes/docker.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/runtimes/limiters.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/runtimes/modal.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/runtimes/prime.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/runtimes/subprocess.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/scoring.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/serve/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/serve/client.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/serve/pool.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/serve/server.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/serve/types.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/state.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/task.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/lean/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/lean/scoring.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/lean/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/trace.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/types.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/utils/__init__.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/utils/aio.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/utils/format.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/utils/install.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/utils/logging.py +0 -0
- {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/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.dev428
|
|
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
|
|
@@ -29,9 +29,9 @@ class QATask(vf.Task):
|
|
|
29
29
|
answer: str = ""
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def make_trace(reply: str = "It is Paris.") -> vf.Trace:
|
|
32
|
+
def make_trace(reply: str = "It is Paris.", answer: str = "Paris") -> vf.Trace:
|
|
33
33
|
return vf.Trace(
|
|
34
|
-
task=QATask(idx=0, prompt="Capital of France?", answer=
|
|
34
|
+
task=QATask(idx=0, prompt="Capital of France?", answer=answer),
|
|
35
35
|
nodes=[
|
|
36
36
|
MessageNode(
|
|
37
37
|
parent=None,
|
|
@@ -47,23 +47,31 @@ def make_trace(reply: str = "It is Paris.") -> vf.Trace:
|
|
|
47
47
|
|
|
48
48
|
@pytest.fixture
|
|
49
49
|
def fake_judge_model(monkeypatch):
|
|
50
|
-
"""Fake the judge's model call, recording each prompt for assertions.
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
"""Fake the judge's model call, recording each prompt for assertions. Rubric calls (a JSON
|
|
51
|
+
`verdicts` instruction or a `schema`) reply one reasoned verdict per `- name: text` criterion,
|
|
52
|
+
"yes" iff it mentions Paris; other judges reply plain "yes"/"no" by the response block."""
|
|
53
53
|
prompts: list[str] = []
|
|
54
54
|
|
|
55
55
|
async def fake_complete(
|
|
56
56
|
self, messages, *, trace=None, schema=None, parse=None, **sampling
|
|
57
57
|
):
|
|
58
58
|
prompts.append(messages)
|
|
59
|
-
|
|
59
|
+
# Rubric calls carry criteria lines + a JSON `verdicts` instruction; reply one verdict per
|
|
60
|
+
# criterion (yes iff its text mentions Paris) with a reason. Other judges get plain yes/no.
|
|
61
|
+
if schema is not None or '"verdicts"' in messages:
|
|
60
62
|
verdicts = [
|
|
61
|
-
{
|
|
63
|
+
{
|
|
64
|
+
"name": name,
|
|
65
|
+
"reason": "cites Paris" if "Paris" in text else "no Paris",
|
|
66
|
+
"verdict": "yes" if "Paris" in text else "no",
|
|
67
|
+
}
|
|
62
68
|
for name, text in re.findall(r"^- ([^:]+): (.+)$", messages, re.M)
|
|
63
69
|
]
|
|
64
70
|
response = JudgeResponse(
|
|
65
|
-
text=json.dumps(verdicts),
|
|
66
|
-
parsed=schema.model_validate({"verdicts": verdicts})
|
|
71
|
+
text=json.dumps({"verdicts": verdicts}),
|
|
72
|
+
parsed=schema.model_validate({"verdicts": verdicts})
|
|
73
|
+
if schema
|
|
74
|
+
else None,
|
|
67
75
|
)
|
|
68
76
|
else:
|
|
69
77
|
response = JudgeResponse(
|
|
@@ -501,7 +509,7 @@ def test_rubric_rejects_bad_files(tmp_path):
|
|
|
501
509
|
|
|
502
510
|
async def test_rubric_score(tmp_path, fake_judge_model):
|
|
503
511
|
# verdicts: mentions_paris=1 (w=3), is_polite=0 (w=1) -> weighted mean 0.75, from ONE
|
|
504
|
-
#
|
|
512
|
+
# judge call; each verdict lands as a `<name>/<criterion>` metric.
|
|
505
513
|
judge = rubric_judge(tmp_path)
|
|
506
514
|
trace = make_trace()
|
|
507
515
|
assert await judge.score(trace.task, trace) == 0.75
|
|
@@ -513,16 +521,73 @@ async def test_rubric_verdict_mismatch_raises(tmp_path, monkeypatch):
|
|
|
513
521
|
# A reply that doesn't verdict exactly the rubric's criteria is a judge failure: raise
|
|
514
522
|
# (-> rollout error), don't guess or silently score 0.
|
|
515
523
|
async def wrong_names(self, messages, *, trace=None, schema=None, parse=None, **s):
|
|
516
|
-
verdicts = {"verdicts": [{"name": "typo", "verdict": "yes"}]}
|
|
517
|
-
return JudgeResponse(text=
|
|
524
|
+
verdicts = {"verdicts": [{"name": "typo", "reason": "x", "verdict": "yes"}]}
|
|
525
|
+
return JudgeResponse(text=json.dumps(verdicts), parsed=None)
|
|
518
526
|
|
|
519
527
|
monkeypatch.setattr(Judge, "complete", wrong_names)
|
|
520
528
|
judge = rubric_judge(tmp_path)
|
|
521
529
|
trace = make_trace()
|
|
522
|
-
with pytest.raises(ValueError, match="expected the
|
|
530
|
+
with pytest.raises(ValueError, match="expected the batch"):
|
|
523
531
|
await judge.score(trace.task, trace)
|
|
524
532
|
|
|
525
533
|
|
|
534
|
+
CHOICES_TOML = (
|
|
535
|
+
'[[criteria]]\nname = "depth"\ntext = "How thorough?"\n'
|
|
536
|
+
'choices = ["none", "partial", "good"]\n'
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
async def test_rubric_choices_normalize(tmp_path, monkeypatch):
|
|
541
|
+
# Ordered choices (worst→best) score by rank: "partial" of ["none","partial","good"] -> 0.5.
|
|
542
|
+
async def graded(self, messages, *, trace=None, schema=None, parse=None, **s):
|
|
543
|
+
v = {"verdicts": [{"name": "depth", "reason": "r", "verdict": "partial"}]}
|
|
544
|
+
return JudgeResponse(text=json.dumps(v), parsed=None)
|
|
545
|
+
|
|
546
|
+
monkeypatch.setattr(Judge, "complete", graded)
|
|
547
|
+
judge = rubric_judge(tmp_path, body=CHOICES_TOML, name="q")
|
|
548
|
+
trace = make_trace()
|
|
549
|
+
assert await judge.score(trace.task, trace) == 0.5
|
|
550
|
+
assert trace.metrics == {"q/depth": 0.5}
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
async def test_rubric_off_menu_answer_raises(tmp_path, monkeypatch):
|
|
554
|
+
# A verdict that isn't one of the criterion's choices is a judge failure, not a 0.
|
|
555
|
+
async def off_menu(self, messages, *, trace=None, schema=None, parse=None, **s):
|
|
556
|
+
v = {"verdicts": [{"name": "depth", "reason": "r", "verdict": "maybe"}]}
|
|
557
|
+
return JudgeResponse(text=json.dumps(v), parsed=None)
|
|
558
|
+
|
|
559
|
+
monkeypatch.setattr(Judge, "complete", off_menu)
|
|
560
|
+
judge = rubric_judge(tmp_path, body=CHOICES_TOML)
|
|
561
|
+
trace = make_trace()
|
|
562
|
+
with pytest.raises(ValueError, match="expected one of"):
|
|
563
|
+
await judge.score(trace.task, trace)
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
def test_rubric_choices_validation(tmp_path):
|
|
567
|
+
with pytest.raises(ValueError, match="at least two"):
|
|
568
|
+
rubric_judge(
|
|
569
|
+
tmp_path, body='[[criteria]]\nname = "x"\ntext = "t"\nchoices = ["only"]\n'
|
|
570
|
+
).criteria
|
|
571
|
+
with pytest.raises(ValueError, match="duplicate options"):
|
|
572
|
+
rubric_judge(
|
|
573
|
+
tmp_path,
|
|
574
|
+
body='[[criteria]]\nname = "x"\ntext = "t"\nchoices = ["a", "a"]\n',
|
|
575
|
+
).criteria
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
async def test_rubric_reference_answer_optional(tmp_path, fake_judge_model):
|
|
579
|
+
# off by default: no reference block in the prompt.
|
|
580
|
+
t = make_trace()
|
|
581
|
+
await rubric_judge(tmp_path).score(t.task, t)
|
|
582
|
+
assert "Reference solution" not in fake_judge_model[-1]
|
|
583
|
+
|
|
584
|
+
# answer_field set: the task's gold answer is shown to the judge.
|
|
585
|
+
t = make_trace(answer="ZEBRA-GOLD")
|
|
586
|
+
await rubric_judge(tmp_path, answer_field="answer").score(t.task, t)
|
|
587
|
+
assert "Reference solution" in fake_judge_model[-1]
|
|
588
|
+
assert "ZEBRA-GOLD" in fake_judge_model[-1]
|
|
589
|
+
|
|
590
|
+
|
|
526
591
|
# --- Taskset.score integration -------------------------------------------------------------
|
|
527
592
|
|
|
528
593
|
|
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
"""rubric — an off-the-shelf rubric judge, plugged from config alone.
|
|
2
|
+
|
|
3
|
+
Reads a rubric — a list of criteria — from a JSON or TOML file and asks the judge model to grade
|
|
4
|
+
each by picking one of its ordered `choices` (default `["no", "yes"]`, a binary check), scored to
|
|
5
|
+
[0, 1] by rank — worst → best, so the first choice is 0.0 and the last 1.0 (all in one call by
|
|
6
|
+
default, or batched `max_criteria`-at-a-time). Grading uses plain-text JSON by default, or
|
|
7
|
+
structured output when `structured_output=true` (see `RubricJudgeConfig`). The reward is the
|
|
8
|
+
weighted mean of the per-criterion scores (`sum(w*v) / sum(w)`, so it stays in [0, 1]); each score
|
|
9
|
+
is also recorded as a `<name>/<criterion>` metric. Criterion weights come from the rubric file and
|
|
10
|
+
are overridable from config (`weights`); the aggregate weighs into `trace.reward` via the judge's
|
|
11
|
+
`weight`:
|
|
12
|
+
|
|
13
|
+
[[env.taskset.judges]]
|
|
14
|
+
id = "rubric"
|
|
15
|
+
path = "rubrics/quality.toml"
|
|
16
|
+
weight = 0.5
|
|
17
|
+
weights = { cites_sources = 2.0 } # override the file's per-criterion weight
|
|
18
|
+
|
|
19
|
+
with `rubrics/quality.toml` listing the criteria (JSON takes `{"criteria": [...]}` or a bare list):
|
|
20
|
+
|
|
21
|
+
[[criteria]]
|
|
22
|
+
name = "cites_sources"
|
|
23
|
+
text = "The response cites at least one specific source."
|
|
24
|
+
weight = 1.0
|
|
25
|
+
# choices default to ["no", "yes"]; give an ordered worst→best list for a graded criterion:
|
|
26
|
+
# choices = ["none", "partial", "thorough"] # -> 0.0, 0.5, 1.0
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
import asyncio
|
|
30
|
+
import json
|
|
31
|
+
import math
|
|
32
|
+
import re
|
|
33
|
+
import tomllib
|
|
34
|
+
from functools import cached_property
|
|
35
|
+
from pathlib import Path
|
|
36
|
+
from typing import cast
|
|
37
|
+
|
|
38
|
+
from pydantic import field_validator
|
|
39
|
+
|
|
40
|
+
from verifiers.v1.judge import (
|
|
41
|
+
Judge,
|
|
42
|
+
JudgeConfig,
|
|
43
|
+
JudgeView,
|
|
44
|
+
judge_question,
|
|
45
|
+
judge_response,
|
|
46
|
+
)
|
|
47
|
+
from verifiers.v1.task import Task
|
|
48
|
+
from verifiers.v1.trace import Trace
|
|
49
|
+
from verifiers.v1.types import ID, StrictBaseModel
|
|
50
|
+
|
|
51
|
+
# A sibling text file so it doubles as a starting point for a config `prompt_file`.
|
|
52
|
+
RUBRIC_PROMPT = (Path(__file__).resolve().parent / "rubric.txt").read_text(
|
|
53
|
+
encoding="utf-8"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
# Appended to the prompt when `structured_output` is off, so the reply is JSON we can parse. Each
|
|
57
|
+
# criterion carries a one-sentence `reason` written *before* the verdict (chain-of-thought), so the
|
|
58
|
+
# verdict follows from it and the reasoning is auditable in `trace.info["judge"]`.
|
|
59
|
+
JSON_SUFFIX = (
|
|
60
|
+
"\n\nRespond with ONLY a JSON object and nothing else, in exactly this shape:\n"
|
|
61
|
+
'{"verdicts": [{"name": "<criterion name>", "reason": "<one sentence citing specific '
|
|
62
|
+
'evidence from the response>", "verdict": "<answer>"}, ...]}\n'
|
|
63
|
+
"with one entry per criterion, using each criterion's exact name. For each, first write the "
|
|
64
|
+
"one-sentence reason grounded in the response, then set verdict to exactly one of the options "
|
|
65
|
+
"listed in parentheses after that criterion."
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def normalize_choice(choice: str, choices: list[str]) -> float:
|
|
70
|
+
"""Score a chosen option to [0, 1] by rank. `choices` are ordered worst → best, so the first
|
|
71
|
+
scores 0.0, the last 1.0, and the rest evenly spaced (`choices` always has >= 2 entries)."""
|
|
72
|
+
return choices.index(choice) / (len(choices) - 1)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def first_verdicts_object(text: str) -> dict | None:
|
|
76
|
+
"""The first balanced JSON object in `text` that carries a `verdicts` key. Scanning for the
|
|
77
|
+
key (not just the first `{`) skips prose and, crucially, an echoed format example — the one
|
|
78
|
+
in `JSON_SUFFIX` fails to parse (its trailing `...` isn't JSON) and is passed over rather
|
|
79
|
+
than mistaken for the answer. Returns `None` if no such object is found."""
|
|
80
|
+
decoder = json.JSONDecoder()
|
|
81
|
+
idx = text.find("{")
|
|
82
|
+
while idx != -1:
|
|
83
|
+
try:
|
|
84
|
+
obj, _ = decoder.raw_decode(text[idx:])
|
|
85
|
+
except json.JSONDecodeError:
|
|
86
|
+
obj = None
|
|
87
|
+
if isinstance(obj, dict) and "verdicts" in obj:
|
|
88
|
+
return obj
|
|
89
|
+
idx = text.find("{", idx + 1)
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class Criterion(StrictBaseModel):
|
|
94
|
+
"""One rubric entry the judge grades by picking one of `choices`, scored to [0, 1] by rank.
|
|
95
|
+
Defaults to a binary yes/no check (1/0)."""
|
|
96
|
+
|
|
97
|
+
name: str
|
|
98
|
+
"""Key for the criterion's metric (`<judge name>/<name>`) and its `weights` override."""
|
|
99
|
+
text: str
|
|
100
|
+
"""The check itself, phrased so the first (best) choice means satisfied."""
|
|
101
|
+
weight: float = 1.0
|
|
102
|
+
"""The criterion's share of the reward (overridable per name via `weights` in config)."""
|
|
103
|
+
choices: list[str] = ["no", "yes"]
|
|
104
|
+
"""Allowed answers, ordered **worst → best**: the first scores 0.0, the last 1.0, the rest
|
|
105
|
+
evenly spaced by rank. Default `["no", "yes"]` is a binary check. Needs >= 2, no duplicates."""
|
|
106
|
+
|
|
107
|
+
@field_validator("choices")
|
|
108
|
+
@classmethod
|
|
109
|
+
def _check_choices(cls, v: list[str]) -> list[str]:
|
|
110
|
+
if len(v) < 2:
|
|
111
|
+
raise ValueError(f"`choices` needs at least two options, got {v}")
|
|
112
|
+
if len(set(v)) != len(v):
|
|
113
|
+
raise ValueError(f"`choices` has duplicate options: {v}")
|
|
114
|
+
return v
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class RubricJudgeConfig(JudgeConfig):
|
|
118
|
+
id: ID = "rubric"
|
|
119
|
+
"""Pinned to the built-in, so a code-level default entry needs no explicit id."""
|
|
120
|
+
path: Path
|
|
121
|
+
"""The rubric file (`.toml` or `.json`) listing the criteria — see the module docstring
|
|
122
|
+
for the shape. A relative path resolves against the eval's working directory."""
|
|
123
|
+
weights: dict[str, float] = {}
|
|
124
|
+
"""Per-criterion weight overrides by criterion name (config wins over the file)."""
|
|
125
|
+
question_field: str = ""
|
|
126
|
+
"""Task field to fill the prompt's `{question}`; empty = the task's prompt rendered as
|
|
127
|
+
text (`Task.prompt_text`)."""
|
|
128
|
+
answer_field: str = ""
|
|
129
|
+
"""Optional task field holding a reference answer (e.g. a gold patch) to show the judge, like
|
|
130
|
+
the reference judge. Empty (default) shows none — `{reference}` renders blank. A list-valued
|
|
131
|
+
field is joined one item per line. Needs `{reference}` in the prompt (the built-in `rubric.txt`
|
|
132
|
+
has it)."""
|
|
133
|
+
view: JudgeView = "full_trace"
|
|
134
|
+
"""How much of the rollout fills `{response}` (see `JudgeView`). Defaults to the whole
|
|
135
|
+
transcript — rubric criteria typically grade the process (tool use, citations,
|
|
136
|
+
intermediate steps), not just the final answer."""
|
|
137
|
+
max_criteria: int | None = None
|
|
138
|
+
"""How many criteria to grade per judge call. `None` (default) grades all criteria in one
|
|
139
|
+
call. `1` sends one call per criterion (n independent judges); `k` batches them k-at-a-time.
|
|
140
|
+
Batches are graded concurrently and merged. Smaller batches trade more calls for focus/
|
|
141
|
+
robustness. Must be >= 1."""
|
|
142
|
+
structured_output: bool = False
|
|
143
|
+
"""Grade via JSON-schema structured output (`response_format`) when `True`; grade via plain-text
|
|
144
|
+
output parsed as JSON when `False` (the default). Plain text is far more reliable on endpoints
|
|
145
|
+
whose structured decoding is flaky (e.g. GLM-5.2 and other non-OpenAI models on some providers
|
|
146
|
+
return empty completions for structured calls, especially over long transcripts); OpenAI models
|
|
147
|
+
handle either. Transient HTTP failures are already retried by the OpenAI client."""
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
class CriterionVerdict(StrictBaseModel):
|
|
151
|
+
"""One criterion's reply, matched back to the rubric by `name`: a short `reason`
|
|
152
|
+
(chain-of-thought, always recorded for auditability in `trace.info["judge"]`) written *before*
|
|
153
|
+
the `verdict`, so the verdict follows from it. `verdict` is one of the criterion's `choices`
|
|
154
|
+
(validated per criterion in `grade_batch`, since choices vary by criterion)."""
|
|
155
|
+
|
|
156
|
+
name: str
|
|
157
|
+
reason: str
|
|
158
|
+
verdict: str
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class RubricVerdicts(StrictBaseModel):
|
|
162
|
+
"""The judge's reply: one reasoned verdict per rubric criterion."""
|
|
163
|
+
|
|
164
|
+
verdicts: list[CriterionVerdict]
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class RubricJudge(Judge[RubricVerdicts, RubricJudgeConfig]):
|
|
168
|
+
"""Scores every rubric criterion 1/0 (in one judge call, or batched `max_criteria` at a
|
|
169
|
+
time) and rewards their weighted mean."""
|
|
170
|
+
|
|
171
|
+
prompt = RUBRIC_PROMPT
|
|
172
|
+
schema = RubricVerdicts
|
|
173
|
+
|
|
174
|
+
@cached_property
|
|
175
|
+
def criteria(self) -> list[Criterion]:
|
|
176
|
+
"""The rubric, parsed once from `config.path` (TOML by suffix, else JSON) with the
|
|
177
|
+
config's `weights` overrides applied. Fails loudly on a missing/empty file, duplicate
|
|
178
|
+
criterion names, or an override naming no criterion."""
|
|
179
|
+
path = self.config.path
|
|
180
|
+
text = path.read_text(encoding="utf-8")
|
|
181
|
+
data = (
|
|
182
|
+
tomllib.loads(text) if path.suffix.lower() == ".toml" else json.loads(text)
|
|
183
|
+
)
|
|
184
|
+
items = data.get("criteria", []) if isinstance(data, dict) else data
|
|
185
|
+
criteria = [Criterion.model_validate(item) for item in items]
|
|
186
|
+
if not criteria:
|
|
187
|
+
raise ValueError(f"rubric file '{path}' lists no criteria")
|
|
188
|
+
names = [criterion.name for criterion in criteria]
|
|
189
|
+
if len(set(names)) != len(names):
|
|
190
|
+
raise ValueError(f"rubric file '{path}' has duplicate criterion names")
|
|
191
|
+
if unknown := set(self.config.weights) - set(names):
|
|
192
|
+
raise ValueError(
|
|
193
|
+
f"`weights` overrides name no criterion in '{path}': {sorted(unknown)}"
|
|
194
|
+
)
|
|
195
|
+
criteria = [
|
|
196
|
+
criterion.model_copy(
|
|
197
|
+
update={
|
|
198
|
+
"weight": self.config.weights.get(criterion.name, criterion.weight)
|
|
199
|
+
}
|
|
200
|
+
)
|
|
201
|
+
for criterion in criteria
|
|
202
|
+
]
|
|
203
|
+
if bad := [c.name for c in criteria if not 0 <= c.weight < math.inf]:
|
|
204
|
+
# A negative weight would invert a criterion (pushing the reward out of [0, 1]);
|
|
205
|
+
# NaN/inf (which json.loads accepts) would corrupt the weighted mean.
|
|
206
|
+
raise ValueError(
|
|
207
|
+
f"rubric '{path}' has negative or non-finite criterion weights: {bad}"
|
|
208
|
+
)
|
|
209
|
+
if sum(criterion.weight for criterion in criteria) <= 0:
|
|
210
|
+
raise ValueError(f"rubric '{path}' has no positive criterion weight")
|
|
211
|
+
return criteria
|
|
212
|
+
|
|
213
|
+
async def grade_batch(
|
|
214
|
+
self, task: Task, trace: Trace, batch: list[Criterion]
|
|
215
|
+
) -> dict[str, float]:
|
|
216
|
+
"""Grade one batch of criteria in a single judge call — structured output, or plain-text
|
|
217
|
+
JSON when `structured_output` is off (which avoids flaky structured decoding). Returns
|
|
218
|
+
`{name: score}`, each the chosen option normalized to [0, 1] by rank (best → worst),
|
|
219
|
+
matched back to the batch by name. `score` fans this out per batch."""
|
|
220
|
+
|
|
221
|
+
def render(
|
|
222
|
+
c: Criterion,
|
|
223
|
+
) -> str: # every criterion states its own allowed answers inline
|
|
224
|
+
return f"- {c.name}: {c.text} (answer one of, worst to best: {', '.join(c.choices)})"
|
|
225
|
+
|
|
226
|
+
reference = "" # optional gold answer shown to the judge; blank unless `answer_field` set
|
|
227
|
+
if self.config.answer_field:
|
|
228
|
+
answer = getattr(task, self.config.answer_field, None)
|
|
229
|
+
if answer is None:
|
|
230
|
+
raise ValueError(
|
|
231
|
+
f"rubric judge found no {self.config.answer_field!r} field on the task; "
|
|
232
|
+
"point `answer_field` at the task's reference-answer field or leave it empty"
|
|
233
|
+
)
|
|
234
|
+
if isinstance(answer, (list, tuple)):
|
|
235
|
+
answer = "\n".join(str(item) for item in answer)
|
|
236
|
+
# A clearly-announced section (leading blank separates it from the Task block; the
|
|
237
|
+
# template's newline before Response closes it). Absent when `answer_field` is unset.
|
|
238
|
+
# Fence longer than any backtick run in the answer, so a patch/markdown containing ```
|
|
239
|
+
# can't close it early and spill into the prompt as instructions.
|
|
240
|
+
fence = "`" * (
|
|
241
|
+
max((len(m) for m in re.findall(r"`+", answer)), default=2) + 1
|
|
242
|
+
)
|
|
243
|
+
reference = (
|
|
244
|
+
"\nReference solution (a correct implementation of this task, for comparison):\n"
|
|
245
|
+
f"{fence}\n{answer}\n{fence}\n"
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
fields = dict(
|
|
249
|
+
question=judge_question(task, self.config.question_field),
|
|
250
|
+
response=judge_response(trace, self.config.view),
|
|
251
|
+
criteria="\n".join(render(c) for c in batch),
|
|
252
|
+
reference=reference,
|
|
253
|
+
)
|
|
254
|
+
if self.config.structured_output:
|
|
255
|
+
result = await self.evaluate(trace=trace, **fields)
|
|
256
|
+
verdicts = cast(RubricVerdicts, result.parsed).verdicts
|
|
257
|
+
else:
|
|
258
|
+
messages = cast(str, self.build_messages(**fields)) + JSON_SUFFIX
|
|
259
|
+
result = await self.complete(
|
|
260
|
+
messages, trace=trace
|
|
261
|
+
) # no schema -> plain text
|
|
262
|
+
obj = first_verdicts_object(result.text)
|
|
263
|
+
if obj is None:
|
|
264
|
+
raise ValueError(
|
|
265
|
+
f"judge returned no verdicts JSON object: {result.text!r}"
|
|
266
|
+
)
|
|
267
|
+
verdicts = RubricVerdicts.model_validate(obj).verdicts
|
|
268
|
+
# Exactly one verdict per criterion in the batch, matched by name — anything else is a
|
|
269
|
+
# judge failure and must error the rollout, not score the model (see `judge_verdict`).
|
|
270
|
+
by_criterion = {c.name: c for c in batch}
|
|
271
|
+
if sorted(v.name for v in verdicts) != sorted(by_criterion):
|
|
272
|
+
raise ValueError(
|
|
273
|
+
f"judge verdicts name {sorted(v.name for v in verdicts)}, expected the "
|
|
274
|
+
f"batch's {sorted(by_criterion)}"
|
|
275
|
+
)
|
|
276
|
+
scores: dict[str, float] = {}
|
|
277
|
+
for v in verdicts:
|
|
278
|
+
choices = by_criterion[v.name].choices
|
|
279
|
+
if (
|
|
280
|
+
v.verdict not in choices
|
|
281
|
+
): # an off-menu answer is a judge failure, not a 0
|
|
282
|
+
raise ValueError(
|
|
283
|
+
f"judge answered {v.verdict!r} for '{v.name}', expected one of {choices}"
|
|
284
|
+
)
|
|
285
|
+
scores[v.name] = normalize_choice(v.verdict, choices)
|
|
286
|
+
return scores
|
|
287
|
+
|
|
288
|
+
async def score(self, task: Task, trace: Trace) -> float:
|
|
289
|
+
criteria = self.criteria
|
|
290
|
+
# Split into batches of `max_criteria` (None = one batch of all), then grade the batches
|
|
291
|
+
# concurrently (one judge call each) and merge.
|
|
292
|
+
k = self.config.max_criteria
|
|
293
|
+
if k is not None and k < 1:
|
|
294
|
+
raise ValueError(f"`max_criteria` must be >= 1 or None, got {k}")
|
|
295
|
+
batches = (
|
|
296
|
+
[criteria]
|
|
297
|
+
if k is None
|
|
298
|
+
else [criteria[i : i + k] for i in range(0, len(criteria), k)]
|
|
299
|
+
)
|
|
300
|
+
# Fan out one call per batch; if any fails, cancel the siblings so a judge failure
|
|
301
|
+
# doesn't keep billing the remaining batches.
|
|
302
|
+
tasks = [
|
|
303
|
+
asyncio.ensure_future(self.grade_batch(task, trace, batch))
|
|
304
|
+
for batch in batches
|
|
305
|
+
]
|
|
306
|
+
try:
|
|
307
|
+
results = await asyncio.gather(*tasks)
|
|
308
|
+
except BaseException:
|
|
309
|
+
for t in tasks:
|
|
310
|
+
t.cancel()
|
|
311
|
+
await asyncio.gather(*tasks, return_exceptions=True)
|
|
312
|
+
raise
|
|
313
|
+
by_name: dict[str, float] = {}
|
|
314
|
+
for batch_verdicts in results:
|
|
315
|
+
by_name.update(batch_verdicts)
|
|
316
|
+
for criterion in criteria:
|
|
317
|
+
trace.record_metric(
|
|
318
|
+
f"{self.reward_name}/{criterion.name}", by_name[criterion.name]
|
|
319
|
+
)
|
|
320
|
+
total = sum(criterion.weight for criterion in criteria)
|
|
321
|
+
return sum(c.weight * by_name[c.name] for c in criteria) / total
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
__all__ = [
|
|
325
|
+
"Criterion",
|
|
326
|
+
"CriterionVerdict",
|
|
327
|
+
"RubricJudge",
|
|
328
|
+
"RubricJudgeConfig",
|
|
329
|
+
"RubricVerdicts",
|
|
330
|
+
]
|
|
@@ -4,7 +4,7 @@ Task:
|
|
|
4
4
|
```
|
|
5
5
|
{question}
|
|
6
6
|
```
|
|
7
|
-
|
|
7
|
+
{reference}
|
|
8
8
|
Response:
|
|
9
9
|
```
|
|
10
10
|
{response}
|
|
@@ -13,4 +13,4 @@ Response:
|
|
|
13
13
|
Criteria:
|
|
14
14
|
{criteria}
|
|
15
15
|
|
|
16
|
-
For each criterion,
|
|
16
|
+
For each criterion, answer under its exact name with exactly one of the options given in parentheses after it.
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
"""rubric — an off-the-shelf rubric judge, plugged from config alone.
|
|
2
|
-
|
|
3
|
-
Reads a rubric — a list of yes/no criteria — from a JSON or TOML file and asks the judge model
|
|
4
|
-
to grade all criteria in one structured-output call, scoring each 1/0. The reward is the weighted
|
|
5
|
-
mean of the verdicts (`sum(w*v) / sum(w)`, so it stays in [0, 1]); each verdict is also recorded
|
|
6
|
-
as a `<name>/<criterion>` metric. Criterion weights come from the rubric file and are overridable
|
|
7
|
-
from config (`weights`); the aggregate weighs into `trace.reward` via the judge's `weight`:
|
|
8
|
-
|
|
9
|
-
[[env.taskset.judges]]
|
|
10
|
-
id = "rubric"
|
|
11
|
-
path = "rubrics/quality.toml"
|
|
12
|
-
weight = 0.5
|
|
13
|
-
weights = { cites_sources = 2.0 } # override the file's per-criterion weight
|
|
14
|
-
|
|
15
|
-
with `rubrics/quality.toml` listing the criteria (JSON takes `{"criteria": [...]}` or a bare list):
|
|
16
|
-
|
|
17
|
-
[[criteria]]
|
|
18
|
-
name = "cites_sources"
|
|
19
|
-
text = "The response cites at least one specific source."
|
|
20
|
-
weight = 1.0
|
|
21
|
-
"""
|
|
22
|
-
|
|
23
|
-
import json
|
|
24
|
-
import math
|
|
25
|
-
import tomllib
|
|
26
|
-
from functools import cached_property
|
|
27
|
-
from pathlib import Path
|
|
28
|
-
from typing import Literal, cast
|
|
29
|
-
|
|
30
|
-
from verifiers.v1.judge import (
|
|
31
|
-
Judge,
|
|
32
|
-
JudgeConfig,
|
|
33
|
-
JudgeView,
|
|
34
|
-
judge_question,
|
|
35
|
-
judge_response,
|
|
36
|
-
)
|
|
37
|
-
from verifiers.v1.task import Task
|
|
38
|
-
from verifiers.v1.trace import Trace
|
|
39
|
-
from verifiers.v1.types import ID, StrictBaseModel
|
|
40
|
-
|
|
41
|
-
# A sibling text file so it doubles as a starting point for a config `prompt_file`.
|
|
42
|
-
RUBRIC_PROMPT = (Path(__file__).resolve().parent / "rubric.txt").read_text(
|
|
43
|
-
encoding="utf-8"
|
|
44
|
-
)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class Criterion(StrictBaseModel):
|
|
48
|
-
"""One rubric entry: a yes/no check the judge scores 1/0."""
|
|
49
|
-
|
|
50
|
-
name: str
|
|
51
|
-
"""Key for the criterion's metric (`<judge name>/<name>`) and its `weights` override."""
|
|
52
|
-
text: str
|
|
53
|
-
"""The check itself, phrased so "yes" means satisfied."""
|
|
54
|
-
weight: float = 1.0
|
|
55
|
-
"""The criterion's share of the reward (overridable per name via `weights` in config)."""
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class RubricJudgeConfig(JudgeConfig):
|
|
59
|
-
id: ID = "rubric"
|
|
60
|
-
"""Pinned to the built-in, so a code-level default entry needs no explicit id."""
|
|
61
|
-
path: Path
|
|
62
|
-
"""The rubric file (`.toml` or `.json`) listing the criteria — see the module docstring
|
|
63
|
-
for the shape. A relative path resolves against the eval's working directory."""
|
|
64
|
-
weights: dict[str, float] = {}
|
|
65
|
-
"""Per-criterion weight overrides by criterion name (config wins over the file)."""
|
|
66
|
-
question_field: str = ""
|
|
67
|
-
"""Task field to fill the prompt's `{question}`; empty = the task's prompt rendered as
|
|
68
|
-
text (`Task.prompt_text`)."""
|
|
69
|
-
view: JudgeView = "full_trace"
|
|
70
|
-
"""How much of the rollout fills `{response}` (see `JudgeView`). Defaults to the whole
|
|
71
|
-
transcript — rubric criteria typically grade the process (tool use, citations,
|
|
72
|
-
intermediate steps), not just the final answer."""
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
class CriterionVerdict(StrictBaseModel):
|
|
76
|
-
"""One criterion's verdict in the judge's reply, matched back to the rubric by `name`."""
|
|
77
|
-
|
|
78
|
-
name: str
|
|
79
|
-
verdict: Literal["yes", "no"]
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
class RubricVerdicts(StrictBaseModel):
|
|
83
|
-
"""The judge's structured reply: one verdict per rubric criterion."""
|
|
84
|
-
|
|
85
|
-
verdicts: list[CriterionVerdict]
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
class RubricJudge(Judge[RubricVerdicts, RubricJudgeConfig]):
|
|
89
|
-
"""Scores every rubric criterion 1/0 in one structured judge call; rewards their
|
|
90
|
-
weighted mean."""
|
|
91
|
-
|
|
92
|
-
prompt = RUBRIC_PROMPT
|
|
93
|
-
schema = RubricVerdicts
|
|
94
|
-
|
|
95
|
-
@cached_property
|
|
96
|
-
def criteria(self) -> list[Criterion]:
|
|
97
|
-
"""The rubric, parsed once from `config.path` (TOML by suffix, else JSON) with the
|
|
98
|
-
config's `weights` overrides applied. Fails loudly on a missing/empty file, duplicate
|
|
99
|
-
criterion names, or an override naming no criterion."""
|
|
100
|
-
path = self.config.path
|
|
101
|
-
text = path.read_text(encoding="utf-8")
|
|
102
|
-
data = (
|
|
103
|
-
tomllib.loads(text) if path.suffix.lower() == ".toml" else json.loads(text)
|
|
104
|
-
)
|
|
105
|
-
items = data.get("criteria", []) if isinstance(data, dict) else data
|
|
106
|
-
criteria = [Criterion.model_validate(item) for item in items]
|
|
107
|
-
if not criteria:
|
|
108
|
-
raise ValueError(f"rubric file '{path}' lists no criteria")
|
|
109
|
-
names = [criterion.name for criterion in criteria]
|
|
110
|
-
if len(set(names)) != len(names):
|
|
111
|
-
raise ValueError(f"rubric file '{path}' has duplicate criterion names")
|
|
112
|
-
if unknown := set(self.config.weights) - set(names):
|
|
113
|
-
raise ValueError(
|
|
114
|
-
f"`weights` overrides name no criterion in '{path}': {sorted(unknown)}"
|
|
115
|
-
)
|
|
116
|
-
criteria = [
|
|
117
|
-
criterion.model_copy(
|
|
118
|
-
update={
|
|
119
|
-
"weight": self.config.weights.get(criterion.name, criterion.weight)
|
|
120
|
-
}
|
|
121
|
-
)
|
|
122
|
-
for criterion in criteria
|
|
123
|
-
]
|
|
124
|
-
if bad := [c.name for c in criteria if not 0 <= c.weight < math.inf]:
|
|
125
|
-
# A negative weight would invert a criterion (pushing the reward out of [0, 1]);
|
|
126
|
-
# NaN/inf (which json.loads accepts) would corrupt the weighted mean.
|
|
127
|
-
raise ValueError(
|
|
128
|
-
f"rubric '{path}' has negative or non-finite criterion weights: {bad}"
|
|
129
|
-
)
|
|
130
|
-
if sum(criterion.weight for criterion in criteria) <= 0:
|
|
131
|
-
raise ValueError(f"rubric '{path}' has no positive criterion weight")
|
|
132
|
-
return criteria
|
|
133
|
-
|
|
134
|
-
async def score(self, task: Task, trace: Trace) -> float:
|
|
135
|
-
criteria = self.criteria
|
|
136
|
-
result = await self.evaluate(
|
|
137
|
-
trace=trace,
|
|
138
|
-
question=judge_question(task, self.config.question_field),
|
|
139
|
-
response=judge_response(trace, self.config.view),
|
|
140
|
-
criteria="\n".join(f"- {c.name}: {c.text}" for c in criteria),
|
|
141
|
-
)
|
|
142
|
-
verdicts = cast(RubricVerdicts, result.parsed).verdicts
|
|
143
|
-
# Exactly one verdict per criterion, matched by name — anything else is a judge
|
|
144
|
-
# failure and must error the rollout, not score the model (see `judge_verdict`).
|
|
145
|
-
if sorted(v.name for v in verdicts) != sorted(c.name for c in criteria):
|
|
146
|
-
raise ValueError(
|
|
147
|
-
f"judge verdicts name {sorted(v.name for v in verdicts)}, expected the "
|
|
148
|
-
f"rubric's {sorted(c.name for c in criteria)}"
|
|
149
|
-
)
|
|
150
|
-
by_name = {v.name: float(v.verdict == "yes") for v in verdicts}
|
|
151
|
-
for criterion in criteria:
|
|
152
|
-
trace.record_metric(
|
|
153
|
-
f"{self.reward_name}/{criterion.name}", by_name[criterion.name]
|
|
154
|
-
)
|
|
155
|
-
total = sum(criterion.weight for criterion in criteria)
|
|
156
|
-
return sum(c.weight * by_name[c.name] for c in criteria) / total
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
__all__ = [
|
|
160
|
-
"Criterion",
|
|
161
|
-
"CriterionVerdict",
|
|
162
|
-
"RubricJudge",
|
|
163
|
-
"RubricJudgeConfig",
|
|
164
|
-
"RubricVerdicts",
|
|
165
|
-
]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|