-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathrun_unified_eval.py
More file actions
executable file
·302 lines (265 loc) · 13.1 KB
/
Copy pathrun_unified_eval.py
File metadata and controls
executable file
·302 lines (265 loc) · 13.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
#!/usr/bin/env python3
"""Command-line interface for the unified task evaluation system."""
import argparse
import json
from pathlib import Path
import sys
import os
# Add project root to path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from tasks.base_task import TaskConfig
from tasks.evaluator import TaskEvaluator, ModelConfig, EvaluationConfig
from tasks.registry import TaskRegistry
def create_model_config_from_args(args) -> ModelConfig:
"""Create ModelConfig from command line arguments."""
return ModelConfig(
model_id=args.model_id,
backend=args.backend,
checkpoint=args.checkpoint,
local_path=args.local_path,
api_key=args.api_key,
temperature=args.temperature,
max_tokens=args.max_tokens,
top_p=args.top_p,
tensor_parallel_size=args.tensor_parallel_size,
trust_remote_code=args.trust_remote_code
)
def create_eval_config_from_args(args) -> EvaluationConfig:
"""Create EvaluationConfig from command line arguments."""
return EvaluationConfig(
output_dir=args.output_dir,
save_predictions=args.save_predictions,
save_detailed_results=args.save_detailed_results,
batch_size=args.batch_size,
retry_attempts=args.retry_attempts,
retry_delay=args.retry_delay
)
def main():
# Check for list categories flag first (before full argument parsing)
if "--list_textfrct_categories" in sys.argv:
print_textfrct_categories()
return 0
parser = argparse.ArgumentParser(description="Unified Task Evaluation System")
# Task arguments
task_group = parser.add_argument_group("Task Configuration")
# Discover available tasks dynamically
registry = TaskRegistry()
available_tasks = list(registry.discover_tasks().keys())
task_group.add_argument("--task_type", type=str, required=True,
choices=available_tasks,
help=f"Type of task to run. Available: {', '.join(available_tasks)}")
# TextFRCT specific arguments (only if textfrct is available)
if "textfrct" in available_tasks:
task_group.add_argument("--skip_subjective", action="store_true",
help="Skip subjective categories (for TextFRCT)")
textfrct_group = parser.add_argument_group("TextFRCT Configuration")
textfrct_group.add_argument("--textfrct_categories", type=str, nargs="*",
help="Specific TextFRCT categories to evaluate (e.g., CV1 CV2 FA1). "
"If not specified, all categories are used. "
"Common categories: CV1 (scrambled words), CV2 (hidden words), "
"CV3 (incomplete words), FA1 (associations), FA2 (opposites), "
"V1-V5 (vocabulary), RG1-RG3 (reasoning)")
textfrct_group.add_argument("--list_textfrct_categories", action="store_true",
help="List all available TextFRCT categories and exit")
# Model arguments
model_group = parser.add_argument_group("Model Configuration")
model_group.add_argument("--model_id", type=str, required=True,
help="Model identifier")
model_group.add_argument("--backend", type=str, required=True,
choices=["vllm", "transformers", "openai", "together"],
help="Model backend to use")
model_group.add_argument("--checkpoint", type=str,
help="Model checkpoint/revision")
model_group.add_argument("--local_path", type=str,
help="Local path to model (overrides model_id)")
model_group.add_argument("--api_key", type=str,
help="API key for OpenAI/Together")
# Generation arguments
gen_group = parser.add_argument_group("Generation Configuration")
gen_group.add_argument("--temperature", type=float, default=0.0,
help="Generation temperature")
gen_group.add_argument("--max_tokens", type=int, default=100,
help="Maximum tokens to generate")
gen_group.add_argument("--top_p", type=float, default=1.0,
help="Top-p sampling parameter")
gen_group.add_argument("--tensor_parallel_size", type=int,
help="Tensor parallel size for vLLM")
gen_group.add_argument("--trust_remote_code", action="store_true", default=True,
help="Trust remote code for model loading")
# Evaluation arguments
eval_group = parser.add_argument_group("Evaluation Configuration")
eval_group.add_argument("--output_dir", type=str, default="results",
help="Output directory for results")
eval_group.add_argument("--save_predictions", action="store_true", default=True,
help="Save prediction results")
eval_group.add_argument("--save_detailed_results", action="store_true", default=True,
help="Save detailed results with prompts and predictions")
eval_group.add_argument("--batch_size", type=int, default=1,
help="Batch size for evaluation")
eval_group.add_argument("--retry_attempts", type=int, default=3,
help="Number of retry attempts for API calls")
eval_group.add_argument("--retry_delay", type=float, default=1.0,
help="Delay between retry attempts")
args = parser.parse_args()
# Create configurations
model_config = create_model_config_from_args(args)
eval_config = create_eval_config_from_args(args)
# Create task dynamically using registry - NO HARDCODED CONDITIONALS!
print(f"Creating {args.task_type} task...")
# Get the task class from registry
task_class = registry.get_task_class(args.task_type)
if not task_class:
print(f"Error: Task '{args.task_type}' not found in registry")
return 1
# Create task-specific configuration
if args.task_type == "textfrct":
# TextFRCT needs special configuration and constructor arguments
config = TaskConfig(
name="textfrct_cli",
description="TextFRCT evaluation from CLI",
data_path="dataset/TextFRCT.csv",
data_format="csv",
input_column="question",
output_column="answer",
evaluation_metrics=["accuracy"],
metadata={
"skip_subjective": getattr(args, 'skip_subjective', False),
"categories": getattr(args, 'textfrct_categories', None)
}
)
task = task_class(
config,
skip_subjective=getattr(args, 'skip_subjective', False),
categories=getattr(args, 'textfrct_categories', None)
)
if hasattr(args, 'textfrct_categories') and args.textfrct_categories:
print(f"Filtering to categories: {args.textfrct_categories}")
elif args.task_type == "basic_arithmetic":
# BasicArithmetic uses in-memory data
config = TaskConfig(
name="basic_arithmetic_cli",
description="Basic arithmetic evaluation from CLI",
data_format="memory",
data_path=None,
in_memory_data=None, # Signal to use task's default data
input_column="question",
output_column="answer",
evaluation_metrics=["accuracy"]
)
task = task_class(config)
elif args.task_type == "ioi_task":
# IOITask uses mib-bench/ioi dataset
config = TaskConfig(
name="ioi_task_cli",
description="Indirect Object Identification (IOI) evaluation from mib-bench/ioi dataset",
data_format="huggingface",
data_path="mib-bench/ioi",
input_column="prompt", # The incomplete sentence
output_column="choices", # List of choices, use with answer_index
evaluation_metrics=["accuracy"]
)
task = task_class(config)
else:
# Generic task creation for other tasks
config = TaskConfig(
name=f"{args.task_type}_cli",
description=f"{args.task_type} evaluation from CLI",
data_path=f"dataset/{args.task_type}.csv", # Default data path
data_format="csv",
input_column="question",
output_column="answer",
evaluation_metrics=["accuracy"]
)
task = task_class(config)
print(f"✅ Successfully created {args.task_type} task")
# Create evaluator and run evaluation
print("Creating evaluator...")
evaluator = TaskEvaluator(model_config, eval_config)
print("Running evaluation...")
results = evaluator.evaluate_task(task)
# Print summary results
print("\n" + "="*50)
print("EVALUATION RESULTS")
print("="*50)
print(f"Task: {results['task_name']}")
print(f"Model: {results['model_id']}")
print(f"Backend: {results['backend']}")
print(f"Examples: {results['num_examples']}")
print("\nMetrics:")
for metric, value in results['metrics'].items():
if isinstance(value, float):
print(f" {metric}: {value:.4f}")
else:
print(f" {metric}: {value}")
print(f"\nDetailed results saved to: {eval_config.output_dir}")
return 0
def print_textfrct_categories():
"""Print all available TextFRCT categories with descriptions."""
print("Available TextFRCT Categories:")
print("=" * 50)
categories = {
"CV1": "Scrambled Words - Unscramble letters to form words",
"CV2": "Hidden Words - Find words hidden in letter strings",
"CV3": "Incomplete Words - Complete words with missing letters",
"FA1": "Controlled Association - Generate related words",
"FA2": "Opposites - Generate antonyms",
"FA3": "Figures of Speech - Complete metaphors/similes",
"FE1": "Making Sentences - Create sentences from patterns",
"FE2": "Arranging Words - Form sentences from word lists",
"FE3": "Rewriting - Rewrite sentences with same meaning",
"FI1": "Topics Test - Generate ideas about topics",
"FI2": "Theme Test - Write paragraphs about themes",
"FI3": "Thing Categories - List items in categories",
"FW1": "Word Fluency - Generate words with constraints",
"FW2": "First and Last Letters - Words starting/ending with letters",
"FW3": "Pattern Words - Words matching letter patterns",
"I1": "Letter Sets - Pattern recognition with letters",
"I2": "Figure Classification - Spatial reasoning",
"MA2": "Object-Number - Associate objects with numbers",
"MA3": "First Names - Recall associated names",
"RG1": "Arithmetic Aptitude - Basic math operations",
"RG2": "Number Series - Continue number sequences",
"RG3": "Mathematical Reasoning - Solve math word problems",
"RL1": "Syllogistic Reasoning - Logical syllogisms",
"RL3": "Necessary Inference - Required logical conclusions",
"RL4": "Language Deciphering - Decode artificial languages",
"V1": "Vocabulary Level 1 - Basic vocabulary",
"V2": "Vocabulary Level 2 - Intermediate vocabulary",
"V3": "Vocabulary Level 3 - Advanced vocabulary",
"V4": "Vocabulary Level 4 - Expert vocabulary",
"V5": "Vocabulary Level 5 - Scholar vocabulary",
"XU1": "Object Combination - Combine objects creatively",
"XU2": "Substitute Uses - Alternative uses for objects",
"XU3": "Object Grouping - Group objects by function",
"XU4": "Different Uses - Creative uses for objects"
}
# Group by main category
groups = {
"CV (Convergent Visual)": ["CV1", "CV2", "CV3"],
"FA (Fluent Associational)": ["FA1", "FA2", "FA3"],
"FE (Flexible Expression)": ["FE1", "FE2", "FE3"],
"FI (Fluent Ideational)": ["FI1", "FI2", "FI3"],
"FW (Fluent Word)": ["FW1", "FW2", "FW3"],
"I (Inductive)": ["I1", "I2"],
"MA (Memory/Association)": ["MA2", "MA3"],
"RG (Reasoning)": ["RG1", "RG2", "RG3"],
"RL (Reasoning/Logic)": ["RL1", "RL3", "RL4"],
"V (Vocabulary)": ["V1", "V2", "V3", "V4", "V5"],
"XU (Creative)": ["XU1", "XU2", "XU3", "XU4"]
}
for group_name, group_categories in groups.items():
print(f"\n{group_name}:")
for cat in group_categories:
if cat in categories:
print(f" {cat}: {categories[cat]}")
print(f"\nExample usage:")
print(f" # Test only scrambled words and vocabulary:")
print(f" python run_unified_eval.py --task_type textfrct --textfrct_categories CV1 V1 V2")
print(f" ")
print(f" # Test only reasoning tasks:")
print(f" python run_unified_eval.py --task_type textfrct --textfrct_categories RG1 RG2 RG3 RL1")
print(f" ")
print(f" # Test all categories (default):")
print(f" python run_unified_eval.py --task_type textfrct")
if __name__ == "__main__":
exit(main())