1414from codeclash .analysis .llm_as_judge .categorize_actions import _all_categories as ACTION_CATEGORIES
1515from codeclash .analysis .llm_as_judge .hallucination import claim_categories as CLAIM_CATEGORIES
1616from codeclash .analysis .llm_as_judge .hallucination import source_categories as SOURCE_CATEGORIES
17- from codeclash .analysis .llm_as_judge .utils import Instance
17+ from codeclash .analysis .llm_as_judge .utils import Instance , InstanceBatch
1818from codeclash .utils .log import get_logger
1919
2020logger = get_logger ("AggregateResults" , emoji = "📊" )
@@ -36,9 +36,13 @@ def __init__(self):
3636 self .action_categories_data_id = f"action_categories_v{ ACTION_CATEGORIES_VERSION } "
3737 self .hallucination_data_id = f"hallucination_v{ HALLUCINATION_VERSION } "
3838
39- def aggregate_results_to_dataframe (self , input_dir : Path ) -> pd .DataFrame :
39+ def aggregate_results_to_dataframe (self , input_dir : Path , * , instance_ids : set [ str ] | None = None ) -> pd .DataFrame :
4040 """Aggregate all llm_as_judge.json results from the input directory into a DataFrame.
4141
42+ Args:
43+ input_dir: Directory containing llm_as_judge.json files
44+ instance_ids: If provided, only include results for these instance IDs
45+
4246 Returns:
4347 DataFrame with flattened structure containing all evaluation data merged by instance_id
4448 """
@@ -47,6 +51,8 @@ def aggregate_results_to_dataframe(self, input_dir: Path) -> pd.DataFrame:
4751 llm_judge_files = list (input_dir .rglob ("llm_as_judge.json" ))
4852
4953 logger .info (f"Found { len (llm_judge_files )} llm_as_judge.json files" )
54+ if instance_ids is not None :
55+ logger .info (f"Filtering to { len (instance_ids )} specific instances" )
5056
5157 for file_path in llm_judge_files :
5258 logger .debug (f"Processing { file_path } " )
@@ -70,6 +76,10 @@ def aggregate_results_to_dataframe(self, input_dir: Path) -> pd.DataFrame:
7076 continue
7177
7278 for instance_id , instance_data in instances .items ():
79+ # Skip if we're filtering and this instance isn't in the filter set
80+ if instance_ids is not None and instance_id not in instance_ids :
81+ continue
82+
7383 # Initialize instance data if not seen before
7484 if instance_id not in instance_data_dict :
7585 instance_data_dict [instance_id ] = self ._initialize_instance_row (instance_data )
@@ -82,6 +92,15 @@ def aggregate_results_to_dataframe(self, input_dir: Path) -> pd.DataFrame:
8292 except Exception as e :
8393 logger .error (f"Error processing { file_path } : { e } " , exc_info = True )
8494
95+ # Check if all expected instances were found
96+ if instance_ids is not None :
97+ found_instance_ids = set (instance_data_dict .keys ())
98+ missing_instance_ids = instance_ids - found_instance_ids
99+ if missing_instance_ids :
100+ raise ValueError (
101+ f"Could not find { len (missing_instance_ids )} instances in llm_as_judge.json files: { sorted (missing_instance_ids )} "
102+ )
103+
85104 # Convert to list of rows for DataFrame
86105 rows = list (instance_data_dict .values ())
87106 df = pd .DataFrame (rows )
@@ -220,15 +239,29 @@ def main() -> None:
220239 parser .add_argument (
221240 "-o" , "--output-file" , type = Path , help = "Path to the output Parquet file" , default = "aggregated_results.parquet"
222241 )
242+ parser .add_argument (
243+ "--instance-file" ,
244+ type = Path ,
245+ help = "Path to instances.json file (output of get_instances.py) to filter to specific instances" ,
246+ )
223247 args = parser .parse_args ()
224248
225249 if not args .input_dir .exists ():
226250 logger .error (f"Input directory does not exist: { args .input_dir } " )
227251 return
228252
253+ # Load instance filter if provided
254+ instance_ids = None
255+ if args .instance_file is not None :
256+ if not args .instance_file .exists ():
257+ raise FileNotFoundError (f"Instance file does not exist: { args .instance_file } " )
258+ instance_batch = InstanceBatch .model_validate_json (args .instance_file .read_text ())
259+ instance_ids = {instance .instance_id for instance in instance_batch .instances }
260+ logger .info (f"Loaded { len (instance_ids )} instances from { args .instance_file } " )
261+
229262 logger .info (f"Aggregating results from { args .input_dir } " )
230263 aggregator = ResultsAggregator ()
231- df = aggregator .aggregate_results_to_dataframe (args .input_dir )
264+ df = aggregator .aggregate_results_to_dataframe (args .input_dir , instance_ids = instance_ids )
232265
233266 df .to_parquet (args .output_file , compression = "snappy" , index = False )
234267 logger .info (f"Wrote aggregated results to { args .output_file } " )
0 commit comments