Spaces:
Sleeping
Sleeping
Download src/elbench/loaders/general_capability_loader.py from adelevett/ELBench-live: direct link, hf CLI and curl.
- Browser
- Download file 14.8 kB
-
https://huggingface.co/spaces/adelevett/ELBench-live/resolve/main/src/elbench/loaders/general_capability_loader.py
- Command line
-
hf download hf://spaces/adelevett/ELBench-live/src/elbench/loaders/general_capability_loader.py
-
curl -L -o general_capability_loader.py https://huggingface.co/spaces/adelevett/ELBench-live/resolve/main/src/elbench/loaders/general_capability_loader.py
14.8 kB
| from __future__ import annotations | |
| import json | |
| import re | |
| from typing import Any, Iterator | |
| from elbench.loaders.base import BaseLoader | |
| from elbench.registry import ResolvedRegistryItem | |
| from elbench.schemas.evaluation import RawRecord, Sample | |
| class MMLUProJsonlLoader(BaseLoader): | |
| def iter_raw_records(self, item: ResolvedRegistryItem) -> Iterator[RawRecord]: | |
| with item.path.open("r", encoding="utf-8") as handle: | |
| for row_index, line in enumerate(handle, start=1): | |
| if not line.strip(): | |
| continue | |
| yield RawRecord( | |
| source_path=str(item.path), | |
| source_file=item.entry.canonical_name, | |
| row_index=row_index, | |
| record=json.loads(line), | |
| ) | |
| def iter_samples(self, item: ResolvedRegistryItem) -> Iterator[Sample]: | |
| for raw_record in self.iter_raw_records(item): | |
| record = raw_record.record | |
| target = self._string_or_none(record.get("target")) | |
| choices = self._choices(record.get("choices")) | |
| metadata = self._metadata(record, raw_record.row_index) | |
| dimension = self._dimension(record, metadata) | |
| yield Sample( | |
| sample_id=self._sample_id( | |
| item.entry.canonical_name, | |
| record, | |
| raw_record.row_index, | |
| namespace=dimension, | |
| ), | |
| source_file=item.entry.canonical_name, | |
| source_path=str(item.path), | |
| module=item.entry.module, | |
| subset=item.entry.subset, | |
| task=item.entry.task, | |
| dimension=dimension, | |
| prompt=self._build_zero_shot_prompt(record, choices, item.entry.task), | |
| reference={"target": target}, | |
| metadata=metadata, | |
| raw_record=record, | |
| ) | |
| def _build_zero_shot_prompt(self, record: dict[str, Any], choices: list[str], task: str | None) -> str: | |
| question = self._extract_question(record) | |
| option_lines = [f"{chr(65 + index)}) {choice}" for index, choice in enumerate(choices)] | |
| letters = ",".join(chr(65 + index) for index in range(len(choices))) | |
| if task == "ceval": | |
| return "\n".join( | |
| [ | |
| "请回答以下单项选择题。", | |
| "请先逐步思考,再给出答案。", | |
| f"你回答的最后一行必须严格使用格式:答案:[LETTER],其中 [LETTER] 是 {letters} 中的一个。", | |
| "", | |
| "问题:", | |
| question, | |
| "选项:", | |
| *option_lines, | |
| ] | |
| ) | |
| return "\n".join( | |
| [ | |
| "Answer the following multiple choice question.", | |
| "Think step by step before answering.", | |
| f"The last line of your response must be exactly: ANSWER: [LETTER], where [LETTER] is one of {letters}.", | |
| "", | |
| "Question:", | |
| question, | |
| "Options:", | |
| *option_lines, | |
| ] | |
| ) | |
| def _extract_question(self, record: dict[str, Any]) -> str: | |
| input_messages = record.get("input") | |
| if isinstance(input_messages, list): | |
| for message in reversed(input_messages): | |
| if not isinstance(message, dict): | |
| continue | |
| content = message.get("content") | |
| if not isinstance(content, str): | |
| continue | |
| matches = re.findall(r"Question:\n(.*?)\nOptions:", content, flags=re.S) | |
| if not matches: | |
| matches = re.findall(r"问题[::]\s*(.*?)\n选项[::]", content, flags=re.S) | |
| if matches: | |
| return matches[-1].strip() | |
| raise ValueError("Cannot extract multiple-choice question from input messages.") | |
| def _metadata(self, record: dict[str, Any], row_index: int) -> dict[str, Any]: | |
| metadata = {} | |
| raw_metadata = record.get("metadata") | |
| if isinstance(raw_metadata, dict): | |
| metadata.update(raw_metadata) | |
| metadata["choices"] = self._choices(record.get("choices")) | |
| metadata["subset_key"] = self._string_or_none(record.get("subset_key")) | |
| metadata["row_index"] = row_index | |
| return metadata | |
| def _dimension(self, record: dict[str, Any], metadata: dict[str, Any]) -> str | None: | |
| return ( | |
| self._string_or_none(record.get("subset_key")) | |
| or self._string_or_none(metadata.get("subject")) | |
| or self._string_or_none(metadata.get("id")) | |
| ) | |
| def _sample_id( | |
| self, | |
| canonical_name: str, | |
| record: dict[str, Any], | |
| row_index: int, | |
| namespace: str | None = None, | |
| ) -> str: | |
| value = record.get("id") | |
| if value in (None, ""): | |
| value = row_index | |
| value_part = self._slug_component(value) | |
| namespace_part = self._slug_component(namespace) | |
| if namespace_part: | |
| return f"{canonical_name.replace('.', '_')}-{namespace_part}-{value_part}" | |
| return f"{canonical_name.replace('.', '_')}-{value_part}" | |
| def _choices(self, value: Any) -> list[str]: | |
| if not isinstance(value, list) or not value: | |
| raise ValueError("Multiple-choice record must contain a non-empty choices list.") | |
| return [str(choice) for choice in value] | |
| def _string_or_none(self, value: Any) -> str | None: | |
| if value in (None, ""): | |
| return None | |
| return str(value) | |
| def _slug_component(self, value: Any) -> str: | |
| if value in (None, ""): | |
| return "" | |
| text = re.sub(r"[^\w]+", "_", str(value)).strip("_") | |
| return text or str(value) | |
| def expected_answer_from_sample(self, sample: Sample) -> str | None: | |
| reference = sample.reference or {} | |
| if isinstance(reference, dict): | |
| value = reference.get("target") | |
| else: | |
| value = reference | |
| if value in (None, ""): | |
| return None | |
| normalized = str(value).strip().upper() | |
| return normalized[0] if normalized else None | |
| def valid_letters_from_sample(self, sample: Sample) -> list[str]: | |
| choices = sample.metadata.get("choices") | |
| if isinstance(choices, list) and choices: | |
| return [chr(65 + index) for index in range(len(choices))] | |
| return list("ABCDEFGHIJ") | |
| class CEvalJsonlLoader(MMLUProJsonlLoader): | |
| pass | |
| class IFEvalJsonlLoader(BaseLoader): | |
| def iter_raw_records(self, item: ResolvedRegistryItem) -> Iterator[RawRecord]: | |
| with item.path.open("r", encoding="utf-8") as handle: | |
| for row_index, line in enumerate(handle, start=1): | |
| if not line.strip(): | |
| continue | |
| yield RawRecord( | |
| source_path=str(item.path), | |
| source_file=item.entry.canonical_name, | |
| row_index=row_index, | |
| record=json.loads(line), | |
| ) | |
| def iter_samples(self, item: ResolvedRegistryItem) -> Iterator[Sample]: | |
| for raw_record in self.iter_raw_records(item): | |
| record = raw_record.record | |
| metadata = self._metadata(record, raw_record.row_index) | |
| yield Sample( | |
| sample_id=self._sample_id(item.entry.canonical_name, record, raw_record.row_index), | |
| source_file=item.entry.canonical_name, | |
| source_path=str(item.path), | |
| module=item.entry.module, | |
| subset=item.entry.subset, | |
| task=item.entry.task, | |
| dimension="default", | |
| prompt=self._prompt(record, metadata), | |
| reference={"target": self._string_or_empty(record.get("target"))}, | |
| metadata=metadata, | |
| raw_record=record, | |
| ) | |
| def _metadata(self, record: dict[str, Any], row_index: int) -> dict[str, Any]: | |
| metadata: dict[str, Any] = {} | |
| raw_metadata = record.get("metadata") | |
| if isinstance(raw_metadata, dict): | |
| metadata.update(raw_metadata) | |
| metadata["instruction_id_list"] = self._instruction_ids(metadata.get("instruction_id_list")) | |
| metadata["kwargs"] = self._kwargs(metadata.get("kwargs")) | |
| metadata["key"] = self._string_or_empty(metadata.get("key")) | |
| metadata["prompt"] = self._prompt(record, metadata) | |
| metadata["row_index"] = row_index | |
| return metadata | |
| def _prompt(self, record: dict[str, Any], metadata: dict[str, Any]) -> str: | |
| prompt = metadata.get("prompt") | |
| if isinstance(prompt, str) and prompt: | |
| return prompt | |
| input_messages = record.get("input") | |
| if isinstance(input_messages, list): | |
| for message in input_messages: | |
| if isinstance(message, dict) and isinstance(message.get("content"), str): | |
| return message["content"] | |
| return "" | |
| def _kwargs(self, value: Any) -> list[dict[str, Any]]: | |
| if not isinstance(value, list): | |
| return [] | |
| parsed_kwargs = [] | |
| for item in value: | |
| if isinstance(item, dict): | |
| parsed_kwargs.append(item) | |
| continue | |
| if isinstance(item, str): | |
| try: | |
| parsed = json.loads(item) | |
| except json.JSONDecodeError: | |
| parsed = {} | |
| parsed_kwargs.append(parsed if isinstance(parsed, dict) else {}) | |
| continue | |
| parsed_kwargs.append({}) | |
| return parsed_kwargs | |
| def _instruction_ids(self, value: Any) -> list[str]: | |
| if not isinstance(value, list): | |
| return [] | |
| return [str(item) for item in value] | |
| def _sample_id(self, canonical_name: str, record: dict[str, Any], row_index: int) -> str: | |
| value = record.get("id") | |
| if value in (None, ""): | |
| value = row_index | |
| return f"{canonical_name.replace('.', '_')}-{value}" | |
| def _string_or_empty(self, value: Any) -> str: | |
| if value in (None, ""): | |
| return "" | |
| return str(value) | |
| def instruction_ids_from_sample(self, sample: Sample) -> list[str]: | |
| return self._instruction_ids(sample.metadata.get("instruction_id_list")) | |
| def kwargs_from_sample(self, sample: Sample) -> list[dict[str, Any]]: | |
| return self._kwargs(sample.metadata.get("kwargs")) | |
| def prompt_key_from_sample(self, sample: Sample) -> str: | |
| return self._string_or_empty(sample.metadata.get("key")) | |
| class MATH500JsonlLoader(BaseLoader): | |
| def iter_raw_records(self, item: ResolvedRegistryItem) -> Iterator[RawRecord]: | |
| with item.path.open("r", encoding="utf-8") as handle: | |
| for row_index, line in enumerate(handle, start=1): | |
| if not line.strip(): | |
| continue | |
| yield RawRecord( | |
| source_path=str(item.path), | |
| source_file=item.entry.canonical_name, | |
| row_index=row_index, | |
| record=json.loads(line), | |
| ) | |
| def iter_samples(self, item: ResolvedRegistryItem) -> Iterator[Sample]: | |
| for raw_record in self.iter_raw_records(item): | |
| record = raw_record.record | |
| metadata = self._metadata(record, raw_record.row_index) | |
| yield Sample( | |
| sample_id=self._sample_id(item.entry.canonical_name, record, raw_record.row_index), | |
| source_file=item.entry.canonical_name, | |
| source_path=str(item.path), | |
| module=item.entry.module, | |
| subset=item.entry.subset, | |
| task=item.entry.task, | |
| dimension=self._string_or_none(record.get("subset_key")) or "default", | |
| prompt=self._prompt(record), | |
| reference={"target": self._string_or_empty(record.get("target"))}, | |
| metadata=metadata, | |
| raw_record=record, | |
| ) | |
| def _metadata(self, record: dict[str, Any], row_index: int) -> dict[str, Any]: | |
| metadata: dict[str, Any] = {} | |
| raw_metadata = record.get("metadata") | |
| if isinstance(raw_metadata, dict): | |
| metadata.update(raw_metadata) | |
| metadata["subset_key"] = self._string_or_none(record.get("subset_key")) | |
| metadata["row_index"] = row_index | |
| return metadata | |
| def _prompt(self, record: dict[str, Any]) -> str: | |
| input_messages = record.get("input") | |
| if isinstance(input_messages, list): | |
| for message in input_messages: | |
| if isinstance(message, dict) and isinstance(message.get("content"), str): | |
| return message["content"] | |
| return "" | |
| def _sample_id(self, canonical_name: str, record: dict[str, Any], row_index: int) -> str: | |
| value = record.get("id") | |
| subset_key = self._string_or_none(record.get("subset_key")) or "default" | |
| if value in (None, ""): | |
| value = row_index | |
| subset_slug = re.sub(r"[^A-Za-z0-9]+", "_", subset_key).strip("_").lower() | |
| return f"{canonical_name.replace('.', '_')}-{subset_slug}-{value}" | |
| def _string_or_none(self, value: Any) -> str | None: | |
| if value in (None, ""): | |
| return None | |
| return str(value) | |
| def _string_or_empty(self, value: Any) -> str: | |
| if value in (None, ""): | |
| return "" | |
| return str(value) | |
| def expected_answer_from_sample(self, sample: Sample) -> str: | |
| reference = sample.reference or {} | |
| if isinstance(reference, dict): | |
| value = reference.get("target") | |
| else: | |
| value = reference | |
| return "" if value in (None, "") else str(value) | |
| class AIMEJsonlLoader(MATH500JsonlLoader): | |
| def iter_samples(self, item: ResolvedRegistryItem) -> Iterator[Sample]: | |
| for raw_record in self.iter_raw_records(item): | |
| record = raw_record.record | |
| metadata = self._metadata(record, raw_record.row_index) | |
| yield Sample( | |
| sample_id=self._sample_id(item.entry.canonical_name, record, raw_record.row_index), | |
| source_file=item.entry.canonical_name, | |
| source_path=str(item.path), | |
| module=item.entry.module, | |
| subset=item.entry.subset, | |
| task=item.entry.task, | |
| dimension="default", | |
| prompt=self._prompt(record), | |
| reference={"target": self._string_or_empty(record.get("target"))}, | |
| metadata=metadata, | |
| raw_record=record, | |
| ) | |