czty's picture
Add files using upload-large-folder tool
11f4e59 verified
Raw
History Blame Contribute Delete
4.8 kB
import numpy as np
import pandas as pd
from biomni.task.base_task import base_task
np.random.seed(42)
def shuffle(x):
np.random.shuffle(x)
return x
class humanity_last_exam(base_task):
def __init__(self, path="./data", category="Biology/Medicine", answer_type="multipleChoice"):
if category not in [
"Other",
"Humanities/Social Science",
"Math",
"Physics",
"Computer Science/AI",
"Biology/Medicine",
"Chemistry",
"Engineering",
]:
raise ValueError(
"category must be one of ['Other', 'Humanities/Social Science', 'Math', 'Physics', 'Computer Science/AI', 'Biology/Medicine', 'Chemistry', 'Engineering']"
)
if answer_type not in ["exactMatch", "multipleChoice"]:
raise ValueError("answer_type must be one of ['exactMatch' or 'multipleChoice']")
self.dataset = category # Store dataset type
self.answer_type = answer_type
df = pd.read_parquet(path + "/hle/test_sampled_biology_medicine.parquet")
# Extract answer choices from question text
def extract_options(question):
# Find the "Answer Choices:" section
if "Answer Choices:" not in question:
return []
choices = question.split("Answer Choices:")[1].strip()
# Split on A., B., C. etc and clean up
options = []
letters = [
"A.",
"B.",
"C.",
"D.",
"E.",
"F.",
"G.",
"H.",
"I.",
"J.",
"K.",
"L.",
"M.",
"N.",
"O.",
"P.",
"Q.",
"R.",
"S.",
"T.",
"U.",
"V.",
"W.",
"X.",
"Y.",
"Z.",
]
for i, letter in enumerate(letters):
if letter in choices:
# Define the next letter if available
next_letter = letters[i + 1] if i + 1 < len(letters) else None
# Split between current letter and next letter
parts = choices.split(letter)[1]
if next_letter and next_letter in parts:
option = parts.split(next_letter)[0].strip()
else:
option = parts.strip()
options.append(option)
return options
def extract_question(question):
return question.split("Answer Choices:")[0].strip()
# Extract options and answers only for multiple choice questions and category is the same as the dataset
df = df[df["category"] == self.dataset]
df = df[df["answer_type"] == "multipleChoice"]
df["question_text"] = df.question
df["letter_answer"] = df["answer"].apply(lambda x: x[0])
self.query = df.question_text.values
# self.options = df.options_letters.values
self.answer = df.letter_answer.values
self.prompt = """Question: {question}"""
def get_example(self, index=None):
if index is None:
index = np.random.randint(len(self.query))
return {
"prompt": self.prompt.format(
question=self.query[index],
# options = self.options[index]
),
"answer": self.answer[index],
}
def get_iterator(self):
for i in range(len(self.query)):
yield self.get_example(i)
def evaluate(self, response):
## expected a list/array of symbols
from sklearn.metrics import accuracy_score
ground_truth = self.answer
response = np.array(response)
return {
"accuracy": accuracy_score(ground_truth, response),
"coverage": np.mean(response != self.refrain_label),
"refrain_ratio": np.mean(response == self.refrain_label),
"precision": accuracy_score(
ground_truth[np.where(response != self.refrain_label)],
response[np.where(response != self.refrain_label)],
),
}
def output_class(self):
from pydantic import BaseModel, Field
class MultipleChoiceOutput(BaseModel):
"""Multiple choice output."""
choice: str | None = Field(
description="Multiple choice answer. For example, if there is <answer>A</answer> in the prompt, the output should be 'A'."
)
return MultipleChoiceOutput