RGB Evaluation commited on
Commit
5253a83
·
1 Parent(s): b1ccc5d

fix: Information Integration evaluation - handle multiple answer variants with pipe-separated format

Browse files
Files changed (2) hide show
  1. src/data_loader.py +19 -3
  2. src/evaluator.py +41 -2
src/data_loader.py CHANGED
@@ -83,10 +83,26 @@ class RGBDataLoader:
83
  return data
84
 
85
  def _format_answer(self, answer: Any) -> str:
86
- """Format answer to string for comparison."""
 
 
 
 
87
  if isinstance(answer, list):
88
- # Join list answers with comma
89
- return ", ".join(str(a) for a in answer)
 
 
 
 
 
 
 
 
 
 
 
 
90
  return str(answer)
91
 
92
  def load_noise_robustness(
 
83
  return data
84
 
85
  def _format_answer(self, answer: Any) -> str:
86
+ """
87
+ Format answer to string for comparison.
88
+ For nested lists (information integration), flatten to list of alternatives.
89
+ For simple lists (noise robustness), take first or join.
90
+ """
91
  if isinstance(answer, list):
92
+ # Check if it's a nested list (from en_int.json with answer variants)
93
+ if answer and isinstance(answer[0], list):
94
+ # Flatten nested list: [['variant1', 'variant2'], 'other_answer'] → all variants
95
+ variants = []
96
+ for item in answer:
97
+ if isinstance(item, list):
98
+ variants.extend(item)
99
+ else:
100
+ variants.append(str(item))
101
+ # Return as pipe-separated alternatives for matching
102
+ return "|".join(variants)
103
+ else:
104
+ # Simple list: join with pipe as alternatives
105
+ return "|".join(str(a) for a in answer)
106
  return str(answer)
107
 
108
  def load_noise_robustness(
src/evaluator.py CHANGED
@@ -143,6 +143,7 @@ class RGBEvaluator:
143
  """
144
  Normalize an answer for comparison.
145
  Removes punctuation, extra whitespace, and converts to lowercase.
 
146
  """
147
  if not answer:
148
  return ""
@@ -153,6 +154,9 @@ class RGBEvaluator:
153
  # Remove common punctuation at the end
154
  answer = re.sub(r'[.!?,;:]+$', '', answer)
155
 
 
 
 
156
  # Remove extra whitespace
157
  answer = ' '.join(answer.split())
158
 
@@ -187,19 +191,54 @@ class RGBEvaluator:
187
  def is_correct(self, response: str, ground_truth: str, strict: bool = False) -> bool:
188
  """
189
  Check if the response matches the ground truth answer.
 
190
 
191
  Args:
192
  response: The model's response.
193
- ground_truth: The correct answer.
194
  strict: If True, requires exact match. If False, allows partial match.
195
 
196
  Returns:
197
  True if the answer is correct, False otherwise.
198
  """
199
  norm_response = self.normalize_answer(response)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  norm_truth = self.normalize_answer(ground_truth)
201
 
202
- if not norm_response or not norm_truth:
203
  return False
204
 
205
  if strict:
 
143
  """
144
  Normalize an answer for comparison.
145
  Removes punctuation, extra whitespace, and converts to lowercase.
146
+ Also removes commas from dates for consistent matching.
147
  """
148
  if not answer:
149
  return ""
 
154
  # Remove common punctuation at the end
155
  answer = re.sub(r'[.!?,;:]+$', '', answer)
156
 
157
+ # Remove all commas within the text (helps with date matching like "Jan, 2, 2022" -> "jan 2 2022")
158
+ answer = answer.replace(',', '')
159
+
160
  # Remove extra whitespace
161
  answer = ' '.join(answer.split())
162
 
 
191
  def is_correct(self, response: str, ground_truth: str, strict: bool = False) -> bool:
192
  """
193
  Check if the response matches the ground truth answer.
194
+ Supports pipe-separated alternatives (for information integration with variants).
195
 
196
  Args:
197
  response: The model's response.
198
+ ground_truth: The correct answer (can be pipe-separated alternatives).
199
  strict: If True, requires exact match. If False, allows partial match.
200
 
201
  Returns:
202
  True if the answer is correct, False otherwise.
203
  """
204
  norm_response = self.normalize_answer(response)
205
+
206
+ if not norm_response:
207
+ return False
208
+
209
+ # Handle pipe-separated alternatives (information integration with answer variants)
210
+ if "|" in ground_truth:
211
+ alternatives = [self.normalize_answer(alt.strip()) for alt in ground_truth.split("|")]
212
+ # Check if response matches ANY of the alternatives
213
+ for alternative in alternatives:
214
+ if not alternative:
215
+ continue
216
+
217
+ # Check each matching strategy for this alternative
218
+ if strict:
219
+ if norm_response == alternative:
220
+ return True
221
+ else:
222
+ # Substring match
223
+ if alternative in norm_response:
224
+ return True
225
+ # Short answer in long answer
226
+ if len(norm_response) < len(alternative) and norm_response in alternative:
227
+ return True
228
+ # Token overlap
229
+ truth_tokens = set(alternative.split())
230
+ response_tokens = set(norm_response.split())
231
+ if len(truth_tokens) > 0:
232
+ overlap = len(truth_tokens & response_tokens) / len(truth_tokens)
233
+ if overlap >= 0.8:
234
+ return True
235
+
236
+ return False
237
+
238
+ # Single answer (original logic)
239
  norm_truth = self.normalize_answer(ground_truth)
240
 
241
+ if not norm_truth:
242
  return False
243
 
244
  if strict: