-
Notifications
You must be signed in to change notification settings - Fork 44
Expand file tree
/
Copy pathpipeline.py
More file actions
167 lines (141 loc) · 5.58 KB
/
Copy pathpipeline.py
File metadata and controls
167 lines (141 loc) · 5.58 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
#!/usr/bin/env python3
"""
MCPMark Unified Evaluation Pipeline
===================================
This script provides an automated evaluation pipeline for testing Large Language Models (LLMs)
on various Multi-Step Cognitive Processes (MCP) services like Notion, GitHub, and PostgreSQL.
"""
import argparse
from datetime import datetime
from pathlib import Path
from dotenv import load_dotenv
from src.logger import get_logger
from src.evaluator import MCPEvaluator
from src.agents import AGENT_REGISTRY
from src.factory import MCPServiceFactory
from src.model_config import ModelConfig
# Initialize logger
logger = get_logger(__name__)
def main():
"""Main entry point for the evaluation pipeline."""
parser = argparse.ArgumentParser(description="MCPMark Unified Evaluation Pipeline.")
supported_mcp_services = MCPServiceFactory.get_supported_mcp_services()
supported_models = ModelConfig.get_supported_models()
# Main configuration
parser.add_argument(
"--mcp",
default="filesystem",
choices=supported_mcp_services,
help="MCP service to use (default: filesystem)",
)
parser.add_argument(
"--models",
required=True,
help="Comma-separated list of models to evaluate (e.g., 'o3,k2,gpt-4.1')",
)
parser.add_argument(
"--agent",
default="mcpmark",
choices=sorted(AGENT_REGISTRY.keys()),
help="Agent implementation to use (default: mcpmark)",
)
parser.add_argument(
"--tasks",
default="all",
help='Tasks to run: (1). "all"; (2). "category"; or (3). "category/task".',
)
parser.add_argument(
"--exp-name",
default=None,
help="Experiment name; results are saved under results/<exp-name>/ (default: YYYY-MM-DD-HH-MM-SS)",
)
parser.add_argument(
"--k",
type=int,
default=4,
help="Number of evaluation runs (default: 1)",
)
# Execution configuration
parser.add_argument(
"--timeout", type=int, default=3600, help="Timeout in seconds for agent execution"
)
parser.add_argument(
"--reasoning-effort",
default="default",
choices=["default", "minimal", "low", "medium", "high"],
help="Reasoning effort level for supported models (default: None)",
)
# Output configuration
parser.add_argument(
"--output-dir",
type=Path,
default=Path("./results"),
help="Directory to save results",
)
# Load arguments and environment variables
args = parser.parse_args()
load_dotenv(dotenv_path=".mcp_env", override=False)
# Validate k parameter and exp-name requirement
if args.k > 1 and args.exp_name is None:
parser.error("--exp-name is required when k > 1")
# Generate default exp-name if not provided
if args.exp_name is None:
args.exp_name = datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
# Parse models (no validation - allow unsupported models)
model_list = [m.strip() for m in args.models.split(",") if m.strip()]
if not model_list:
parser.error("No valid models provided")
# Log warning for unsupported models but don't error
unsupported_models = [m for m in model_list if m not in supported_models]
if unsupported_models:
logger.warning(
f"Using unsupported models: {', '.join(unsupported_models)}. Will use OPENAI_BASE_URL and OPENAI_API_KEY from environment."
)
logger.info("MCPMark Evaluation")
logger.info(f"Experiment: {args.exp_name} | {len(model_list)} Model(s): {', '.join(model_list)}")
if args.k > 1:
logger.info(f"Running {args.k} evaluation runs for pass@k metrics")
# Run k evaluation runs
for run_idx in range(1, args.k + 1):
if args.k > 1:
logger.info(f"\n{'=' * 80}")
logger.info(f"Starting Run {run_idx}/{args.k}")
logger.info(f"{'=' * 80}\n")
# For k-runs, results/{exp}/{mcp}__{model}/run-N
run_exp_name = f"run-{run_idx}"
run_output_dir = args.output_dir / args.exp_name
else:
# For single run, still use run-1 under service_model
run_exp_name = "run-1"
run_output_dir = args.output_dir / args.exp_name
# Run evaluation for each model
for i, model in enumerate(model_list, 1):
logger.info(f"\n{'=' * 60}")
if args.k > 1:
logger.info(f"Run {run_idx}/{args.k} | Model {i}/{len(model_list)}: {model}")
else:
logger.info(f"Starting evaluation {i}/{len(model_list)}: {model}")
logger.info(f"{'=' * 60}\n")
# Initialize and run the evaluation pipeline for this model
pipeline = MCPEvaluator(
mcp_service=args.mcp,
model=model,
timeout=args.timeout,
exp_name=run_exp_name,
output_dir=run_output_dir,
reasoning_effort=args.reasoning_effort,
agent_name=args.agent,
)
pipeline.run_evaluation(args.tasks)
logger.info(
f"📁 Results: {pipeline.base_experiment_dir}"
)
logger.info(f"\n{'=' * 60}")
if args.k > 1:
logger.info(f"✓ All {args.k} runs completed for {len(model_list)} model(s)")
logger.info(f"Run `python -m src.aggregators.aggregate_results --exp-name {args.exp_name}` to compute all metrics")
else:
logger.info(f"✓ All evaluations completed for {len(model_list)} model(s)")
logger.info(f"{'=' * 60}")
if __name__ == "__main__":
main()