"""Compare two lm-eval code-task run directories.""" from __future__ import annotations import argparse import ast import json import statistics from pathlib import Path from diffulex_bench.tasks.humaneval.llada2_utils import extract_code as extract_humaneval_code from diffulex_bench.tasks.mbpp.llada2_utils import ( _code_text_for_prediction as mbpp_code_text_for_prediction, ) from diffulex_bench.tasks.mbpp.llada2_utils import extract_code as extract_mbpp_code def _first_file(run_dir: Path, pattern: str) -> Path: matches = sorted(run_dir.glob(pattern)) if not matches: raise FileNotFoundError(f"No file matching {pattern!r} under {run_dir}") return matches[0] def _sample_path(run_dir: Path) -> Path: return _first_file(run_dir, "**/samples_*.jsonl") def _result_path(run_dir: Path) -> Path: return _first_file(run_dir, "**/results_*.json") def _load_samples(run_dir: Path) -> dict[int, dict]: path = _sample_path(run_dir) rows = [json.loads(line) for line in path.read_text(encoding="utf-8").splitlines()] return {int(row["doc_id"]): row for row in rows} def _extract_code(row: dict) -> str: pred = row["filtered_resps"][0] doc = row["doc"] task_id = str(doc.get("task_id", "")).lower() if "humaneval" in task_id: text = pred if "```" in pred else doc.get("prefix", "") + pred return extract_humaneval_code(text) return extract_mbpp_code(mbpp_code_text_for_prediction(doc, pred)) def _syntax_error(row: dict) -> bool: try: ast.parse(_extract_code(row)) return False except SyntaxError: return True def _score(row: dict) -> int: return int(row.get("exact_match", 0)) def _short(text: str, limit: int) -> str: text = text.replace("\r", "") if len(text) <= limit: return text return text[:limit] + "\n..." def _print_run_summary(label: str, run_dir: Path, rows: dict[int, dict]) -> None: result = json.loads(_result_path(run_dir).read_text(encoding="utf-8")) task_name = next(iter(result["results"])) scores = [_score(row) for row in rows.values()] preds = [row["filtered_resps"][0] for row in rows.values()] lengths = [len(pred) for pred in preds] syntax = sum(_syntax_error(row) for row in rows.values()) masks = sum("<|mask|>" in pred for pred in preds) no_fence = sum("```" not in pred for pred in preds) long = sum(len(pred) > 3000 for pred in preds) metadata = result["configs"][task_name].get("metadata", {}) print(f"\n### {label}: {run_dir.name}") print("result:", result["results"][task_name]) print(f"pass: {sum(scores)}/{len(scores)} = {sum(scores) / len(scores):.6f}") print( "metadata:", { k: metadata.get(k) for k in ( "buffer_size", "block_size", "max_nfe", "max_new_tokens", "decoding_strategy", "sampling_mode", "accept_threshold", "remask_threshold", "token_merge_mode", "token_merge_top_k", ) }, ) print( "response_chars mean/p50/max:", round(statistics.mean(lengths), 1), statistics.median(lengths), max(lengths), ) print("syntax_errors:", syntax, "mask_outputs:", masks, "no_fence:", no_fence, "long>3000:", long) def main() -> int: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("base_run", type=Path) parser.add_argument("candidate_run", type=Path) parser.add_argument("--examples", type=int, default=5) parser.add_argument("--chars", type=int, default=900) args = parser.parse_args() base = _load_samples(args.base_run) cand = _load_samples(args.candidate_run) ids = sorted(set(base) & set(cand)) _print_run_summary("base", args.base_run, base) _print_run_summary("candidate", args.candidate_run, cand) both_right = [i for i in ids if _score(base[i]) == 1 and _score(cand[i]) == 1] regress = [i for i in ids if _score(base[i]) == 1 and _score(cand[i]) == 0] improve = [i for i in ids if _score(base[i]) == 0 and _score(cand[i]) == 1] both_wrong = [i for i in ids if _score(base[i]) == 0 and _score(cand[i]) == 0] print("\n=== migration ===") print("both_right:", len(both_right), "regress:", len(regress), "improve:", len(improve), "both_wrong:", len(both_wrong)) print("regress first:", regress[:20]) print("improve first:", improve[:20]) print("regress syntax in base/candidate:", sum(_syntax_error(base[i]) for i in regress), sum(_syntax_error(cand[i]) for i in regress)) for title, selected in (("REGRESS", regress[: args.examples]), ("IMPROVE", improve[: args.examples])): print(f"\n=== {title} examples ===") for doc_id in selected: before = base[doc_id] after = cand[doc_id] doc = before["doc"] prompt = doc.get("prompt") or doc.get("text") or doc.get("question") or "" tests = "\n".join(doc.get("test_list", [])) print(f"\n--- doc_id {doc_id} task_id {doc.get('task_id')} ---") print("prompt:", _short(prompt, 240)) print("tests:", _short(tests, 360)) print("[base]", _score(before), "syntax_error", _syntax_error(before), "chars", len(before["filtered_resps"][0])) print(_short(before["filtered_resps"][0], args.chars)) print("[candidate]", _score(after), "syntax_error", _syntax_error(after), "chars", len(after["filtered_resps"][0])) print(_short(after["filtered_resps"][0], args.chars)) return 0 if __name__ == "__main__": raise SystemExit(main())