evalscope 0.10.0__py3-none-any.whl → 0.11.0__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.
Potentially problematic release.
This version of evalscope might be problematic. Click here for more details.
- evalscope/arguments.py +1 -0
- evalscope/benchmarks/aime24/__init__.py +0 -0
- evalscope/benchmarks/aime24/aime24_adapter.py +49 -0
- evalscope/benchmarks/arc/arc_adapter.py +5 -7
- evalscope/benchmarks/bbh/bbh_adapter.py +17 -9
- evalscope/benchmarks/benchmark.py +2 -2
- evalscope/benchmarks/ceval/ceval_adapter.py +9 -9
- evalscope/benchmarks/cmmlu/cmmlu_adapter.py +9 -11
- evalscope/benchmarks/competition_math/competition_math_adapter.py +34 -23
- evalscope/benchmarks/data_adapter.py +18 -12
- evalscope/benchmarks/data_collection/__init__.py +0 -0
- evalscope/benchmarks/data_collection/data_collection_adapter.py +71 -0
- evalscope/benchmarks/general_mcq/__init__.py +0 -0
- evalscope/benchmarks/general_mcq/general_mcq_adapter.py +129 -0
- evalscope/benchmarks/general_qa/general_qa_adapter.py +6 -6
- evalscope/benchmarks/gpqa/__init__.py +0 -0
- evalscope/benchmarks/gpqa/chain_of_thought.txt +81 -0
- evalscope/benchmarks/gpqa/gpqa_adapter.py +121 -0
- evalscope/benchmarks/gsm8k/gsm8k_adapter.py +8 -13
- evalscope/benchmarks/hellaswag/hellaswag_adapter.py +3 -7
- evalscope/benchmarks/humaneval/humaneval_adapter.py +5 -6
- evalscope/benchmarks/ifeval/ifeval_adapter.py +14 -14
- evalscope/benchmarks/ifeval/instructions.py +3 -4
- evalscope/benchmarks/iquiz/iquiz_adapter.py +5 -5
- evalscope/benchmarks/math_500/__init__.py +0 -0
- evalscope/benchmarks/math_500/math_500_adapter.py +49 -0
- evalscope/benchmarks/mmlu/mmlu_adapter.py +7 -11
- evalscope/benchmarks/mmlu_pro/mmlu_pro_adapter.py +27 -15
- evalscope/benchmarks/race/race_adapter.py +3 -3
- evalscope/benchmarks/trivia_qa/trivia_qa_adapter.py +1 -2
- evalscope/benchmarks/truthful_qa/truthful_qa_adapter.py +8 -8
- evalscope/cli/start_app.py +3 -2
- evalscope/collections/evaluator.py +103 -39
- evalscope/collections/sampler.py +2 -1
- evalscope/collections/schema.py +1 -2
- evalscope/config.py +1 -0
- evalscope/evaluator/evaluator.py +78 -64
- evalscope/metrics/math_parser.py +526 -0
- evalscope/metrics/metrics.py +16 -1
- evalscope/metrics/named_metrics.py +31 -7
- evalscope/models/chat_adapter.py +69 -47
- evalscope/models/choice_adapter.py +52 -45
- evalscope/models/custom_adapter.py +2 -2
- evalscope/models/local_model.py +4 -0
- evalscope/models/server_adapter.py +28 -34
- evalscope/report/app.py +298 -96
- evalscope/run.py +10 -7
- evalscope/utils/chat_service.py +2 -2
- evalscope/utils/io_utils.py +1 -1
- evalscope/version.py +2 -2
- {evalscope-0.10.0.dist-info → evalscope-0.11.0.dist-info}/METADATA +20 -11
- {evalscope-0.10.0.dist-info → evalscope-0.11.0.dist-info}/RECORD +57 -47
- tests/cli/test_run.py +93 -16
- evalscope/benchmarks/ceval/samples.jsonl +0 -1
- evalscope/metrics/math_accuracy.py +0 -200
- {evalscope-0.10.0.dist-info → evalscope-0.11.0.dist-info}/LICENSE +0 -0
- {evalscope-0.10.0.dist-info → evalscope-0.11.0.dist-info}/WHEEL +0 -0
- {evalscope-0.10.0.dist-info → evalscope-0.11.0.dist-info}/entry_points.txt +0 -0
- {evalscope-0.10.0.dist-info → evalscope-0.11.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Copyright (c) Alibaba, Inc. and its affiliates.
|
|
2
|
+
import csv
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
from evalscope.benchmarks import Benchmark, DataAdapter
|
|
6
|
+
from evalscope.constants import EvalType
|
|
7
|
+
from evalscope.metrics.metrics import exact_match
|
|
8
|
+
from evalscope.models import MultiChoiceModelAdapter
|
|
9
|
+
from evalscope.utils import ResponseParser
|
|
10
|
+
from evalscope.utils.logger import get_logger
|
|
11
|
+
|
|
12
|
+
# flake8: noqa
|
|
13
|
+
|
|
14
|
+
logger = get_logger()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@Benchmark.register(
|
|
18
|
+
name='general_mcq',
|
|
19
|
+
dataset_id='general_mcq',
|
|
20
|
+
model_adapter=MultiChoiceModelAdapter,
|
|
21
|
+
subset_list=['default'],
|
|
22
|
+
metric_list=['AverageAccuracy'],
|
|
23
|
+
few_shot_num=0,
|
|
24
|
+
train_split='dev',
|
|
25
|
+
eval_split='val',
|
|
26
|
+
prompt_template='请回答问题,并选出其中的正确答案\n{query}',
|
|
27
|
+
)
|
|
28
|
+
class GeneralMCQAdapter(DataAdapter):
|
|
29
|
+
|
|
30
|
+
choices = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
|
|
31
|
+
|
|
32
|
+
def __init__(self, **kwargs):
|
|
33
|
+
super().__init__(**kwargs)
|
|
34
|
+
|
|
35
|
+
def load_from_disk(self, dataset_name_or_path, subset_list, work_dir, **kwargs) -> dict:
|
|
36
|
+
data_dict = {}
|
|
37
|
+
for subset_name in subset_list:
|
|
38
|
+
for split_name in [self.train_split, self.eval_split]:
|
|
39
|
+
if os.path.exists(dataset_name_or_path):
|
|
40
|
+
file_path = os.path.join(dataset_name_or_path, f'{subset_name}_{split_name}.csv')
|
|
41
|
+
else:
|
|
42
|
+
file_path = os.path.join(work_dir, dataset_name_or_path, f'{subset_name}_{split_name}.csv')
|
|
43
|
+
if os.path.exists(file_path):
|
|
44
|
+
with open(file_path, encoding='utf-8') as f:
|
|
45
|
+
rows = []
|
|
46
|
+
reader = csv.reader(f)
|
|
47
|
+
header = next(reader)
|
|
48
|
+
for row in reader:
|
|
49
|
+
item = dict(zip(header, row))
|
|
50
|
+
rows.append(item)
|
|
51
|
+
|
|
52
|
+
if subset_name in data_dict:
|
|
53
|
+
data_dict[subset_name].update({split_name: rows})
|
|
54
|
+
else:
|
|
55
|
+
data_dict[subset_name] = {split_name: rows}
|
|
56
|
+
|
|
57
|
+
return data_dict
|
|
58
|
+
|
|
59
|
+
def gen_prompt(self, input_d: dict, subset_name: str, few_shot_list: list, **kwargs) -> dict:
|
|
60
|
+
"""
|
|
61
|
+
Generate model prompt from raw input, unify the prompt format for C-Eval benchmark.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
input_d (dict): The raw input. A single data format of the C-Eval:
|
|
65
|
+
|
|
66
|
+
{'id': 0,
|
|
67
|
+
'question': '下列关于税法基本原则的表述中,不正确的是____。',
|
|
68
|
+
'A': '税收法定原则包括税收要件法定原则和税务合法性原则',
|
|
69
|
+
'B': '税收公平原则源于法律上的平等性原则',
|
|
70
|
+
'C': '税收效率原则包含经济效率和行政效率两个方面',
|
|
71
|
+
'D': '税务机关按法定程序依法征税,可以自由做出减征、停征或免征税款的决定',
|
|
72
|
+
'answer': 'D'}
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
{'data': ['prompt ...']}
|
|
76
|
+
"""
|
|
77
|
+
|
|
78
|
+
few_shot_prompts = [self._format_example(input_d=sample, include_answer=True) for sample in few_shot_list]
|
|
79
|
+
|
|
80
|
+
if len(few_shot_prompts) > 0:
|
|
81
|
+
context: str = '\n'.join(few_shot_prompts) + '\n'
|
|
82
|
+
else:
|
|
83
|
+
context = ''
|
|
84
|
+
context = context.strip() + self._format_example(input_d=input_d, include_answer=False)
|
|
85
|
+
|
|
86
|
+
full_prompt = self.prompt_template.format(query=context)
|
|
87
|
+
|
|
88
|
+
return {'data': [full_prompt], 'multi_choices': self.choices, 'system_prompt': self.system_prompt}
|
|
89
|
+
|
|
90
|
+
def get_gold_answer(self, input_d: dict) -> str:
|
|
91
|
+
# Get the gold choice
|
|
92
|
+
return input_d.get('answer', '')
|
|
93
|
+
|
|
94
|
+
def parse_pred_result(self, result: str, raw_input_d: dict = None, eval_type: str = EvalType.CHECKPOINT) -> str:
|
|
95
|
+
"""
|
|
96
|
+
Parse the model output to get the answer. Could be the best choice index.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
result: Predicted answer from the model. Usually a string for chat.
|
|
100
|
+
raw_input_d (dict): The raw input. Depending on the dataset.
|
|
101
|
+
eval_type: `checkpoint` or `service` or `custom`. Default is `checkpoint`.
|
|
102
|
+
|
|
103
|
+
Returns:
|
|
104
|
+
The parsed answer. Depending on the dataset. Usually a string for chat.
|
|
105
|
+
"""
|
|
106
|
+
if eval_type == EvalType.CHECKPOINT:
|
|
107
|
+
return result
|
|
108
|
+
elif eval_type == EvalType.SERVICE:
|
|
109
|
+
return ResponseParser.parse_first_option_with_choices(result, self.choices)
|
|
110
|
+
elif eval_type == EvalType.CUSTOM:
|
|
111
|
+
return ResponseParser.parse_first_option_with_choices(result, self.choices)
|
|
112
|
+
else:
|
|
113
|
+
raise ValueError(f'Invalid eval_type: {eval_type}')
|
|
114
|
+
|
|
115
|
+
def match(self, gold: str, pred: str) -> float:
|
|
116
|
+
return exact_match(gold=gold, pred=pred)
|
|
117
|
+
|
|
118
|
+
@classmethod
|
|
119
|
+
def _format_example(cls, input_d: dict, include_answer=True):
|
|
120
|
+
example = '问题:' + input_d['question']
|
|
121
|
+
for choice in cls.choices:
|
|
122
|
+
if choice in input_d:
|
|
123
|
+
example += f'\n{choice}. {input_d[f"{choice}"]}'
|
|
124
|
+
|
|
125
|
+
if include_answer:
|
|
126
|
+
example += '\n答案: ' + input_d['answer'] + '\n\n'
|
|
127
|
+
else:
|
|
128
|
+
example += '\n答案: '
|
|
129
|
+
return example
|
|
@@ -5,7 +5,7 @@ from collections import defaultdict
|
|
|
5
5
|
from typing import List
|
|
6
6
|
|
|
7
7
|
from evalscope.benchmarks import Benchmark, DataAdapter
|
|
8
|
-
from evalscope.metrics import
|
|
8
|
+
from evalscope.metrics import bleu_ngram_one_sample, compute_rouge_score_one_sample_zh, mean
|
|
9
9
|
from evalscope.models import ChatGenerationModelAdapter
|
|
10
10
|
from evalscope.utils.io_utils import jsonl_to_list
|
|
11
11
|
from evalscope.utils.logger import get_logger
|
|
@@ -18,7 +18,7 @@ logger = get_logger()
|
|
|
18
18
|
dataset_id='general_qa',
|
|
19
19
|
model_adapter=ChatGenerationModelAdapter,
|
|
20
20
|
subset_list=['default'],
|
|
21
|
-
metric_list=[AverageBLEU],
|
|
21
|
+
metric_list=['AverageBLEU'],
|
|
22
22
|
few_shot_num=0,
|
|
23
23
|
train_split=None,
|
|
24
24
|
eval_split='test',
|
|
@@ -30,16 +30,16 @@ class GeneralQAAdapter(DataAdapter):
|
|
|
30
30
|
|
|
31
31
|
super().__init__(**kwargs)
|
|
32
32
|
|
|
33
|
-
def load(self,
|
|
33
|
+
def load(self, **kwargs) -> dict:
|
|
34
34
|
|
|
35
|
-
data_file_list = glob.glob(os.path.join(
|
|
35
|
+
data_file_list = glob.glob(os.path.join(self.dataset_id, '*.jsonl'))
|
|
36
36
|
data_list = []
|
|
37
37
|
|
|
38
38
|
try:
|
|
39
39
|
for file_path in data_file_list:
|
|
40
40
|
data_list.extend(jsonl_to_list(file_path))
|
|
41
41
|
except Exception as e:
|
|
42
|
-
raise ValueError(f'Failed to load data from {
|
|
42
|
+
raise ValueError(f'Failed to load data from {self.dataset_id}, got error: {e}')
|
|
43
43
|
|
|
44
44
|
data_dict = {'default': {'test': data_list}}
|
|
45
45
|
|
|
@@ -66,7 +66,7 @@ class GeneralQAAdapter(DataAdapter):
|
|
|
66
66
|
|
|
67
67
|
# if len(history) > 0:
|
|
68
68
|
# prompt = '\n'.join(history) + '\n' + prompt
|
|
69
|
-
return {'data': [prompt], 'system_prompt': self.
|
|
69
|
+
return {'data': [prompt], 'system_prompt': self.system_prompt}
|
|
70
70
|
|
|
71
71
|
def get_gold_answer(self, input_d: dict) -> str:
|
|
72
72
|
"""
|
|
File without changes
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
Question: In a given population, 1 out of every 400 people has a cancer caused by a completely recessive allele, b. Assuming the population is in Hardy-Weinberg equilibrium, which of the following is the expected proportion of individuals who carry the b allele but are not expected to develop the cancer?
|
|
2
|
+
Choices:
|
|
3
|
+
(A) 1/400
|
|
4
|
+
(B) 19/400
|
|
5
|
+
(C) 20/400
|
|
6
|
+
(D) 38/400
|
|
7
|
+
Let's think step by step:
|
|
8
|
+
The expected proportion of individuals who carry the b allele but are not expected to develop the cancer equals to the frequency of heterozygous allele in the given population.
|
|
9
|
+
According to the Hardy-Weinberg equation p∧2 + 2pq + q∧2 = 1, where p is the frequency of dominant allele frequency, q is the frequency of recessive allele frequency, p∧2 is the frequency of the homozygous dominant allele, q∧2 is the frequency of the recessive allele, and 2pq is the frequency of the heterozygous allele.
|
|
10
|
+
Given that q∧2=1/400, hence, q=0.05 and p=1-q=0.95.
|
|
11
|
+
The frequency of the heterozygous allele is 2pq=2*0.05*0.95=38/400.
|
|
12
|
+
The correct answer is (D)
|
|
13
|
+
Question: A Fe pellet of 0.056 g is first dissolved in 10 mL of hydrobromic acid HBr (0.1 M). The resulting solution is then titrated by KMnO4 (0.02 M). How many equivalence points are there?
|
|
14
|
+
Choices:
|
|
15
|
+
(A) Two points, 25 ml and 35 ml
|
|
16
|
+
(B) One point, 25 mL
|
|
17
|
+
(C) One point, 10 ml
|
|
18
|
+
(D) Two points, 25 ml and 30 ml
|
|
19
|
+
Let's think step by step:
|
|
20
|
+
HBr will react with Fe to produce Fe2+. MnO4- will first react with Fe2+ then Br-.
|
|
21
|
+
Two equivalence points will exist 25 ml and 35 ml.
|
|
22
|
+
HBr will react with Fe to produce Fe2+. MnO4- will first react with Fe2+ then Br-.
|
|
23
|
+
Two equivalence points will exist 25 ml and 35 ml.
|
|
24
|
+
In the beaker there is Fe2+ and Br-.
|
|
25
|
+
When considering titration with two analytes one will have to consider which reaction will occur first.
|
|
26
|
+
Since it is a redox titration consider the reduction potential of:
|
|
27
|
+
E0 (Br2 /Br- ) = 1.09 V E0 (MnO4-/ Mn2+) = 1.49 V E0 (Fe3+/Fe2+) =0.77 V
|
|
28
|
+
[Fe2+]=m/MV=0.1M.
|
|
29
|
+
Reaction 1: MnO4- + 5Fe2+ + 8H+ → Mn2+ + 5Fe3+ + 4H2O
|
|
30
|
+
Reaction 2: 2MnO4- + 10Br- + 16H+ → 2Mn2+ + 5Br2 + 8H2O
|
|
31
|
+
So MnO4- will first react with Fe2+ with a stoichiometry of 1:5 so Veq1 will be 10 ml.
|
|
32
|
+
Then when Fe2+ is used up, MnO4- will react with Br- with a stoichiometry of 2:10 then V added will be 25 ml so Veq2=25+10=35 ml.
|
|
33
|
+
The correct answer is (A)
|
|
34
|
+
Question: Consider a quantum mechanical system containing a particle of mass $m$ moving in an istropic three dimensional potential of the form $V(r) = 1/2 m \omega^2 r^2$ corresponding to the acted force obeying Hooke’s law. Here, $\omega$ is the angular frequency of oscillation and $r$ is the radial distance of the particle from the origin in spherical polar coordinate. What is the value of energy of the third excited state, and how many linearly independent eigenfunctions are possible for the same energy eigenvalue?
|
|
35
|
+
Choices:
|
|
36
|
+
(A) 11 \pi^2 \hbar^2 / (2m r^2), 3
|
|
37
|
+
(B) (9/2) \hbar \omega , 10
|
|
38
|
+
(C) 11 \pi^2 \hbar^2 / (2m r^2), 10
|
|
39
|
+
(D) (9/2) \hbar \omega, 3
|
|
40
|
+
Let's think step by step:
|
|
41
|
+
This problem is nothing but the three dimensional simple harmonic oscillator (SHO) problem.
|
|
42
|
+
The energy spectrum of three dimensional SHO is $E_n= (n+3/2)\hbar \omega$ where $n=0,1,2,3….$.
|
|
43
|
+
For third excited state n=3.
|
|
44
|
+
3+3/2=6/2+3/2=9/2.
|
|
45
|
+
Thus the corresponding energy is $(9/2)\hbar \omega$.
|
|
46
|
+
The degeneracy of the state is $g_n= (n+1)(n+2)/2$.
|
|
47
|
+
For n=3, degeneracy is (3+1)*(3+2)/2=4*5/2=10.
|
|
48
|
+
The correct answer is (B)
|
|
49
|
+
Question: "Your overhear two chemists talking to each other as they leave a synthetic organic chemistry lab. One asks the other "So, how did it go?" The second chemist replies, "Not well - my compounds are on top of each other." What is the second chemist most likely referring to?"
|
|
50
|
+
Choices:
|
|
51
|
+
(A) The compounds they are working with have similar polarities.
|
|
52
|
+
(B) The compounds they are working with have similar boiling points.
|
|
53
|
+
(C) The compounds they are working with are bonding to each other through non-covalent/van der Waals interactions.
|
|
54
|
+
(D) The compounds they are working with have similar optical rotations.
|
|
55
|
+
Let's think step by step:
|
|
56
|
+
"On top of each other" commonly refers to two compounds that have similar Rf values on chromatography (a common operation in synthetic chemistry).
|
|
57
|
+
Similar Rf values arise for compounds with similar polarities.
|
|
58
|
+
The correct answer is (A)
|
|
59
|
+
Question: Two people are playing the following game. A fair coin is tossed into the air. Person A says that in a single toss of the coin, the tail will come. So it's like the first shot or the third shot or the fifth shot. Person B says that the coin will come with a double toss. So like the second, fourth, sixth or eighth shot. Imagine this game played forever. What is the probability that person A wins this game?
|
|
60
|
+
Choices:
|
|
61
|
+
(A) 1/2
|
|
62
|
+
(B) 1/4
|
|
63
|
+
(C) 2/3
|
|
64
|
+
(D) 1/8
|
|
65
|
+
Let's think step by step:
|
|
66
|
+
When finding the correct answer, the probability of playing forever and the coin's single-point toss will be calculated.
|
|
67
|
+
For example, a tail may appear on the first shot.
|
|
68
|
+
This probability is 1/2. if the first toss doesn't come up, it shouldn't come to the second roll either, because the second throw is an even number.
|
|
69
|
+
So it can come in the third shot.
|
|
70
|
+
This is (1/2)(1/2)(1/2).
|
|
71
|
+
So (1/2)^3=1/8.
|
|
72
|
+
Or it could come on the fifth shot.
|
|
73
|
+
This is (1/2)^5=1/32.
|
|
74
|
+
This is actually a geometric series that goes on forever.
|
|
75
|
+
We can write this series as follows.
|
|
76
|
+
(1/2) + (1/2)^3 + (1/2)^5 + (1/2)^7 + ……….
|
|
77
|
+
The solution for this series is as follows : a1/(1-r) where a1 is the first number and r is the sequence or r= a2/a1 or a3/a2 etc.
|
|
78
|
+
a1=1/2
|
|
79
|
+
r=(1/2)^2=1/4
|
|
80
|
+
So a1/(1-r)=(1/2)/(1-1/4)=(1/2)/(3/4)=2/3.
|
|
81
|
+
The correct answer is (C)
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import random
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
from evalscope.benchmarks import Benchmark, DataAdapter
|
|
6
|
+
from evalscope.constants import EvalType
|
|
7
|
+
from evalscope.metrics import exact_match
|
|
8
|
+
from evalscope.models import ChatGenerationModelAdapter
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@Benchmark.register(
|
|
12
|
+
name='gpqa',
|
|
13
|
+
dataset_id='modelscope/gpqa',
|
|
14
|
+
model_adapter=ChatGenerationModelAdapter,
|
|
15
|
+
subset_list=['gpqa_extended', 'gpqa_main', 'gpqa_diamond'],
|
|
16
|
+
metric_list=['AveragePass@1'],
|
|
17
|
+
few_shot_num=5,
|
|
18
|
+
train_split='train',
|
|
19
|
+
eval_split='train', # only have train split
|
|
20
|
+
prompt_template='{query}\nPlease reason step by step, and put your final answer within \\boxed{{}}.',
|
|
21
|
+
)
|
|
22
|
+
class GPQAAdapter(DataAdapter):
|
|
23
|
+
|
|
24
|
+
def __init__(self, **kwargs):
|
|
25
|
+
super().__init__(**kwargs)
|
|
26
|
+
|
|
27
|
+
self.choices = ['A', 'B', 'C', 'D']
|
|
28
|
+
if self.few_shot_num and self.few_shot_num > 0:
|
|
29
|
+
self.prompt_prefix = 'Here are some example questions from experts. Answer the final question yourself, following the format of the previous questions exactly.\n' # noqa: E501
|
|
30
|
+
self.prompt_prefix += open(os.path.join(os.path.dirname(__file__), 'chain_of_thought.txt'),
|
|
31
|
+
'r').read() + '\nQuestion: '
|
|
32
|
+
else:
|
|
33
|
+
self.prompt_prefix = 'What is the correct answer to this question:'
|
|
34
|
+
|
|
35
|
+
def gen_prompt(self, input_d: dict, subset_name: str, few_shot_list: list, **kwargs) -> dict:
|
|
36
|
+
"""
|
|
37
|
+
Generate model prompt from input data.
|
|
38
|
+
example:
|
|
39
|
+
{
|
|
40
|
+
"question":"Two people are playing the following game. A fair coin is tossed into the air. Person A says that in a single toss of the coin, the tail will come. So it's like the first shot or the third shot or the fifth shot. Person B says that the coin will come with a double toss. So like the second, fourth, sixth or eighth shot. Imagine this game played forever. What is the probability that person A wins this game?",
|
|
41
|
+
"choice1":"1/2",
|
|
42
|
+
"choice2":"1/4",
|
|
43
|
+
"choice3":"2/3",
|
|
44
|
+
"choice4":"1/8",
|
|
45
|
+
"answer":"C",
|
|
46
|
+
}
|
|
47
|
+
""" # noqa: E501
|
|
48
|
+
processed_input_d = self.__process_input(input_d)
|
|
49
|
+
input_d['answer'] = processed_input_d['answer'] # add answer to input_d for answer extraction
|
|
50
|
+
query = self.prompt_prefix + f"{input_d['Question']}\n{self.__form_options(processed_input_d['choices'])}" # noqa: E501
|
|
51
|
+
|
|
52
|
+
prompt = self.prompt_template.format(query=query)
|
|
53
|
+
return {'data': [prompt], 'multi_choices': self.choices, 'system_prompt': self.system_prompt}
|
|
54
|
+
|
|
55
|
+
def __process_input(self, input_d: dict) -> dict:
|
|
56
|
+
|
|
57
|
+
def preprocess(text):
|
|
58
|
+
if text is None:
|
|
59
|
+
return ' '
|
|
60
|
+
text = text.strip()
|
|
61
|
+
text = text.replace(' [title]', '. ')
|
|
62
|
+
text = re.sub('\\[.*?\\]', '', text)
|
|
63
|
+
text = text.replace(' ', ' ')
|
|
64
|
+
return text
|
|
65
|
+
|
|
66
|
+
choices = [
|
|
67
|
+
preprocess(input_d['Incorrect Answer 1']),
|
|
68
|
+
preprocess(input_d['Incorrect Answer 2']),
|
|
69
|
+
preprocess(input_d['Incorrect Answer 3']),
|
|
70
|
+
preprocess(input_d['Correct Answer']),
|
|
71
|
+
]
|
|
72
|
+
random.shuffle(choices)
|
|
73
|
+
correct_answer_index = choices.index(preprocess(input_d['Correct Answer']))
|
|
74
|
+
|
|
75
|
+
out_doc = {
|
|
76
|
+
'choices': [choices[0], choices[1], choices[2], choices[3]],
|
|
77
|
+
'answer': f'{chr(65 + correct_answer_index)}',
|
|
78
|
+
}
|
|
79
|
+
return out_doc
|
|
80
|
+
|
|
81
|
+
def __form_options(self, options: list):
|
|
82
|
+
option_str = 'Choices:\n'
|
|
83
|
+
for opt, choice in zip(options, self.choices):
|
|
84
|
+
option_str += f'({choice}) {opt}' + '\n'
|
|
85
|
+
return option_str
|
|
86
|
+
|
|
87
|
+
def get_gold_answer(self, input_d: dict) -> str:
|
|
88
|
+
"""
|
|
89
|
+
Parse the raw input labels (gold).
|
|
90
|
+
"""
|
|
91
|
+
return input_d['answer']
|
|
92
|
+
|
|
93
|
+
def parse_pred_result(self, result: str, raw_input_d: dict = None, eval_type: str = EvalType.CHECKPOINT) -> str:
|
|
94
|
+
"""
|
|
95
|
+
Parse the predicted result and extract proper answer.
|
|
96
|
+
"""
|
|
97
|
+
return GPQAAdapter.get_multiple_choice_answer(result)
|
|
98
|
+
|
|
99
|
+
def match(self, gold: str, pred: str) -> float:
|
|
100
|
+
"""
|
|
101
|
+
Match the gold answer and the predicted answer.
|
|
102
|
+
"""
|
|
103
|
+
return exact_match(gold=gold, pred=pred)
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
def get_multiple_choice_answer(pred: str):
|
|
107
|
+
tmp = re.findall(r'\b(A|B|C|D)\b', pred.upper())
|
|
108
|
+
if tmp:
|
|
109
|
+
pred = tmp
|
|
110
|
+
else:
|
|
111
|
+
pred = [pred.strip().strip('.')]
|
|
112
|
+
|
|
113
|
+
if len(pred) == 0:
|
|
114
|
+
pred = ''
|
|
115
|
+
else:
|
|
116
|
+
pred = pred[-1]
|
|
117
|
+
|
|
118
|
+
# Remove the period at the end, again!
|
|
119
|
+
pred = pred.rstrip('.').rstrip('/')
|
|
120
|
+
|
|
121
|
+
return pred
|
|
@@ -6,7 +6,6 @@ import os
|
|
|
6
6
|
import re
|
|
7
7
|
|
|
8
8
|
from evalscope.benchmarks import Benchmark, DataAdapter
|
|
9
|
-
from evalscope.metrics import AverageAccuracy
|
|
10
9
|
from evalscope.models import ChatGenerationModelAdapter
|
|
11
10
|
from evalscope.utils.io_utils import jsonl_to_list
|
|
12
11
|
from evalscope.utils.logger import get_logger
|
|
@@ -19,11 +18,11 @@ logger = get_logger()
|
|
|
19
18
|
dataset_id='modelscope/gsm8k',
|
|
20
19
|
model_adapter=ChatGenerationModelAdapter,
|
|
21
20
|
subset_list=['main'],
|
|
22
|
-
metric_list=[AverageAccuracy],
|
|
21
|
+
metric_list=['AverageAccuracy'],
|
|
23
22
|
few_shot_num=4,
|
|
24
23
|
train_split='train',
|
|
25
24
|
eval_split='test',
|
|
26
|
-
prompt_template='
|
|
25
|
+
prompt_template="Question: {query}\nLet's think step by step\nAnswer:",
|
|
27
26
|
)
|
|
28
27
|
class GSM8KAdapter(DataAdapter):
|
|
29
28
|
|
|
@@ -73,10 +72,11 @@ class GSM8KAdapter(DataAdapter):
|
|
|
73
72
|
}
|
|
74
73
|
"""
|
|
75
74
|
use_fewshot = self.few_shot_num > 0
|
|
75
|
+
context = self._generate_prompt(use_fewshot=use_fewshot)
|
|
76
76
|
|
|
77
|
-
full_prompt = self.
|
|
77
|
+
full_prompt = context + self.prompt_template.format(query=input_d['question'])
|
|
78
78
|
|
|
79
|
-
return {'data': [full_prompt], 'system_prompt': self.
|
|
79
|
+
return {'data': [full_prompt], 'system_prompt': self.system_prompt}
|
|
80
80
|
|
|
81
81
|
def get_gold_answer(self, input_d: dict) -> str:
|
|
82
82
|
# Extract the gold answer from the input dict.
|
|
@@ -123,7 +123,7 @@ class GSM8KAdapter(DataAdapter):
|
|
|
123
123
|
return number_equal(gold_ans=gold, pred_ans=pred)
|
|
124
124
|
|
|
125
125
|
@classmethod
|
|
126
|
-
def _generate_prompt(cls,
|
|
126
|
+
def _generate_prompt(cls, use_fewshot: bool = True) -> str:
|
|
127
127
|
if use_fewshot:
|
|
128
128
|
# Use 4-shot examples by system
|
|
129
129
|
context = (
|
|
@@ -135,14 +135,9 @@ class GSM8KAdapter(DataAdapter):
|
|
|
135
135
|
"When Bella buys 2/5 times more marbles, she'll have increased the number of marbles by 2/5*60 = 24\nThe total number of marbles she'll have is 60+24 = 84\nIf Bella currently has 60 marbles, and she has two times as many marbles as frisbees, she has 60/2 = 30 frisbees.\nIf Bella buys 2/5 times more frisbees, she'll have 2/5*30 = 12 more frisbees.\nThe total number of frisbees she'll have will increase to 30+12 = 42\nBella also has 20 more frisbees than deck cards, meaning she has 30-20 = 10 deck cards\nIf she buys 2/5 times more deck cards, she'll have 2/5*10 = 4 more deck cards.\nThe total number of deck cards she'll have is 10+4 = 14\nTogether, Bella will have a total of 14+42+84 = 140 items\nThe answer is 140\n\n"
|
|
136
136
|
"Question: A group of 4 fruit baskets contains 9 apples, 15 oranges, and 14 bananas in the first three baskets and 2 less of each fruit in the fourth basket. How many fruits are there?\nLet's think step by step\n"
|
|
137
137
|
'For the first three baskets, the number of apples and oranges in one basket is 9+15=24\nIn total, together with bananas, the number of fruits in one basket is 24+14=38 for the first three baskets.\nSince there are three baskets each having 38 fruits, there are 3*38=114 fruits in the first three baskets.\nThe number of apples in the fourth basket is 9-2=7\nThere are also 15-2=13 oranges in the fourth basket\nThe combined number of oranges and apples in the fourth basket is 13+7=20\nThe fourth basket also contains 14-2=12 bananas.\nIn total, the fourth basket has 20+12=32 fruits.\nThe four baskets together have 32+114=146 fruits.\nThe answer is 146\n\n'
|
|
138
|
-
|
|
139
|
-
# context = input_d['question']
|
|
140
|
-
# fewshot_prompts = ['Question: ' + item_d['question'] + '\nAnswer: ' + item_d['answer'] for item_d in few_shot_list]
|
|
141
|
-
# fewshot_prompts = fewshot_prompts + ['Question: ' + context + '\nAnswer:']
|
|
142
|
-
# context = '\n\n'.join(fewshot_prompts)
|
|
138
|
+
)
|
|
143
139
|
else:
|
|
144
|
-
context =
|
|
145
|
-
context = 'Question: ' + context + '\nAnswer:'
|
|
140
|
+
context = ''
|
|
146
141
|
return context
|
|
147
142
|
|
|
148
143
|
@staticmethod
|
|
@@ -5,7 +5,7 @@ import re
|
|
|
5
5
|
|
|
6
6
|
from evalscope.benchmarks import Benchmark, DataAdapter
|
|
7
7
|
from evalscope.constants import EvalType
|
|
8
|
-
from evalscope.metrics import
|
|
8
|
+
from evalscope.metrics import exact_match
|
|
9
9
|
from evalscope.models import ContinuationLogitsModelAdapter
|
|
10
10
|
from evalscope.utils.io_utils import jsonl_to_list
|
|
11
11
|
from evalscope.utils.logger import get_logger
|
|
@@ -21,7 +21,7 @@ logger = get_logger()
|
|
|
21
21
|
dataset_id='modelscope/hellaswag',
|
|
22
22
|
model_adapter=ContinuationLogitsModelAdapter,
|
|
23
23
|
subset_list=['default'],
|
|
24
|
-
metric_list=[AverageAccuracy],
|
|
24
|
+
metric_list=['AverageAccuracy'],
|
|
25
25
|
few_shot_num=0,
|
|
26
26
|
train_split='train',
|
|
27
27
|
eval_split='validation',
|
|
@@ -89,11 +89,7 @@ class HellaSwagAdapter(DataAdapter):
|
|
|
89
89
|
|
|
90
90
|
ctx_continuation_pair_list = [(context.strip(), ' ' + cont.strip()) for cont in endings]
|
|
91
91
|
|
|
92
|
-
return {
|
|
93
|
-
'data': ctx_continuation_pair_list,
|
|
94
|
-
'multi_choices': self.choices,
|
|
95
|
-
'system_prompt': self.prompt_template
|
|
96
|
-
}
|
|
92
|
+
return {'data': ctx_continuation_pair_list, 'multi_choices': self.choices, 'system_prompt': self.system_prompt}
|
|
97
93
|
|
|
98
94
|
def get_gold_answer(self, input_d: dict) -> str:
|
|
99
95
|
# Get the gold choice
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import re
|
|
3
3
|
|
|
4
4
|
from evalscope.benchmarks import Benchmark, DataAdapter
|
|
5
|
-
from evalscope.metrics import Pass1
|
|
6
5
|
from evalscope.models import ChatGenerationModelAdapter
|
|
7
6
|
from evalscope.utils.logger import get_logger
|
|
8
7
|
|
|
@@ -17,11 +16,11 @@ logger = get_logger()
|
|
|
17
16
|
dataset_id='modelscope/humaneval',
|
|
18
17
|
model_adapter=ChatGenerationModelAdapter,
|
|
19
18
|
subset_list=['openai_humaneval'],
|
|
20
|
-
metric_list=[
|
|
19
|
+
metric_list=['Pass@1'],
|
|
21
20
|
few_shot_num=0,
|
|
22
21
|
train_split=None,
|
|
23
22
|
eval_split='test',
|
|
24
|
-
prompt_template='',
|
|
23
|
+
prompt_template='Complete the following python code:\n{query}',
|
|
25
24
|
)
|
|
26
25
|
class HumanevalAdapter(DataAdapter):
|
|
27
26
|
"""
|
|
@@ -64,10 +63,10 @@ class HumanevalAdapter(DataAdapter):
|
|
|
64
63
|
input_d (dict): The raw input. A single data format of the Humaneval:
|
|
65
64
|
{'task_id': '', 'prompt': '', 'entry_point': '', 'canonical_solution': '', 'test': ''}
|
|
66
65
|
"""
|
|
67
|
-
|
|
68
|
-
full_prompt =
|
|
66
|
+
query = input_d['prompt']
|
|
67
|
+
full_prompt = self.prompt_template.format(query=query)
|
|
69
68
|
|
|
70
|
-
return {'data': [full_prompt], 'system_prompt': self.
|
|
69
|
+
return {'data': [full_prompt], 'system_prompt': self.system_prompt}
|
|
71
70
|
|
|
72
71
|
@classmethod
|
|
73
72
|
def _postprocess(cls, text: str) -> str:
|
|
@@ -2,11 +2,10 @@ from collections import defaultdict
|
|
|
2
2
|
from typing import Any, Dict, List
|
|
3
3
|
|
|
4
4
|
from evalscope.benchmarks import Benchmark, DataAdapter
|
|
5
|
-
from evalscope.benchmarks.ifeval.utils import
|
|
5
|
+
from evalscope.benchmarks.ifeval.utils import process_results
|
|
6
6
|
from evalscope.constants import EvalType
|
|
7
|
-
from evalscope.metrics import Metric, mean
|
|
7
|
+
from evalscope.metrics import Metric, mean, metric_registry
|
|
8
8
|
from evalscope.models import ChatGenerationModelAdapter
|
|
9
|
-
from evalscope.utils.utils import normalize_score
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
@Benchmark.register(
|
|
@@ -15,10 +14,10 @@ from evalscope.utils.utils import normalize_score
|
|
|
15
14
|
model_adapter=ChatGenerationModelAdapter,
|
|
16
15
|
subset_list=['default'],
|
|
17
16
|
metric_list=[
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
'prompt_level_strict_acc',
|
|
18
|
+
'inst_level_strict_acc',
|
|
19
|
+
'prompt_level_loose_acc',
|
|
20
|
+
'inst_level_loose_acc',
|
|
22
21
|
],
|
|
23
22
|
few_shot_num=0,
|
|
24
23
|
train_split=None,
|
|
@@ -30,8 +29,14 @@ class IFEvalAdapter(DataAdapter):
|
|
|
30
29
|
def __init__(self, **kwargs):
|
|
31
30
|
super().__init__(**kwargs)
|
|
32
31
|
|
|
32
|
+
# register metrics
|
|
33
|
+
metric_registry.register(Metric(name='prompt_level_strict_acc', object=mean))
|
|
34
|
+
metric_registry.register(Metric(name='inst_level_strict_acc', object=mean))
|
|
35
|
+
metric_registry.register(Metric(name='prompt_level_loose_acc', object=mean))
|
|
36
|
+
metric_registry.register(Metric(name='inst_level_loose_acc', object=mean))
|
|
37
|
+
|
|
33
38
|
def gen_prompt(self, input_d: dict, subset_name: str, few_shot_list: list, **kwargs) -> Any:
|
|
34
|
-
return {'data': [input_d['prompt']], 'system_prompt': self.
|
|
39
|
+
return {'data': [input_d['prompt']], 'system_prompt': self.system_prompt}
|
|
35
40
|
|
|
36
41
|
def get_gold_answer(self, input_d: dict) -> str:
|
|
37
42
|
return input_d
|
|
@@ -49,9 +54,4 @@ class IFEvalAdapter(DataAdapter):
|
|
|
49
54
|
for k, v in res.items():
|
|
50
55
|
res_dict[k].append(v)
|
|
51
56
|
|
|
52
|
-
|
|
53
|
-
for metric in self.metric_list:
|
|
54
|
-
metric_name = metric.name
|
|
55
|
-
pred_value = res_dict[metric_name]
|
|
56
|
-
metrics.append({'metric_name': metric_name, 'score': metric.object(pred_value), 'num': len(pred_value)})
|
|
57
|
-
return metrics
|
|
57
|
+
return super().compute_metric(res_dict)
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
|
|
16
16
|
import collections
|
|
17
17
|
import json
|
|
18
|
-
import langdetect
|
|
19
18
|
import logging
|
|
20
19
|
import random
|
|
21
20
|
import re
|
|
@@ -163,7 +162,7 @@ class ResponseLanguageChecker(Instruction):
|
|
|
163
162
|
True if the language of `value` follows instruction; otherwise False.
|
|
164
163
|
"""
|
|
165
164
|
assert isinstance(value, str)
|
|
166
|
-
|
|
165
|
+
import langdetect
|
|
167
166
|
try:
|
|
168
167
|
return langdetect.detect(value) == self._language
|
|
169
168
|
except langdetect.LangDetectException as e:
|
|
@@ -1339,7 +1338,7 @@ class CapitalLettersEnglishChecker(Instruction):
|
|
|
1339
1338
|
def check_following(self, value):
|
|
1340
1339
|
"""Checks that the response is in English and in all capital letters."""
|
|
1341
1340
|
assert isinstance(value, str)
|
|
1342
|
-
|
|
1341
|
+
import langdetect
|
|
1343
1342
|
try:
|
|
1344
1343
|
return value.isupper() and langdetect.detect(value) == 'en'
|
|
1345
1344
|
except langdetect.LangDetectException as e:
|
|
@@ -1367,7 +1366,7 @@ class LowercaseLettersEnglishChecker(Instruction):
|
|
|
1367
1366
|
def check_following(self, value):
|
|
1368
1367
|
"""Checks that the response is in English and in all lowercase letters."""
|
|
1369
1368
|
assert isinstance(value, str)
|
|
1370
|
-
|
|
1369
|
+
import langdetect
|
|
1371
1370
|
try:
|
|
1372
1371
|
return value.islower() and langdetect.detect(value) == 'en'
|
|
1373
1372
|
except langdetect.LangDetectException as e:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from evalscope.benchmarks import Benchmark, DataAdapter
|
|
2
|
-
from evalscope.constants import
|
|
3
|
-
from evalscope.metrics import
|
|
2
|
+
from evalscope.constants import EvalType
|
|
3
|
+
from evalscope.metrics import exact_match
|
|
4
4
|
from evalscope.models import ChatGenerationModelAdapter
|
|
5
5
|
from evalscope.utils.utils import ResponseParser
|
|
6
6
|
|
|
@@ -10,11 +10,11 @@ from evalscope.utils.utils import ResponseParser
|
|
|
10
10
|
dataset_id='AI-ModelScope/IQuiz',
|
|
11
11
|
model_adapter=ChatGenerationModelAdapter,
|
|
12
12
|
subset_list=['IQ', 'EQ'],
|
|
13
|
-
metric_list=[AverageAccuracy],
|
|
13
|
+
metric_list=['AverageAccuracy'],
|
|
14
14
|
few_shot_num=0,
|
|
15
15
|
train_split=None,
|
|
16
16
|
eval_split='test',
|
|
17
|
-
|
|
17
|
+
system_prompt='你是一个高智商和高情商的专家,你被要求回答一个选择题,并选出一个正确的选项,解释原因,最终输出格式为:`答案是(选项)`。', # noqa: E501
|
|
18
18
|
)
|
|
19
19
|
class IQuizAdapter(DataAdapter):
|
|
20
20
|
|
|
@@ -36,7 +36,7 @@ class IQuizAdapter(DataAdapter):
|
|
|
36
36
|
"""
|
|
37
37
|
prompt = f"问题: {input_d['question']}\n"
|
|
38
38
|
prompt += self.__form_options(input_d['choices'])
|
|
39
|
-
return {'data': [prompt], 'multi_choices': self.choices, 'system_prompt': self.
|
|
39
|
+
return {'data': [prompt], 'multi_choices': self.choices, 'system_prompt': self.system_prompt}
|
|
40
40
|
|
|
41
41
|
def __form_options(self, options: list):
|
|
42
42
|
option_str = '选项:\n'
|
|
File without changes
|