"""Sampled relabeling of test-split difficulty buckets (protocol item: outcome-selection fix). Greedy labeling couples bucket selection to the same coin flips as the k=0 eval (circular: a bucket defined by baseline failure shows baseline ~0%). Fix: labels from 3 temperature-sampled direct attempts, independent of the greedy eval — hard_s = 0/3 sampled direct correct AND (plan/CoT reachable); easy_s = >=2/3 correct; else mid_s. Adds 'label_sampled' to the data JSONs. """ import json import sys from concurrent.futures import ThreadPoolExecutor from pathlib import Path import torch from loop_common import DIRECT_SUFFIX as GSM_SUFFIX from loop_common import chat_prompt, last_number, num_eq from prep_mbpp import (DIRECT_SUFFIX as MBPP_SUFFIX, extract_code, mbpp_prompt, run_tests) sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from jlens.core import load_model # noqa: E402 OUT = Path(__file__).resolve().parent.parent / "results-loop" N_SAMPLES = 3 TEMP = 0.8 @torch.no_grad() def sample_batch(model, tok, prompts, max_new, batch=24, seed=0): outs = [[] for _ in prompts] for s in range(N_SAMPLES): torch.manual_seed(1000 + s + seed) for i in range(0, len(prompts), batch): chunk = prompts[i : i + batch] enc = tok(chunk, return_tensors="pt", padding=True, add_special_tokens=False).to("cuda") gen = model.generate(**enc, max_new_tokens=max_new, do_sample=True, temperature=TEMP, top_p=0.95, pad_token_id=tok.pad_token_id or 0) for j in range(len(chunk)): outs[i + j].append( tok.decode(gen[j, enc["input_ids"].shape[1]:], skip_special_tokens=True)) print(f" sample {s+1}/{N_SAMPLES} done", flush=True) return outs def relabel(items, n_correct, reachable_key): for it, nc in zip(items, n_correct): if nc == 0: it["label_sampled"] = ("hard" if it[reachable_key] else "drop") elif nc >= 2: it["label_sampled"] = "easy" else: it["label_sampled"] = "mid" def main(): model, tok = load_model(dtype=torch.bfloat16) tok.padding_side = "left" # --- MBPP test --- mbpp = json.load(open(OUT / "mbpp_data.json")) mtest = [it for it in mbpp if it["split"] == "test"] print(f"MBPP: sampling {len(mtest)} items x{N_SAMPLES}", flush=True) gens = sample_batch(model, tok, [mbpp_prompt(tok, it, MBPP_SUFFIX) for it in mtest], max_new=220) nc = [] with ThreadPoolExecutor(8) as ex: for it, gs in zip(mtest, gens): oks = list(ex.map(lambda g: run_tests(extract_code(g), it), gs)) nc.append(sum(oks)) relabel(mtest, nc, "plan_ok") json.dump(mbpp, open(OUT / "mbpp_data.json", "w"), indent=1) dist = {l: sum(it.get("label_sampled") == l for it in mtest) for l in ("easy", "mid", "hard", "drop")} agree = sum(it["label"] == it.get("label_sampled") for it in mtest if it.get("label_sampled") != "mid") print(f"MBPP sampled labels: {dist} (greedy-agreement excl. mid: " f"{agree}/{sum(1 for it in mtest if it.get('label_sampled') != 'mid')})", flush=True) # --- GSM8K test --- gsm = json.load(open(OUT / "star_data.json")) gtest = [it for it in gsm if it["split"] == "test"] print(f"GSM: sampling {len(gtest)} items x{N_SAMPLES}", flush=True) gens = sample_batch(model, tok, [chat_prompt(tok, it["question"], GSM_SUFFIX) for it in gtest], max_new=10) nc = [sum(num_eq(last_number(g), it["gold"]) for g in gs) for it, gs in zip(gtest, gens)] relabel(gtest, nc, "cot_ok") json.dump(gsm, open(OUT / "star_data.json", "w"), indent=1) dist = {l: sum(it.get("label_sampled") == l for it in gtest) for l in ("easy", "mid", "hard", "drop")} print(f"GSM sampled labels: {dist}", flush=True) if __name__ == "__main__": main()