fix: normalize explicit TSQA choice labels
Browse files- Benchmark_eval/TSQA/_build/schema.py +40 -4
- results/4level_grpo_min2/TSQA/_infer/score/schema.py +40 -4
- results/ChatTS-14B/TSQA/_infer/score/schema.py +40 -4
- results/GPT-4o/TSQA/_infer/score/schema.py +40 -4
- results/Qwen2.5-7B-Instruct/TSQA/_infer/score/schema.py +40 -4
- results/Time-MQA-Mistral-7B/TSQA/_infer/score/schema.py +40 -4
- results/Time-MQA-Qwen-2.5-7B/TSQA/_infer/score/schema.py +40 -4
- results/joint_grpo_min2/TSQA/_infer/score/schema.py +40 -4
- results/joint_sft/TSQA/_infer/score/schema.py +40 -4
- results/joint_sft_14B/TSQA/_infer/score/schema.py +40 -4
- results/ts-align-bk-joint-grpo-min2/TSQA/_infer/score/schema.py +40 -4
- results/ts-align/TSQA/_infer/score/schema.py +40 -4
Benchmark_eval/TSQA/_build/schema.py
CHANGED
|
@@ -162,7 +162,20 @@ _BOXED_RE = re.compile(r"\\boxed\s*\{([^{}]*)\}")
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
-
_LETTER_RE = re.compile(r"\b([A-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
|
| 168 |
def answer_block(text: str) -> str:
|
|
@@ -233,10 +246,12 @@ def parse_number(text: str) -> float | None:
|
|
| 233 |
|
| 234 |
|
| 235 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 236 |
-
"""
|
| 237 |
|
| 238 |
-
Order: \\boxed{}
|
| 239 |
-
|
|
|
|
|
|
|
| 240 |
"""
|
| 241 |
boxed = extract_boxed(text)
|
| 242 |
if boxed:
|
|
@@ -255,6 +270,27 @@ def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
|
| 255 |
for opt in options:
|
| 256 |
if opt and opt.lower() in low:
|
| 257 |
return opt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
return None
|
| 259 |
|
| 260 |
|
|
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
+
_LETTER_RE = re.compile(r"\b([A-Ha-h])\b")
|
| 166 |
+
_LEADING_CHOICE_RE = re.compile(
|
| 167 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s*(?=$|\n))"
|
| 168 |
+
)
|
| 169 |
+
_EXPLICIT_CHOICE_RE = re.compile(
|
| 170 |
+
r"(?is)(?:\*{0,2})(?:(?:final|correct)\s+)?"
|
| 171 |
+
r"(?:answer|option|choice|conclusion)(?:\*{0,2})\s*"
|
| 172 |
+
r"(?:is\s*[::]?|[::])\s*(?:\*{0,2})(?:option\s+)?"
|
| 173 |
+
r"\(?\s*([A-Ha-h])\b"
|
| 174 |
+
)
|
| 175 |
+
_EXPLICIT_TRUE_FALSE_RE = re.compile(
|
| 176 |
+
r"(?is)(?:answer|conclusion|statement)\s*(?:is\s*[::]?|[::])\s*"
|
| 177 |
+
r"(true|false)\b"
|
| 178 |
+
)
|
| 179 |
|
| 180 |
|
| 181 |
def answer_block(text: str) -> str:
|
|
|
|
| 246 |
|
| 247 |
|
| 248 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 249 |
+
"""Extract an explicit choice without scraping arbitrary prose.
|
| 250 |
|
| 251 |
+
Order: \\boxed{} -> <answer> -> leading option label -> explicit answer cue.
|
| 252 |
+
The two fallbacks accept unambiguous forms such as ``B) False``, a leading
|
| 253 |
+
bare ``B``, ``Final answer: B``, or ``Conclusion: B``. They deliberately do
|
| 254 |
+
not search for isolated letters elsewhere in prose.
|
| 255 |
"""
|
| 256 |
boxed = extract_boxed(text)
|
| 257 |
if boxed:
|
|
|
|
| 270 |
for opt in options:
|
| 271 |
if opt and opt.lower() in low:
|
| 272 |
return opt
|
| 273 |
+
leading = _LEADING_CHOICE_RE.match(text)
|
| 274 |
+
if leading:
|
| 275 |
+
return leading.group(1).upper()
|
| 276 |
+
explicit = list(_EXPLICIT_CHOICE_RE.finditer(text))
|
| 277 |
+
if explicit:
|
| 278 |
+
return explicit[-1].group(1).upper()
|
| 279 |
+
if options:
|
| 280 |
+
true_false_labels = {}
|
| 281 |
+
for option in options:
|
| 282 |
+
match = re.match(
|
| 283 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s+)\s*"
|
| 284 |
+
r"(true|false)\b",
|
| 285 |
+
option,
|
| 286 |
+
re.IGNORECASE,
|
| 287 |
+
)
|
| 288 |
+
if match:
|
| 289 |
+
true_false_labels[match.group(2).lower()] = match.group(1).upper()
|
| 290 |
+
if len(true_false_labels) == 2:
|
| 291 |
+
tf_matches = list(_EXPLICIT_TRUE_FALSE_RE.finditer(text))
|
| 292 |
+
if tf_matches:
|
| 293 |
+
return true_false_labels[tf_matches[-1].group(1).lower()]
|
| 294 |
return None
|
| 295 |
|
| 296 |
|
results/4level_grpo_min2/TSQA/_infer/score/schema.py
CHANGED
|
@@ -162,7 +162,20 @@ _BOXED_RE = re.compile(r"\\boxed\s*\{([^{}]*)\}")
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
-
_LETTER_RE = re.compile(r"\b([A-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
|
| 168 |
def answer_block(text: str) -> str:
|
|
@@ -233,10 +246,12 @@ def parse_number(text: str) -> float | None:
|
|
| 233 |
|
| 234 |
|
| 235 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 236 |
-
"""
|
| 237 |
|
| 238 |
-
Order: \\boxed{}
|
| 239 |
-
|
|
|
|
|
|
|
| 240 |
"""
|
| 241 |
boxed = extract_boxed(text)
|
| 242 |
if boxed:
|
|
@@ -255,6 +270,27 @@ def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
|
| 255 |
for opt in options:
|
| 256 |
if opt and opt.lower() in low:
|
| 257 |
return opt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
return None
|
| 259 |
|
| 260 |
|
|
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
+
_LETTER_RE = re.compile(r"\b([A-Ha-h])\b")
|
| 166 |
+
_LEADING_CHOICE_RE = re.compile(
|
| 167 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s*(?=$|\n))"
|
| 168 |
+
)
|
| 169 |
+
_EXPLICIT_CHOICE_RE = re.compile(
|
| 170 |
+
r"(?is)(?:\*{0,2})(?:(?:final|correct)\s+)?"
|
| 171 |
+
r"(?:answer|option|choice|conclusion)(?:\*{0,2})\s*"
|
| 172 |
+
r"(?:is\s*[::]?|[::])\s*(?:\*{0,2})(?:option\s+)?"
|
| 173 |
+
r"\(?\s*([A-Ha-h])\b"
|
| 174 |
+
)
|
| 175 |
+
_EXPLICIT_TRUE_FALSE_RE = re.compile(
|
| 176 |
+
r"(?is)(?:answer|conclusion|statement)\s*(?:is\s*[::]?|[::])\s*"
|
| 177 |
+
r"(true|false)\b"
|
| 178 |
+
)
|
| 179 |
|
| 180 |
|
| 181 |
def answer_block(text: str) -> str:
|
|
|
|
| 246 |
|
| 247 |
|
| 248 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 249 |
+
"""Extract an explicit choice without scraping arbitrary prose.
|
| 250 |
|
| 251 |
+
Order: \\boxed{} -> <answer> -> leading option label -> explicit answer cue.
|
| 252 |
+
The two fallbacks accept unambiguous forms such as ``B) False``, a leading
|
| 253 |
+
bare ``B``, ``Final answer: B``, or ``Conclusion: B``. They deliberately do
|
| 254 |
+
not search for isolated letters elsewhere in prose.
|
| 255 |
"""
|
| 256 |
boxed = extract_boxed(text)
|
| 257 |
if boxed:
|
|
|
|
| 270 |
for opt in options:
|
| 271 |
if opt and opt.lower() in low:
|
| 272 |
return opt
|
| 273 |
+
leading = _LEADING_CHOICE_RE.match(text)
|
| 274 |
+
if leading:
|
| 275 |
+
return leading.group(1).upper()
|
| 276 |
+
explicit = list(_EXPLICIT_CHOICE_RE.finditer(text))
|
| 277 |
+
if explicit:
|
| 278 |
+
return explicit[-1].group(1).upper()
|
| 279 |
+
if options:
|
| 280 |
+
true_false_labels = {}
|
| 281 |
+
for option in options:
|
| 282 |
+
match = re.match(
|
| 283 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s+)\s*"
|
| 284 |
+
r"(true|false)\b",
|
| 285 |
+
option,
|
| 286 |
+
re.IGNORECASE,
|
| 287 |
+
)
|
| 288 |
+
if match:
|
| 289 |
+
true_false_labels[match.group(2).lower()] = match.group(1).upper()
|
| 290 |
+
if len(true_false_labels) == 2:
|
| 291 |
+
tf_matches = list(_EXPLICIT_TRUE_FALSE_RE.finditer(text))
|
| 292 |
+
if tf_matches:
|
| 293 |
+
return true_false_labels[tf_matches[-1].group(1).lower()]
|
| 294 |
return None
|
| 295 |
|
| 296 |
|
results/ChatTS-14B/TSQA/_infer/score/schema.py
CHANGED
|
@@ -162,7 +162,20 @@ _BOXED_RE = re.compile(r"\\boxed\s*\{([^{}]*)\}")
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
-
_LETTER_RE = re.compile(r"\b([A-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
|
| 168 |
def answer_block(text: str) -> str:
|
|
@@ -233,10 +246,12 @@ def parse_number(text: str) -> float | None:
|
|
| 233 |
|
| 234 |
|
| 235 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 236 |
-
"""
|
| 237 |
|
| 238 |
-
Order: \\boxed{}
|
| 239 |
-
|
|
|
|
|
|
|
| 240 |
"""
|
| 241 |
boxed = extract_boxed(text)
|
| 242 |
if boxed:
|
|
@@ -255,6 +270,27 @@ def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
|
| 255 |
for opt in options:
|
| 256 |
if opt and opt.lower() in low:
|
| 257 |
return opt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
return None
|
| 259 |
|
| 260 |
|
|
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
+
_LETTER_RE = re.compile(r"\b([A-Ha-h])\b")
|
| 166 |
+
_LEADING_CHOICE_RE = re.compile(
|
| 167 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s*(?=$|\n))"
|
| 168 |
+
)
|
| 169 |
+
_EXPLICIT_CHOICE_RE = re.compile(
|
| 170 |
+
r"(?is)(?:\*{0,2})(?:(?:final|correct)\s+)?"
|
| 171 |
+
r"(?:answer|option|choice|conclusion)(?:\*{0,2})\s*"
|
| 172 |
+
r"(?:is\s*[::]?|[::])\s*(?:\*{0,2})(?:option\s+)?"
|
| 173 |
+
r"\(?\s*([A-Ha-h])\b"
|
| 174 |
+
)
|
| 175 |
+
_EXPLICIT_TRUE_FALSE_RE = re.compile(
|
| 176 |
+
r"(?is)(?:answer|conclusion|statement)\s*(?:is\s*[::]?|[::])\s*"
|
| 177 |
+
r"(true|false)\b"
|
| 178 |
+
)
|
| 179 |
|
| 180 |
|
| 181 |
def answer_block(text: str) -> str:
|
|
|
|
| 246 |
|
| 247 |
|
| 248 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 249 |
+
"""Extract an explicit choice without scraping arbitrary prose.
|
| 250 |
|
| 251 |
+
Order: \\boxed{} -> <answer> -> leading option label -> explicit answer cue.
|
| 252 |
+
The two fallbacks accept unambiguous forms such as ``B) False``, a leading
|
| 253 |
+
bare ``B``, ``Final answer: B``, or ``Conclusion: B``. They deliberately do
|
| 254 |
+
not search for isolated letters elsewhere in prose.
|
| 255 |
"""
|
| 256 |
boxed = extract_boxed(text)
|
| 257 |
if boxed:
|
|
|
|
| 270 |
for opt in options:
|
| 271 |
if opt and opt.lower() in low:
|
| 272 |
return opt
|
| 273 |
+
leading = _LEADING_CHOICE_RE.match(text)
|
| 274 |
+
if leading:
|
| 275 |
+
return leading.group(1).upper()
|
| 276 |
+
explicit = list(_EXPLICIT_CHOICE_RE.finditer(text))
|
| 277 |
+
if explicit:
|
| 278 |
+
return explicit[-1].group(1).upper()
|
| 279 |
+
if options:
|
| 280 |
+
true_false_labels = {}
|
| 281 |
+
for option in options:
|
| 282 |
+
match = re.match(
|
| 283 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s+)\s*"
|
| 284 |
+
r"(true|false)\b",
|
| 285 |
+
option,
|
| 286 |
+
re.IGNORECASE,
|
| 287 |
+
)
|
| 288 |
+
if match:
|
| 289 |
+
true_false_labels[match.group(2).lower()] = match.group(1).upper()
|
| 290 |
+
if len(true_false_labels) == 2:
|
| 291 |
+
tf_matches = list(_EXPLICIT_TRUE_FALSE_RE.finditer(text))
|
| 292 |
+
if tf_matches:
|
| 293 |
+
return true_false_labels[tf_matches[-1].group(1).lower()]
|
| 294 |
return None
|
| 295 |
|
| 296 |
|
results/GPT-4o/TSQA/_infer/score/schema.py
CHANGED
|
@@ -162,7 +162,20 @@ _BOXED_RE = re.compile(r"\\boxed\s*\{([^{}]*)\}")
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
-
_LETTER_RE = re.compile(r"\b([A-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
|
| 168 |
def answer_block(text: str) -> str:
|
|
@@ -233,10 +246,12 @@ def parse_number(text: str) -> float | None:
|
|
| 233 |
|
| 234 |
|
| 235 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 236 |
-
"""
|
| 237 |
|
| 238 |
-
Order: \\boxed{}
|
| 239 |
-
|
|
|
|
|
|
|
| 240 |
"""
|
| 241 |
boxed = extract_boxed(text)
|
| 242 |
if boxed:
|
|
@@ -255,6 +270,27 @@ def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
|
| 255 |
for opt in options:
|
| 256 |
if opt and opt.lower() in low:
|
| 257 |
return opt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
return None
|
| 259 |
|
| 260 |
|
|
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
+
_LETTER_RE = re.compile(r"\b([A-Ha-h])\b")
|
| 166 |
+
_LEADING_CHOICE_RE = re.compile(
|
| 167 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s*(?=$|\n))"
|
| 168 |
+
)
|
| 169 |
+
_EXPLICIT_CHOICE_RE = re.compile(
|
| 170 |
+
r"(?is)(?:\*{0,2})(?:(?:final|correct)\s+)?"
|
| 171 |
+
r"(?:answer|option|choice|conclusion)(?:\*{0,2})\s*"
|
| 172 |
+
r"(?:is\s*[::]?|[::])\s*(?:\*{0,2})(?:option\s+)?"
|
| 173 |
+
r"\(?\s*([A-Ha-h])\b"
|
| 174 |
+
)
|
| 175 |
+
_EXPLICIT_TRUE_FALSE_RE = re.compile(
|
| 176 |
+
r"(?is)(?:answer|conclusion|statement)\s*(?:is\s*[::]?|[::])\s*"
|
| 177 |
+
r"(true|false)\b"
|
| 178 |
+
)
|
| 179 |
|
| 180 |
|
| 181 |
def answer_block(text: str) -> str:
|
|
|
|
| 246 |
|
| 247 |
|
| 248 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 249 |
+
"""Extract an explicit choice without scraping arbitrary prose.
|
| 250 |
|
| 251 |
+
Order: \\boxed{} -> <answer> -> leading option label -> explicit answer cue.
|
| 252 |
+
The two fallbacks accept unambiguous forms such as ``B) False``, a leading
|
| 253 |
+
bare ``B``, ``Final answer: B``, or ``Conclusion: B``. They deliberately do
|
| 254 |
+
not search for isolated letters elsewhere in prose.
|
| 255 |
"""
|
| 256 |
boxed = extract_boxed(text)
|
| 257 |
if boxed:
|
|
|
|
| 270 |
for opt in options:
|
| 271 |
if opt and opt.lower() in low:
|
| 272 |
return opt
|
| 273 |
+
leading = _LEADING_CHOICE_RE.match(text)
|
| 274 |
+
if leading:
|
| 275 |
+
return leading.group(1).upper()
|
| 276 |
+
explicit = list(_EXPLICIT_CHOICE_RE.finditer(text))
|
| 277 |
+
if explicit:
|
| 278 |
+
return explicit[-1].group(1).upper()
|
| 279 |
+
if options:
|
| 280 |
+
true_false_labels = {}
|
| 281 |
+
for option in options:
|
| 282 |
+
match = re.match(
|
| 283 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s+)\s*"
|
| 284 |
+
r"(true|false)\b",
|
| 285 |
+
option,
|
| 286 |
+
re.IGNORECASE,
|
| 287 |
+
)
|
| 288 |
+
if match:
|
| 289 |
+
true_false_labels[match.group(2).lower()] = match.group(1).upper()
|
| 290 |
+
if len(true_false_labels) == 2:
|
| 291 |
+
tf_matches = list(_EXPLICIT_TRUE_FALSE_RE.finditer(text))
|
| 292 |
+
if tf_matches:
|
| 293 |
+
return true_false_labels[tf_matches[-1].group(1).lower()]
|
| 294 |
return None
|
| 295 |
|
| 296 |
|
results/Qwen2.5-7B-Instruct/TSQA/_infer/score/schema.py
CHANGED
|
@@ -162,7 +162,20 @@ _BOXED_RE = re.compile(r"\\boxed\s*\{([^{}]*)\}")
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
-
_LETTER_RE = re.compile(r"\b([A-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
|
| 168 |
def answer_block(text: str) -> str:
|
|
@@ -233,10 +246,12 @@ def parse_number(text: str) -> float | None:
|
|
| 233 |
|
| 234 |
|
| 235 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 236 |
-
"""
|
| 237 |
|
| 238 |
-
Order: \\boxed{}
|
| 239 |
-
|
|
|
|
|
|
|
| 240 |
"""
|
| 241 |
boxed = extract_boxed(text)
|
| 242 |
if boxed:
|
|
@@ -255,6 +270,27 @@ def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
|
| 255 |
for opt in options:
|
| 256 |
if opt and opt.lower() in low:
|
| 257 |
return opt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
return None
|
| 259 |
|
| 260 |
|
|
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
+
_LETTER_RE = re.compile(r"\b([A-Ha-h])\b")
|
| 166 |
+
_LEADING_CHOICE_RE = re.compile(
|
| 167 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s*(?=$|\n))"
|
| 168 |
+
)
|
| 169 |
+
_EXPLICIT_CHOICE_RE = re.compile(
|
| 170 |
+
r"(?is)(?:\*{0,2})(?:(?:final|correct)\s+)?"
|
| 171 |
+
r"(?:answer|option|choice|conclusion)(?:\*{0,2})\s*"
|
| 172 |
+
r"(?:is\s*[::]?|[::])\s*(?:\*{0,2})(?:option\s+)?"
|
| 173 |
+
r"\(?\s*([A-Ha-h])\b"
|
| 174 |
+
)
|
| 175 |
+
_EXPLICIT_TRUE_FALSE_RE = re.compile(
|
| 176 |
+
r"(?is)(?:answer|conclusion|statement)\s*(?:is\s*[::]?|[::])\s*"
|
| 177 |
+
r"(true|false)\b"
|
| 178 |
+
)
|
| 179 |
|
| 180 |
|
| 181 |
def answer_block(text: str) -> str:
|
|
|
|
| 246 |
|
| 247 |
|
| 248 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 249 |
+
"""Extract an explicit choice without scraping arbitrary prose.
|
| 250 |
|
| 251 |
+
Order: \\boxed{} -> <answer> -> leading option label -> explicit answer cue.
|
| 252 |
+
The two fallbacks accept unambiguous forms such as ``B) False``, a leading
|
| 253 |
+
bare ``B``, ``Final answer: B``, or ``Conclusion: B``. They deliberately do
|
| 254 |
+
not search for isolated letters elsewhere in prose.
|
| 255 |
"""
|
| 256 |
boxed = extract_boxed(text)
|
| 257 |
if boxed:
|
|
|
|
| 270 |
for opt in options:
|
| 271 |
if opt and opt.lower() in low:
|
| 272 |
return opt
|
| 273 |
+
leading = _LEADING_CHOICE_RE.match(text)
|
| 274 |
+
if leading:
|
| 275 |
+
return leading.group(1).upper()
|
| 276 |
+
explicit = list(_EXPLICIT_CHOICE_RE.finditer(text))
|
| 277 |
+
if explicit:
|
| 278 |
+
return explicit[-1].group(1).upper()
|
| 279 |
+
if options:
|
| 280 |
+
true_false_labels = {}
|
| 281 |
+
for option in options:
|
| 282 |
+
match = re.match(
|
| 283 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s+)\s*"
|
| 284 |
+
r"(true|false)\b",
|
| 285 |
+
option,
|
| 286 |
+
re.IGNORECASE,
|
| 287 |
+
)
|
| 288 |
+
if match:
|
| 289 |
+
true_false_labels[match.group(2).lower()] = match.group(1).upper()
|
| 290 |
+
if len(true_false_labels) == 2:
|
| 291 |
+
tf_matches = list(_EXPLICIT_TRUE_FALSE_RE.finditer(text))
|
| 292 |
+
if tf_matches:
|
| 293 |
+
return true_false_labels[tf_matches[-1].group(1).lower()]
|
| 294 |
return None
|
| 295 |
|
| 296 |
|
results/Time-MQA-Mistral-7B/TSQA/_infer/score/schema.py
CHANGED
|
@@ -162,7 +162,20 @@ _BOXED_RE = re.compile(r"\\boxed\s*\{([^{}]*)\}")
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
-
_LETTER_RE = re.compile(r"\b([A-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
|
| 168 |
def answer_block(text: str) -> str:
|
|
@@ -233,10 +246,12 @@ def parse_number(text: str) -> float | None:
|
|
| 233 |
|
| 234 |
|
| 235 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 236 |
-
"""
|
| 237 |
|
| 238 |
-
Order: \\boxed{}
|
| 239 |
-
|
|
|
|
|
|
|
| 240 |
"""
|
| 241 |
boxed = extract_boxed(text)
|
| 242 |
if boxed:
|
|
@@ -255,6 +270,27 @@ def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
|
| 255 |
for opt in options:
|
| 256 |
if opt and opt.lower() in low:
|
| 257 |
return opt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
return None
|
| 259 |
|
| 260 |
|
|
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
+
_LETTER_RE = re.compile(r"\b([A-Ha-h])\b")
|
| 166 |
+
_LEADING_CHOICE_RE = re.compile(
|
| 167 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s*(?=$|\n))"
|
| 168 |
+
)
|
| 169 |
+
_EXPLICIT_CHOICE_RE = re.compile(
|
| 170 |
+
r"(?is)(?:\*{0,2})(?:(?:final|correct)\s+)?"
|
| 171 |
+
r"(?:answer|option|choice|conclusion)(?:\*{0,2})\s*"
|
| 172 |
+
r"(?:is\s*[::]?|[::])\s*(?:\*{0,2})(?:option\s+)?"
|
| 173 |
+
r"\(?\s*([A-Ha-h])\b"
|
| 174 |
+
)
|
| 175 |
+
_EXPLICIT_TRUE_FALSE_RE = re.compile(
|
| 176 |
+
r"(?is)(?:answer|conclusion|statement)\s*(?:is\s*[::]?|[::])\s*"
|
| 177 |
+
r"(true|false)\b"
|
| 178 |
+
)
|
| 179 |
|
| 180 |
|
| 181 |
def answer_block(text: str) -> str:
|
|
|
|
| 246 |
|
| 247 |
|
| 248 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 249 |
+
"""Extract an explicit choice without scraping arbitrary prose.
|
| 250 |
|
| 251 |
+
Order: \\boxed{} -> <answer> -> leading option label -> explicit answer cue.
|
| 252 |
+
The two fallbacks accept unambiguous forms such as ``B) False``, a leading
|
| 253 |
+
bare ``B``, ``Final answer: B``, or ``Conclusion: B``. They deliberately do
|
| 254 |
+
not search for isolated letters elsewhere in prose.
|
| 255 |
"""
|
| 256 |
boxed = extract_boxed(text)
|
| 257 |
if boxed:
|
|
|
|
| 270 |
for opt in options:
|
| 271 |
if opt and opt.lower() in low:
|
| 272 |
return opt
|
| 273 |
+
leading = _LEADING_CHOICE_RE.match(text)
|
| 274 |
+
if leading:
|
| 275 |
+
return leading.group(1).upper()
|
| 276 |
+
explicit = list(_EXPLICIT_CHOICE_RE.finditer(text))
|
| 277 |
+
if explicit:
|
| 278 |
+
return explicit[-1].group(1).upper()
|
| 279 |
+
if options:
|
| 280 |
+
true_false_labels = {}
|
| 281 |
+
for option in options:
|
| 282 |
+
match = re.match(
|
| 283 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s+)\s*"
|
| 284 |
+
r"(true|false)\b",
|
| 285 |
+
option,
|
| 286 |
+
re.IGNORECASE,
|
| 287 |
+
)
|
| 288 |
+
if match:
|
| 289 |
+
true_false_labels[match.group(2).lower()] = match.group(1).upper()
|
| 290 |
+
if len(true_false_labels) == 2:
|
| 291 |
+
tf_matches = list(_EXPLICIT_TRUE_FALSE_RE.finditer(text))
|
| 292 |
+
if tf_matches:
|
| 293 |
+
return true_false_labels[tf_matches[-1].group(1).lower()]
|
| 294 |
return None
|
| 295 |
|
| 296 |
|
results/Time-MQA-Qwen-2.5-7B/TSQA/_infer/score/schema.py
CHANGED
|
@@ -162,7 +162,20 @@ _BOXED_RE = re.compile(r"\\boxed\s*\{([^{}]*)\}")
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
-
_LETTER_RE = re.compile(r"\b([A-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
|
| 168 |
def answer_block(text: str) -> str:
|
|
@@ -233,10 +246,12 @@ def parse_number(text: str) -> float | None:
|
|
| 233 |
|
| 234 |
|
| 235 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 236 |
-
"""
|
| 237 |
|
| 238 |
-
Order: \\boxed{}
|
| 239 |
-
|
|
|
|
|
|
|
| 240 |
"""
|
| 241 |
boxed = extract_boxed(text)
|
| 242 |
if boxed:
|
|
@@ -255,6 +270,27 @@ def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
|
| 255 |
for opt in options:
|
| 256 |
if opt and opt.lower() in low:
|
| 257 |
return opt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
return None
|
| 259 |
|
| 260 |
|
|
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
+
_LETTER_RE = re.compile(r"\b([A-Ha-h])\b")
|
| 166 |
+
_LEADING_CHOICE_RE = re.compile(
|
| 167 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s*(?=$|\n))"
|
| 168 |
+
)
|
| 169 |
+
_EXPLICIT_CHOICE_RE = re.compile(
|
| 170 |
+
r"(?is)(?:\*{0,2})(?:(?:final|correct)\s+)?"
|
| 171 |
+
r"(?:answer|option|choice|conclusion)(?:\*{0,2})\s*"
|
| 172 |
+
r"(?:is\s*[::]?|[::])\s*(?:\*{0,2})(?:option\s+)?"
|
| 173 |
+
r"\(?\s*([A-Ha-h])\b"
|
| 174 |
+
)
|
| 175 |
+
_EXPLICIT_TRUE_FALSE_RE = re.compile(
|
| 176 |
+
r"(?is)(?:answer|conclusion|statement)\s*(?:is\s*[::]?|[::])\s*"
|
| 177 |
+
r"(true|false)\b"
|
| 178 |
+
)
|
| 179 |
|
| 180 |
|
| 181 |
def answer_block(text: str) -> str:
|
|
|
|
| 246 |
|
| 247 |
|
| 248 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 249 |
+
"""Extract an explicit choice without scraping arbitrary prose.
|
| 250 |
|
| 251 |
+
Order: \\boxed{} -> <answer> -> leading option label -> explicit answer cue.
|
| 252 |
+
The two fallbacks accept unambiguous forms such as ``B) False``, a leading
|
| 253 |
+
bare ``B``, ``Final answer: B``, or ``Conclusion: B``. They deliberately do
|
| 254 |
+
not search for isolated letters elsewhere in prose.
|
| 255 |
"""
|
| 256 |
boxed = extract_boxed(text)
|
| 257 |
if boxed:
|
|
|
|
| 270 |
for opt in options:
|
| 271 |
if opt and opt.lower() in low:
|
| 272 |
return opt
|
| 273 |
+
leading = _LEADING_CHOICE_RE.match(text)
|
| 274 |
+
if leading:
|
| 275 |
+
return leading.group(1).upper()
|
| 276 |
+
explicit = list(_EXPLICIT_CHOICE_RE.finditer(text))
|
| 277 |
+
if explicit:
|
| 278 |
+
return explicit[-1].group(1).upper()
|
| 279 |
+
if options:
|
| 280 |
+
true_false_labels = {}
|
| 281 |
+
for option in options:
|
| 282 |
+
match = re.match(
|
| 283 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s+)\s*"
|
| 284 |
+
r"(true|false)\b",
|
| 285 |
+
option,
|
| 286 |
+
re.IGNORECASE,
|
| 287 |
+
)
|
| 288 |
+
if match:
|
| 289 |
+
true_false_labels[match.group(2).lower()] = match.group(1).upper()
|
| 290 |
+
if len(true_false_labels) == 2:
|
| 291 |
+
tf_matches = list(_EXPLICIT_TRUE_FALSE_RE.finditer(text))
|
| 292 |
+
if tf_matches:
|
| 293 |
+
return true_false_labels[tf_matches[-1].group(1).lower()]
|
| 294 |
return None
|
| 295 |
|
| 296 |
|
results/joint_grpo_min2/TSQA/_infer/score/schema.py
CHANGED
|
@@ -162,7 +162,20 @@ _BOXED_RE = re.compile(r"\\boxed\s*\{([^{}]*)\}")
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
-
_LETTER_RE = re.compile(r"\b([A-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
|
| 168 |
def answer_block(text: str) -> str:
|
|
@@ -233,10 +246,12 @@ def parse_number(text: str) -> float | None:
|
|
| 233 |
|
| 234 |
|
| 235 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 236 |
-
"""
|
| 237 |
|
| 238 |
-
Order: \\boxed{}
|
| 239 |
-
|
|
|
|
|
|
|
| 240 |
"""
|
| 241 |
boxed = extract_boxed(text)
|
| 242 |
if boxed:
|
|
@@ -255,6 +270,27 @@ def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
|
| 255 |
for opt in options:
|
| 256 |
if opt and opt.lower() in low:
|
| 257 |
return opt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
return None
|
| 259 |
|
| 260 |
|
|
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
+
_LETTER_RE = re.compile(r"\b([A-Ha-h])\b")
|
| 166 |
+
_LEADING_CHOICE_RE = re.compile(
|
| 167 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s*(?=$|\n))"
|
| 168 |
+
)
|
| 169 |
+
_EXPLICIT_CHOICE_RE = re.compile(
|
| 170 |
+
r"(?is)(?:\*{0,2})(?:(?:final|correct)\s+)?"
|
| 171 |
+
r"(?:answer|option|choice|conclusion)(?:\*{0,2})\s*"
|
| 172 |
+
r"(?:is\s*[::]?|[::])\s*(?:\*{0,2})(?:option\s+)?"
|
| 173 |
+
r"\(?\s*([A-Ha-h])\b"
|
| 174 |
+
)
|
| 175 |
+
_EXPLICIT_TRUE_FALSE_RE = re.compile(
|
| 176 |
+
r"(?is)(?:answer|conclusion|statement)\s*(?:is\s*[::]?|[::])\s*"
|
| 177 |
+
r"(true|false)\b"
|
| 178 |
+
)
|
| 179 |
|
| 180 |
|
| 181 |
def answer_block(text: str) -> str:
|
|
|
|
| 246 |
|
| 247 |
|
| 248 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 249 |
+
"""Extract an explicit choice without scraping arbitrary prose.
|
| 250 |
|
| 251 |
+
Order: \\boxed{} -> <answer> -> leading option label -> explicit answer cue.
|
| 252 |
+
The two fallbacks accept unambiguous forms such as ``B) False``, a leading
|
| 253 |
+
bare ``B``, ``Final answer: B``, or ``Conclusion: B``. They deliberately do
|
| 254 |
+
not search for isolated letters elsewhere in prose.
|
| 255 |
"""
|
| 256 |
boxed = extract_boxed(text)
|
| 257 |
if boxed:
|
|
|
|
| 270 |
for opt in options:
|
| 271 |
if opt and opt.lower() in low:
|
| 272 |
return opt
|
| 273 |
+
leading = _LEADING_CHOICE_RE.match(text)
|
| 274 |
+
if leading:
|
| 275 |
+
return leading.group(1).upper()
|
| 276 |
+
explicit = list(_EXPLICIT_CHOICE_RE.finditer(text))
|
| 277 |
+
if explicit:
|
| 278 |
+
return explicit[-1].group(1).upper()
|
| 279 |
+
if options:
|
| 280 |
+
true_false_labels = {}
|
| 281 |
+
for option in options:
|
| 282 |
+
match = re.match(
|
| 283 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s+)\s*"
|
| 284 |
+
r"(true|false)\b",
|
| 285 |
+
option,
|
| 286 |
+
re.IGNORECASE,
|
| 287 |
+
)
|
| 288 |
+
if match:
|
| 289 |
+
true_false_labels[match.group(2).lower()] = match.group(1).upper()
|
| 290 |
+
if len(true_false_labels) == 2:
|
| 291 |
+
tf_matches = list(_EXPLICIT_TRUE_FALSE_RE.finditer(text))
|
| 292 |
+
if tf_matches:
|
| 293 |
+
return true_false_labels[tf_matches[-1].group(1).lower()]
|
| 294 |
return None
|
| 295 |
|
| 296 |
|
results/joint_sft/TSQA/_infer/score/schema.py
CHANGED
|
@@ -162,7 +162,20 @@ _BOXED_RE = re.compile(r"\\boxed\s*\{([^{}]*)\}")
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
-
_LETTER_RE = re.compile(r"\b([A-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
|
| 168 |
def answer_block(text: str) -> str:
|
|
@@ -233,10 +246,12 @@ def parse_number(text: str) -> float | None:
|
|
| 233 |
|
| 234 |
|
| 235 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 236 |
-
"""
|
| 237 |
|
| 238 |
-
Order: \\boxed{}
|
| 239 |
-
|
|
|
|
|
|
|
| 240 |
"""
|
| 241 |
boxed = extract_boxed(text)
|
| 242 |
if boxed:
|
|
@@ -255,6 +270,27 @@ def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
|
| 255 |
for opt in options:
|
| 256 |
if opt and opt.lower() in low:
|
| 257 |
return opt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
return None
|
| 259 |
|
| 260 |
|
|
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
+
_LETTER_RE = re.compile(r"\b([A-Ha-h])\b")
|
| 166 |
+
_LEADING_CHOICE_RE = re.compile(
|
| 167 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s*(?=$|\n))"
|
| 168 |
+
)
|
| 169 |
+
_EXPLICIT_CHOICE_RE = re.compile(
|
| 170 |
+
r"(?is)(?:\*{0,2})(?:(?:final|correct)\s+)?"
|
| 171 |
+
r"(?:answer|option|choice|conclusion)(?:\*{0,2})\s*"
|
| 172 |
+
r"(?:is\s*[::]?|[::])\s*(?:\*{0,2})(?:option\s+)?"
|
| 173 |
+
r"\(?\s*([A-Ha-h])\b"
|
| 174 |
+
)
|
| 175 |
+
_EXPLICIT_TRUE_FALSE_RE = re.compile(
|
| 176 |
+
r"(?is)(?:answer|conclusion|statement)\s*(?:is\s*[::]?|[::])\s*"
|
| 177 |
+
r"(true|false)\b"
|
| 178 |
+
)
|
| 179 |
|
| 180 |
|
| 181 |
def answer_block(text: str) -> str:
|
|
|
|
| 246 |
|
| 247 |
|
| 248 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 249 |
+
"""Extract an explicit choice without scraping arbitrary prose.
|
| 250 |
|
| 251 |
+
Order: \\boxed{} -> <answer> -> leading option label -> explicit answer cue.
|
| 252 |
+
The two fallbacks accept unambiguous forms such as ``B) False``, a leading
|
| 253 |
+
bare ``B``, ``Final answer: B``, or ``Conclusion: B``. They deliberately do
|
| 254 |
+
not search for isolated letters elsewhere in prose.
|
| 255 |
"""
|
| 256 |
boxed = extract_boxed(text)
|
| 257 |
if boxed:
|
|
|
|
| 270 |
for opt in options:
|
| 271 |
if opt and opt.lower() in low:
|
| 272 |
return opt
|
| 273 |
+
leading = _LEADING_CHOICE_RE.match(text)
|
| 274 |
+
if leading:
|
| 275 |
+
return leading.group(1).upper()
|
| 276 |
+
explicit = list(_EXPLICIT_CHOICE_RE.finditer(text))
|
| 277 |
+
if explicit:
|
| 278 |
+
return explicit[-1].group(1).upper()
|
| 279 |
+
if options:
|
| 280 |
+
true_false_labels = {}
|
| 281 |
+
for option in options:
|
| 282 |
+
match = re.match(
|
| 283 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s+)\s*"
|
| 284 |
+
r"(true|false)\b",
|
| 285 |
+
option,
|
| 286 |
+
re.IGNORECASE,
|
| 287 |
+
)
|
| 288 |
+
if match:
|
| 289 |
+
true_false_labels[match.group(2).lower()] = match.group(1).upper()
|
| 290 |
+
if len(true_false_labels) == 2:
|
| 291 |
+
tf_matches = list(_EXPLICIT_TRUE_FALSE_RE.finditer(text))
|
| 292 |
+
if tf_matches:
|
| 293 |
+
return true_false_labels[tf_matches[-1].group(1).lower()]
|
| 294 |
return None
|
| 295 |
|
| 296 |
|
results/joint_sft_14B/TSQA/_infer/score/schema.py
CHANGED
|
@@ -162,7 +162,20 @@ _BOXED_RE = re.compile(r"\\boxed\s*\{([^{}]*)\}")
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
-
_LETTER_RE = re.compile(r"\b([A-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
|
| 168 |
def answer_block(text: str) -> str:
|
|
@@ -233,10 +246,12 @@ def parse_number(text: str) -> float | None:
|
|
| 233 |
|
| 234 |
|
| 235 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 236 |
-
"""
|
| 237 |
|
| 238 |
-
Order: \\boxed{}
|
| 239 |
-
|
|
|
|
|
|
|
| 240 |
"""
|
| 241 |
boxed = extract_boxed(text)
|
| 242 |
if boxed:
|
|
@@ -255,6 +270,27 @@ def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
|
| 255 |
for opt in options:
|
| 256 |
if opt and opt.lower() in low:
|
| 257 |
return opt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
return None
|
| 259 |
|
| 260 |
|
|
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
+
_LETTER_RE = re.compile(r"\b([A-Ha-h])\b")
|
| 166 |
+
_LEADING_CHOICE_RE = re.compile(
|
| 167 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s*(?=$|\n))"
|
| 168 |
+
)
|
| 169 |
+
_EXPLICIT_CHOICE_RE = re.compile(
|
| 170 |
+
r"(?is)(?:\*{0,2})(?:(?:final|correct)\s+)?"
|
| 171 |
+
r"(?:answer|option|choice|conclusion)(?:\*{0,2})\s*"
|
| 172 |
+
r"(?:is\s*[::]?|[::])\s*(?:\*{0,2})(?:option\s+)?"
|
| 173 |
+
r"\(?\s*([A-Ha-h])\b"
|
| 174 |
+
)
|
| 175 |
+
_EXPLICIT_TRUE_FALSE_RE = re.compile(
|
| 176 |
+
r"(?is)(?:answer|conclusion|statement)\s*(?:is\s*[::]?|[::])\s*"
|
| 177 |
+
r"(true|false)\b"
|
| 178 |
+
)
|
| 179 |
|
| 180 |
|
| 181 |
def answer_block(text: str) -> str:
|
|
|
|
| 246 |
|
| 247 |
|
| 248 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 249 |
+
"""Extract an explicit choice without scraping arbitrary prose.
|
| 250 |
|
| 251 |
+
Order: \\boxed{} -> <answer> -> leading option label -> explicit answer cue.
|
| 252 |
+
The two fallbacks accept unambiguous forms such as ``B) False``, a leading
|
| 253 |
+
bare ``B``, ``Final answer: B``, or ``Conclusion: B``. They deliberately do
|
| 254 |
+
not search for isolated letters elsewhere in prose.
|
| 255 |
"""
|
| 256 |
boxed = extract_boxed(text)
|
| 257 |
if boxed:
|
|
|
|
| 270 |
for opt in options:
|
| 271 |
if opt and opt.lower() in low:
|
| 272 |
return opt
|
| 273 |
+
leading = _LEADING_CHOICE_RE.match(text)
|
| 274 |
+
if leading:
|
| 275 |
+
return leading.group(1).upper()
|
| 276 |
+
explicit = list(_EXPLICIT_CHOICE_RE.finditer(text))
|
| 277 |
+
if explicit:
|
| 278 |
+
return explicit[-1].group(1).upper()
|
| 279 |
+
if options:
|
| 280 |
+
true_false_labels = {}
|
| 281 |
+
for option in options:
|
| 282 |
+
match = re.match(
|
| 283 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s+)\s*"
|
| 284 |
+
r"(true|false)\b",
|
| 285 |
+
option,
|
| 286 |
+
re.IGNORECASE,
|
| 287 |
+
)
|
| 288 |
+
if match:
|
| 289 |
+
true_false_labels[match.group(2).lower()] = match.group(1).upper()
|
| 290 |
+
if len(true_false_labels) == 2:
|
| 291 |
+
tf_matches = list(_EXPLICIT_TRUE_FALSE_RE.finditer(text))
|
| 292 |
+
if tf_matches:
|
| 293 |
+
return true_false_labels[tf_matches[-1].group(1).lower()]
|
| 294 |
return None
|
| 295 |
|
| 296 |
|
results/ts-align-bk-joint-grpo-min2/TSQA/_infer/score/schema.py
CHANGED
|
@@ -162,7 +162,20 @@ _BOXED_RE = re.compile(r"\\boxed\s*\{([^{}]*)\}")
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
-
_LETTER_RE = re.compile(r"\b([A-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
|
| 168 |
def answer_block(text: str) -> str:
|
|
@@ -233,10 +246,12 @@ def parse_number(text: str) -> float | None:
|
|
| 233 |
|
| 234 |
|
| 235 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 236 |
-
"""
|
| 237 |
|
| 238 |
-
Order: \\boxed{}
|
| 239 |
-
|
|
|
|
|
|
|
| 240 |
"""
|
| 241 |
boxed = extract_boxed(text)
|
| 242 |
if boxed:
|
|
@@ -255,6 +270,27 @@ def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
|
| 255 |
for opt in options:
|
| 256 |
if opt and opt.lower() in low:
|
| 257 |
return opt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
return None
|
| 259 |
|
| 260 |
|
|
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
+
_LETTER_RE = re.compile(r"\b([A-Ha-h])\b")
|
| 166 |
+
_LEADING_CHOICE_RE = re.compile(
|
| 167 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s*(?=$|\n))"
|
| 168 |
+
)
|
| 169 |
+
_EXPLICIT_CHOICE_RE = re.compile(
|
| 170 |
+
r"(?is)(?:\*{0,2})(?:(?:final|correct)\s+)?"
|
| 171 |
+
r"(?:answer|option|choice|conclusion)(?:\*{0,2})\s*"
|
| 172 |
+
r"(?:is\s*[::]?|[::])\s*(?:\*{0,2})(?:option\s+)?"
|
| 173 |
+
r"\(?\s*([A-Ha-h])\b"
|
| 174 |
+
)
|
| 175 |
+
_EXPLICIT_TRUE_FALSE_RE = re.compile(
|
| 176 |
+
r"(?is)(?:answer|conclusion|statement)\s*(?:is\s*[::]?|[::])\s*"
|
| 177 |
+
r"(true|false)\b"
|
| 178 |
+
)
|
| 179 |
|
| 180 |
|
| 181 |
def answer_block(text: str) -> str:
|
|
|
|
| 246 |
|
| 247 |
|
| 248 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 249 |
+
"""Extract an explicit choice without scraping arbitrary prose.
|
| 250 |
|
| 251 |
+
Order: \\boxed{} -> <answer> -> leading option label -> explicit answer cue.
|
| 252 |
+
The two fallbacks accept unambiguous forms such as ``B) False``, a leading
|
| 253 |
+
bare ``B``, ``Final answer: B``, or ``Conclusion: B``. They deliberately do
|
| 254 |
+
not search for isolated letters elsewhere in prose.
|
| 255 |
"""
|
| 256 |
boxed = extract_boxed(text)
|
| 257 |
if boxed:
|
|
|
|
| 270 |
for opt in options:
|
| 271 |
if opt and opt.lower() in low:
|
| 272 |
return opt
|
| 273 |
+
leading = _LEADING_CHOICE_RE.match(text)
|
| 274 |
+
if leading:
|
| 275 |
+
return leading.group(1).upper()
|
| 276 |
+
explicit = list(_EXPLICIT_CHOICE_RE.finditer(text))
|
| 277 |
+
if explicit:
|
| 278 |
+
return explicit[-1].group(1).upper()
|
| 279 |
+
if options:
|
| 280 |
+
true_false_labels = {}
|
| 281 |
+
for option in options:
|
| 282 |
+
match = re.match(
|
| 283 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s+)\s*"
|
| 284 |
+
r"(true|false)\b",
|
| 285 |
+
option,
|
| 286 |
+
re.IGNORECASE,
|
| 287 |
+
)
|
| 288 |
+
if match:
|
| 289 |
+
true_false_labels[match.group(2).lower()] = match.group(1).upper()
|
| 290 |
+
if len(true_false_labels) == 2:
|
| 291 |
+
tf_matches = list(_EXPLICIT_TRUE_FALSE_RE.finditer(text))
|
| 292 |
+
if tf_matches:
|
| 293 |
+
return true_false_labels[tf_matches[-1].group(1).lower()]
|
| 294 |
return None
|
| 295 |
|
| 296 |
|
results/ts-align/TSQA/_infer/score/schema.py
CHANGED
|
@@ -162,7 +162,20 @@ _BOXED_RE = re.compile(r"\\boxed\s*\{([^{}]*)\}")
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
-
_LETTER_RE = re.compile(r"\b([A-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
|
| 168 |
def answer_block(text: str) -> str:
|
|
@@ -233,10 +246,12 @@ def parse_number(text: str) -> float | None:
|
|
| 233 |
|
| 234 |
|
| 235 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 236 |
-
"""
|
| 237 |
|
| 238 |
-
Order: \\boxed{}
|
| 239 |
-
|
|
|
|
|
|
|
| 240 |
"""
|
| 241 |
boxed = extract_boxed(text)
|
| 242 |
if boxed:
|
|
@@ -255,6 +270,27 @@ def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
|
| 255 |
for opt in options:
|
| 256 |
if opt and opt.lower() in low:
|
| 257 |
return opt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
return None
|
| 259 |
|
| 260 |
|
|
|
|
| 162 |
_ANSWER_RE = re.compile(r"<answer>\s*(.*?)\s*</answer>", re.DOTALL | re.IGNORECASE)
|
| 163 |
_THINK_RE = re.compile(r"<think>.*?</think>", re.DOTALL | re.IGNORECASE)
|
| 164 |
_NUM_RE = re.compile(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?")
|
| 165 |
+
_LETTER_RE = re.compile(r"\b([A-Ha-h])\b")
|
| 166 |
+
_LEADING_CHOICE_RE = re.compile(
|
| 167 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s*(?=$|\n))"
|
| 168 |
+
)
|
| 169 |
+
_EXPLICIT_CHOICE_RE = re.compile(
|
| 170 |
+
r"(?is)(?:\*{0,2})(?:(?:final|correct)\s+)?"
|
| 171 |
+
r"(?:answer|option|choice|conclusion)(?:\*{0,2})\s*"
|
| 172 |
+
r"(?:is\s*[::]?|[::])\s*(?:\*{0,2})(?:option\s+)?"
|
| 173 |
+
r"\(?\s*([A-Ha-h])\b"
|
| 174 |
+
)
|
| 175 |
+
_EXPLICIT_TRUE_FALSE_RE = re.compile(
|
| 176 |
+
r"(?is)(?:answer|conclusion|statement)\s*(?:is\s*[::]?|[::])\s*"
|
| 177 |
+
r"(true|false)\b"
|
| 178 |
+
)
|
| 179 |
|
| 180 |
|
| 181 |
def answer_block(text: str) -> str:
|
|
|
|
| 246 |
|
| 247 |
|
| 248 |
def parse_choice(text: str, options: list[str] | None = None) -> str | None:
|
| 249 |
+
"""Extract an explicit choice without scraping arbitrary prose.
|
| 250 |
|
| 251 |
+
Order: \\boxed{} -> <answer> -> leading option label -> explicit answer cue.
|
| 252 |
+
The two fallbacks accept unambiguous forms such as ``B) False``, a leading
|
| 253 |
+
bare ``B``, ``Final answer: B``, or ``Conclusion: B``. They deliberately do
|
| 254 |
+
not search for isolated letters elsewhere in prose.
|
| 255 |
"""
|
| 256 |
boxed = extract_boxed(text)
|
| 257 |
if boxed:
|
|
|
|
| 270 |
for opt in options:
|
| 271 |
if opt and opt.lower() in low:
|
| 272 |
return opt
|
| 273 |
+
leading = _LEADING_CHOICE_RE.match(text)
|
| 274 |
+
if leading:
|
| 275 |
+
return leading.group(1).upper()
|
| 276 |
+
explicit = list(_EXPLICIT_CHOICE_RE.finditer(text))
|
| 277 |
+
if explicit:
|
| 278 |
+
return explicit[-1].group(1).upper()
|
| 279 |
+
if options:
|
| 280 |
+
true_false_labels = {}
|
| 281 |
+
for option in options:
|
| 282 |
+
match = re.match(
|
| 283 |
+
r"^\s*\(?\s*([A-Ha-h])(?:\s*\)|\s*[.:\-]|\s+)\s*"
|
| 284 |
+
r"(true|false)\b",
|
| 285 |
+
option,
|
| 286 |
+
re.IGNORECASE,
|
| 287 |
+
)
|
| 288 |
+
if match:
|
| 289 |
+
true_false_labels[match.group(2).lower()] = match.group(1).upper()
|
| 290 |
+
if len(true_false_labels) == 2:
|
| 291 |
+
tf_matches = list(_EXPLICIT_TRUE_FALSE_RE.finditer(text))
|
| 292 |
+
if tf_matches:
|
| 293 |
+
return true_false_labels[tf_matches[-1].group(1).lower()]
|
| 294 |
return None
|
| 295 |
|
| 296 |
|