Files
paddlepaddle--paddlenlp/llm/benchmark/mmlu_pro/evaluate_from_api.py
T
wehub-resource-sync 2aaeece67c
Codestyle Check / Lint (push) Has been cancelled
Codestyle Check / Check bypass (push) Has been cancelled
Pipelines-Test / Pipelines-Test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:37:14 +08:00

430 lines
15 KiB
Python

import os
import json
import re
import random
from tqdm import tqdm
import time
from datasets import load_dataset
import argparse
import requests
API_KEY = ""
random.seed(12345)
def get_client():
if args.model_name in ["gpt-4", "gpt-4o", "o1-preview"]:
openai.api_key = API_KEY
client = openai
elif args.model_name in ["deepseek-chat", "deepseek-coder"]:
client = OpenAI(api_key=API_KEY, base_url="https://api.deepseek.com/")
elif args.model_name in ["gemini-1.5-flash-latest", "gemini-1.5-pro-latest",
"gemini-1.5-flash-8b", "gemini-002-pro", "gemini-002-flash"]:
genai.configure(api_key=API_KEY)
generation_config = {
"temperature": 0.0,
"top_p": 1,
"max_output_tokens": 4000,
"response_mime_type": "text/plain",
}
safety_settings = [
{
"category": "HARM_CATEGORY_HARASSMENT",
"threshold": "BLOCK_NONE",
},
{
"category": "HARM_CATEGORY_HATE_SPEECH",
"threshold": "BLOCK_NONE",
},
{
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
"threshold": "BLOCK_NONE",
},
{
"category": "HARM_CATEGORY_DANGEROUS_CONTENT",
"threshold": "BLOCK_NONE",
},
]
client = genai.GenerativeModel(
model_name=args.model_name,
safety_settings=safety_settings,
generation_config=generation_config,
)
elif args.model_name in ["claude-3-opus-20240229", "claude-3-sonnet-20240229"]:
client = anthropic.Anthropic(
api_key=API_KEY,
)
elif args.model_name in ["jamba-1.5-large"]:
client = AI21Client(api_key=API_KEY)
elif args.model_name in ["iask"]:
client = {"Authorization": f"Bearer {API_KEY}"}
else:
client = None
print("For other model API calls, please implement the client definition method yourself.")
return client
def call_api(client, instruction, inputs):
start = time.time()
if args.model_name in ["gpt-4", "gpt-4o", "deepseek-chat", "deepseek-coder"]:
message_text = [{"role": "user", "content": instruction + inputs}]
completion = client.chat.completions.create(
model=args.model_name,
messages=message_text,
temperature=0,
max_tokens=4000,
top_p=1,
frequency_penalty=0,
presence_penalty=0,
)
result = completion.choices[0].message.content
elif args.model_name in ["o1-preview"]:
message_text = [{"role": "user", "content": instruction + inputs}]
completion = client.chat.completions.create(
model=args.model_name,
messages=message_text,
)
result = completion.choices[0].message.content
elif args.model_name in ["gemini-1.5-flash-latest", "gemini-1.5-pro-latest", "gemini-1.5-flash-8b"]:
chat_session = client.start_chat(
history=[]
)
result = chat_session.send_message(instruction + inputs).text
elif args.model_name in ["claude-3-opus-20240229", "claude-3-sonnet-20240229"]:
message = client.messages.create(
model=args.model_name,
max_tokens=4000,
system="",
messages=[
{"role": "user", "content": instruction + inputs}
],
temperature=0.0,
top_p=1,
)
result = message.content[0].text
elif args.model_name in ["jamba-1.5-large"]:
message_text = [ChatMessage(content=instruction + inputs, role="user")]
completion = client.chat.completions.create(
model=args.model_name,
messages=message_text,
documents=[],
tools=[],
n=1,
max_tokens=2048,
temperature=0,
top_p=1,
stop=[],
response_format=ResponseFormat(type="text"),
)
result = completion.choices[0].message.content
elif args.model_name in ["iask"]:
payload = {
"prompt": instruction + inputs,
"mode": "truth",
"detail_level": "detailed",
"stream": False
}
response = requests.post("https://api.iask.ai/v1/query", headers=client, json=payload, timeout=300)
if response.status_code != 200:
print("API call failed with status code", response.status_code, response.json())
return response.json()["response"]["message"]
else:
result = response.json()["response"]["message"]
return result
else:
print("For other model API calls, please implement the request method yourself.")
result = None
print("cost time", time.time() - start)
return result
def load_mmlu_pro():
dataset = load_dataset("TIGER-Lab/MMLU-Pro")
test_df, val_df = dataset["test"], dataset["validation"]
test_df = preprocess(test_df)
val_df = preprocess(val_df)
return test_df, val_df
def preprocess(test_df):
res_df = []
for each in test_df:
options = []
for opt in each["options"]:
if opt == "N/A":
continue
options.append(opt)
each["options"] = options
res_df.append(each)
res = {}
for each in res_df:
if each["category"] not in res:
res[each["category"]] = []
res[each["category"]].append(each)
return res
def format_example(question, options, cot_content=""):
if cot_content == "":
cot_content = "Let's think step by step."
if cot_content.startswith("A: "):
cot_content = cot_content[3:]
example = "Question: {}\nOptions: ".format(question)
choice_map = "ABCDEFGHIJ"
for i, opt in enumerate(options):
example += "{}. {}\n".format(choice_map[i], opt)
if cot_content == "":
example += "Answer: "
else:
example += "Answer: " + cot_content + "\n\n"
return example
def extract_answer(text):
pattern = r"answer is \(?([A-J])\)?"
match = re.search(pattern, text)
if match:
return match.group(1)
else:
print("1st answer extract failed\n" + text)
return extract_again(text)
def extract_again(text):
match = re.search(r'.*[aA]nswer:\s*([A-J])', text)
if match:
return match.group(1)
else:
return extract_final(text)
def extract_final(text):
pattern = r"\b[A-J]\b(?!.*\b[A-J]\b)"
match = re.search(pattern, text, re.DOTALL)
if match:
return match.group(0)
else:
return None
def call_generate(prompt, **kwargs):
url = f"http://{kwargs['ip']}:{kwargs['port']}/v1/chat/completions"
headers = {"Content-Type": "application/json"}
if kwargs['backend'] == 'paddle':
data = {
"text": prompt,
"max_dec_len": 2048,
# "min_dec_len": 1,
"topp": 0.95,
"temperature": 0.6,
"stream": True,
"return_all_tokens": False,
}
elif kwargs['backend'] == 'trtllm':
data = {
"model": "openlm-research/open_llama_13b",
"messages":
[
{"role":"user","content": prompt}
],
"top_p": 0.95,
"temperature": 0.6,
"max_tokens": 2048,
"stream": False
}
elif kwargs['backend'] == 'vllm':
data = {
"model": "/root/r1/models/",
"messages":
[
{"role":"user","content": prompt}
],
"top_p": 0.95,
"temperature": 0.6,
"max_tokens": 2048,
"stream": False
}
response = requests.post(url, headers=headers, data=json.dumps(data))
chunks = []
for chunk in response.iter_content(chunk_size=1000000):
chunks.append(chunk)
lines = b"".join(chunks).decode("utf-8")
lines = lines.strip().split('\n')
if kwargs['backend'] == 'paddle':
return json.loads(lines[-1])["tokens_all"]
elif kwargs['backend'] == 'trtllm' or kwargs['backend'] == 'vllm':
return json.loads(lines[-1])["choices"][0]["message"]["content"]
def single_request(client, single_question, cot_examples_dict, exist_result):
exist = True
q_id = single_question["question_id"]
for each in exist_result:
if q_id == each["question_id"] and single_question["question"] == each["question"]:
pred = extract_answer(each["model_outputs"])
return pred, each["model_outputs"], exist
exist = False
category = single_question["category"]
cot_examples = cot_examples_dict[category]
question = single_question["question"]
options = single_question["options"]
prompt = "The following are multiple choice questions (with answers) about {}. Think step by" \
" step and then output the answer in the format of \"The answer is (X)\" at the end.\n\n" \
.format(category)
for each in cot_examples:
prompt += format_example(each["question"], each["options"], each["cot_content"])
input_text = format_example(question, options)
try:
response = call_generate(prompt+input_text, ip=args.ip, port=args.port, backend=args.backend)
response = response.replace('**', '')
except Exception as e:
print("error", e)
return None, None, exist
pred = extract_answer(response)
return pred, response, exist
def update_result(output_res_path):
category_record = {}
res = []
success = False
while not success:
try:
if os.path.exists(output_res_path):
with open(output_res_path, "r") as fi:
res = json.load(fi)
for each in res:
category = each["category"]
if category not in category_record:
category_record[category] = {"corr": 0.0, "wrong": 0.0}
if not each["pred"]:
x = random.randint(0, len(each["options"]) - 1)
if x == each["answer_index"]:
category_record[category]["corr"] += 1
else:
category_record[category]["wrong"] += 1
elif each["pred"] == each["answer"]:
category_record[category]["corr"] += 1
else:
category_record[category]["wrong"] += 1
success = True
except Exception as e:
print("Error", e, "sleep 2 seconds")
time.sleep(2)
return res, category_record
def merge_result(res, curr):
merged = False
for i, single in enumerate(res):
if single["question_id"] == curr["question_id"] and single["question"] == curr["question"]:
res[i] = curr
merged = True
if not merged:
res.append(curr)
return res
def evaluate(subjects):
# client = get_client()
test_df, dev_df = load_mmlu_pro()
if not subjects:
subjects = list(test_df.keys())
print("assigned subjects", subjects)
for subject in subjects:
test_data = test_df[subject]
output_res_path = os.path.join(args.output_dir, subject + "_result.json")
output_summary_path = os.path.join(args.output_dir, subject + "_summary.json")
res, category_record = update_result(output_res_path)
k = 0
for each in tqdm(test_data):
# k += 1
# if k % 10 != 0:
# continue
label = each["answer"]
category = subject
# import pdb;pdb.set_trace()
pred, response, exist = single_request(None, each, dev_df, res)
if response is not None:
res, category_record = update_result(output_res_path)
if category not in category_record:
category_record[category] = {"corr": 0.0, "wrong": 0.0}
each["pred"] = pred
each["model_outputs"] = response
merge_result(res, each)
if pred is not None:
if pred == label:
category_record[category]["corr"] += 1
else:
category_record[category]["wrong"] += 1
else:
category_record[category]["wrong"] += 1
# import pdb;pdb.set_trace()
save_res(res, output_res_path)
save_summary(category_record, output_summary_path)
res, category_record = update_result(output_res_path)
save_res(res, output_res_path)
save_summary(category_record, output_summary_path)
def save_res(res, output_res_path):
temp = []
exist_q_id = []
for each in res:
if each["question_id"] not in exist_q_id:
exist_q_id.append(each["question_id"])
temp.append(each)
else:
continue
res = temp
with open(output_res_path, "w") as fo:
fo.write(json.dumps(res))
def save_summary(category_record, output_summary_path):
total_corr = 0.0
total_wrong = 0.0
for k, v in category_record.items():
if k == "total":
continue
cat_acc = v["corr"] / (v["corr"] + v["wrong"])
category_record[k]["acc"] = cat_acc
total_corr += v["corr"]
total_wrong += v["wrong"]
acc = total_corr / (total_corr + total_wrong)
category_record["total"] = {"corr": total_corr, "wrong": total_wrong, "acc": acc}
with open(output_summary_path, "w") as fo:
fo.write(json.dumps(category_record))
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--backend", type=str, default="paddle")
parser.add_argument("--ip", type=str, default="")
parser.add_argument("--port", type=str, default="")
parser.add_argument("--output_dir", "-o", type=str, default="eval_results/")
parser.add_argument("--model_name", "-m", type=str, default="gpt-4",
choices=["gpt-4", "gpt-4o", "o1-preview",
"deepseek-chat", "deepseek-coder",
"gemini-1.5-flash-latest",
"gemini-1.5-pro-latest",
"claude-3-opus-20240229",
"gemini-1.5-flash-8b",
"claude-3-sonnet-20240229",
"gemini-002-pro",
"gemini-002-flash"])
parser.add_argument("--assigned_subjects", "-a", type=str, default="all")
assigned_subjects = []
args = parser.parse_args()
if args.assigned_subjects == "all":
assigned_subjects = []
else:
assigned_subjects = args.assigned_subjects.split(",")
os.makedirs(args.output_dir, exist_ok=True)
evaluate(assigned_subjects)