| import os |
| import sys |
| import json |
| import re |
| import torch |
| from transformers import AutoTokenizer |
|
|
| sys.path.append(os.path.dirname(os.path.abspath(__file__))) |
| from model import RecursiveCausalLM, ModelConfig, KVCache |
|
|
| def extract_last_number(text): |
| nums = re.findall(r'-?\d*\.?\d+', text.replace(',', '')) |
| return float(nums[-1]) if nums else None |
|
|
| def generate_completion(model, tokenizer, prompt, device, max_tokens=100): |
| input_ids = tokenizer.encode(prompt, return_tensors="pt").to(device) |
| kv_cache = KVCache(model.config, max_batch_size=1, device=device, dtype=torch.float16) |
| |
| generated_tokens = [] |
| use_amp = (device.type == "cuda") |
| |
| with torch.no_grad(): |
| with torch.amp.autocast(device_type="cuda", enabled=use_amp, dtype=torch.float16): |
| logits, _ = model(input_ids, kv_cache=kv_cache) |
| |
| next_token_logits = logits[0, -1, :] |
| |
| for _ in range(max_tokens): |
| |
| next_token_logits = next_token_logits / 0.1 |
| v, _ = torch.topk(next_token_logits, min(50, next_token_logits.size(-1))) |
| next_token_logits[next_token_logits < v[-1]] = -float('Inf') |
| probs = torch.softmax(next_token_logits, dim=-1) |
| next_token = torch.multinomial(probs, num_samples=1).item() |
| generated_tokens.append(next_token) |
| |
| if next_token == tokenizer.eos_token_id: |
| break |
| |
| curr_input = torch.tensor([[next_token]], dtype=torch.long, device=device) |
| with torch.no_grad(): |
| with torch.amp.autocast(device_type="cuda", enabled=use_amp, dtype=torch.float16): |
| logits, _ = model(curr_input, kv_cache=kv_cache) |
| next_token_logits = logits[0, -1, :] |
| |
| return tokenizer.decode(generated_tokens) |
|
|
| def main(): |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
| print("=======================================================================") |
| print("π― THE OFFICIAL PRM MATHEMATICAL EVALUATOR") |
| print("=======================================================================\n") |
| |
| config = ModelConfig( |
| vocab_size=50272, |
| d_model=768, |
| n_iterations=16, |
| n_heads=12, |
| n_kv_heads=4, |
| d_ff=2048, |
| max_seq_len=512 |
| ) |
| |
| model_path = "/home/zeus/micro_llm_200m/uct_target_rl_math.pt" |
| dataset_path = "/home/zeus/micro_llm_200m/three_domain_sft_dataset_math_heavy.json" |
| tokenizer_path = "/home/zeus/micro_llm_200m/tokenizer" |
| |
| tokenizer = AutoTokenizer.from_pretrained(tokenizer_path) |
| model = RecursiveCausalLM(config).to(device) |
| model.load_state_dict(torch.load(model_path, map_location=device, weights_only=False)["model_state_dict"], strict=False) |
| model.eval() |
| |
| |
| with open(dataset_path, "r", encoding="utf-8") as f: |
| data = json.load(f) |
| |
| math_items = [item for item in data if item.get("domain") == "math"] |
| print(f"Loaded {len(math_items)} total arithmetic prompts.") |
| |
| |
| eval_count = min(50, len(math_items)) |
| print(f"Running rigorous evaluation on {eval_count} test cases...\n") |
| |
| correct_count = 0 |
| for idx in range(eval_count): |
| item = math_items[idx] |
| prompt = item["prompt"] |
| gold_response = item["response"] |
| |
| gold_num = extract_last_number(gold_response) |
| |
| |
| completion = generate_completion(model, tokenizer, prompt, device) |
| gen_num = extract_last_number(completion) |
| |
| is_correct = False |
| if gold_num is not None and gen_num is not None and abs(gold_num - gen_num) < 1e-4: |
| is_correct = True |
| correct_count += 1 |
| |
| status_str = "β
PASS" if is_correct else "β FAIL" |
| print(f"Sample {idx+1:2d}/50 | Prompt: '{prompt.strip()}'") |
| print(f" | Generated: '{completion.strip()}'") |
| print(f" | Expected: {gold_num} | Predicted: {gen_num} | {status_str}") |
| print("-" * 75) |
| |
| accuracy = (correct_count / eval_count) * 100 |
| print("\n=======================================================================") |
| print("π FINAL MATHEMATICAL EVALUATION REPORT") |
| print("=======================================================================") |
| print(f"-> Total Evaluated Prompts: {eval_count}") |
| print(f"-> Total Correct Answers: {correct_count}") |
| print(f"-> Exact Match (EM) Accuracy: {accuracy:.2f}%") |
| print("=======================================================================") |
|
|
| if __name__ == '__main__': |
| main() |
|
|