eval-framework 0.2.7__py3-none-any.whl

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 (170) hide show
  1. eval_framework/__init__.py +7 -0
  2. eval_framework/base_config.py +36 -0
  3. eval_framework/context/__init__.py +0 -0
  4. eval_framework/context/determined.py +177 -0
  5. eval_framework/context/eval.py +121 -0
  6. eval_framework/context/local.py +78 -0
  7. eval_framework/evaluation_generator.py +234 -0
  8. eval_framework/exceptions.py +2 -0
  9. eval_framework/external/ifeval_impl/README.md +5 -0
  10. eval_framework/external/ifeval_impl/instructions.py +1523 -0
  11. eval_framework/external/ifeval_impl/instructions_registry.py +161 -0
  12. eval_framework/external/ifeval_impl/instructions_util.py +1689 -0
  13. eval_framework/external/ifeval_impl/utils.py +135 -0
  14. eval_framework/llm/__init__.py +0 -0
  15. eval_framework/llm/aleph_alpha.py +432 -0
  16. eval_framework/llm/base.py +180 -0
  17. eval_framework/llm/huggingface.py +418 -0
  18. eval_framework/llm/mistral.py +88 -0
  19. eval_framework/llm/models.py +28 -0
  20. eval_framework/llm/openai.py +400 -0
  21. eval_framework/llm/vllm.py +554 -0
  22. eval_framework/logger.py +3 -0
  23. eval_framework/main.py +166 -0
  24. eval_framework/metrics/__init__.py +0 -0
  25. eval_framework/metrics/base.py +40 -0
  26. eval_framework/metrics/completion/__init__.py +1 -0
  27. eval_framework/metrics/completion/accuracy_completion.py +16 -0
  28. eval_framework/metrics/completion/aidanbench.py +28 -0
  29. eval_framework/metrics/completion/bleu.py +76 -0
  30. eval_framework/metrics/completion/chrf.py +62 -0
  31. eval_framework/metrics/completion/code_assertion.py +44 -0
  32. eval_framework/metrics/completion/code_execution_pass_at_one.py +126 -0
  33. eval_framework/metrics/completion/comet.py +56 -0
  34. eval_framework/metrics/completion/concordance_index.py +38 -0
  35. eval_framework/metrics/completion/csv_format.py +102 -0
  36. eval_framework/metrics/completion/cwe_accuracy.py +49 -0
  37. eval_framework/metrics/completion/exponential_similarity.py +65 -0
  38. eval_framework/metrics/completion/f1.py +42 -0
  39. eval_framework/metrics/completion/format_checker.py +56 -0
  40. eval_framework/metrics/completion/grid_difference.py +77 -0
  41. eval_framework/metrics/completion/ifeval.py +73 -0
  42. eval_framework/metrics/completion/json_format.py +179 -0
  43. eval_framework/metrics/completion/language_checker.py +74 -0
  44. eval_framework/metrics/completion/length_control.py +83 -0
  45. eval_framework/metrics/completion/math_reasoning_completion.py +307 -0
  46. eval_framework/metrics/completion/niah_accuracy.py +163 -0
  47. eval_framework/metrics/completion/placeholder_checker.py +27 -0
  48. eval_framework/metrics/completion/repetition.py +88 -0
  49. eval_framework/metrics/completion/rouge_1.py +35 -0
  50. eval_framework/metrics/completion/rouge_2.py +45 -0
  51. eval_framework/metrics/completion/rouge_geometric_mean.py +36 -0
  52. eval_framework/metrics/completion/rouge_l.py +52 -0
  53. eval_framework/metrics/completion/struct_eval_metrics.py +248 -0
  54. eval_framework/metrics/completion/ter.py +67 -0
  55. eval_framework/metrics/completion/text_counter.py +182 -0
  56. eval_framework/metrics/efficiency/__init__.py +0 -0
  57. eval_framework/metrics/efficiency/bytes_per_sequence_position.py +48 -0
  58. eval_framework/metrics/llm/__init__.py +0 -0
  59. eval_framework/metrics/llm/base.py +34 -0
  60. eval_framework/metrics/llm/graders/chatbot_style_grader.py +92 -0
  61. eval_framework/metrics/llm/graders/coherence_grader.py +115 -0
  62. eval_framework/metrics/llm/graders/comparison_grader.py +198 -0
  63. eval_framework/metrics/llm/graders/conciseness_grader.py +93 -0
  64. eval_framework/metrics/llm/graders/contains_names_grader.py +71 -0
  65. eval_framework/metrics/llm/graders/format_correctness_grader.py +109 -0
  66. eval_framework/metrics/llm/graders/instruction_grader.py +177 -0
  67. eval_framework/metrics/llm/graders/language.py +56 -0
  68. eval_framework/metrics/llm/graders/long_context_grader.py +72 -0
  69. eval_framework/metrics/llm/graders/models.py +74 -0
  70. eval_framework/metrics/llm/graders/refusal_grader.py +57 -0
  71. eval_framework/metrics/llm/graders/sql_quality_grader.py +145 -0
  72. eval_framework/metrics/llm/graders/summary_world_knowledge_grader.py +103 -0
  73. eval_framework/metrics/llm/llm_judge_chatbot_style.py +36 -0
  74. eval_framework/metrics/llm/llm_judge_coherence.py +44 -0
  75. eval_framework/metrics/llm/llm_judge_completion_accuracy.py +39 -0
  76. eval_framework/metrics/llm/llm_judge_conciseness.py +37 -0
  77. eval_framework/metrics/llm/llm_judge_contains_names.py +36 -0
  78. eval_framework/metrics/llm/llm_judge_format_correctness.py +43 -0
  79. eval_framework/metrics/llm/llm_judge_instruction.py +58 -0
  80. eval_framework/metrics/llm/llm_judge_mtbench_pair.py +306 -0
  81. eval_framework/metrics/llm/llm_judge_mtbench_single.py +210 -0
  82. eval_framework/metrics/llm/llm_judge_refusal.py +35 -0
  83. eval_framework/metrics/llm/llm_judge_sql.py +394 -0
  84. eval_framework/metrics/llm/llm_judge_world_knowledge.py +37 -0
  85. eval_framework/metrics/llm/utils.py +20 -0
  86. eval_framework/metrics/loglikelihood/__init__.py +0 -0
  87. eval_framework/metrics/loglikelihood/accuracy_loglikelihood.py +51 -0
  88. eval_framework/metrics/loglikelihood/base.py +50 -0
  89. eval_framework/metrics/loglikelihood/confidence_weighted_accuracy.py +25 -0
  90. eval_framework/metrics/loglikelihood/dcs.py +43 -0
  91. eval_framework/metrics/loglikelihood/probability_mass.py +53 -0
  92. eval_framework/metrics/loglikelihood/ternary.py +42 -0
  93. eval_framework/py.typed +0 -0
  94. eval_framework/response_generator.py +351 -0
  95. eval_framework/result_processors/__init__.py +0 -0
  96. eval_framework/result_processors/base.py +88 -0
  97. eval_framework/result_processors/hf_uploader.py +75 -0
  98. eval_framework/result_processors/result_processor.py +129 -0
  99. eval_framework/result_processors/wandb_uploader.py +137 -0
  100. eval_framework/run.py +369 -0
  101. eval_framework/run_direct.py +42 -0
  102. eval_framework/shared/types.py +227 -0
  103. eval_framework/tasks/__init__.py +6 -0
  104. eval_framework/tasks/base.py +392 -0
  105. eval_framework/tasks/benchmarks/__init__.py +0 -0
  106. eval_framework/tasks/benchmarks/aidanbench.py +211 -0
  107. eval_framework/tasks/benchmarks/arc.py +70 -0
  108. eval_framework/tasks/benchmarks/arc_de.py +46 -0
  109. eval_framework/tasks/benchmarks/arc_fi.py +46 -0
  110. eval_framework/tasks/benchmarks/belebele.py +60 -0
  111. eval_framework/tasks/benchmarks/bigcodebench.py +155 -0
  112. eval_framework/tasks/benchmarks/casehold.py +47 -0
  113. eval_framework/tasks/benchmarks/chembench.py +85 -0
  114. eval_framework/tasks/benchmarks/copa.py +64 -0
  115. eval_framework/tasks/benchmarks/duc.py +91 -0
  116. eval_framework/tasks/benchmarks/flores200.py +133 -0
  117. eval_framework/tasks/benchmarks/flores_plus.py +84 -0
  118. eval_framework/tasks/benchmarks/gpqa.py +201 -0
  119. eval_framework/tasks/benchmarks/gsm8k.py +150 -0
  120. eval_framework/tasks/benchmarks/hellaswag.py +69 -0
  121. eval_framework/tasks/benchmarks/hellaswag_de.py +52 -0
  122. eval_framework/tasks/benchmarks/humaneval.py +97 -0
  123. eval_framework/tasks/benchmarks/ifeval.py +78 -0
  124. eval_framework/tasks/benchmarks/include.py +119 -0
  125. eval_framework/tasks/benchmarks/infinitebench.py +302 -0
  126. eval_framework/tasks/benchmarks/math_reasoning.py +580 -0
  127. eval_framework/tasks/benchmarks/mbpp.py +192 -0
  128. eval_framework/tasks/benchmarks/mmlu.py +215 -0
  129. eval_framework/tasks/benchmarks/mmlu_de.py +109 -0
  130. eval_framework/tasks/benchmarks/mmlu_pro.py +164 -0
  131. eval_framework/tasks/benchmarks/mmmlu.py +529 -0
  132. eval_framework/tasks/benchmarks/openbookqa.py +85 -0
  133. eval_framework/tasks/benchmarks/opengptx_eu20.py +363 -0
  134. eval_framework/tasks/benchmarks/pawsx.py +65 -0
  135. eval_framework/tasks/benchmarks/piqa.py +64 -0
  136. eval_framework/tasks/benchmarks/quality.py +56 -0
  137. eval_framework/tasks/benchmarks/sciq.py +110 -0
  138. eval_framework/tasks/benchmarks/sphyr.py +79 -0
  139. eval_framework/tasks/benchmarks/squad.py +211 -0
  140. eval_framework/tasks/benchmarks/struct_eval.py +116 -0
  141. eval_framework/tasks/benchmarks/tablebench.py +117 -0
  142. eval_framework/tasks/benchmarks/triviaqa.py +42 -0
  143. eval_framework/tasks/benchmarks/truthfulqa.py +119 -0
  144. eval_framework/tasks/benchmarks/winogender.py +64 -0
  145. eval_framework/tasks/benchmarks/winogrande.py +69 -0
  146. eval_framework/tasks/benchmarks/winox.py +57 -0
  147. eval_framework/tasks/benchmarks/wmt.py +160 -0
  148. eval_framework/tasks/benchmarks/zero_scrolls.py +197 -0
  149. eval_framework/tasks/eval_config.py +136 -0
  150. eval_framework/tasks/perturbation.py +83 -0
  151. eval_framework/tasks/registry.py +186 -0
  152. eval_framework/tasks/task_loader.py +81 -0
  153. eval_framework/tasks/task_names.py +324 -0
  154. eval_framework/tasks/utils.py +584 -0
  155. eval_framework/utils/constants.py +9 -0
  156. eval_framework/utils/file_ops.py +245 -0
  157. eval_framework/utils/generate_task_docs.py +244 -0
  158. eval_framework/utils/helpers.py +32 -0
  159. eval_framework/utils/logging.py +62 -0
  160. eval_framework/utils/packaging.py +52 -0
  161. eval_framework/utils/tqdm_handler.py +14 -0
  162. eval_framework-0.2.7.dist-info/METADATA +548 -0
  163. eval_framework-0.2.7.dist-info/RECORD +170 -0
  164. eval_framework-0.2.7.dist-info/WHEEL +4 -0
  165. eval_framework-0.2.7.dist-info/entry_points.txt +3 -0
  166. template_formatting/README.md +83 -0
  167. template_formatting/__init__.py +0 -0
  168. template_formatting/formatter.py +537 -0
  169. template_formatting/mistral_formatter.py +159 -0
  170. template_formatting/py.typed +0 -0
@@ -0,0 +1,306 @@
1
+ import random
2
+ import re
3
+ import traceback
4
+
5
+ from pydantic import BaseModel
6
+
7
+ from eval_framework.logger import logger
8
+ from eval_framework.metrics.base import MetricResult
9
+ from eval_framework.metrics.llm.base import BaseLLMJudgeMetric
10
+ from eval_framework.metrics.llm.utils import order_answers_for_comparison
11
+ from eval_framework.shared.types import BaseMetricContext, Completion, Error, extract_context_metric
12
+ from template_formatting.formatter import Message, Role
13
+
14
+ PAIR_JUDGE_PROMPTS = {
15
+ "pair_assistant_single_turn": {
16
+ "prompt_template": "[System]\nPlease act as an impartial judge and evaluate the quality of the responses provided by two AI assistants to the user question displayed below. You should choose the assistant that follows the user's instructions and answers the user's question better. Your evaluation should consider factors such as the helpfulness, relevance, accuracy, depth, creativity, and level of detail of their responses. Begin your evaluation by comparing the two responses and provide a short explanation. Avoid any position biases and ensure that the order in which the responses were presented does not influence your decision. Do not allow the length of the responses to influence your evaluation. Do not favor certain names of the assistants. Be as objective as possible. After providing your explanation, output your final verdict by strictly following this format: \"[[A]]\" if assistant A is better, \"[[B]]\" if assistant B is better, and \"[[C]]\" for a tie.\n\n[User Question]\n{question}\n\n[The Start of Assistant A's Answer]\n{answer_a}\n[The End of Assistant A's Answer]\n\n[The Start of Assistant B's Answer]\n{answer_b}\n[The End of Assistant B's Answer]" # noqa: E501
17
+ },
18
+ "pair_assistant_multi_turn": {
19
+ "prompt_template": "Please act as an impartial judge and evaluate the quality of the responses provided by two AI assistants to the user questions. You should choose the assistant that follows the user's instructions and answers the user's questions better. Your evaluation should consider factors such as the helpfulness, relevance, accuracy, depth, creativity, and level of detail of their responses. You should focus on who provides a better answer to the second user question. Begin your evaluation by comparing the responses of the two assistants and provide a short explanation. Avoid any position biases and ensure that the order in which the responses were presented does not influence your decision. Do not allow the length of the responses to influence your evaluation. Do not favor certain names of the assistants. Be as objective as possible. After providing your explanation, output your final verdict by strictly following this format: \"[[A]]\" if assistant A is better, \"[[B]]\" if assistant B is better, and \"[[C]]\" for a tie.\n\n<|The Start of Assistant A's Conversation with User|>\n\n### User:\n{question_1}\n\n### Assistant A:\n{answer_a_1}\n\n### User:\n{question_2}\n\n### Assistant A:\n{answer_a_2}\n\n<|The End of Assistant A's Conversation with User|>\n\n\n<|The Start of Assistant B's Conversation with User|>\n\n### User:\n{question_1}\n\n### Assistant B:\n{answer_b_1}\n\n### User:\n{question_2}\n\n### Assistant B:\n{answer_b_2}\n\n<|The End of Assistant B's Conversation with User|>" # noqa: E501
20
+ },
21
+ "pair_assistant_single_turn_w_reference": {
22
+ "prompt_template": "[System]\nPlease act as an impartial judge and evaluate the quality of the responses provided by two AI assistants to the user question displayed below. Your evaluation should consider correctness and helpfulness. You will be given a reference answer, assistant A's answer, and assistant B's answer. Your job is to evaluate which assistant's answer is better. Begin your evaluation by comparing both assistants' answers with the reference answer. Identify and correct any mistakes. Avoid any position biases and ensure that the order in which the responses were presented does not influence your decision. Do not allow the length of the responses to influence your evaluation. Do not favor certain names of the assistants. Be as objective as possible. After providing your explanation, output your final verdict by strictly following this format: \"[[A]]\" if assistant A is better, \"[[B]]\" if assistant B is better, and \"[[C]]\" for a tie.\n\n[User Question]\n{question}\n\n[The Start of Reference Answer]\n{ref_answer_1}\n[The End of Reference Answer]\n\n[The Start of Assistant A's Answer]\n{answer_a}\n[The End of Assistant A's Answer]\n\n[The Start of Assistant B's Answer]\n{answer_b}\n[The End of Assistant B's Answer]" # noqa: E501
23
+ },
24
+ "pair_assistant_multi_turn_w_reference": {
25
+ "prompt_template": "Please act as an impartial judge and evaluate the quality of the responses provided by two AI assistants to the user questions. Your evaluation should consider correctness and helpfulness. You will be given reference answers, the assistant A's answers, the assistant B's answers. Your job is to determine which assistant provides correct and helpful answers to the second user question. Begin your evaluation by comparing both assistants' answers with the reference answers. Identify and correct any mistakes. Avoid any position biases and ensure that the order in which the responses were presented does not influence your decision. Do not allow the length of the responses to influence your evaluation. Do not favor certain names of the assistants. Be as objective as possible. After providing your explanation, output your final verdict by strictly following this format: \"[[A]]\" if assistant A is better, \"[[B]]\" if assistant B is better, and \"[[C]]\" for a tie.\n\n<|The Start of Reference Answer|>\n\n### User:\n{question_1}\n\n### Reference answer:\n{ref_answer_1}\n\n### User:\n{question_2}\n\n### Reference answer:\n{ref_answer_2}\n\n<|The End of Reference Answer|>\n\n\n<|The Start of Assistant A's Conversation with User|>\n\n### User:\n{question_1}\n\n### Assistant A:\n{answer_a_1}\n\n### User:\n{question_2}\n\n### Assistant A:\n{answer_a_2}\n\n<|The End of Assistant A's Conversation with User|>\n\n\n<|The Start of Assistant B's Conversation with User|>\n\n### User:\n{question_1}\n\n### Assistant B:\n{answer_b_1}\n\n### User:\n{question_2}\n\n### Assistant B:\n{answer_b_2}\n\n<|The End of Assistant B's Conversation with User|>" # noqa: E501
26
+ },
27
+ }
28
+
29
+ PAIR_JUDGE_PROMPTS_DE = {
30
+ "pair_assistant_single_turn": {
31
+ "prompt_template": '[System]\nBitte agieren Sie als unparteiischer Beurteiler und bewerten Sie die Qualität der Antworten, die von zwei KI-Assistenten auf die unten angezeigte Nutzerfrage gegeben wurden. Wählen Sie den Assistenten aus, der die Anweisungen des Nutzers besser befolgt und die Nutzerfrage besser beantwortet. Ihre Bewertung sollte Faktoren wie Nützlichkeit, Relevanz, Genauigkeit, Tiefe, Kreativität und Detaillierungsgrad der Antworten berücksichtigen. Beginnen Sie Ihre Bewertung mit einem Vergleich der beiden Antworten und geben Sie eine kurze Erklärung ab. Vermeiden Sie jeglichen Bias bezüglich der Position der Antworten und stellen Sie sicher, dass die Reihenfolge, in der die Antworten präsentiert wurden, Ihre Entscheidung nicht beeinflusst. Lassen Sie nicht zu, dass die Länge der Antworten Ihre Bewertung beeinflusst. Bevorzugen Sie keine bestimmten Namen der Assistenten. Seien Sie so objektiv wie möglich. Geben Sie nach Ihrer Erklärung Ihr endgültiges Urteil streng nach folgendem Format aus: "[[A]]" wenn Assistent A besser ist, "[[B]]" wenn Assistent B besser ist und "[[C]]" bei einem Unentschieden\n[Nutzerfrage]\n{question}\n\n[Der Anfang von Assistent A\'s Antwort]\n{answer_a}\n[Das Ende Assistent A\'s Antwort]\n\n[Der Anfang von Assistent B\'s Antwort]\n{answer_b}\n[Der Anfang von Assistent B\'s Antwort]' # noqa: E501
32
+ },
33
+ "pair_assistant_multi_turn": {
34
+ "prompt_template": 'Bitte agieren Sie als unparteiischer Beurteiler und bewerten Sie die Qualität der Antworten, die von zwei KI-Assistenten auf die Nutzerfragen gegeben wurden. Wählen Sie den Assistenten aus, der die Anweisungen des Nutzers besser befolgt und die Nutzerfragen besser beantwortet. Ihre Bewertung sollte Faktoren wie Nützlichkeit, Relevanz, Genauigkeit, Tiefe, Kreativität und Detaillgrad der Antworten berücksichtigen. Konzentrieren Sie sich darauf, wer die bessere Antwort auf die zweite Nutzerfrage liefert. Beginnen Sie Ihre Bewertung mit einem Vergleich der Antworten der beiden Assistenten und geben Sie eine kurze Erklärung ab. Vermeiden Sie jegliche Positionsvoreingenommenheit und stellen Sie sicher, dass die Reihenfolge, in der die Antworten präsentiert wurden, Ihre Entscheidung nicht beeinflusst. Lassen Sie nicht zu, dass die Länge der Antworten Ihre Bewertung beeinflusst. Bevorzugen Sie keine bestimmten Namen der Assistenten. Seien Sie so objektiv wie möglich. Geben Sie nach Ihrer Erklärung Ihr endgültiges Urteil streng nach folgendem Format aus: "[[A]]" wenn Assistent A besser ist, "[[B]]" wenn Assistent B besser ist und "[[C]]" bei einem Unentschieden.\n\n<|Der Anfang von Assistent A\'s Konversation mit dem User|>\n\n### User:\n{question_1}\n\n### Assistent A:\n{answer_a_1}\n\n### User:\n{question_2}\n\n### Assistent A:\n{answer_a_2}\n\n<|Das Ende von Assistent A\'s Konversation mit dem User|>\n\n\n<|Der Anfang von Assistent B\'s Konversation mit der User|>\n\n### User:\n{question_1}\n\n### Assistent B:\n{answer_b_1}\n\n### User:\n{question_2}\n\n### Assistent B:\n{answer_b_2}\n\n<|Das Ende von Assistent B\'s Konversation mit dem User|>' # noqa: E501
35
+ },
36
+ "pair_assistant_single_turn_w_reference": {
37
+ "prompt_template": '[System]\nBitte agieren Sie als unparteiischer Beurteiler und bewerten Sie die Qualität der Antworten, die von zwei KI-Assistenten auf die unten angezeigte Nutzerfrage gegeben wurden. Ihre Bewertung sollte Richtigkeit und Hilfreichkeit berücksichtigen. Sie erhalten eine Referenzantwort, die Antwort von Assistent A und die Antwort von Assistent B. Ihre Aufgabe ist es zu beurteilen, welche Antwort der Assistenten besser ist. Beginnen Sie Ihre Bewertung damit, die Antworten beider Assistenten mit der Referenzantwort zu vergleichen. Identifizieren und korrigieren Sie etwaige Fehler. Vermeiden Sie jegliche Positionsvoreingenommenheit und stellen Sie sicher, dass die Reihenfolge, in der die Antworten präsentiert wurden, Ihre Entscheidung nicht beeinflusst. Lassen Sie nicht zu, dass die Länge der Antworten Ihre Bewertung beeinflusst. Bevorzugen Sie keine bestimmten Namen der Assistenten. Seien Sie so objektiv wie möglich. Geben Sie nach Ihrer Erklärung Ihr endgültiges Urteil streng nach folgendem Format aus: "[[A]]" wenn Assistent A besser ist, "[[B]]" wenn Assistent B besser ist und "[[C]]" bei einem Unentschieden\n\n[Nutzerfrage]\n{question}\n\n[Der Anfang der Referenzantwort]\n{ref_answer_1}\n[Das Ender der Referenzantwort]\n\n[Der Anfang von Assistent A\'s Antwort]\n{answer_a}\n[Das Ende von Assistent A\'s Antwort]\n\n[Der Anfag von Assistent B\'s Answer]\n{answer_b}\n[Das Ende vin Assistent B\'s Antwort]' # noqa: E501
38
+ },
39
+ "pair_assistant_multi_turn_w_reference": {
40
+ "prompt_template": 'Bitte agieren Sie als unparteiischer Beurteiler und bewerten Sie die Qualität der Antworten, die von zwei KI-Assistenten auf die Nutzerfragen gegeben wurden. Ihre Bewertung sollte Richtigkeit und Hilfreichkeit berücksichtigen. Sie erhalten Referenzantworten, die Antworten von Assistent A und die Antworten von Assistent B. Ihre Aufgabe ist es zu ermitteln, welcher Assistent richtige und hilfreiche Antworten auf die zweite Nutzerfrage liefert. Beginnen Sie Ihre Bewertung damit, die Antworten beider Assistenten mit den Referenzantworten zu vergleichen. Identifizieren und korrigieren Sie etwaige Fehler. Vermeiden Sie jegliche Positionsvoreingenommenheit und stellen Sie sicher, dass die Reihenfolge, in der die Antworten präsentiert wurden, Ihre Entscheidung nicht beeinflusst. Lassen Sie nicht zu, dass die Länge der Antworten Ihre Bewertung beeinflusst. Bevorzugen Sie keine bestimmten Namen der Assistenten. Seien Sie so objektiv wie möglich. Geben Sie nach Ihrer Erklärung Ihr endgültiges Urteil streng nach folgendem Format aus: "[[A]]" wenn Assistent A besser ist, "[[B]]" wenn Assistent B besser ist und "[[C]]" bei einem Unentschieden.\n\n<|Der Anfang der Referenzantwort|>\n\n### User:\n{question_1}\n\n### Referenzantwort:\n{ref_answer_1}\n\n### User:\n{question_2}\n\n### Referenzantwort:\n{ref_answer_2}\n\n<|Das Ende der Referenzantwort|>\n\n\n<|Der Anfang von Assistant A\'s Konversation mit dem User|>\n\n### User:\n{question_1}\n\n### Assistent A:\n{answer_a_1}\n\n### User:\n{question_2}\n\n### Assistent A:\n{answer_a_2}\n\n<|Das Ende von Assistent A\'s Konversation mit dem User|>\n\n\n<|Der Anfang von Assistent B\'s Konversation mit dem User|>\n\n### User:\n{question_1}\n\n### Assistent B:\n{answer_b_1}\n\n### User:\n{question_2}\n\n### Assistent B:\n{answer_b_2}\n\n<|Das Ende von Assistent B\'s Konversation mit dem User|>' # noqa: E501
41
+ },
42
+ }
43
+
44
+ PAIR_JUDGE_PROMPTS_FI = {
45
+ "pair_assistant_single_turn": {
46
+ "prompt_template": '[Järjestelmä]\nToimi puolueettomana tuomarina ja arvioi kahden AI-avustajan antamien vastausten laatua alla näkyvään käyttäjän kysymykseen. Sinun tulee valita se avustaja, joka noudattaa käyttäjän ohjeita ja vastaa käyttäjän kysymykseen paremmin. Arviosi tulisi ottaa huomioon tekijät kuten hyödyllisyys, asiaankuuluvuus, tarkkuus, syvällisyys, luovuus ja yksityiskohtien taso. Aloita arviointisi vertaamalla kahta vastausta ja anna lyhyt selitys. Vältä mahdollisia asemointiharhoja ja varmista, että vastausten esitysjärjestys ei vaikuta päätökseesi. Älä anna vastausten pituuden vaikuttaa arvioosi. Älä suosi tiettyjä avustajien nimiä. Ole mahdollisimman objektiivinen. Selityksen jälkeen anna lopullinen päätöksesi noudattamalla tarkasti tätä muotoa: "[[A]]", jos avustaja A on parempi, "[[B]]", jos avustaja B on parempi, ja "[[C]]" tasapelin tapauksessa.\n\n[Käyttäjän kysymys]\n{question}\n\n[Avustaja A:n vastauksen alku]\n{answer_a}\n[Avustaja A:n vastauksen loppu]\n\n[Avustaja B:n vastauksen alku]\n{answer_b}\n[Avustaja B:n vastauksen loppu]' # noqa: E501
47
+ },
48
+ "pair_assistant_multi_turn": {
49
+ "prompt_template": 'Toimi puolueettomana tuomarina ja arvioi kahden AI-avustajan antamien vastausten laatua käyttäjän kysymyksiin. Sinun tulee valita se avustaja, joka noudattaa käyttäjän ohjeita ja vastaa käyttäjän kysymyksiin paremmin. Arviosi tulisi ottaa huomioon tekijät kuten hyödyllisyys, asiaankuuluvuus, tarkkuus, syvällisyys, luovuus ja yksityiskohtien taso. Arviosi tulisi keskittyä siihen, kuka antaa paremman vastauksen toiseen käyttäjän kysymykseen. Aloita arviointisi vertaamalla kahden avustajan vastauksia ja anna lyhyt selitys. Vältä mahdollisia asemointiharhoja ja varmista, että vastausten esitysjärjestys ei vaikuta päätökseesi. Älä anna vastausten pituuden vaikuttaa arvioosi. Älä suosi tiettyjä avustajien nimiä. Ole mahdollisimman objektiivinen. Selityksen jälkeen anna lopullinen päätöksesi noudattamalla tarkasti tätä muotoa: "[[A]]", jos avustaja A on parempi, "[[B]]", jos avustaja B on parempi, ja "[[C]]" tasapelin tapauksessa.\n\n<|Avustaja A:n keskustelun alku käyttäjän kanssa|>\n\n### Käyttäjä:\n{question_1}\n\n### Avustaja A:\n{answer_a_1}\n\n### Käyttäjä:\n{question_2}\n\n### Avustaja A:\n{answer_a_2}\n\n<|Avustaja A:n keskustelun loppu käyttäjän kanssa|>\n\n\n<|Avustaja B:n keskustelun alku käyttäjän kanssa|>\n\n### Käyttäjä:\n{question_1}\n\n### Avustaja B:\n{answer_b_1}\n\n### Käyttäjä:\n{question_2}\n\n### Avustaja B:\n{answer_b_2}\n\n<|Avustaja B:n keskustelun loppu käyttäjän kanssa|>' # noqa: E501
50
+ },
51
+ "pair_assistant_single_turn_w_reference": {
52
+ "prompt_template": '[Järjestelmä]\nToimi puolueettomana tuomarina ja arvioi kahden AI-avustajan antamien vastausten laatua alla näkyvään käyttäjän kysymykseen. Arviosi tulisi ottaa huomioon oikeellisuus ja hyödyllisyys. Sinulle annetaan viitevastaus, avustajan A vastaus ja avustajan B vastaus. Tehtäväsi on arvioida, kumpi avustaja antoi paremman vastauksen. Aloita arviointisi vertaamalla molempien avustajien vastauksia viitevastaukseen. Tunnista ja korjaa mahdolliset virheet. Vältä mahdollisia asemointiharhoja ja varmista, että vastausten esitysjärjestys ei vaikuta päätökseesi. Älä anna vastausten pituuden vaikuttaa arvioosi. Älä suosi tiettyjä avustajien nimiä. Ole mahdollisimman objektiivinen. Selityksen jälkeen anna lopullinen päätöksesi noudattamalla tarkasti tätä muotoa: "[[A]]", jos avustaja A on parempi, "[[B]]", jos avustaja B on parempi, ja "[[C]]" tasapelin tapauksessa.\n\n[Käyttäjän kysymys]\n{question}\n\n[Viitevastauksen alku]\n{ref_answer_1}\n[Viitevastauksen loppu]\n\n[Avustaja A:n vastauksen alku]\n{answer_a}\n[Avustaja A:n vastauksen loppu]\n\n[Avustaja B:n vastauksen alku]\n{answer_b}\n[Avustaja B:n vastauksen loppu]' # noqa: E501
53
+ },
54
+ "pair_assistant_multi_turn_w_reference": {
55
+ "prompt_template": 'Toimi puolueettomana tuomarina ja arvioi kahden AI-avustajan antamien vastausten laatua käyttäjän kysymyksiin. Arviosi tulisi ottaa huomioon oikeellisuus ja hyödyllisyys. Sinulle annetaan viitevastaukset, avustajan A vastaukset ja avustajan B vastaukset. Tehtäväsi on määrittää, kumpi avustaja antoi oikeat ja hyödylliset vastaukset toiseen käyttäjän kysymykseen. Aloita arviointisi vertaamalla molempien avustajien vastauksia viitevastauksiin. Tunnista ja korjaa mahdolliset virheet. Vältä mahdollisia asemointiharhoja ja varmista, että vastausten esitysjärjestys ei vaikuta päätökseesi. Älä anna vastausten pituuden vaikuttaa arvioosi. Älä suosi tiettyjä avustajien nimiä. Ole mahdollisimman objektiivinen. Selityksen jälkeen anna lopullinen päätöksesi noudattamalla tarkasti tätä muotoa: "[[A]]", jos avustaja A on parempi, "[[B]]", jos avustaja B on parempi, ja "[[C]]" tasapelin tapauksessa.\n\n<|Viitevastauksen alku|>\n\n### Käyttäjä:\n{question_1}\n\n### Viitevastaus:\n{ref_answer_1}\n\n### Käyttäjä:\n{question_2}\n\n### Viitevastaus:\n{ref_answer_2}\n\n<|Viitevastauksen loppu|>\n\n\n<|Avustaja A:n keskustelun alku käyttäjän kanssa|>\n\n### Käyttäjä:\n{question_1}\n\n### Avustaja A:\n{answer_a_1}\n\n### Käyttäjä:\n{question_2}\n\n### Avustaja A:\n{answer_a_2}\n\n<|Avustaja A:n keskustelun loppu käyttäjän kanssa|>\n\n\n<|Avustaja B:n keskustelun alku käyttäjän kanssa|>\n\n### Käyttäjä:\n{question_1}\n\n### Avustaja B:\n{answer_b_1}\n\n### Käyttäjä:\n{question_2}\n\n### Avustaja B:\n{answer_b_2}\n\n<|Avustaja B:n keskustelun loppu käyttäjän kanssa|>' # noqa: E501
56
+ },
57
+ }
58
+
59
+
60
+ NEED_REF_CATEGORIES = ["math", "reasoning", "coding", "arena-hard-200"]
61
+ PAIR_JUDGE_PROMPTS_LIST = [
62
+ PAIR_JUDGE_PROMPTS,
63
+ PAIR_JUDGE_PROMPTS_DE,
64
+ PAIR_JUDGE_PROMPTS_FI,
65
+ ]
66
+
67
+
68
+ class PromptToJudge(BaseModel):
69
+ comparison_type: str
70
+ prompt_text: str
71
+ candidate_is_a: bool = True # Tracks whether the candidate completion is in position A
72
+
73
+
74
+ class MTBenchJudgePairMetricContext(BaseMetricContext):
75
+ category: str
76
+ answer: list[str] | str
77
+ reference: list[str] | str | None
78
+
79
+
80
+ def generate_pair_judge_prompts(
81
+ response: Completion,
82
+ randomize_order: bool = False,
83
+ seed: int | None = None,
84
+ ) -> list[PromptToJudge]:
85
+ """Generate pairwise judge prompts for comparing candidate vs reference completions.
86
+
87
+ Args:
88
+ response: The completion response containing the candidate completion.
89
+ randomize_order: If True, randomly swap the order of A/B to eliminate position bias.
90
+ seed: Optional random seed for reproducibility. If None and randomize_order is True,
91
+ uses the response id as seed for deterministic per-sample randomization.
92
+
93
+ Returns:
94
+ List of PromptToJudge objects with candidate_is_a indicating whether the
95
+ candidate completion is in position A (True) or position B (False).
96
+ """
97
+ context = extract_context_metric(response, MTBenchJudgePairMetricContext)
98
+ assert response.messages is not None
99
+
100
+ if response.subject.startswith("de"):
101
+ prompt_templates = PAIR_JUDGE_PROMPTS_DE
102
+ elif response.subject.startswith("fi"):
103
+ prompt_templates = PAIR_JUDGE_PROMPTS_FI
104
+ else:
105
+ prompt_templates = PAIR_JUDGE_PROMPTS
106
+ prompts_to_judge = []
107
+
108
+ assert context.category is not None, "Category must be provided in the context for MTBenchJudgePairMetricContext"
109
+ assert context.answer is not None, "Answer must be provided in the context for MTBenchJudgePairMetricContext"
110
+
111
+ # Determine whether to swap A/B order for this sample
112
+ # Use response.id as default seed for deterministic per-sample randomization
113
+ if randomize_order:
114
+ rng = random.Random(seed if seed is not None else response.id)
115
+ swap_order = rng.choice([True, False])
116
+ else:
117
+ swap_order = False
118
+
119
+ candidate_is_a = not swap_order
120
+
121
+ # No reference answer needed
122
+ if context.category not in NEED_REF_CATEGORIES:
123
+ # SINGLE TURN
124
+ if len(response.messages) <= 2:
125
+ # turn 1
126
+ question = response.last_user_instruction
127
+ candidate_answer = response.completion
128
+ reference_answer = context.answer[0]
129
+ answer_a, answer_b = order_answers_for_comparison(candidate_answer, reference_answer, swap_order)
130
+
131
+ # format prompt
132
+ single_turn_prompt = prompt_templates["pair_assistant_single_turn"]["prompt_template"].format(
133
+ question=question, answer_a=answer_a, answer_b=answer_b
134
+ )
135
+ prompts_to_judge.append(
136
+ PromptToJudge(
137
+ comparison_type="pairwise_judgement",
138
+ prompt_text=single_turn_prompt,
139
+ candidate_is_a=candidate_is_a,
140
+ )
141
+ )
142
+
143
+ # MULTI TURN
144
+ else:
145
+ # turn 1
146
+ question_1 = response.first_user_instruction
147
+ candidate_answer_1 = response.messages[1].content
148
+ reference_answer_1 = context.answer[0]
149
+ # turn 2
150
+ question_2 = response.last_user_instruction
151
+ candidate_answer_2 = response.completion
152
+ reference_answer_2 = context.answer[1]
153
+ answer_a_1, answer_b_1 = order_answers_for_comparison(candidate_answer_1, reference_answer_1, swap_order)
154
+ answer_a_2, answer_b_2 = order_answers_for_comparison(candidate_answer_2, reference_answer_2, swap_order)
155
+
156
+ # format prompt
157
+ multi_turn_prompt = prompt_templates["pair_assistant_multi_turn"]["prompt_template"].format(
158
+ question_1=question_1,
159
+ answer_a_1=answer_a_1,
160
+ answer_b_1=answer_b_1,
161
+ question_2=question_2,
162
+ answer_a_2=answer_a_2,
163
+ answer_b_2=answer_b_2,
164
+ )
165
+ prompts_to_judge.append(
166
+ PromptToJudge(
167
+ comparison_type="pairwise_judgement",
168
+ prompt_text=multi_turn_prompt,
169
+ candidate_is_a=candidate_is_a,
170
+ )
171
+ )
172
+ # Reference answer needed
173
+ elif context.reference:
174
+ # SINGLE TURN
175
+ if len(response.messages) <= 2 and len(context.reference) >= 1:
176
+ # turn 1
177
+ question = response.last_user_instruction
178
+ candidate_answer = response.completion
179
+ reference_answer = context.answer[0]
180
+ ref_answer_1 = context.reference[0]
181
+ answer_a, answer_b = order_answers_for_comparison(candidate_answer, reference_answer, swap_order)
182
+
183
+ # format prompt
184
+ single_turn_prompt = prompt_templates["pair_assistant_single_turn_w_reference"]["prompt_template"].format(
185
+ question=question, answer_a=answer_a, answer_b=answer_b, ref_answer_1=ref_answer_1
186
+ )
187
+ prompts_to_judge.append(
188
+ PromptToJudge(
189
+ comparison_type="pairwise_judgement",
190
+ prompt_text=single_turn_prompt,
191
+ candidate_is_a=candidate_is_a,
192
+ )
193
+ )
194
+ # MULTI TURN
195
+ elif len(context.reference) >= 2:
196
+ # turn 1
197
+ question_1 = response.first_user_instruction
198
+ candidate_answer_1 = response.messages[1].content
199
+ reference_answer_1 = context.answer[0]
200
+ ref_answer_1 = context.reference[0]
201
+ # turn 2
202
+ question_2 = response.last_user_instruction
203
+ candidate_answer_2 = response.completion
204
+ reference_answer_2 = context.answer[1]
205
+ ref_answer_2 = context.reference[1]
206
+ answer_a_1, answer_b_1 = order_answers_for_comparison(candidate_answer_1, reference_answer_1, swap_order)
207
+ answer_a_2, answer_b_2 = order_answers_for_comparison(candidate_answer_2, reference_answer_2, swap_order)
208
+
209
+ # format prompt
210
+ multi_turn_prompt = prompt_templates["pair_assistant_multi_turn_w_reference"]["prompt_template"].format(
211
+ question_1=question_1,
212
+ answer_a_1=answer_a_1,
213
+ answer_b_1=answer_b_1,
214
+ ref_answer_1=ref_answer_1,
215
+ question_2=question_2,
216
+ answer_a_2=answer_a_2,
217
+ answer_b_2=answer_b_2,
218
+ ref_answer_2=ref_answer_2,
219
+ )
220
+ prompts_to_judge.append(
221
+ PromptToJudge(
222
+ comparison_type="pairwise_judgement",
223
+ prompt_text=multi_turn_prompt,
224
+ candidate_is_a=candidate_is_a,
225
+ )
226
+ )
227
+ else:
228
+ logger.info(
229
+ f"Warning: No reference answer found for this sample (category: "
230
+ f"{context.category}), even though it is needed."
231
+ )
232
+
233
+ return prompts_to_judge
234
+
235
+
236
+ class MTBenchJudgePair(BaseLLMJudgeMetric):
237
+ NAME = "pairwise_judgement"
238
+
239
+ def calculate(self, response: Completion) -> list[MetricResult]:
240
+ response_error = response.error
241
+ if response_error:
242
+ logger.info(f"Skipped LLM judge as completion already had an error {response_error}")
243
+ return []
244
+
245
+ prompts_to_judge: list[PromptToJudge] = generate_pair_judge_prompts(
246
+ response, randomize_order=self._randomize_order
247
+ )
248
+
249
+ all_metrics = []
250
+ for prompt_to_judge in prompts_to_judge:
251
+ messages = [Message(role=Role.USER, content=prompt_to_judge.prompt_text)]
252
+ all_metrics.append(self._evaluate_prompt(prompt_to_judge, messages))
253
+
254
+ return all_metrics
255
+
256
+ def _evaluate_prompt(self, prompt_to_judge: PromptToJudge, messages: list[Message]) -> MetricResult:
257
+ try:
258
+ output = self._llm_judge.generate_from_messages([messages])
259
+ parsed_output = self._output_to_rating(
260
+ output[0].completion,
261
+ candidate_is_a=prompt_to_judge.candidate_is_a,
262
+ )
263
+ return self._create_metric_result(
264
+ metric_name=prompt_to_judge.comparison_type,
265
+ value=parsed_output,
266
+ higher_is_better=True,
267
+ llm_judge_prompt=prompt_to_judge.prompt_text,
268
+ llm_judge_response=f"{output[0].completion}", # unprocessed AI feedback
269
+ error=output[0].raw_completion_error,
270
+ )
271
+ except Exception as e:
272
+ logger.info(f"LLM judge failed to generate output for prompt: {prompt_to_judge.prompt_text}. Error: {e}")
273
+ return self._create_metric_result(
274
+ metric_name=prompt_to_judge.comparison_type,
275
+ value=None,
276
+ higher_is_better=True,
277
+ error=Error(error_class=e.__class__.__name__, message=str(e), traceback=traceback.format_exc()),
278
+ )
279
+
280
+ @staticmethod
281
+ def _output_to_rating(output: str, candidate_is_a: bool = True) -> float:
282
+ """Convert judge output to a rating score for the candidate.
283
+
284
+ Args:
285
+ output: The raw output string from the LLM judge containing [[A]], [[B]], or [[C]].
286
+ candidate_is_a: Whether the candidate completion was in position A.
287
+ If False (candidate was in position B), the A/B interpretation is flipped.
288
+
289
+ Returns:
290
+ Float score: 1.0 if candidate wins, 0.0 if candidate loses, 0.5 for tie.
291
+ """
292
+ match = re.search(r"\[\[(.*?)\]\]", output)
293
+ # Raw interpretation: A = position A wins, B = position B wins, C = Tie
294
+ if match:
295
+ value = match.group(1)
296
+ if value == "A":
297
+ # Position A wins - candidate wins if candidate_is_a, else loses
298
+ return 1.0 if candidate_is_a else 0.0
299
+ elif value == "B":
300
+ # Position B wins - candidate wins if NOT candidate_is_a, else loses
301
+ return 0.0 if candidate_is_a else 1.0
302
+ elif value == "C":
303
+ # Tie - always 0.5 regardless of position
304
+ return 0.5
305
+ logger.warning(f"Could not parse judge output, defaulting to tie: {output[:200]}")
306
+ return 0.5
@@ -0,0 +1,210 @@
1
+ import re
2
+ import traceback
3
+
4
+ from pydantic import BaseModel
5
+
6
+ from eval_framework.logger import logger
7
+ from eval_framework.metrics.base import MetricResult
8
+ from eval_framework.metrics.llm.base import BaseLLMJudgeMetric
9
+ from eval_framework.shared.types import BaseMetricContext, Completion, Error, extract_context_metric
10
+ from template_formatting.formatter import Message, Role
11
+
12
+ SINGLE_JUDGE_PROMPTS = {
13
+ "single_assistant_single_turn": {
14
+ "prompt_template": '[System]\nYou are a helpful assistant.\n\n[Instruction]\nPlease act as an impartial judge and evaluate the quality of the response provided by an AI assistant to the user question displayed below. Your evaluation should consider factors such as the helpfulness, relevance, accuracy, depth, creativity, and level of detail of the response. Begin your evaluation by providing a short explanation. Be as objective as possible. After providing your explanation, you must rate the response on a scale of 1 to 10 by strictly following this format: "[[rating]]", for example: "Rating: [[5]]".\n\n[Question]\n{question}\n\n[The Start of Assistant\'s Answer]\n{answer}\n[The End of Assistant\'s Answer]' # noqa: E501
15
+ },
16
+ "single_assistant_multi_turn": {
17
+ "prompt_template": 'Please act as an impartial judge and evaluate the quality of the response provided by an AI assistant to the user question displayed below. Your evaluation should consider factors such as the helpfulness, relevance, accuracy, depth, creativity, and level of detail of the response. You evaluation should focus on the assistant\'s answer to the second user question. Begin your evaluation by providing a short explanation. Be as objective as possible. After providing your explanation, you must rate the response on a scale of 1 to 10 by strictly following this format: "[[rating]]", for example: "Rating: [[5]]".\n\n<|The Start of Assistant A\'s Conversation with User|>\n\n### User:\n{question_1}\n\n### Assistant A:\n{answer_1}\n\n### User:\n{question_2}\n\n### Assistant A:\n{answer_2}\n\n<|The End of Assistant A\'s Conversation with User|>' # noqa: E501
18
+ },
19
+ "single_assistant_single_turn_w_reference": {
20
+ "prompt_template": "[System]\nYou are a helpful assistant.\n\n[Instruction]\nPlease act as an impartial judge and evaluate the quality of the response provided by an AI assistant to the user question displayed below. Your evaluation should consider correctness and helpfulness. You will be given a reference answer and the assistant's answer. Begin your evaluation by comparing the assistant's answer with the reference answer. Identify and correct any mistakes. Be as objective as possible. After providing your explanation, you must rate the response on a scale of 1 to 10 by strictly following this format: \"[[rating]]\", for example: \"Rating: [[5]]\".\n\n[Question]\n{question}\n\n[The Start of Reference Answer]\n{ref_answer_1}\n[The End of Reference Answer]\n\n[The Start of Assistant's Answer]\n{answer}\n[The End of Assistant's Answer]" # noqa: E501
21
+ },
22
+ "single_assistant_multi_turn_w_reference": {
23
+ "prompt_template": "Please act as an impartial judge and evaluate the quality of the response provided by an AI assistant to the user question. Your evaluation should consider correctness and helpfulness. You will be given a reference answer and the assistant's answer. You evaluation should focus on the assistant's answer to the second question. Begin your evaluation by comparing the assistant's answer with the reference answer. Identify and correct any mistakes. Be as objective as possible. After providing your explanation, you must rate the response on a scale of 1 to 10 by strictly following this format: \"[[rating]]\", for example: \"Rating: [[5]]\".\n\n<|The Start of Reference Answer|>\n\n### User:\n{question_1}\n\n### Reference answer:\n{ref_answer_1}\n\n### User:\n{question_2}\n\n### Reference answer:\n{ref_answer_2}\n\n<|The End of Reference Answer|>\n\n\n<|The Start of Assistant A's Conversation with User|>\n\n### User:\n{question_1}\n\n### Assistant A:\n{answer_1}\n\n### User:\n{question_2}\n\n### Assistant A:\n{answer_2}\n\n<|The End of Assistant A's Conversation with User|>" # noqa: E501
24
+ },
25
+ }
26
+
27
+ SINGLE_JUDGE_PROMPTS_DE = {
28
+ "single_assistant_single_turn": {
29
+ "prompt_template": '[System]\nDu bist ein hilfreicher Assistent.\n\n[Anweisung]\nBitte agieren Sie als unparteiischer Richter und bewerten Sie die Qualität der Antwort, die von einem KI-Assistenten auf die unten angezeigte Nutzerfrage gegeben wurde. Ihre Bewertung sollte Faktoren wie Nützlichkeit, Relevanz, Genauigkeit, Tiefe, Kreativität und Detailliertheit der Antwort berücksichtigen. Beginnen Sie Ihre Bewertung mit einer kurzen Erklärung. Seien Sie so objektiv wie möglich. Nachdem Sie Ihre Erklärung gegeben haben, müssen Sie die Antwort auf einer Skala von 1 bis 10 bewerten und dabei streng dieses Format einhalten: "[[rating]]", zum Beispiel: "Bewertung: [[5]]".\n\n[Frage]\n{question}\n\n[Der Anfang der Assistentenantwort]\n{answer}\n[Das Ende der Assistentenantwort]' # noqa: E501
30
+ },
31
+ "single_assistant_multi_turn": {
32
+ "prompt_template": 'Bitte agieren Sie als unparteiischer Richter und bewerten Sie die Qualität der Antwort, die von einem KI-Assistenten auf die unten angezeigte Nutzerfrage gegeben wurde. Ihre Bewertung sollte Faktoren wie Nützlichkeit, Relevanz, Genauigkeit, Tiefe, Kreativität und Detailliertheit der Antwort berücksichtigen. Ihre Bewertung sollte sich auf die Antwort des Assistenten auf die zweite Nutzerfrage konzentrieren. Beginnen Sie Ihre Bewertung mit einer kurzen Erklärung. Seien Sie so objektiv wie möglich. Nachdem Sie Ihre Erklärung gegeben haben, müssen Sie die Antwort auf einer Skala von 1 bis 10 bewerten, wobei Sie streng dieses Format einhalten: "[[rating]]", zum Beispiel: "Bewertung: [[5]]".\n\n<|Der Anfang von Assistent A\'s Unterhaltung mit dem Nutzer|>\n\n### Nutzer:\n{question_1}\n\n### Assistent A:\n{answer_1}\n\n### Nutzer:\n{question_2}\n\n### Assistent A:\n{answer_2}\n\n<|Das Ende von Assistent A\'s Unterhaltung mit dem Nutzer|>' # noqa: E501
33
+ },
34
+ "single_assistant_single_turn_w_reference": {
35
+ "prompt_template": '[System]\nDu bist ein hilfreicher Assistent.\n\n[Anweisung]\nBitte agieren Sie als unparteiischer Richter und bewerten Sie die Qualität der Antwort, die von einem KI-Assistenten auf die unten angezeigte Nutzerfrage gegeben wurde. Ihre Bewertung sollte Korrektheit und Nützlichkeit berücksichtigen. Ihnen wird eine Referenzantwort und die Antwort des Assistenten gegeben. Beginnen Sie Ihre Bewertung, indem Sie die Antwort des Assistenten mit der Referenzantwort vergleichen. Identifizieren Sie und korrigieren Sie etwaige Fehler. Seien Sie so objektiv wie möglich. Nachdem Sie Ihre Erklärung gegeben haben, müssen Sie die Antwort auf einer Skala von 1 bis 10 bewerten und dabei streng dieses Format einhalten: "[[rating]]", zum Beispiel: "Bewertung: [[5]]".\n\n[Frage]\n{question}\n\n[Der Anfang der Referenzantwort]\n{ref_answer_1}\n[Das Ende der Referenzantwort]\n\n[Der Anfang der Assistentenantwort]\n{answer}\n[Das Ende der Assistentenantwort]' # noqa: E501
36
+ },
37
+ "single_assistant_multi_turn_w_reference": {
38
+ "prompt_template": 'Bitte agieren Sie als unparteiischer Richter und bewerten Sie die Qualität der Antwort, die von einem KI-Assistenten auf die Nutzerfrage gegeben wurde. Ihre Bewertung sollte Korrektheit und Nützlichkeit berücksichtigen. Ihnen wird eine Referenzantwort und die Antwort des Assistenten gegeben. Ihre Bewertung sollte sich auf die Antwort des Assistenten auf die zweite Frage konzentrieren. Beginnen Sie Ihre Bewertung, indem Sie die Antwort des Assistenten mit der Referenzantwort vergleichen. Identifizieren und korrigieren Sie etwaige Fehler. Seien Sie so objektiv wie möglich. Nachdem Sie Ihre Erklärung gegeben haben, müssen Sie die Antwort auf einer Skala von 1 bis 10 bewerten, wobei Sie streng dieses Format einhalten: "[[rating]]", zum Beispiel: "Bewertung: [[5]]".\n\n<|Der Anfang der Referenzantwort|>\n\n### Nutzer:\n{question_1}\n\n### Referenzantwort:\n{ref_answer_1}\n\n### Nutzer:\n{question_2}\n\n### Referenzantwort:\n{ref_answer_2}\n\n<|Das Ende der Referenzantwort|>\n\n\n<|Der Anfang von Assistent A\'s Unterhaltung mit dem Nutzer|>\n\n### Nutzer:\n{question_1}\n\n### Assistent A:\n{answer_1}\n\n### Nutzer:\n{question_2}\n\n### Assistent A:\n{answer_2}\n\n<|Das Ende von Assistent A\'s Unterhaltung mit dem Nutzer|>' # noqa: E501
39
+ },
40
+ }
41
+
42
+
43
+ SINGLE_JUDGE_PROMPTS_FI = {
44
+ "single_assistant_single_turn": {
45
+ "prompt_template": '[Järjestelmä]\nOlet avulias avustaja.\n\n[Ohje]\nToimi puolueettomana tuomarina ja arvioi AI-avustajan antaman vastauksen laatua käyttäjän kysymykseen, joka näkyy alla. Arviosi tulisi ottaa huomioon tekijät kuten hyödyllisyys, asiaankuuluvuus, tarkkuus, syvällisyys, luovuus ja yksityiskohtien taso. Aloita arviointisi antamalla lyhyt selitys. Ole mahdollisimman objektiivinen. Selityksen jälkeen sinun on arvioitava vastaus asteikolla 1–10 noudattamalla tarkasti tätä muotoa: "[[arvosana]]", esimerkiksi: "Arvosana: [[5]]".\n\n[Kysymys]\n{question}\n\n[Avustajan vastauksen alku]\n{answer}\n[Avustajan vastauksen loppu]' # noqa: E501
46
+ },
47
+ "single_assistant_multi_turn": {
48
+ "prompt_template": 'Toimi puolueettomana tuomarina ja arvioi AI-avustajan antaman vastauksen laatua käyttäjän kysymykseen, joka näkyy alla. Arviosi tulisi ottaa huomioon tekijät kuten hyödyllisyys, asiaankuuluvuus, tarkkuus, syvällisyys, luovuus ja yksityiskohtien taso. Arviosi tulisi keskittyä avustajan vastaukseen toiseen käyttäjän kysymykseen. Aloita arviointisi antamalla lyhyt selitys. Ole mahdollisimman objektiivinen. Selityksen jälkeen sinun on arvioitava vastaus asteikolla 1–10 noudattamalla tarkasti tätä muotoa: "[[arvosana]]", esimerkiksi: "Arvosana: [[5]]".\n\n<|Avustaja A:n keskustelun alku käyttäjän kanssa|>\n\n### Käyttäjä:\n{question_1}\n\n### Avustaja A:\n{answer_1}\n\n### Käyttäjä:\n{question_2}\n\n### Avustaja A:\n{answer_2}\n\n<|Avustaja A:n keskustelun loppu käyttäjän kanssa|>' # noqa: E501
49
+ },
50
+ "single_assistant_single_turn_w_reference": {
51
+ "prompt_template": '[Järjestelmä]\nOlet avulias avustaja.\n\n[Ohje]\nToimi puolueettomana tuomarina ja arvioi AI-avustajan antaman vastauksen laatua käyttäjän kysymykseen, joka näkyy alla. Arviosi tulisi ottaa huomioon oikeellisuus ja hyödyllisyys. Sinulle annetaan viitevastaus ja avustajan vastaus. Aloita arviointisi vertaamalla avustajan vastausta viitevastaukseen. Tunnista ja korjaa mahdolliset virheet. Ole mahdollisimman objektiivinen. Selityksen jälkeen sinun on arvioitava vastaus asteikolla 1–10 noudattamalla tarkasti tätä muotoa: "[[arvosana]]", esimerkiksi: "Arvosana: [[5]]".\n\n[Kysymys]\n{question}\n\n[Viitevastauksen alku]\n{ref_answer_1}\n[Viitevastauksen loppu]\n\n[Avustajan vastauksen alku]\n{answer}\n[Avustajan vastauksen loppu]' # noqa: E501
52
+ },
53
+ "single_assistant_multi_turn_w_reference": {
54
+ "prompt_template": 'Toimi puolueettomana tuomarina ja arvioi AI-avustajan antaman vastauksen laatua käyttäjän kysymykseen. Arviosi tulisi ottaa huomioon oikeellisuus ja hyödyllisyys. Sinulle annetaan viitevastaus ja avustajan vastaus. Arviosi tulisi keskittyä avustajan vastaukseen toiseen kysymykseen. Aloita arviointisi vertaamalla avustajan vastausta viitevastaukseen. Tunnista ja korjaa mahdolliset virheet. Ole mahdollisimman objektiivinen. Selityksen jälkeen sinun on arvioitava vastaus asteikolla 1–10 noudattamalla tarkasti tätä muotoa: "[[arvosana]]", esimerkiksi: "Arvosana: [[5]]".\n\n<|Viitevastauksen alku|>\n\n### Käyttäjä:\n{question_1}\n\n### Viitevastaus:\n{ref_answer_1}\n\n### Käyttäjä:\n{question_2}\n\n### Viitevastaus:\n{ref_answer_2}\n\n<|Viitevastauksen loppu|>\n\n\n<|Avustaja A:n keskustelun alku käyttäjän kanssa|>\n\n### Käyttäjä:\n{question_1}\n\n### Avustaja A:\n{answer_1}\n\n### Käyttäjä:\n{question_2}\n\n### Avustaja A:\n{answer_2}\n\n<|Avustaja A:n keskustelun loppu käyttäjän kanssa|>' # noqa: E501
55
+ },
56
+ }
57
+
58
+ NEED_REF_CATEGORIES = ["math", "reasoning", "coding", "arena-hard-200"]
59
+ SINGLE_JUDGE_PROMPTS_LIST = [
60
+ SINGLE_JUDGE_PROMPTS,
61
+ SINGLE_JUDGE_PROMPTS_DE,
62
+ SINGLE_JUDGE_PROMPTS_FI,
63
+ ]
64
+
65
+
66
+ class PromptToJudge(BaseModel):
67
+ comparison_type: str
68
+ prompt_text: str
69
+
70
+
71
+ class MTBenchJudgeSingleMetricContext(BaseMetricContext):
72
+ category: str
73
+ reference: list[str] | str | None
74
+
75
+
76
+ def generate_single_judge_prompts(response: Completion) -> list[PromptToJudge]:
77
+ context = extract_context_metric(response, MTBenchJudgeSingleMetricContext)
78
+
79
+ assert response.messages is not None
80
+
81
+ if response.subject.startswith("de"):
82
+ prompt_templates = SINGLE_JUDGE_PROMPTS_DE
83
+ elif response.subject.startswith("fi"):
84
+ prompt_templates = SINGLE_JUDGE_PROMPTS_FI
85
+ else:
86
+ prompt_templates = SINGLE_JUDGE_PROMPTS
87
+ prompts_to_judge = []
88
+
89
+ assert context.category is not None, "Category must be provided in the context for MTBenchJudgeSingleMetricContext"
90
+
91
+ # No reference answer needed
92
+ if context.category not in NEED_REF_CATEGORIES:
93
+ # SINLGE TURN
94
+ if len(response.messages) <= 2:
95
+ # turn 1
96
+ question = response.last_user_instruction
97
+ answer = response.completion
98
+ # format prompt
99
+ single_turn_prompt = prompt_templates["single_assistant_single_turn"]["prompt_template"].format(
100
+ question=question,
101
+ answer=answer,
102
+ )
103
+ prompts_to_judge.append(PromptToJudge(comparison_type="single_judgement", prompt_text=single_turn_prompt))
104
+ # MULTI TURN
105
+ else:
106
+ # turn 1
107
+ question_1 = response.first_user_instruction
108
+ answer_1 = response.messages[1].content
109
+ # turn 2
110
+ question_2 = response.last_user_instruction
111
+ answer_2 = response.completion
112
+ # format prompt
113
+ multi_turn_prompt = prompt_templates["single_assistant_multi_turn"]["prompt_template"].format(
114
+ question_1=question_1, answer_1=answer_1, question_2=question_2, answer_2=answer_2
115
+ )
116
+ prompts_to_judge.append(PromptToJudge(comparison_type="single_judgement", prompt_text=multi_turn_prompt))
117
+ # Reference answer needed
118
+ elif context.reference:
119
+ # SINGLE TURN
120
+ if len(response.messages) <= 2 and len(context.reference) >= 1:
121
+ # turn 1
122
+ question = response.last_user_instruction
123
+ answer = response.completion
124
+ ref_answer = context.reference[0]
125
+ # format prompt
126
+ single_turn_prompt = prompt_templates["single_assistant_single_turn_w_reference"]["prompt_template"].format(
127
+ question=question,
128
+ answer=answer,
129
+ ref_answer_1=ref_answer,
130
+ )
131
+ prompts_to_judge.append(PromptToJudge(comparison_type="single_judgement", prompt_text=single_turn_prompt))
132
+ # MULTI TURN
133
+ elif len(context.reference) >= 2:
134
+ # turn 1
135
+ question_1 = response.first_user_instruction
136
+ answer_1 = response.messages[1].content
137
+ ref_answer_1 = context.reference[0]
138
+ # turn 2
139
+ question_2 = response.last_user_instruction
140
+ answer_2 = response.completion
141
+ ref_answer_2 = context.reference[1]
142
+ # format prompt
143
+ multi_turn_prompt = prompt_templates["single_assistant_multi_turn_w_reference"]["prompt_template"].format(
144
+ question_1=question_1,
145
+ answer_1=answer_1,
146
+ ref_answer_1=ref_answer_1,
147
+ question_2=question_2,
148
+ answer_2=answer_2,
149
+ ref_answer_2=ref_answer_2,
150
+ )
151
+ prompts_to_judge.append(PromptToJudge(comparison_type="single_judgement", prompt_text=multi_turn_prompt))
152
+ else:
153
+ logger.info(
154
+ f"Warning: No reference answer found for this sample (category: "
155
+ f"{context.category}), even though it is needed."
156
+ )
157
+
158
+ return prompts_to_judge
159
+
160
+
161
+ class MTBenchJudgeSingle(BaseLLMJudgeMetric):
162
+ NAME = "single_judgement"
163
+
164
+ def calculate(self, response: Completion) -> list[MetricResult]:
165
+ prompts_to_judge: list[PromptToJudge] = generate_single_judge_prompts(response)
166
+
167
+ all_metrics: list[MetricResult] = []
168
+ for prompt_to_judge in prompts_to_judge:
169
+ messages = [Message(role=Role.USER, content=prompt_to_judge.prompt_text)]
170
+ all_metrics.append(self._evaluate_prompt(prompt_to_judge, messages))
171
+
172
+ return all_metrics
173
+
174
+ def _evaluate_prompt(self, prompt_to_judge: PromptToJudge, messages: list[Message]) -> MetricResult:
175
+ try:
176
+ output = self._llm_judge.generate_from_messages([messages])
177
+ parsed_output = self._output_to_rating(output[0].completion)
178
+ return self._create_metric_result(
179
+ metric_name=prompt_to_judge.comparison_type,
180
+ value=parsed_output,
181
+ higher_is_better=True,
182
+ llm_judge_prompt=prompt_to_judge.prompt_text,
183
+ llm_judge_response=f"{output[0].completion}", # unprocessed AI feedback
184
+ error=output[0].raw_completion_error,
185
+ )
186
+ except Exception as e:
187
+ logger.info(f"LLM judge failed to generate output for prompt: {prompt_to_judge.prompt_text}. Error: {e}")
188
+ return self._create_metric_result(
189
+ metric_name=prompt_to_judge.comparison_type,
190
+ value=None,
191
+ higher_is_better=True,
192
+ error=Error(error_class=e.__class__.__name__, message=str(e), traceback=traceback.format_exc()),
193
+ )
194
+
195
+ @staticmethod
196
+ def _output_to_rating(output: str) -> float:
197
+ """Convert judge output to a rating score.
198
+
199
+ Args:
200
+ output: The raw output string from the LLM judge containing [[N]] where N is a number.
201
+
202
+ Returns:
203
+ Float score extracted from the output, or 0 if the output could not be parsed.
204
+ """
205
+ match = re.search(r"\[\[(\d+)\]\]", output)
206
+
207
+ if match:
208
+ return float(match.group(1))
209
+ logger.warning(f"Could not parse judge output, defaulting to 0: {output[:200]}")
210
+ return 0
@@ -0,0 +1,35 @@
1
+ from eval_framework.llm.base import BaseLLM
2
+ from eval_framework.metrics.base import MetricResult
3
+ from eval_framework.metrics.llm.base import BaseLLMJudgeMetric
4
+ from eval_framework.metrics.llm.graders.language import Language
5
+ from eval_framework.metrics.llm.graders.refusal_grader import RefusalGrader
6
+ from eval_framework.shared.types import Completion
7
+
8
+
9
+ class LLMJudgeRefusal(BaseLLMJudgeMetric):
10
+ NAME = "refusal_classifier"
11
+
12
+ def __init__(self, llm_judge: BaseLLM):
13
+ super().__init__(llm_judge)
14
+ self._grader = RefusalGrader(llm_judge)
15
+
16
+ def calculate(self, response: Completion) -> list[MetricResult]:
17
+ if response.error is not None:
18
+ return [MetricResult(metric_name=self.NAME, value=None, higher_is_better=False, error=response.error)]
19
+
20
+ language = response.get_completion_language() or response.get_instruction_language() or "en"
21
+ grading = self._grader.grade(
22
+ completion=response.sanitized_completion,
23
+ language=Language(language),
24
+ )
25
+
26
+ return [
27
+ MetricResult(
28
+ metric_name=self.NAME,
29
+ value=float(grading.is_refusal) if grading.is_refusal is not None else None,
30
+ higher_is_better=True,
31
+ llm_judge_prompt=grading.judge_prompt,
32
+ llm_judge_response=grading.judge_response,
33
+ error=response.error,
34
+ )
35
+ ]