feat: restructure output layout and add --folder-name
- Add --folder-name CLI arg; defaults to safe model name, or
{model}_THINKING when --thinking is enabled.
- Move benchmark outputs under output/{folder_name}/{benchmark}/...
- Remove redundant {model_name} subfolder from predictions/reports/reviews.
- Update collect_results.py to write both CSV and Excel to
results/{folder_name}.csv/xlsx.
- Update perf backup/restore paths to match the new layout.
- Patch evalscope CacheManager to drop model_name from cache paths.
This commit is contained in:
parent
1308ddd251
commit
e26fa0fe44
@ -159,13 +159,10 @@ def find_report_candidates(seed_dir: Path, benchmark: str, model_name: str):
|
|||||||
"""Return candidate report paths, accepting variant naming patterns."""
|
"""Return candidate report paths, accepting variant naming patterns."""
|
||||||
# The actual report filename may not match the directory name exactly
|
# The actual report filename may not match the directory name exactly
|
||||||
# (e.g. hle_low directory holds hle.json). Try all .json files under
|
# (e.g. hle_low directory holds hle.json). Try all .json files under
|
||||||
# the model directory.
|
# the reports directory.
|
||||||
candidates = [
|
candidates = [
|
||||||
seed_dir / 'reports' / model_name / f'{benchmark}.json',
|
|
||||||
seed_dir / 'reports' / f'{benchmark}.json',
|
seed_dir / 'reports' / f'{benchmark}.json',
|
||||||
]
|
]
|
||||||
for p in (seed_dir / 'reports' / model_name).glob('*.json'):
|
|
||||||
candidates.append(p)
|
|
||||||
for p in (seed_dir / 'reports').glob('*.json'):
|
for p in (seed_dir / 'reports').glob('*.json'):
|
||||||
candidates.append(p)
|
candidates.append(p)
|
||||||
return candidates
|
return candidates
|
||||||
@ -220,7 +217,7 @@ def find_all_predictions(output_dir: Path, benchmark: str, model_name: str):
|
|||||||
for seed_dir in sorted(bench_dir.iterdir()):
|
for seed_dir in sorted(bench_dir.iterdir()):
|
||||||
if not seed_dir.is_dir():
|
if not seed_dir.is_dir():
|
||||||
continue
|
continue
|
||||||
pred_dir = seed_dir / 'predictions' / model_name
|
pred_dir = seed_dir / 'predictions'
|
||||||
if pred_dir.exists():
|
if pred_dir.exists():
|
||||||
files.extend(sorted(pred_dir.rglob('*.jsonl')))
|
files.extend(sorted(pred_dir.rglob('*.jsonl')))
|
||||||
return files
|
return files
|
||||||
@ -566,23 +563,21 @@ def collect_all(output_dir: Path, model_name: str, out_name: str = None,
|
|||||||
total_row[col] = np.nan
|
total_row[col] = np.nan
|
||||||
df = pd.concat([df, pd.DataFrame([total_row], columns=OUTPUT_COLUMNS)], ignore_index=True)
|
df = pd.concat([df, pd.DataFrame([total_row], columns=OUTPUT_COLUMNS)], ignore_index=True)
|
||||||
|
|
||||||
summary_dir = output_dir / 'results' / safe_model
|
|
||||||
summary_dir.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
if out_name is None:
|
if out_name is None:
|
||||||
out_name = safe_model
|
out_name = safe_model
|
||||||
|
|
||||||
csv_path = summary_dir / f'{out_name}.csv'
|
|
||||||
|
|
||||||
# Excel can optionally be written to a separate project-level results dir
|
# Excel can optionally be written to a separate project-level results dir
|
||||||
# so that the latest summary per model is easy to find independently of
|
# so that the latest summary per model is easy to find independently of
|
||||||
# the per-run output directory.
|
# the per-run output directory. When a separate dir is given, put both
|
||||||
|
# CSV and Excel there.
|
||||||
if excel_output_dir is not None:
|
if excel_output_dir is not None:
|
||||||
xlsx_dir = Path(excel_output_dir)
|
summary_dir = Path(excel_output_dir)
|
||||||
xlsx_dir.mkdir(parents=True, exist_ok=True)
|
|
||||||
xlsx_path = xlsx_dir / f'{out_name}.xlsx'
|
|
||||||
else:
|
else:
|
||||||
xlsx_path = summary_dir / f'{out_name}.xlsx'
|
summary_dir = output_dir / 'results' / safe_model
|
||||||
|
summary_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
csv_path = summary_dir / f'{out_name}.csv'
|
||||||
|
xlsx_path = summary_dir / f'{out_name}.xlsx'
|
||||||
|
|
||||||
df.to_csv(csv_path, index=False, encoding='utf-8-sig')
|
df.to_csv(csv_path, index=False, encoding='utf-8-sig')
|
||||||
df.to_excel(xlsx_path, index=False)
|
df.to_excel(xlsx_path, index=False)
|
||||||
|
|||||||
49
bash/run.py
49
bash/run.py
@ -210,7 +210,7 @@ def build_parser():
|
|||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description='Unified EvalScope benchmark runner',
|
description='Unified EvalScope benchmark runner',
|
||||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
epilog='Suites: full, lite, mid, group1, group2, group3',
|
epilog='Suites: full, lite, mid, group1, group2, group3, official',
|
||||||
)
|
)
|
||||||
|
|
||||||
# Model / API
|
# Model / API
|
||||||
@ -224,6 +224,8 @@ def build_parser():
|
|||||||
help='Parent directory containing datasets/ subdir (default: %(default)s)')
|
help='Parent directory containing datasets/ subdir (default: %(default)s)')
|
||||||
parser.add_argument('--output-dir', default=DEFAULT_OUTPUT_DIR,
|
parser.add_argument('--output-dir', default=DEFAULT_OUTPUT_DIR,
|
||||||
help='Output root directory (default: %(default)s)')
|
help='Output root directory (default: %(default)s)')
|
||||||
|
parser.add_argument('--folder-name', default=None,
|
||||||
|
help='Top-level output folder name; defaults to --model, or --model_THINKING when --thinking is enabled')
|
||||||
parser.add_argument('--config', default=DEFAULT_CONFIG,
|
parser.add_argument('--config', default=DEFAULT_CONFIG,
|
||||||
help='YAML config path (default: %(default)s)')
|
help='YAML config path (default: %(default)s)')
|
||||||
parser.add_argument('--tokenizer-path', default=DEFAULT_TOKENIZER_PATH,
|
parser.add_argument('--tokenizer-path', default=DEFAULT_TOKENIZER_PATH,
|
||||||
@ -477,21 +479,20 @@ def build_task_config(
|
|||||||
# Main
|
# Main
|
||||||
# ============================================================
|
# ============================================================
|
||||||
|
|
||||||
def write_summary(output_dir: str, model_name: str,
|
def write_summary(output_dir: str, model_name: str, folder_name: str,
|
||||||
benchmark_names: list = None):
|
benchmark_names: list = None):
|
||||||
"""Re-aggregate results for the given benchmarks (or all on disk if None)."""
|
"""Re-aggregate results for the given benchmarks (or all on disk if None)."""
|
||||||
try:
|
try:
|
||||||
# Derive a safe file name from the model name
|
|
||||||
safe_name = model_name.replace('/', '_').replace('\\', '_').replace(' ', '_')
|
|
||||||
excel_output_dir = PROJECT_ROOT / 'results'
|
excel_output_dir = PROJECT_ROOT / 'results'
|
||||||
|
excel_output_dir.mkdir(parents=True, exist_ok=True)
|
||||||
if benchmark_names is not None:
|
if benchmark_names is not None:
|
||||||
collect_results_module.eval_benchmark(
|
collect_results_module.eval_benchmark(
|
||||||
benchmark_names, Path(output_dir), model_name, safe_name,
|
benchmark_names, Path(output_dir), model_name, folder_name,
|
||||||
excel_output_dir=excel_output_dir,
|
excel_output_dir=excel_output_dir,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
collect_results_module.collect_all(
|
collect_results_module.collect_all(
|
||||||
Path(output_dir), model_name, safe_name,
|
Path(output_dir), model_name, folder_name,
|
||||||
excel_output_dir=excel_output_dir,
|
excel_output_dir=excel_output_dir,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -499,7 +500,7 @@ def write_summary(output_dir: str, model_name: str,
|
|||||||
|
|
||||||
|
|
||||||
def run_and_summarize(task_cfg, write_summary_flag: bool, output_dir: str,
|
def run_and_summarize(task_cfg, write_summary_flag: bool, output_dir: str,
|
||||||
model_name: str, benchmark_names: list):
|
model_name: str, folder_name: str, benchmark_names: list):
|
||||||
"""Run a benchmark task and optionally refresh the summary table.
|
"""Run a benchmark task and optionally refresh the summary table.
|
||||||
|
|
||||||
``benchmark_names`` is the running list of canonical benchmark names that
|
``benchmark_names`` is the running list of canonical benchmark names that
|
||||||
@ -526,18 +527,18 @@ def run_and_summarize(task_cfg, write_summary_flag: bool, output_dir: str,
|
|||||||
|
|
||||||
backup_after_run(output_dir, dataset_name, model_name, work_dir)
|
backup_after_run(output_dir, dataset_name, model_name, work_dir)
|
||||||
if write_summary_flag:
|
if write_summary_flag:
|
||||||
write_summary(output_dir, model_name, benchmark_names=benchmark_names)
|
write_summary(output_dir, model_name, folder_name, benchmark_names=benchmark_names)
|
||||||
|
|
||||||
|
|
||||||
def backup_after_run(output_dir: str, benchmark: str, model_name: str,
|
def backup_after_run(output_dir: str, benchmark: str, model_name: str,
|
||||||
work_dir: Path):
|
work_dir: Path):
|
||||||
"""Snapshot the just-finished run's perf summary and predictions."""
|
"""Snapshot the just-finished run's perf summary and predictions."""
|
||||||
try:
|
try:
|
||||||
report_json = work_dir / 'reports' / model_name / f'{benchmark}.json'
|
report_json = work_dir / 'reports' / f'{benchmark}.json'
|
||||||
perf_backup_module.backup_perf_stats(
|
perf_backup_module.backup_perf_stats(
|
||||||
Path(output_dir), benchmark, model_name, report_json,
|
Path(output_dir), benchmark, model_name, report_json,
|
||||||
)
|
)
|
||||||
predictions_dir = work_dir / 'predictions' / model_name
|
predictions_dir = work_dir / 'predictions'
|
||||||
perf_backup_module.archive_predictions(
|
perf_backup_module.archive_predictions(
|
||||||
Path(output_dir), benchmark, model_name, predictions_dir,
|
Path(output_dir), benchmark, model_name, predictions_dir,
|
||||||
)
|
)
|
||||||
@ -552,8 +553,8 @@ def restore_before_run(output_dir: str, benchmark: str, model_name: str,
|
|||||||
the larger historical state instead of overwriting it.
|
the larger historical state instead of overwriting it.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
predictions_dir = work_dir / 'predictions' / model_name
|
predictions_dir = work_dir / 'predictions'
|
||||||
report_json = work_dir / 'reports' / model_name / f'{benchmark}.json'
|
report_json = work_dir / 'reports' / f'{benchmark}.json'
|
||||||
restored = perf_backup_module.restore_from_backup(
|
restored = perf_backup_module.restore_from_backup(
|
||||||
Path(output_dir), benchmark, model_name,
|
Path(output_dir), benchmark, model_name,
|
||||||
predictions_dir, report_json,
|
predictions_dir, report_json,
|
||||||
@ -616,12 +617,26 @@ def main():
|
|||||||
|
|
||||||
dataset_configs = load_dataset_configs(args.config)
|
dataset_configs = load_dataset_configs(args.config)
|
||||||
|
|
||||||
|
# Resolve top-level output folder name
|
||||||
|
if args.folder_name:
|
||||||
|
folder_name = args.folder_name
|
||||||
|
elif enable_thinking:
|
||||||
|
safe_model = args.model.replace('/', '_').replace('\\', '_').replace(' ', '_')
|
||||||
|
folder_name = f'{safe_model}_THINKING'
|
||||||
|
else:
|
||||||
|
folder_name = args.model.replace('/', '_').replace('\\', '_').replace(' ', '_')
|
||||||
|
model_output_dir = Path(args.output_dir) / folder_name
|
||||||
|
model_output_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
results_dir = PROJECT_ROOT / 'results'
|
||||||
|
results_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
print('=' * 60)
|
print('=' * 60)
|
||||||
print(f'Config: {args.config}')
|
print(f'Config: {args.config}')
|
||||||
print(f'Model: {args.model}')
|
print(f'Model: {args.model}')
|
||||||
print(f'API URL: {args.api_url}')
|
print(f'API URL: {args.api_url}')
|
||||||
print(f'Dataset Dir: {args.dataset_dir}')
|
print(f'Dataset Dir: {args.dataset_dir}')
|
||||||
print(f'Output Dir: {args.output_dir}')
|
print(f'Output Root: {args.output_dir}')
|
||||||
|
print(f'Output Folder: {folder_name}')
|
||||||
print(f'Suite: {args.suite}')
|
print(f'Suite: {args.suite}')
|
||||||
print(f'Limit: {limit if limit is not None else "ALL"}')
|
print(f'Limit: {limit if limit is not None else "ALL"}')
|
||||||
print(f'Thinking: {enable_thinking}')
|
print(f'Thinking: {enable_thinking}')
|
||||||
@ -651,13 +666,13 @@ def main():
|
|||||||
ds_cfg = get_dataset_config(dataset_name)
|
ds_cfg = get_dataset_config(dataset_name)
|
||||||
task_cfg = build_task_config(
|
task_cfg = build_task_config(
|
||||||
dataset_name, ds_cfg, args.batch_size, enable_thinking, args.seed, limit,
|
dataset_name, ds_cfg, args.batch_size, enable_thinking, args.seed, limit,
|
||||||
args.output_dir, args.model, args.api_url, args.dataset_dir, judge_model_args,
|
str(model_output_dir), args.model, args.api_url, args.dataset_dir, judge_model_args,
|
||||||
run_idx=run_idx,
|
run_idx=run_idx,
|
||||||
thinking_max_tokens_scale=args.thinking_max_tokens_scale,
|
thinking_max_tokens_scale=args.thinking_max_tokens_scale,
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
run_and_summarize(task_cfg, args.write_summary, args.output_dir, args.model,
|
run_and_summarize(task_cfg, args.write_summary, str(model_output_dir), args.model,
|
||||||
benchmark_names=benchmark_names)
|
folder_name=folder_name, benchmark_names=benchmark_names)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'ERROR in {dataset_name} (run {run_idx + 1 if run_idx else 1}): {e}')
|
print(f'ERROR in {dataset_name} (run {run_idx + 1 if run_idx else 1}): {e}')
|
||||||
|
|
||||||
@ -689,7 +704,7 @@ def main():
|
|||||||
run_one(dataset_name, benchmark_names=benchmark_names)
|
run_one(dataset_name, benchmark_names=benchmark_names)
|
||||||
|
|
||||||
if args.write_summary:
|
if args.write_summary:
|
||||||
write_summary(args.output_dir, args.model, benchmark_names=benchmark_names)
|
write_summary(str(model_output_dir), args.model, folder_name, benchmark_names=benchmark_names)
|
||||||
print('\nAll benchmarks done!')
|
print('\nAll benchmarks done!')
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -118,7 +118,7 @@ class CacheManager:
|
|||||||
Returns:
|
Returns:
|
||||||
Path to the prediction cache file
|
Path to the prediction cache file
|
||||||
"""
|
"""
|
||||||
file_path = os.path.join(self.outputs.predictions_dir, self.model_name, f'{self.benchmark_name}_{subset}.jsonl')
|
file_path = os.path.join(self.outputs.predictions_dir, f'{self.benchmark_name}_{subset}.jsonl')
|
||||||
# Ensure the directory exists
|
# Ensure the directory exists
|
||||||
if self.outputs.is_make:
|
if self.outputs.is_make:
|
||||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||||
@ -189,7 +189,7 @@ class CacheManager:
|
|||||||
Returns:
|
Returns:
|
||||||
Path to the review cache file
|
Path to the review cache file
|
||||||
"""
|
"""
|
||||||
file_path = os.path.join(self.outputs.reviews_dir, self.model_name, f'{self.benchmark_name}_{subset}.jsonl')
|
file_path = os.path.join(self.outputs.reviews_dir, f'{self.benchmark_name}_{subset}.jsonl')
|
||||||
# Ensure the directory exists
|
# Ensure the directory exists
|
||||||
if self.outputs.is_make:
|
if self.outputs.is_make:
|
||||||
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
os.makedirs(os.path.dirname(file_path), exist_ok=True)
|
||||||
@ -235,7 +235,7 @@ class CacheManager:
|
|||||||
Returns:
|
Returns:
|
||||||
Path to the reports directory for this model
|
Path to the reports directory for this model
|
||||||
"""
|
"""
|
||||||
report_path = os.path.join(self.outputs.reports_dir, self.model_name)
|
report_path = self.outputs.reports_dir
|
||||||
# Ensure the directory exists
|
# Ensure the directory exists
|
||||||
if self.outputs.is_make:
|
if self.outputs.is_make:
|
||||||
os.makedirs(report_path, exist_ok=True)
|
os.makedirs(report_path, exist_ok=True)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user