Skip to content

Commit b04b8a4

Browse files
committed
Enh(analysis): Aggregate results into parquet file
1 parent 25333d1 commit b04b8a4

1 file changed

Lines changed: 37 additions & 24 deletions

File tree

codeclash/analysis/llm_as_judge/aggregate_results.py

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
#!/usr/bin/env python3
22

3+
"""Aggregate results from multiple llm_as_judge.json files
4+
and save as a compressed parquet file for efficient storage and loading.
5+
"""
6+
37
import argparse
48
import json
59
from pathlib import Path
610
from typing import Any
711

12+
import pandas as pd
13+
814
from codeclash.analysis.llm_as_judge.utils import Instance
915
from codeclash.utils.log import get_logger
1016

1117
logger = get_logger("AggregateResults", emoji="📊")
1218

1319

14-
def aggregate_results(input_dir: Path) -> dict[str, Any]:
15-
"""Aggregate all llm_as_judge.json results from the input directory.
20+
def aggregate_results_to_dataframe(input_dir: Path) -> pd.DataFrame:
21+
"""Aggregate all llm_as_judge.json results from the input directory into a DataFrame.
1622
1723
Returns:
18-
Dictionary with structure {data_id: {instance_id: result_data}}
24+
DataFrame with flattened structure containing all evaluation data
1925
"""
20-
aggregated = {}
26+
rows = []
2127
llm_judge_files = list(input_dir.rglob("llm_as_judge.json"))
2228

2329
logger.info(f"Found {len(llm_judge_files)} llm_as_judge.json files")
@@ -33,51 +39,58 @@ def aggregate_results(input_dir: Path) -> dict[str, Any]:
3339

3440
file_data = json.loads(content)
3541

36-
# Merge each data_id from this file into the aggregated results
42+
# Process each data_id and instance
3743
for data_id, instances in file_data.items():
38-
if data_id not in aggregated:
39-
aggregated[data_id] = {}
40-
41-
# Check for duplicate instance_ids
4244
for instance_id, instance_data in instances.items():
43-
if instance_id in aggregated[data_id]:
44-
logger.warning(f"Duplicate instance_id '{instance_id}' found in {file_path}")
45-
46-
# Add model info
45+
# Extract instance metadata
4746
instance = Instance.model_validate(instance_data["instance"])
4847
model_name, opponent_model_name = instance.get_lm_name_self_opponent()
49-
instance_data.setdefault("info", {})
50-
instance_data["info"]["model_name"] = model_name
51-
instance_data["info"]["opponent_model_name"] = opponent_model_name
5248

53-
aggregated[data_id][instance_id] = instance_data
49+
# Create a flat row with all information
50+
row = {
51+
"data_id": data_id,
52+
"instance_id": instance_id,
53+
"tournament_name": instance.tournament_name,
54+
"player_name": instance.player_name,
55+
"round_number": instance.round_number,
56+
"model_name": model_name,
57+
"opponent_model_name": opponent_model_name,
58+
}
59+
60+
# Add all evaluation results
61+
if "result" in instance_data:
62+
result_data = instance_data["result"]
63+
for key, value in result_data.items():
64+
row[key] = value
65+
66+
rows.append(row)
5467

5568
except json.JSONDecodeError as e:
5669
logger.error(f"Failed to parse JSON in {file_path}: {e}")
5770
except Exception as e:
5871
logger.error(f"Error processing {file_path}: {e}", exc_info=True)
5972

60-
total_instances = sum(len(instances) for instances in aggregated.values())
61-
logger.info(f"Aggregated {total_instances} instances across {len(aggregated)} data versions")
73+
df = pd.DataFrame(rows)
74+
logger.info(f"Created DataFrame with {len(df)} rows and {len(df.columns)} columns")
6275

63-
return aggregated
76+
return df
6477

6578

6679
def main() -> None:
67-
parser = argparse.ArgumentParser(description="Aggregate LLM-as-judge evaluation results")
80+
parser = argparse.ArgumentParser(description="Aggregate LLM-as-judge evaluation results to Parquet")
6881
parser.add_argument("input_dir", type=Path, help="Path to the input directory containing tournament results")
6982
parser.add_argument("-o", "--output-file", type=Path,
70-
help="Path to the output file", default="aggregated_results.json")
83+
help="Path to the output Parquet file", default="aggregated_results.parquet")
7184
args = parser.parse_args()
7285

7386
if not args.input_dir.exists():
7487
logger.error(f"Input directory does not exist: {args.input_dir}")
7588
return
7689

7790
logger.info(f"Aggregating results from {args.input_dir}")
78-
aggregated = aggregate_results(args.input_dir)
91+
df = aggregate_results_to_dataframe(args.input_dir)
7992

80-
args.output_file.write_text(json.dumps(aggregated, indent=2))
93+
df.to_parquet(args.output_file, compression="snappy", index=False)
8194
logger.info(f"Wrote aggregated results to {args.output_file}")
8295

8396

0 commit comments

Comments
 (0)