Files
2026-07-13 13:24:13 +08:00

178 lines
6.0 KiB
Python

import json
import argparse
import os.path
from glob import glob
from tqdm import tqdm
import collections
import torch
def load_rewards(reward_file):
if os.path.exists(reward_file):
rewards = json.load(open(reward_file))
else:
rewards = []
for file in glob(reward_file):
print(file)
rewards.extend(json.load(open(file)))
return rewards
def reward_reduction(ending_logits, reduction: str = "min", norm: bool = True):
if norm:
ending_logits = torch.tensor(ending_logits)
ending_probs = torch.softmax(ending_logits, dim=-1).tolist()
step_rewards = [step[1] for step in ending_probs]
else:
step_rewards = [step[1] for step in ending_logits]
if reduction == "min":
reward = min(step_rewards)
elif reduction == "product":
reward = 1
for prob in step_rewards:
reward *= prob
elif reduction == "sum":
reward = sum(step_rewards)
else:
raise ValueError(f"Invalid reduction method: {reduction}")
return reward
def merge_rewards(group_logits, weights, reduction: str = "min", norm: bool = True, group_reduction: str = "min"):
# rewards = []
# for g_id, item in group_logits.items():
# if len(item["ending_logits"]) == 0:
# continue
# r = reward_reduction(item["ending_logits"], reduction, norm)
# rewards.append(weights[g_id] * r)
# if len(rewards) == 0:
# return 0
# if group_reduction == "min":
# reward = min(rewards)
# elif group_reduction == "product":
# reward = 1
# for r in rewards:
# reward *= r
# elif group_reduction == "sum":
# reward = sum(rewards)
# else:
# raise ValueError(f"Invalid group reduction method: {group_reduction}")
ending_logits = []
if len(group_logits) == 0:
return 0
_len = len(group_logits[0]["ending_logits"])
if _len == 0:
return 0
for g_id, item in group_logits.items():
assert len(item["ending_logits"]) == _len
ending_logits.append(item["ending_logits"])
ending_logits = torch.tensor(ending_logits)
assert ending_logits.size() == (len(group_logits), _len, 2), ending_logits.size()
if norm:
ending_logits = torch.softmax(ending_logits, dim=-1)
ending_logits = ending_logits[:, :, 1]
else:
ending_logits = ending_logits[:, :, 1]
ending_logits = ending_logits * torch.tensor(weights).view(-1, 1)
if group_reduction == "min":
ending_logits = torch.min(ending_logits, dim=0)[0]
elif group_reduction == "product":
ending_logits = torch.prod(ending_logits, dim=0)
elif group_reduction == "sum":
ending_logits = torch.sum(ending_logits, dim=0)
else:
raise ValueError(f"Invalid group reduction method: {group_reduction}")
if reduction == "min":
reward = torch.min(ending_logits).item()
elif reduction == "product":
reward = torch.prod(ending_logits).item()
elif reduction == "sum":
reward = torch.sum(ending_logits).item()
else:
raise ValueError(f"Invalid reduction method: {reduction}")
return reward
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--response_file", type=str, required=True)
parser.add_argument("--reward_file", type=str, required=True, nargs='+')
parser.add_argument("--weights", type=float, nargs='+', default=[1.0])
parser.add_argument("--reduction", type=str, default="min")
parser.add_argument("--raw_logits", action="store_true", default=False)
parser.add_argument("--group_reduction", type=str, default="min")
args = parser.parse_args()
if os.path.exists(args.response_file):
responses = json.load(open(args.response_file))
else:
responses = []
for file in glob(args.response_file):
print(file)
responses.extend(json.load(open(file)))
id2reward = collections.defaultdict(dict)
assert len(args.reward_file) == len(args.weights)
print(args.reward_file)
print(args.weights)
for _g_id, _reward_group in enumerate(args.reward_file):
rewards = load_rewards(_reward_group)
for r in rewards:
id2reward[r["index"]][_g_id] = r
_k = [1, 3, 5]
prm_pass_at_k = {k: 0 for k in _k}
missing = 0
missing_reward = 0
sc_cnt = 0
ultimate_results = []
for item in tqdm(responses):
sorted_results = []
if not item["response"] or not item["pred"] or not item["res"]:
missing += 1
continue
for i, (resp, pred, r) in enumerate(zip(item["response"], item["pred"], item["res"])):
resp_id = f"{item['id']}_{i}"
if resp_id not in id2reward:
missing_reward += 1
continue
process_rewards = id2reward[resp_id]
# if len(process_rewards["ending_logits"]) == 0:
# continue
# reward = merge_rewards(process_rewards["ending_logits"], args.reduction, not args.raw_logits)
reward = merge_rewards(process_rewards, args.weights, args.reduction, not args.raw_logits, args.group_reduction)
sorted_results.append((resp, pred, r, reward))
if not sorted_results:
continue
sorted_results = sorted(sorted_results, key=lambda x: x[-1], reverse=True)
ultimate_results.append(sorted_results)
for k in _k:
if any([r[2] for r in sorted_results[:k]]):
prm_pass_at_k[k] += 1
if item["sc_res"]:
sc_cnt += 1
print(f"Total: {len(responses)}")
print(f"Missing: {missing}")
print(f"Missing reward: {missing_reward}")
print(f"SC: {sc_cnt}")
for k, v in prm_pass_at_k.items():
print(f"PRM pass at {k}: {v}")
print(f"PRM pass at {k} rate: {v / len(responses) * 100:.2f}%")
print(f"SC rate: {sc_cnt / len(responses) * 100:.2f}%")
json.dump(ultimate_results[:100], open("debug.json", "w"), indent=2)
if __name__ == '__main__':
main()