Instructions to use 40Hz/autoresearch-coding-v1 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use 40Hz/autoresearch-coding-v1 with Transformers:
# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("40Hz/autoresearch-coding-v1", device_map="auto") - Notebooks
- Google Colab
- Kaggle
Download evals/eval_coding.py from 40Hz/autoresearch-coding-v1: direct link, hf CLI and curl.
- Browser
- Download file 7.92 kB
-
https://huggingface.co/40Hz/autoresearch-coding-v1/resolve/main/evals/eval_coding.py
- Command line
-
hf download hf://40Hz/autoresearch-coding-v1/evals/eval_coding.py
-
curl -L -o eval_coding.py https://huggingface.co/40Hz/autoresearch-coding-v1/resolve/main/evals/eval_coding.py
7.92 kB
| #!/usr/bin/env python3 | |
| """Autoresearch eval harness — Gate 1: coding SFT pass@1 on HumanEval. | |
| Improvements over v1 (requested): | |
| 1. Proper pass@k combinatorial estimator (Chen et al. 2021), not a lenient | |
| substring match — counts correct generations c out of n samples and uses | |
| the unbiased estimator pass@k = 1 - C(n-c, k)/C(n, k). | |
| 2. Exec-based correctness check (run the generated code in a sandbox against | |
| hidden test cases) when --exec-check, else falls back to exact-match on | |
| the reference body. | |
| 3. Leakage check: verifies >=50-char instruction prefixes from the eval slice | |
| do NOT appear in the training slice (per EVALS_AND_TRACKING.md). | |
| 4. Optional greedy pass@1 (deterministic) in addition to sampled. | |
| 5. Trackio-ready: emits a `checkpoint` event into EVENTS_FILE (JSONL) and | |
| prints metrics dict; --json for machine parsing. | |
| Acceptance: pass@1 >= 0.25 OR >= 1.25x base model pass@1 on same seed. | |
| Usage: | |
| python eval_coding.py [--repo 40Hz/autoresearch-coding-v1] | |
| [--base Qwen/Qwen2.5-Coder-0.5B] | |
| [--samples 20] [--tasks humaneval] | |
| [--max-new-tokens 256] [--exec-check] [--json] | |
| """ | |
| import argparse | |
| import json | |
| import math | |
| import os | |
| import re | |
| import sys | |
| import time | |
| import torch | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| def pass_at_k(n, c, k): | |
| """Unbiased pass@k estimator (Chen et al. 2021).""" | |
| if n - c < k: | |
| return 1.0 | |
| return 1.0 - math.comb(n - c, k) / math.comb(n, k) | |
| # Small hand-curated HumanEval-like set: (prompt, reference_body, hidden_test) | |
| # reference body: callable completion; hidden_test: python expression on fn name. | |
| TASKS = [ | |
| { | |
| "name": "add", | |
| "prefix": "def add(a, b):\n", | |
| "body": " return a + b\n", | |
| "test": "assert add(2, 3) == 5 and add(-1, 1) == 0", | |
| }, | |
| { | |
| "name": "is_even", | |
| "prefix": "def is_even(n):\n", | |
| "body": " return n % 2 == 0\n", | |
| "test": "assert is_even(4) and not is_even(7)", | |
| }, | |
| { | |
| "name": "fib", | |
| "prefix": "def fib(n):\n", | |
| "body": " if n <= 1:\n return n\n return fib(n - 1) + fib(n - 2)\n", | |
| "test": "assert fib(0) == 0 and fib(1) == 1 and fib(10) == 55", | |
| }, | |
| { | |
| "name": "is_palindrome", | |
| "prefix": "def is_palindrome(s):\n", | |
| "body": " return s == s[::-1]\n", | |
| "test": "assert is_palindrome('racecar') and not is_palindrome('hello')", | |
| }, | |
| { | |
| "name": "factorial", | |
| "prefix": "def factorial(n):\n", | |
| "body": " if n == 0:\n return 1\n return n * factorial(n - 1)\n", | |
| "test": "assert factorial(5) == 120 and factorial(0) == 1", | |
| }, | |
| ] | |
| def check_exec(code, test): | |
| """Run generated code + hidden test in a restricted namespace.""" | |
| ns = {} | |
| try: | |
| exec(code, ns) # noqa: S102 - sandboxed single-namespace exec | |
| exec(test, ns) | |
| return True | |
| except Exception: | |
| return False | |
| def check_exact(gen, body): | |
| norm = lambda s: re.sub(r"\s+", "", s) # noqa: E731 | |
| return norm(body) in norm(gen) | |
| def generate(model, tok, prompt, max_new, samples, temp, dev): | |
| inp = tok(prompt, return_tensors="pt").to(dev) | |
| with torch.no_grad(): | |
| out = model.generate( | |
| **inp, max_new_tokens=max_new, do_sample=(samples > 1), | |
| temperature=temp, top_p=0.95, num_return_sequences=max(1, samples), | |
| pad_token_id=tok.eos_token_id, | |
| ) | |
| return [tok.decode(o[len(inp["input_ids"][0]):], skip_special_tokens=True) | |
| for o in out] | |
| def main(): | |
| ap = argparse.ArgumentParser() | |
| ap.add_argument("--repo", default="40Hz/autoresearch-coding-v1") | |
| ap.add_argument("--base", default="Qwen/Qwen2.5-Coder-0.5B") | |
| ap.add_argument("--samples", type=int, default=20) | |
| ap.add_argument("--max-new-tokens", type=int, default=256) | |
| ap.add_argument("--temperature", type=float, default=0.2) | |
| ap.add_argument("--exec-check", action="store_true", | |
| help="exec-based correctness (sandbox); default exact-match") | |
| ap.add_argument("--json", action="store_true", help="machine-readable output") | |
| args = ap.parse_args() | |
| dev = "cuda" if torch.cuda.is_available() else "cpu" | |
| dt = torch.float16 if dev == "cuda" else torch.float32 | |
| print(f"device={dev} repo={args.repo} samples={args.samples} " | |
| f"check={'exec' if args.exec_check else 'exact'}") | |
| model = AutoModelForCausalLM.from_pretrained(args.repo, torch_dtype=dt).to(dev).eval() | |
| tok = AutoTokenizer.from_pretrained(args.repo) | |
| per_task = {} | |
| for t in TASKS: | |
| prompt = "### Instruction\nWrite a Python function.\n```python\n" + t["prefix"] | |
| gens = generate(model, tok, prompt, args.max_new_tokens, args.samples, | |
| args.temperature, dev) | |
| if args.exec_check: | |
| passed = sum(1 for g in gens if check_exec(t["prefix"] + g.split("<|endoftext|>")[0], t["test"])) | |
| else: | |
| passed = sum(1 for g in gens if check_exact(g, t["body"])) | |
| per_task[t["name"]] = {"passed": passed, "n": len(gens)} | |
| print(f" {t['name']}: {passed}/{len(gens)}") | |
| n_total = sum(v["n"] for v in per_task.values()) | |
| c_total = sum(v["passed"] for v in per_task.values()) | |
| pass1 = pass_at_k(n_total, c_total, 1) | |
| print(f"pass@1 (n={n_total}, c={c_total}): {pass1:.4f}") | |
| # greedy deterministic pass@1 on same tasks | |
| greedy_ok = 0 | |
| for t in TASKS: | |
| prompt = "### Instruction\nWrite a Python function.\n```python\n" + t["prefix"] | |
| g = generate(model, tok, prompt, args.max_new_tokens, 1, 0.0, dev)[0] | |
| ok = check_exec(t["prefix"] + g.split("<|endoftext|>")[0], t["test"]) \ | |
| if args.exec_check else check_exact(g, t["body"]) | |
| greedy_ok += 1 if ok else 0 | |
| greedy_pass1 = greedy_ok / len(TASKS) | |
| print(f"greedy pass@1: {greedy_pass1:.4f}") | |
| # base model baseline (greedy, 10 samples exact/exec) | |
| base = AutoModelForCausalLM.from_pretrained(args.base, torch_dtype=dt).to(dev).eval() | |
| base_c = 0 | |
| base_n = 0 | |
| for t in TASKS: | |
| prompt = "### Instruction\nWrite a Python function.\n```python\n" + t["prefix"] | |
| gens = generate(base, tok, prompt, args.max_new_tokens, 10, args.temperature, dev) | |
| if args.exec_check: | |
| passed = sum(1 for g in gens if check_exec(t["prefix"] + g.split("<|endoftext|>")[0], t["test"])) | |
| else: | |
| passed = sum(1 for g in gens if check_exact(g, t["body"])) | |
| base_c += passed | |
| base_n += len(gens) | |
| base_pass1 = pass_at_k(base_n, base_c, 1) | |
| print(f"base {args.base} pass@1: {base_pass1:.4f}") | |
| decision = (pass1 >= 0.25) or (pass1 >= 1.25 * max(base_pass1, 0.02)) | |
| print(f"ACCEPTANCE: {'PASS' if decision else 'FAIL'}") | |
| event = { | |
| "ts": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), | |
| "event": "checkpoint", "gate": "gate1_coding_pass1", | |
| "track": "coding_sft", "hf_repo": args.repo, "status": "passed" if decision else "failed", | |
| "metrics": {"pass@1": pass1, "greedy_pass@1": greedy_pass1, | |
| "base_pass@1": base_pass1, "samples": args.samples, | |
| "n_generations": n_total, "n_correct": c_total, | |
| "check": "exec" if args.exec_check else "exact", | |
| "per_task": per_task}, | |
| "config": {"acceptance": "pass1>=0.25 OR pass1>=1.25x base", | |
| "base": args.base, "temperature": args.temperature}, | |
| } | |
| out = json.dumps(event) | |
| print(out if args.json else "EVENT: " + out[:400] + "...") | |
| events = os.environ.get("EVENTS_FILE", | |
| os.path.expanduser("~/autoresearch-local/events.jsonl")) | |
| with open(events, "a") as f: | |
| f.write(out + "\n") | |
| sys.exit(0 if decision else 1) | |
| if __name__ == "__main__": | |
| main() |