Views
No views yet
<extra_0> marker is appended to every step,
and a two-way classification head predicts, at each marker, whether the step is correct.| Base model | Qwen/Qwen2.5-Math-1.5B-Instruct |
| Architecture | Qwen2ForProcessRewardModel (custom code in modeling_qwen2_rm.py) |
| Reward head | Linear(hidden, hidden) -> ReLU -> Linear(hidden, 2) on top of every token |
| Hidden size / layers | 1536 / 28 |
| Max position embeddings | 4096 |
| Step marker | <extra_0> (single special token) |
| Supervision | step-level labels over the reasoning steps of the solution |
| Weights dtype | bfloat16 |
transformers>=4.40.0. The latest version is recommended.trust_remote_code=True -- the PRM class ships with the checkpoint.[!Important]Qwen2.5-1.5B-SHARP-Step is a process reward model used for scoring reasoning steps, not for generation.
"\n\n").<extra_0> to the end of every step.Question: {question}\n\nSolution:\n{steps}, which is the format used during training.<extra_0> position take the probability of the positive class. The result is a
value between 0 and 1, where low values mark a hallucinated or incorrect step.1import torch
2import torch.nn.functional as F
3from transformers import AutoModel, AutoTokenizer
4
5
6def build_prompt(question, steps):
7 body = "\n\n".join(f"{step.strip()}<extra_0>" for step in steps)
8 return f"Question: {question}\n\nSolution:\n{body}"
9
10
11def make_step_rewards(logits, token_masks):
12 probabilities = F.softmax(logits, dim=-1)
13 probabilities = probabilities * token_masks.unsqueeze(-1) # bs, seq_len, num_labels
14
15 all_scores_res = []
16 for i in range(probabilities.size(0)):
17 sample = probabilities[i] # seq_len, num_labels
18 positive_probs = sample[sample != 0].view(-1, 2)[:, 1] # valid_tokens, num_labels
19 all_scores_res.append(positive_probs.cpu().tolist())
20 return all_scores_res
21
22
23model_name = "ZaandaTeika/Qwen2.5-1.5B-SHARP-Step"
24
25tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
26model = AutoModel.from_pretrained(
27 model_name,
28 device_map="auto",
29 torch_dtype=torch.bfloat16,
30 trust_remote_code=True,
31).eval()
32
33data = {
34 "question": "Natalia sold clips to 48 of her friends in April, and then she sold half as many clips in May. How many clips did Natalia sell altogether in April and May?",
35 "steps": [
36 "In April, Natalia sold 48 clips.",
37 "In May she sold half as many, so she sold 48 / 2 = 24 clips.",
38 "Altogether she sold 48 + 24 = 72 clips. The answer is \\boxed{72}.",
39 ],
40}
41
42prompt = build_prompt(data["question"], data["steps"])
43input_ids = tokenizer.encode(prompt, return_tensors="pt").to(model.device)
44
45with torch.no_grad():
46 outputs = model(input_ids=input_ids)
47
48step_sep_id = tokenizer.encode("<extra_0>", add_special_tokens=False)[0]
49token_masks = input_ids == step_sep_id
50step_reward = make_step_rewards(outputs[0], token_masks)
51print(step_reward) # one score per step