eval-framework 0.13.2__tar.gz → 0.13.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. {eval_framework-0.13.2 → eval_framework-0.13.3}/PKG-INFO +3 -3
  2. {eval_framework-0.13.2 → eval_framework-0.13.3}/pyproject.toml +5 -5
  3. {eval_framework-0.13.2 → eval_framework-0.13.3}/pyproject.toml.orig +5 -5
  4. eval_framework-0.13.3/src/eval_framework/answer.py +143 -0
  5. eval_framework-0.13.3/src/eval_framework/benchmarks/cot.py +101 -0
  6. eval_framework-0.13.3/src/eval_framework/benchmarks/gpqa.py +137 -0
  7. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/gpqa_ellamind.py +65 -9
  8. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/mmlu.py +18 -68
  9. eval_framework-0.13.3/src/eval_framework/benchmarks/mmlu_pro.py +164 -0
  10. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/social_iqa.py +3 -79
  11. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/winogrande.py +3 -26
  12. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/winogrande_ellamind.py +2 -0
  13. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/composed.py +20 -32
  14. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/eval_kind.py +4 -54
  15. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/llm/base.py +6 -0
  16. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/dataset_loading.py +8 -7
  17. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/task_names.py +6 -8
  18. eval_framework-0.13.2/src/eval_framework/tasks/benchmarks/gpqa.py +0 -252
  19. eval_framework-0.13.2/src/eval_framework/tasks/benchmarks/mmlu_pro.py +0 -197
  20. {eval_framework-0.13.2 → eval_framework-0.13.3}/LICENSE +0 -0
  21. {eval_framework-0.13.2 → eval_framework-0.13.3}/README.md +0 -0
  22. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/__init__.py +0 -0
  23. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/base_config.py +0 -0
  24. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/__init__.py +0 -0
  25. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/arc.py +0 -0
  26. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/arc_de.py +0 -0
  27. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/arc_ellamind.py +0 -0
  28. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/copa.py +0 -0
  29. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/csqa.py +0 -0
  30. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/csqa_ellamind.py +0 -0
  31. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/goldenswag.py +0 -0
  32. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/hellaswag.py +0 -0
  33. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/hellaswag_ellamind.py +0 -0
  34. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/hle_ellamind.py +0 -0
  35. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/medqa.py +0 -0
  36. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/piqa.py +0 -0
  37. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/piqa_ellamind.py +0 -0
  38. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/sciq.py +0 -0
  39. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/simpleqa_ellamind.py +0 -0
  40. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/benchmarks/siqa_ellamind.py +0 -0
  41. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/choices.py +0 -0
  42. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/context/__init__.py +0 -0
  43. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/context/determined.py +0 -0
  44. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/context/eval.py +0 -0
  45. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/context/local.py +0 -0
  46. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/contract.py +0 -0
  47. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/evaluation_generator.py +0 -0
  48. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/exceptions.py +0 -0
  49. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/external/drop_process_results.py +0 -0
  50. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/external/ifeval_impl/README.md +0 -0
  51. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/external/ifeval_impl/instructions.py +0 -0
  52. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/external/ifeval_impl/instructions_registry.py +0 -0
  53. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/external/ifeval_impl/instructions_util.py +0 -0
  54. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/external/ifeval_impl/utils.py +0 -0
  55. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/fewshot.py +0 -0
  56. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/llm/__init__.py +0 -0
  57. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/llm/aleph_alpha.py +0 -0
  58. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/llm/huggingface.py +0 -0
  59. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/llm/models.py +0 -0
  60. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/llm/openai.py +0 -0
  61. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/logger.py +0 -0
  62. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/main.py +0 -0
  63. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/__init__.py +0 -0
  64. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/aggregators/__init__.py +0 -0
  65. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/aggregators/aggregators.py +0 -0
  66. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/base.py +0 -0
  67. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/__init__.py +0 -0
  68. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/accuracy_completion.py +0 -0
  69. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/code_assertion.py +0 -0
  70. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/code_execution_pass_at_one.py +0 -0
  71. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/concordance_index.py +0 -0
  72. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/csv_format.py +0 -0
  73. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/drop_completion.py +0 -0
  74. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/exponential_similarity.py +0 -0
  75. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/f1.py +0 -0
  76. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/format_checker.py +0 -0
  77. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/grid_difference.py +0 -0
  78. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/ifeval.py +0 -0
  79. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/json_format.py +0 -0
  80. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/language_checker.py +0 -0
  81. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/length_control.py +0 -0
  82. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/math_minerva_completion.py +0 -0
  83. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/math_reasoning_completion.py +0 -0
  84. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/minerva_math_utils.py +0 -0
  85. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/multipl_e_assertion.py +0 -0
  86. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/placeholder_checker.py +0 -0
  87. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/repetition.py +0 -0
  88. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/rouge_1.py +0 -0
  89. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/rouge_2.py +0 -0
  90. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/rouge_geometric_mean.py +0 -0
  91. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/rouge_l.py +0 -0
  92. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/completion/text_counter.py +0 -0
  93. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/efficiency/__init__.py +0 -0
  94. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/efficiency/bytes_per_sequence_position.py +0 -0
  95. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/efficiency/finish_reason.py +0 -0
  96. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/efficiency/token_counters.py +0 -0
  97. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/__init__.py +0 -0
  98. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/base.py +0 -0
  99. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/graders/chatbot_style_grader.py +0 -0
  100. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/graders/coherence_grader.py +0 -0
  101. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/graders/comparison_grader.py +0 -0
  102. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/graders/conciseness_grader.py +0 -0
  103. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/graders/contains_names_grader.py +0 -0
  104. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/graders/format_correctness_grader.py +0 -0
  105. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/graders/instruction_grader.py +0 -0
  106. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/graders/language.py +0 -0
  107. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/graders/long_context_grader.py +0 -0
  108. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/graders/models.py +0 -0
  109. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/graders/refusal_grader.py +0 -0
  110. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/graders/sql_quality_grader.py +0 -0
  111. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/graders/summary_world_knowledge_grader.py +0 -0
  112. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/llm_judge_chatbot_style.py +0 -0
  113. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/llm_judge_coherence.py +0 -0
  114. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/llm_judge_completion_accuracy.py +0 -0
  115. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/llm_judge_conciseness.py +0 -0
  116. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/llm_judge_contains_names.py +0 -0
  117. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/llm_judge_format_correctness.py +0 -0
  118. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/llm_judge_instruction.py +0 -0
  119. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/llm_judge_mtbench_pair.py +0 -0
  120. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/llm_judge_mtbench_single.py +0 -0
  121. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/llm_judge_refusal.py +0 -0
  122. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/llm_judge_sql.py +0 -0
  123. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/llm_judge_world_knowledge.py +0 -0
  124. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/llm/utils.py +0 -0
  125. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/loglikelihood/__init__.py +0 -0
  126. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/loglikelihood/accuracy_loglikelihood.py +0 -0
  127. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/loglikelihood/base.py +0 -0
  128. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/loglikelihood/bits_per_byte.py +0 -0
  129. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/loglikelihood/confidence_weighted_accuracy.py +0 -0
  130. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/loglikelihood/dcs.py +0 -0
  131. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/loglikelihood/probability_mass.py +0 -0
  132. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/metrics/loglikelihood/ternary.py +0 -0
  133. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/py.typed +0 -0
  134. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/response_generator.py +0 -0
  135. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/result_processors/__init__.py +0 -0
  136. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/result_processors/base.py +0 -0
  137. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/result_processors/hf_uploader.py +0 -0
  138. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/result_processors/result_processor.py +0 -0
  139. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/result_processors/wandb_uploader.py +0 -0
  140. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/run.py +0 -0
  141. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/run_direct.py +0 -0
  142. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/shared/errors.py +0 -0
  143. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/shared/types.py +0 -0
  144. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/subjects.py +0 -0
  145. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/suite.py +0 -0
  146. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/Dockerfile_codebench +0 -0
  147. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/__init__.py +0 -0
  148. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/base.py +0 -0
  149. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/__init__.py +0 -0
  150. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/bigcodebench.py +0 -0
  151. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/drop.py +0 -0
  152. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/global_mmlu.py +0 -0
  153. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/gsm8k.py +0 -0
  154. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/gsm8k_ellamind.py +0 -0
  155. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/hendrycks_math_ellamind.py +0 -0
  156. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/humaneval.py +0 -0
  157. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/humaneval_ellamind.py +0 -0
  158. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/humaneval_plus.py +0 -0
  159. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/ifeval.py +0 -0
  160. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/math_reasoning.py +0 -0
  161. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/mbpp.py +0 -0
  162. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/mbpp_ellamind.py +0 -0
  163. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/multipl_e.py +0 -0
  164. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/naturalqs_open.py +0 -0
  165. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/benchmarks/squad.py +0 -0
  166. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/dataset_revisions.py +0 -0
  167. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/eval_config.py +0 -0
  168. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/frozen-hf-dataset-revisions.json +0 -0
  169. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/hf-dataset-revisions.json +0 -0
  170. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/lazy.py +0 -0
  171. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/markdown_doc.py +0 -0
  172. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/registry.py +0 -0
  173. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/task_loader.py +0 -0
  174. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/task_style.py +0 -0
  175. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/tasks/utils.py +0 -0
  176. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/utils/constants.py +0 -0
  177. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/utils/file_ops.py +0 -0
  178. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/utils/helpers.py +0 -0
  179. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/utils/logging.py +0 -0
  180. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/utils/packaging.py +0 -0
  181. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/eval_framework/utils/tqdm_handler.py +0 -0
  182. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/template_formatting/README.md +0 -0
  183. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/template_formatting/__init__.py +0 -0
  184. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/template_formatting/formatter.py +0 -0
  185. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/template_formatting/mistral_formatter.py +0 -0
  186. {eval_framework-0.13.2 → eval_framework-0.13.3}/src/template_formatting/py.typed +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: eval-framework
3
- Version: 0.13.2
3
+ Version: 0.13.3
4
4
  Summary: Evaluation Framework
5
5
  Author: Aleph Alpha Research
6
6
  License: Apache License
@@ -232,7 +232,7 @@ Requires-Dist: jsonlines>=4,<5
232
232
  Requires-Dist: lxml>=6.1.3,<7
233
233
  Requires-Dist: python-iso639>=2026.7.23
234
234
  Requires-Dist: wandb>=0.30.0,<1
235
- Requires-Dist: boto3>=1.43.94,<2
235
+ Requires-Dist: boto3>=1.43.95,<2
236
236
  Requires-Dist: numpy>=2.5.3
237
237
  Requires-Dist: antlr4-python3-runtime==4.11.0
238
238
  Requires-Dist: scipy>=1.18.1,<2
@@ -241,7 +241,7 @@ Requires-Dist: eval-framework[determined,api,openai,transformers,accelerate,opti
241
241
  Requires-Dist: aleph-alpha-client>=11.5.1 ; extra == 'api'
242
242
  Requires-Dist: determined>=0.38.1,<0.39 ; extra == 'determined'
243
243
  Requires-Dist: tensorboard==2.21.0 ; extra == 'determined'
244
- Requires-Dist: openai>=3.14.0,<4 ; extra == 'openai'
244
+ Requires-Dist: openai>=3.14.1,<4 ; extra == 'openai'
245
245
  Requires-Dist: tiktoken>=0.14.0,<1 ; extra == 'openai'
246
246
  Requires-Dist: transformers>=4.45.2,<5 ; extra == 'openai'
247
247
  Requires-Dist: transformers>=4.45.2,<5 ; extra == 'optional'
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "eval-framework"
3
- version = "0.13.2"
3
+ version = "0.13.3"
4
4
  description = "Evaluation Framework"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12,<3.15"
@@ -35,7 +35,7 @@ dependencies = [
35
35
  "lxml>=6.1.3,<7",
36
36
  "python-iso639>=2026.7.23",
37
37
  "wandb>=0.30.0,<1",
38
- "boto3>=1.43.94,<2",
38
+ "boto3>=1.43.95,<2",
39
39
  "numpy>=2.5.3",
40
40
  "antlr4-python3-runtime==4.11.0",
41
41
  "scipy>=1.18.1,<2",
@@ -54,7 +54,7 @@ determined = [
54
54
  ]
55
55
  api = ["aleph-alpha-client>=11.5.1"]
56
56
  openai = [
57
- "openai>=3.14.0,<4",
57
+ "openai>=3.14.1,<4",
58
58
  "tiktoken>=0.14.0,<1",
59
59
  "transformers>=4.45.2,<5",
60
60
  ]
@@ -86,7 +86,7 @@ dev = [
86
86
  "types-pyyaml>=6.0.12.20260906,<7",
87
87
  "types-python-dateutil>=2.9.0.20260807,<3",
88
88
  "types-requests>=2.33.0.20260906,<3",
89
- "plotly>=7.0.0,<8",
89
+ "plotly>=7.1.0,<8",
90
90
  "ruff>=0.16.7",
91
91
  "pip-licenses>=5.5.5",
92
92
  ]
@@ -96,7 +96,7 @@ flash-attn = [
96
96
  ]
97
97
 
98
98
  [build-system]
99
- requires = ["uv_build>=0.12.13,<0.12.14"]
99
+ requires = ["uv_build>=0.12.15,<0.12.16"]
100
100
  build-backend = "uv_build"
101
101
 
102
102
  [tool.uv]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "eval-framework"
3
- version = "0.13.2"
3
+ version = "0.13.3"
4
4
  description = "Evaluation Framework"
5
5
  readme = "README.md"
6
6
  license = { file = "LICENSE" }
@@ -39,7 +39,7 @@ dependencies = [
39
39
  "lxml>=6.1.3,<7",
40
40
  "python-iso639>=2026.7.23",
41
41
  "wandb>=0.30.0,<1",
42
- "boto3>=1.43.94,<2",
42
+ "boto3>=1.43.95,<2",
43
43
  "numpy>=2.5.3",
44
44
  # is a dependency of sympy, but not explicitly listed in the requirements.txt
45
45
  # https://github.com/sympy/sympy/blob/0204fa34e8f6f6f8ccb4de01209be9a2345c9d6e/doc/src/contributing/dependencies.md?plain=1#L125
@@ -55,7 +55,7 @@ determined = [
55
55
  ]
56
56
  api = ["aleph-alpha-client>=11.5.1"]
57
57
  openai = [
58
- "openai>=3.14.0,<4",
58
+ "openai>=3.14.1,<4",
59
59
  "tiktoken>=0.14.0,<1",
60
60
  "transformers>=4.45.2,<5",
61
61
  ]
@@ -92,7 +92,7 @@ dev = [
92
92
  "types-pyyaml>=6.0.12.20260906,<7",
93
93
  "types-python-dateutil>=2.9.0.20260807,<3",
94
94
  "types-requests>=2.33.0.20260906,<3",
95
- "plotly>=7.0.0,<8",
95
+ "plotly>=7.1.0,<8",
96
96
  "ruff>=0.16.7",
97
97
  "pip-licenses>=5.5.5",
98
98
  ]
@@ -102,7 +102,7 @@ flash-attn = [
102
102
  ]
103
103
 
104
104
  [build-system]
105
- requires = ["uv_build>=0.12.13,<0.12.14"]
105
+ requires = ["uv_build>=0.12.15,<0.12.16"]
106
106
  build-backend = "uv_build"
107
107
 
108
108
  [tool.uv.build-backend]
@@ -0,0 +1,143 @@
1
+ """How a benchmark obtains the model's scored answer.
2
+
3
+ An ``AnswerPolicy`` owns the "answer side" of a composed benchmark — the mode the model answers in
4
+ (loglikelihood over candidates vs. free-form completion), the bounds on any generation (stop sequences,
5
+ token limit), and how the raw generation is distilled into the answer that metrics score. It is injected
6
+ into ``compose`` next to the eval kind, so the kind stays purely about the prompt and candidates.
7
+ """
8
+
9
+ import re
10
+ from abc import ABC, abstractmethod
11
+ from typing import TYPE_CHECKING, final, override
12
+
13
+ from eval_framework.contract import ResponseType
14
+ from eval_framework.metrics.efficiency.bytes_per_sequence_position import (
15
+ BytesCompletion,
16
+ BytesLoglikelihood,
17
+ SequencePositionsCompletion,
18
+ SequencePositionsLoglikelihood,
19
+ )
20
+ from eval_framework.metrics.efficiency.finish_reason import FinishReason
21
+ from eval_framework.metrics.efficiency.token_counters import TokenCounts
22
+ from eval_framework.shared.types import BaseMetricContext
23
+ from template_formatting.formatter import Message
24
+
25
+ if TYPE_CHECKING:
26
+ from eval_framework.metrics.base import BaseMetric
27
+
28
+
29
+ class AnswerPolicy(ABC):
30
+ """The answer side of a kind: the response type, the generation bounds, and answer extraction."""
31
+
32
+ @abstractmethod
33
+ def response_type(self) -> ResponseType:
34
+ """Whether the model is scored by loglikelihood over candidates or by free-form completion."""
35
+
36
+ @abstractmethod
37
+ def metrics(self) -> list[type["BaseMetric"]]:
38
+ """The bookkeeping metrics this answer mode always reports (efficiency / token counts), added to the
39
+ kind's scoring metrics."""
40
+
41
+ @abstractmethod
42
+ def stop_sequences(self) -> list[str]:
43
+ """Stop sequences for completion generation (empty when nothing is generated)."""
44
+
45
+ @abstractmethod
46
+ def max_tokens(self) -> int | None:
47
+ """Token limit for completion generation, or None for no limit."""
48
+
49
+ @abstractmethod
50
+ def extract_answer(
51
+ self,
52
+ completion_text: str,
53
+ *,
54
+ context: BaseMetricContext | list[BaseMetricContext] | None,
55
+ ground_truth: str | list[str] | None,
56
+ messages: list[Message],
57
+ ) -> str:
58
+ """The answer to score, distilled from the raw generation."""
59
+
60
+
61
+ @final
62
+ class PickFromCandidates(AnswerPolicy):
63
+ """Loglikelihood scoring: the model is scored over fixed candidate completions and the answer is the
64
+ best-scoring candidate, taken verbatim — nothing is generated, so nothing is bounded or extracted."""
65
+
66
+ @override
67
+ def response_type(self) -> ResponseType:
68
+ return ResponseType.LOGLIKELIHOODS
69
+
70
+ @override
71
+ def metrics(self) -> list[type["BaseMetric"]]:
72
+ return [BytesLoglikelihood, SequencePositionsLoglikelihood]
73
+
74
+ @override
75
+ def stop_sequences(self) -> list[str]:
76
+ return []
77
+
78
+ @override
79
+ def max_tokens(self) -> int | None:
80
+ return None
81
+
82
+ @override
83
+ def extract_answer(
84
+ self,
85
+ completion_text: str,
86
+ *,
87
+ context: BaseMetricContext | list[BaseMetricContext] | None,
88
+ ground_truth: str | list[str] | None,
89
+ messages: list[Message],
90
+ ) -> str:
91
+ return completion_text
92
+
93
+
94
+ @final
95
+ class ExtractFromCompletion(AnswerPolicy):
96
+ """Free-form completion: the model generates (bounded by ``stop_sequences`` / ``max_tokens``) and the
97
+ scored answer is pulled out with ``answer_re``. ``last_match`` takes the final match, upper-cased (for
98
+ lenient case-insensitive patterns); otherwise the first match is returned as-is. ``"[invalid]"`` when
99
+ nothing matches."""
100
+
101
+ def __init__(
102
+ self,
103
+ answer_re: re.Pattern[str],
104
+ stop_sequences: list[str] | None = None,
105
+ *,
106
+ last_match: bool = False,
107
+ max_tokens: int | None = None,
108
+ ) -> None:
109
+ self._answer_re = answer_re
110
+ self._stop_sequences = stop_sequences or []
111
+ self._last_match = last_match
112
+ self._max_tokens = max_tokens
113
+
114
+ @override
115
+ def response_type(self) -> ResponseType:
116
+ return ResponseType.COMPLETION
117
+
118
+ @override
119
+ def metrics(self) -> list[type["BaseMetric"]]:
120
+ return [BytesCompletion, SequencePositionsCompletion, TokenCounts, FinishReason]
121
+
122
+ @override
123
+ def stop_sequences(self) -> list[str]:
124
+ return self._stop_sequences
125
+
126
+ @override
127
+ def max_tokens(self) -> int | None:
128
+ return self._max_tokens
129
+
130
+ @override
131
+ def extract_answer(
132
+ self,
133
+ completion_text: str,
134
+ *,
135
+ context: BaseMetricContext | list[BaseMetricContext] | None,
136
+ ground_truth: str | list[str] | None,
137
+ messages: list[Message],
138
+ ) -> str:
139
+ if self._last_match:
140
+ matches = self._answer_re.findall(completion_text)
141
+ return matches[-1].upper() if matches else "[invalid]"
142
+ match = self._answer_re.search(completion_text)
143
+ return match.group(1) if match else "[invalid]"
@@ -0,0 +1,101 @@
1
+ """Shared chain-of-thought scaffolding for multiple-choice benchmarks.
2
+
3
+ A CoT variant asks the model to reason freely and conclude with a stated answer letter, which is pulled back
4
+ out at scoring time (the injected ``ExtractFromCompletion``). The prompt surface — an optional preamble, the body,
5
+ and any inert scored candidates — is injected per benchmark; the CoT contract is fixed here: one free-form
6
+ sample, no assistant cue, the bare answer letter as ground truth, scored by accuracy.
7
+ """
8
+
9
+ import re
10
+ from collections.abc import Callable
11
+ from typing import TYPE_CHECKING, Any, final, override
12
+
13
+ from eval_framework.answer import ExtractFromCompletion
14
+ from eval_framework.choices import ChoiceReader
15
+ from eval_framework.eval_kind import EvalKind, SampleBody
16
+ from eval_framework.metrics.completion.accuracy_completion import AccuracyCompletion
17
+ from eval_framework.tasks.task_style import InitialPrompt
18
+ from eval_framework.tasks.utils import get_n_letters
19
+
20
+ if TYPE_CHECKING:
21
+ from eval_framework.metrics.base import BaseMetric
22
+
23
+ # (raw question, in-order choices) -> the prompt body shown to the model.
24
+ CotPrompt = Callable[[str, list[str]], str]
25
+ # (this item's answer-letter keys) -> inert scored candidates carried on the sample (usually none).
26
+ CotCandidates = Callable[[list[str]], list[str]]
27
+
28
+
29
+ def tulu3_cot_prompt(raw_question: str, choices: list[str]) -> str:
30
+ """The parenthesised-option CoT body shared by MMLU-Pro and GPQA.
31
+
32
+ Reasoning prompt from Figure 44 of the Tülu 3 paper: https://arxiv.org/pdf/2411.15124
33
+ """
34
+ keys = get_n_letters(len(choices))
35
+ options = "\n".join(f"({key}) {choice}" for key, choice in zip(keys, choices))
36
+ return (
37
+ "Answer the following multiple-choice question by giving the correct answer letter in parentheses. "
38
+ "Provide CONCISE reasoning for the answer, and make sure to finish the response with "
39
+ '"Therefore, the answer is (ANSWER_LETTER)" where (ANSWER_LETTER) is one of (A), (B), (C), (D), (E), etc.'
40
+ f"\n\nQuestion: {raw_question}\n{options}"
41
+ "\n\nAnswer the above question and REMEMBER to finish your response with the exact phrase "
42
+ '"Therefore, the answer is (ANSWER_LETTER)" where (ANSWER_LETTER) is one of (A), (B), (C), (D), (E), etc.'
43
+ )
44
+
45
+
46
+ def tulu_answer() -> ExtractFromCompletion:
47
+ """Extracts the parenthesised letter that ``tulu3_cot_prompt`` asks the model to conclude with —
48
+ ``"Therefore, the answer is (X)"``. Kept here beside the prompt because both encode the same ``(X)``
49
+ format. The accepted letters are the fixed A–J the prompt's ``"(A), (B), ..., (E), etc."`` implies."""
50
+ return ExtractFromCompletion(re.compile(r"Therefore, the answer is \(([ABCDEFGHIJ])\)"), ["Question:"])
51
+
52
+
53
+ def tulu_answer_v2(n_options: int) -> ExtractFromCompletion:
54
+ """Lenient variant of ``tulu_answer``: no required ``"Therefore,"``, optional colon and parentheses,
55
+ case-insensitive, taking the last match. Only the accepted letter range is benchmark-specific, so it is
56
+ built from ``n_options``."""
57
+ letters = "".join(get_n_letters(n_options))
58
+ return ExtractFromCompletion(
59
+ re.compile(rf"\banswer\s+is:?\s*\(?([{letters}])\b\)?", re.IGNORECASE), last_match=True
60
+ )
61
+
62
+
63
+ @final
64
+ class Cot(EvalKind):
65
+ """Multiple-choice chain-of-thought (see the module docstring). ``build_prompt`` renders the body,
66
+ ``preamble`` an optional subject-templated top line, and ``candidates`` any inert scored letters kept for
67
+ faithful parity with a loglikelihood baseline (free-form scoring ignores them)."""
68
+
69
+ def __init__(
70
+ self,
71
+ reader: ChoiceReader,
72
+ *,
73
+ build_prompt: CotPrompt,
74
+ preamble: InitialPrompt | None = None,
75
+ candidates: CotCandidates | None = None,
76
+ ) -> None:
77
+ self._reader = reader
78
+ self._build_prompt = build_prompt
79
+ self._preamble = preamble
80
+ self._candidates = candidates
81
+
82
+ @override
83
+ def metrics(self) -> list[type["BaseMetric"]]:
84
+ return [AccuracyCompletion]
85
+
86
+ @override
87
+ def initial_prompt(self, subject_label: str) -> str | None:
88
+ return self._preamble(subject_label) if self._preamble is not None else None
89
+
90
+ @override
91
+ def samples(self, item: dict[str, Any]) -> list[SampleBody]:
92
+ fields = self._reader.read(item)
93
+ keys = get_n_letters(len(fields.choices))
94
+ return [
95
+ SampleBody(
96
+ prompt=self._build_prompt(fields.raw_question, fields.choices),
97
+ cue="", # no assistant cue — the model continues into its own reasoning
98
+ possible_completions=self._candidates(keys) if self._candidates is not None else [],
99
+ ground_truth=keys[fields.correct_index], # the bare answer letter
100
+ )
101
+ ]
@@ -0,0 +1,137 @@
1
+ """GPQA (Graduate-level Google-Proof Q&A): https://huggingface.co/datasets/Idavidrein/gpqa
2
+
3
+ Gated, expert-written multiple-choice science questions. Each item has one ``Correct Answer`` and three
4
+ ``Incorrect Answer N`` distractors; the reader shuffles them together, seeded from the option texts so an
5
+ item's option order is stable across runs. The registered variants:
6
+
7
+ - ``GPQA_OLMES``: OLMES-style loglikelihood over the full ``gpqa_extended`` config.
8
+ - ``GPQA_DIAMOND_COT`` / ``_V2``: chain-of-thought completion over the harder ``gpqa_diamond`` config; they
9
+ share one prompt and differ only in how the concluding answer letter is extracted.
10
+
11
+ One question carries a raw sequence far too long for the prompt budget and is dropped from every config.
12
+ """
13
+
14
+ import hashlib
15
+ import random
16
+ import re
17
+ from typing import Any, final, override
18
+
19
+ from eval_framework.answer import AnswerPolicy
20
+ from eval_framework.benchmarks.cot import Cot, tulu3_cot_prompt, tulu_answer, tulu_answer_v2
21
+ from eval_framework.choices import ChoiceFields, ChoiceReader
22
+ from eval_framework.composed import ComposedBenchmark
23
+ from eval_framework.contract import Benchmark
24
+ from eval_framework.fewshot import NoFewShot
25
+ from eval_framework.subjects import ListOfSubjects
26
+ from eval_framework.tasks.base import Language
27
+ from eval_framework.tasks.dataset_loading import DatasetPolicy
28
+ from eval_framework.tasks.dataset_revisions import pinned_by_framework
29
+ from eval_framework.tasks.task_style import MCStyle
30
+
31
+ GPQA_DATASET_PATH = "Idavidrein/gpqa"
32
+
33
+ # One question embeds a raw DNA/protein sequence long enough to blow the prompt budget; it is excluded.
34
+ _OVERLONG_QUESTION = (
35
+ "Hello, you are embarking on a new project. You need to produce the HP1alpha protein in E. coli. "
36
+ "Which of these plasmids will you choose?"
37
+ )
38
+
39
+
40
+ def _gpqa_preamble(subject_label: str) -> str:
41
+ # GPQA shows a fixed expert-framing preamble; the subject (a config name) is not part of it.
42
+ return (
43
+ "Here are some example questions from experts. An explanation is given before the final answer. "
44
+ "Answer the final question yourself, giving your reasoning beforehand."
45
+ )
46
+
47
+
48
+ def _preprocess(text: str | None) -> str:
49
+ """Clean an answer option: GPQA options carry stray ``[title]`` / ``[...]`` markup and doubled spaces."""
50
+ if text is None:
51
+ return " "
52
+ text = text.strip()
53
+ text = text.replace(" [title]", ". ")
54
+ text = re.sub(r"\[.*?\]", "", text)
55
+ text = text.replace(" ", " ")
56
+ return text
57
+
58
+
59
+ @final
60
+ class GpqaReader(ChoiceReader):
61
+ """Reads a GPQA item: three ``Incorrect Answer N`` distractors and the ``Correct Answer``, shuffled
62
+ together. The shuffle is seeded from the (preprocessed) option texts, so the same item always yields the
63
+ same option order regardless of the order in which items are evaluated."""
64
+
65
+ @override
66
+ def read(self, item: dict[str, Any]) -> ChoiceFields:
67
+ choices = [_preprocess(item[f"Incorrect Answer {i}"]) for i in range(1, 4)]
68
+ correct = _preprocess(item["Correct Answer"])
69
+ seed = int(hashlib.sha256(f"{choices} {correct}".encode()).hexdigest(), 16)
70
+ rng = random.Random(seed)
71
+ rng.shuffle(choices)
72
+ correct_index = rng.randint(0, 3)
73
+ choices.insert(correct_index, correct)
74
+ return ChoiceFields(raw_question=item["Question"].strip(), choices=choices, correct_index=correct_index)
75
+
76
+
77
+ def _gpqa_cot_candidates(keys: list[str]) -> list[str]:
78
+ # COT is free-form, so these letter labels are not scored; they are carried alongside the sample to keep
79
+ # it identical to the loglikelihood-shaped baseline (and thus its formatter hash).
80
+ return [f" ({key})" for key in keys]
81
+
82
+
83
+ def _gpqa_dataset(dataset: DatasetPolicy | None) -> DatasetPolicy:
84
+ return (
85
+ dataset
86
+ if dataset is not None
87
+ else pinned_by_framework(GPQA_DATASET_PATH).subset(
88
+ lambda row: row["Question"] != _OVERLONG_QUESTION, description="excluding one over-long question"
89
+ )
90
+ )
91
+
92
+
93
+ def gpqa_olmes(dataset: DatasetPolicy | None = None) -> Benchmark:
94
+ styler = MCStyle(
95
+ question_prefix="Question: ",
96
+ cue_text="Answer:",
97
+ space_prefixed_labels=True,
98
+ initial_prompt=_gpqa_preamble,
99
+ )
100
+ return ComposedBenchmark.choice(
101
+ id="GPQA_OLMES",
102
+ reader=GpqaReader(),
103
+ styler=styler,
104
+ sample_split="train",
105
+ fewshot_split="train",
106
+ subjects=ListOfSubjects(["gpqa_extended"]),
107
+ dataset_policy=_gpqa_dataset(dataset),
108
+ language=Language.ENG,
109
+ )
110
+
111
+
112
+ def _gpqa_diamond_cot(id: str, answer: AnswerPolicy, dataset: DatasetPolicy | None = None) -> Benchmark:
113
+ return ComposedBenchmark.compose(
114
+ id=id,
115
+ kind=Cot(GpqaReader(), build_prompt=tulu3_cot_prompt, candidates=_gpqa_cot_candidates),
116
+ answer=answer,
117
+ sample_split="train",
118
+ fewshot=NoFewShot(),
119
+ subjects=ListOfSubjects(["gpqa_diamond"]),
120
+ dataset_policy=_gpqa_dataset(dataset),
121
+ language=Language.ENG,
122
+ )
123
+
124
+
125
+ def gpqa_diamond_cot(dataset: DatasetPolicy | None = None) -> Benchmark:
126
+ return _gpqa_diamond_cot("GPQA_DIAMOND_COT", tulu_answer(), dataset)
127
+
128
+
129
+ def gpqa_diamond_cot_v2(dataset: DatasetPolicy | None = None) -> Benchmark:
130
+ return _gpqa_diamond_cot("GPQA_DIAMOND_COT_V2", tulu_answer_v2(4), dataset)
131
+
132
+
133
+ GPQA_BENCHMARKS: list[Benchmark] = [
134
+ gpqa_olmes(),
135
+ gpqa_diamond_cot(),
136
+ gpqa_diamond_cot_v2(),
137
+ ]
@@ -4,18 +4,27 @@ https://huggingface.co/datasets/ellamind/gpqa-multilingual
4
4
 
5
5
  GPQA uses a single distractor set (``incorrect_answers``). The diamond variants restrict evaluation to
6
6
  the diamond subset — the 198 hardest questions (``is_diamond``) from the original GPQA-Diamond benchmark.
7
+ The COT variant has the model reason in German and conclude with the answer letter, which is
8
+ leniently regex-extracted from the generation (free-form completion, 0-shot).
7
9
  """
8
10
 
11
+ import re
9
12
  from typing import Any, final, override
10
13
 
14
+ from eval_framework.answer import ExtractFromCompletion
15
+ from eval_framework.benchmarks.cot import Cot
11
16
  from eval_framework.choices import ChoiceFields, ChoiceReader
12
17
  from eval_framework.composed import ComposedBenchmark
13
18
  from eval_framework.contract import Benchmark
19
+ from eval_framework.fewshot import NoFewShot
14
20
  from eval_framework.subjects import ListOfSubjects
15
21
  from eval_framework.tasks.base import Language
16
22
  from eval_framework.tasks.dataset_loading import DatasetPolicy
17
23
  from eval_framework.tasks.dataset_revisions import pinned_by_framework
18
24
  from eval_framework.tasks.task_style import BPBStyle, ClozeStyle, MCStyle, TaskStyler, shuffle_correct_with_distractors
25
+ from eval_framework.tasks.utils import get_n_letters
26
+
27
+ GPQA_ELLAMIND_DATASET_PATH = "ellamind/gpqa-multilingual"
19
28
 
20
29
 
21
30
  @final
@@ -33,7 +42,7 @@ class GpqaReader(ChoiceReader):
33
42
 
34
43
 
35
44
  def _gpqa_ellamind_benchmark(id: str, styler: TaskStyler, dataset: DatasetPolicy | None = None) -> Benchmark:
36
- dataset_policy = dataset if dataset is not None else pinned_by_framework("ellamind/gpqa-multilingual")
45
+ dataset_policy = dataset if dataset is not None else pinned_by_framework(GPQA_ELLAMIND_DATASET_PATH)
37
46
  return ComposedBenchmark.choice(
38
47
  id=id,
39
48
  reader=GpqaReader(),
@@ -46,16 +55,49 @@ def _gpqa_ellamind_benchmark(id: str, styler: TaskStyler, dataset: DatasetPolicy
46
55
  )
47
56
 
48
57
 
49
- def _gpqa_ellamind_diamond_benchmark(id: str, styler: TaskStyler, dataset: DatasetPolicy | None = None) -> Benchmark:
58
+ def _diamond_dataset(dataset: DatasetPolicy | None) -> DatasetPolicy:
50
59
  # The diamond variants keep only the ``is_diamond`` rows of the full dataset.
51
- source = (
52
- dataset
53
- if dataset is not None
54
- else pinned_by_framework("ellamind/gpqa-multilingual").subset(
55
- lambda row: row["is_diamond"], description="the diamond subset"
56
- )
60
+ if dataset is not None:
61
+ return dataset
62
+ return pinned_by_framework(GPQA_ELLAMIND_DATASET_PATH).subset(
63
+ lambda row: row["is_diamond"], description="the diamond subset"
64
+ )
65
+
66
+
67
+ def _gpqa_ellamind_diamond_benchmark(id: str, styler: TaskStyler, dataset: DatasetPolicy | None = None) -> Benchmark:
68
+ return _gpqa_ellamind_benchmark(id, styler, _diamond_dataset(dataset))
69
+
70
+
71
+ _ANSWER_PHRASE = '"Daher ist die Antwort (ANTWORTBUCHSTABE)"'
72
+ _LETTER_CLAUSE = "wobei (ANTWORTBUCHSTABE) einer von (A), (B), (C), (D), (E) usw. ist."
73
+
74
+
75
+ def tulu3_cot_prompt_de(raw_question: str, choices: list[str]) -> str:
76
+ """German translation of ``tulu3_cot_prompt`` (Figure 44 of the Tülu 3 paper,
77
+ https://arxiv.org/pdf/2411.15124): the model reasons briefly and concludes with "Daher ist die Antwort
78
+ (X)". The answer format is stated twice — once before the question and once as a reminder after it."""
79
+ keys = get_n_letters(len(choices))
80
+ options = "\n".join(f"({key}) {choice}" for key, choice in zip(keys, choices))
81
+ return (
82
+ "Beantworte die folgende Multiple-Choice-Frage, indem du den Buchstaben der richtigen "
83
+ "Antwort in Klammern angibst. Begründe deine Antwort KURZ und beende deine Antwort "
84
+ f"unbedingt mit {_ANSWER_PHRASE}, {_LETTER_CLAUSE}"
85
+ f"\n\nFrage: {raw_question}\n{options}"
86
+ "\n\nBeantworte die obige Frage und DENKE DARAN, deine Antwort mit genau dem Satz "
87
+ f"{_ANSWER_PHRASE} abzuschließen, {_LETTER_CLAUSE}"
88
+ )
89
+
90
+
91
+ def tulu_answer_de() -> ExtractFromCompletion:
92
+ """Extracts the letter that ``tulu3_cot_prompt_de`` asks the model to conclude with, as leniently as
93
+ ``tulu_answer_v2``: the last match wins, the parentheses are optional, and there is no stop sequence to
94
+ cut the generation short. It also accepts the English "answer is X", because a model prompted in German
95
+ often still concludes in English. The match is anchored on the answer phrase, so a bare "Antwort D" in the
96
+ reasoning does not count. GPQA always has four options, so only A–D are accepted."""
97
+ return ExtractFromCompletion(
98
+ re.compile(r"\b(?:ist\s+die\s+Antwort|Antwort\s+ist|Antwort:|answer\s+is)\s*\(?([A-D])\b\)?", re.IGNORECASE),
99
+ last_match=True,
57
100
  )
58
- return _gpqa_ellamind_benchmark(id, styler, source)
59
101
 
60
102
 
61
103
  def gpqa_ellamind_mc_de(dataset: DatasetPolicy | None = None) -> Benchmark:
@@ -86,6 +128,19 @@ def gpqa_ellamind_diamond_bpb_de(dataset: DatasetPolicy | None = None) -> Benchm
86
128
  )
87
129
 
88
130
 
131
+ def gpqa_ellamind_diamond_cot_de(dataset: DatasetPolicy | None = None) -> Benchmark:
132
+ return ComposedBenchmark.compose(
133
+ id="GPQA_ELLAMIND_DIAMOND_COT_DE",
134
+ kind=Cot(GpqaReader(), build_prompt=tulu3_cot_prompt_de),
135
+ answer=tulu_answer_de(),
136
+ sample_split="train",
137
+ fewshot=NoFewShot(),
138
+ subjects=ListOfSubjects(["deu"]),
139
+ dataset_policy=_diamond_dataset(dataset),
140
+ language=Language.DEU,
141
+ )
142
+
143
+
89
144
  GPQA_ELLAMIND_BENCHMARKS: list[Benchmark] = [
90
145
  gpqa_ellamind_mc_de(),
91
146
  gpqa_ellamind_cloze_de(),
@@ -93,4 +148,5 @@ GPQA_ELLAMIND_BENCHMARKS: list[Benchmark] = [
93
148
  gpqa_ellamind_diamond_cloze_de(),
94
149
  gpqa_ellamind_bpb_de(),
95
150
  gpqa_ellamind_diamond_bpb_de(),
151
+ gpqa_ellamind_diamond_cot_de(),
96
152
  ]