Skip to content

Commit 02b6cce

Browse files
committed
Merge branch 'main' of github.com:emagedoc/CodeClash
2 parents c16dd73 + ed0b56c commit 02b6cce

4 files changed

Lines changed: 131 additions & 3 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ logs/**
88
# Kilian's specific ignores
99
batch_submit.sh
1010
round_scores.json
11+
*.parquet
1112

1213

1314
# -------------
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/usr/bin/env python3
2+
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+
7+
import argparse
8+
import json
9+
from pathlib import Path
10+
from typing import Any
11+
12+
import pandas as pd
13+
14+
from codeclash.analysis.llm_as_judge.utils import Instance
15+
from codeclash.utils.log import get_logger
16+
17+
logger = get_logger("AggregateResults", emoji="📊")
18+
19+
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.
22+
23+
Returns:
24+
DataFrame with flattened structure containing all evaluation data
25+
"""
26+
rows = []
27+
llm_judge_files = list(input_dir.rglob("llm_as_judge.json"))
28+
29+
logger.info(f"Found {len(llm_judge_files)} llm_as_judge.json files")
30+
31+
for file_path in llm_judge_files:
32+
logger.debug(f"Processing {file_path}")
33+
34+
try:
35+
content = file_path.read_text().strip()
36+
if not content:
37+
logger.warning(f"Skipping empty file: {file_path}")
38+
continue
39+
40+
file_data = json.loads(content)
41+
42+
# Process each data_id and instance
43+
for data_id, instances in file_data.items():
44+
for instance_id, instance_data in instances.items():
45+
# Extract instance metadata
46+
instance = Instance.model_validate(instance_data["instance"])
47+
model_name, opponent_model_name = instance.get_lm_name_self_opponent()
48+
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)
67+
68+
except json.JSONDecodeError as e:
69+
logger.error(f"Failed to parse JSON in {file_path}: {e}")
70+
except Exception as e:
71+
logger.error(f"Error processing {file_path}: {e}", exc_info=True)
72+
73+
df = pd.DataFrame(rows)
74+
logger.info(f"Created DataFrame with {len(df)} rows and {len(df.columns)} columns")
75+
76+
return df
77+
78+
79+
def main() -> None:
80+
parser = argparse.ArgumentParser(description="Aggregate LLM-as-judge evaluation results to Parquet")
81+
parser.add_argument("input_dir", type=Path, help="Path to the input directory containing tournament results")
82+
parser.add_argument("-o", "--output-file", type=Path,
83+
help="Path to the output Parquet file", default="aggregated_results.parquet")
84+
args = parser.parse_args()
85+
86+
if not args.input_dir.exists():
87+
logger.error(f"Input directory does not exist: {args.input_dir}")
88+
return
89+
90+
logger.info(f"Aggregating results from {args.input_dir}")
91+
df = aggregate_results_to_dataframe(args.input_dir)
92+
93+
df.to_parquet(args.output_file, compression="snappy", index=False)
94+
logger.info(f"Wrote aggregated results to {args.output_file}")
95+
96+
97+
if __name__ == "__main__":
98+
main()

codeclash/analysis/llm_as_judge/big_questions.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#!/usr/bin/env python3
22
import argparse
33
import json
4+
import logging
45
import random
56
import re
67
from concurrent.futures import ThreadPoolExecutor, as_completed
@@ -9,12 +10,19 @@
910

1011
import jinja2
1112
import yaml
12-
from minisweagent.models import GLOBAL_MODEL_STATS, get_model
13+
from minisweagent.models import GLOBAL_MODEL_STATS
1314
from pydantic import BaseModel
1415
from rich.console import Console, Group
1516
from rich.markdown import Markdown
1617
from rich.panel import Panel
1718
from rich.table import Table
19+
from tenacity import (
20+
before_sleep_log,
21+
retry,
22+
retry_if_not_exception_type,
23+
stop_after_attempt,
24+
wait_exponential,
25+
)
1826
from typing_extensions import Any
1927

2028
from codeclash.analysis.llm_as_judge.utils import FileLock, Instance, InstanceBatch, get_instances
@@ -25,6 +33,24 @@
2533
config_path = Path(__file__).parent / "big_questions.yaml"
2634

2735

36+
from minisweagent.models.portkey_model import PortkeyModel
37+
38+
39+
class PortkeyWithStructuredOutput(PortkeyModel):
40+
@retry(
41+
stop=stop_after_attempt(10),
42+
wait=wait_exponential(multiplier=1, min=4, max=60),
43+
before_sleep=before_sleep_log(logger, logging.WARNING),
44+
retry=retry_if_not_exception_type((KeyboardInterrupt, TypeError, ValueError)),
45+
)
46+
def _query(self, messages: list[dict[str, str]], **kwargs):
47+
return self.client.beta.chat.completions.parse(
48+
model=self.config.model_name,
49+
messages=messages,
50+
**(self.config.model_kwargs | kwargs),
51+
)
52+
53+
2854
class BigQuestionsModelResponseSchema(BaseModel):
2955
"""Schema for structured output of the model."""
3056

@@ -91,7 +117,10 @@ def extract_triple_backticks(text: str) -> str:
91117
class BigQuestions:
92118
def __init__(self, config: BigQuestionsConfig):
93119
self.config = config
94-
self.model = get_model(config.model.model_name, config={"model_kwargs": config.model.model_kwargs, "model_class": config.model.model_class})
120+
self.model = PortkeyWithStructuredOutput(
121+
model_name=config.model.model_name,
122+
model_kwargs=config.model.model_kwargs,
123+
)
95124

96125
@property
97126
def data_id(self) -> str:

codeclash/analysis/llm_as_judge/big_questions.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ instance_prompt: |
209209
210210
{{ trajectory_message_str }}
211211
model:
212-
model_name: 'openai/gpt-5'
212+
model_name: '@openai/gpt-5'
213213
# model_class: portkey
214214
model_kwargs:
215215
reasoning_effort: high

0 commit comments

Comments
 (0)