Download utils.py from shobhitagnihotri/open-coding-env: direct link, hf CLI and curl.
- Browser
- Download file 8.12 kB
-
https://huggingface.co/spaces/shobhitagnihotri/open-coding-env/resolve/main/utils.py
- Command line
-
hf download hf://spaces/shobhitagnihotri/open-coding-env/utils.py
-
curl -L -o utils.py https://huggingface.co/spaces/shobhitagnihotri/open-coding-env/resolve/main/utils.py
8.12 kB
| """Plumbing for the one-GRPO-step walkthrough. | |
| Nothing in this file is a concept the notebook teaches -- it is the prompt | |
| text, the sampling boilerplate and the fake environment, kept here so the | |
| notebook itself can stay about the harness, the reward and the update. | |
| Every method of MockEnv is a lie. The comments say which kind. | |
| """ | |
| import difflib | |
| import re | |
| import pandas as pd | |
| import torch | |
| from IPython.display import display | |
| TARGET = "astropy/modeling/separable.py" | |
| # Verbatim source at astropy@d16bfe05, trimmed to the one function the issue is | |
| # about. The bug is the asymmetry: the cleft branch assigns `left`, the cright | |
| MOCK_FILE = '''import numpy as np | |
| class Model: | |
| """Mock model class.""" | |
| pass | |
| def _compute_n_outputs(left, right): | |
| return left.shape[0] if hasattr(left, "shape") else 1 | |
| def _coord_matrix(model, side, noutp): | |
| return np.zeros((noutp, 1)) | |
| def _cstack(left, right): | |
| """ | |
| Function corresponding to '&' operation. | |
| Parameters | |
| ---------- | |
| left, right : `astropy.modeling.Model` or ndarray | |
| If input is of an array, it is the output of `coord_matrix`. | |
| Returns | |
| ------- | |
| result : ndarray | |
| Result from this operation. | |
| """ | |
| noutp = _compute_n_outputs(left, right) | |
| if isinstance(left, Model): | |
| cleft = _coord_matrix(left, 'left', noutp) | |
| else: | |
| cleft = np.zeros((noutp, left.shape[1])) | |
| cleft[: left.shape[0], : left.shape[1]] = left | |
| if isinstance(right, Model): | |
| cright = _coord_matrix(right, 'right', noutp) | |
| else: | |
| cright = np.zeros((noutp, right.shape[1])) | |
| cright[-right.shape[0]:, -right.shape[1]:] = 1 | |
| return np.hstack([cleft, cright])''' | |
| RE_BASH = re.compile(r"```(?:bash|sh)?\s*\n(.*?)```", re.S) | |
| RE_HEREDOC = re.compile(r"cat\s*>\s*(\S+)\s*<<\s*'?EOF'?\n(.*?)\nEOF", re.S) | |
| SYSTEM = f"""You are a software engineering agent. You are in a Python repository. | |
| Fix the bug described in the issue. | |
| Respond with exactly ONE bash command per message, in a fenced block: | |
| ```bash | |
| your command here | |
| ``` | |
| Useful commands: | |
| ls | |
| cat {TARGET} | |
| grep -n "pattern" {TARGET} | |
| python -m pytest | |
| To rewrite a file: | |
| ```bash | |
| cat > {TARGET} <<'EOF' | |
| ...full new contents... | |
| EOF | |
| ``` | |
| One short sentence of reasoning, then exactly one command block.""" | |
| NO_COMMAND = "No command found. Reply with exactly one ```bash block." | |
| def first_bash_block(reply): | |
| """The parse step: pull one action out of free text, or None.""" | |
| m = RE_BASH.search(reply) | |
| return m.group(1).strip() if m else None | |
| def show_rollout(rollout, preview=160): | |
| """Trajectory table, commands issued, and the candidate patch. | |
| `preview` caps the preview column; pass None to show messages in full. | |
| """ | |
| def author(i, m): | |
| if m["role"] == "assistant": | |
| return "model" | |
| return "harness" if i < 2 else "environment" | |
| def shorten(text): | |
| one_line = text.replace("\n", " | ") | |
| if preview is None or len(one_line) <= preview: | |
| return one_line | |
| return one_line[:preview] + " […]" | |
| msgs = rollout["messages"] | |
| n_turns = (len(msgs) - 2) // 2 | |
| print(f"{len(msgs)} messages = 2 setup + 2 per turn x {n_turns} turns\n") | |
| display(pd.DataFrame([ | |
| {"i": i, "turn": "setup" if i < 2 else (i - 2) // 2, | |
| "role": m["role"], "written by": author(i, m), | |
| "chars": len(m["content"]), | |
| "preview": shorten(m["content"])} | |
| for i, m in enumerate(msgs) | |
| ])) | |
| print("\ncommands:") | |
| for c in rollout["calls"]: | |
| print(" $", c.splitlines()[0] + (" ..." if "\n" in c else "")) | |
| print("\ncandidate patch:") | |
| print(rollout["patch"] or "(no file changed)") | |
| def show_group(group, reward): | |
| """Summary table for a group of rollouts, then every trace verbatim.""" | |
| display(pd.DataFrame([ | |
| {"rollout": i, | |
| "reward": reward[i], | |
| "patch_lines": len(r["patch"].split("\n")) if r["patch"] else 0, | |
| "n_commands": len(r["calls"])} | |
| for i, r in enumerate(group) | |
| ])) | |
| for i, r in enumerate(group): | |
| print(f"\n================ rollout {i} ================") | |
| for cmd in r["calls"]: | |
| print(" $", cmd) | |
| print("\ncandidate patch:") | |
| print(r["patch"] or "(no file changed)") | |
| def scripted_sampler(replies): | |
| """A stand-in for `generate`: replays canned replies, ignoring the prompt. | |
| Lets the same harness be driven by a competent 'model' so a demo can show | |
| what a successful rollout looks like. | |
| """ | |
| it = iter(replies) | |
| def sample(model, tok, prompt, **kwargs): | |
| return next(it, "```bash\nls\n```") | |
| return sample | |
| def generate(model, tok, prompt, max_new_tokens=200, temperature=1.0, max_length=3072): | |
| """The call step: sample a continuation, return only the new text.""" | |
| device = next(model.parameters()).device | |
| ip = tok(prompt, return_tensors="pt", truncation=True, max_length=max_length).to(device) | |
| with torch.no_grad(): | |
| out = model.generate(**ip, max_new_tokens=max_new_tokens, | |
| do_sample=temperature > 0, | |
| temperature=max(temperature, 1e-5), top_p=0.95, | |
| pad_token_id=tok.pad_token_id or tok.eos_token_id) | |
| return tok.decode(out[0][ip["input_ids"].shape[1]:], skip_special_tokens=True).strip() | |
| class MockEnv: | |
| """A shell that never runs a shell. | |
| Stands in for the container a real harness would exec into. Handles ls, | |
| cat, grep, pytest and a heredoc write; anything else returns a stub. | |
| """ | |
| def __init__(self, failing_tests=()): | |
| self.fs = {TARGET: MOCK_FILE} | |
| self.orig = dict(self.fs) | |
| self.failing_tests = list(failing_tests) | |
| self.calls = [] | |
| def run(self, cmd): | |
| self.calls.append(cmd) | |
| m = RE_HEREDOC.search(cmd) | |
| if m: # real effect on the virtual FS | |
| path, body = m.group(1), m.group(2) | |
| self.fs[path] = body | |
| return f"[mock env] wrote {len(body.splitlines())} lines to {path}" | |
| if cmd.strip().startswith("ls"): # canned | |
| return "\n".join(sorted(self.fs)) + "\nsetup.py\nREADME.rst\ntests/" | |
| if cmd.strip().startswith("cat "): # real source, one function of it | |
| path = cmd.split()[-1] | |
| if path in self.fs: | |
| return ("[mock env] only the region near the bug is available\n" | |
| + self.fs[path]) | |
| return f"cat: {path}: No such file or directory" | |
| if cmd.strip().startswith("grep"): # real search over the fragment | |
| pat = re.findall(r'"([^"]*)"|\'([^\']*)\'', cmd) | |
| pat = next((a or b for a, b in pat), "") | |
| src = self.fs.get(cmd.split()[-1], "") | |
| hits = [f"{i + 1}:{line}" for i, line in enumerate(src.split("\n")) | |
| if pat and pat in line] | |
| return "\n".join(hits) if hits else "(no matches)" | |
| if "pytest" in cmd: # canned failure, real test names | |
| body = "\n".join(f"FAILED {n}" for n in self.failing_tests) | |
| return (f"{body}\n=== {len(self.failing_tests)} failed ===\n" | |
| "[mock env] test names are real, but nothing was executed") | |
| name = cmd.split()[0] if cmd.split() else cmd | |
| return (f"bash: {name}: command not found\n" | |
| "[mock env] implements only: ls, cat, grep, pytest, cat > FILE <<'EOF'") | |
| def patch(self): | |
| """The candidate patch: a real unified diff of the virtual FS. | |
| A file the agent created did not exist at the start, so it diffs | |
| against empty -- the same as `git diff` for a new file. | |
| """ | |
| out = [] | |
| for path, body in self.fs.items(): | |
| before = self.orig.get(path, "") | |
| if body != before: | |
| out += list(difflib.unified_diff( | |
| before.split("\n"), body.split("\n"), | |
| fromfile=f"a/{path}", tofile=f"b/{path}", lineterm="")) | |
| return "\n".join(out) | |