Download harness/scripts/check_render_parity.py from agentic-ptb/opus-max-record: direct link, hf CLI and curl.
- Browser
- Download file 2.51 kB
-
https://huggingface.co/agentic-ptb/opus-max-record/resolve/main/harness/scripts/check_render_parity.py
- Command line
-
hf download hf://agentic-ptb/opus-max-record/harness/scripts/check_render_parity.py
-
curl -L -o check_render_parity.py https://huggingface.co/agentic-ptb/opus-max-record/resolve/main/harness/scripts/check_render_parity.py
2.51 kB
| #!/usr/bin/env python3 | |
| """Show that the RL rollout path and the serving path render different system prompts. | |
| The renderer serialises whatever tool objects it is handed. verifiers hands it its own flat | |
| `ToolSpec`, so the tool block comes out as {"name":…,"description":…,"parameters":…}; the served | |
| chat template emits {"type":"function","function":{…}}. That is a ~68-character difference in the | |
| system prompt on *every turn* of an RL rollout, which is why GRPO through pi scores 0 on tasks | |
| the same harness solves ~16% of the time under the eval client. | |
| Fix (in shared verifiers, so not done here): hand the renderer OAI-nested tools. | |
| python3 scripts/check_render_parity.py [ckpt] [trace.jsonl] | |
| """ | |
| import copy, json, sys | |
| from transformers import AutoTokenizer | |
| from renderers.base import create_renderer | |
| from renderers.configs import Qwen35RendererConfig | |
| WS = "/mnt/pvc/users/simon/agentptb/runs/a-opus-max/workspace" | |
| ckpt = sys.argv[1] if len(sys.argv) > 1 else f"{WS}/ckpt/sft_v5/weights/step_900" | |
| trace = sys.argv[2] if len(sys.argv) > 2 else f"{WS}/runs/verify_ws/traces.jsonl" | |
| tk = AutoTokenizer.from_pretrained(ckpt) | |
| rend = create_renderer(tk, Qwen35RendererConfig()) | |
| t = [json.loads(l) for l in open(trace)][0]["traces"][0] | |
| msgs = [n["message"] for n in t["nodes"][:6]] | |
| tools = t["tools"] | |
| oai = [{"type": "function", "function": {"name": x["name"], "description": x.get("description", ""), | |
| "parameters": x.get("parameters")}} for x in tools] | |
| srv_msgs = [] | |
| for m in copy.deepcopy(msgs): | |
| if m.get("tool_calls"): | |
| m["tool_calls"] = [{"id": tc.get("id"), "type": "function", | |
| "function": {"name": tc.get("name"), | |
| "arguments": json.loads(tc.get("arguments") or "{}")}} | |
| for tc in m["tool_calls"]] | |
| if isinstance(m.get("content"), list): | |
| m["content"] = "".join(p.get("text", "") for p in m["content"] if isinstance(p, dict)) | |
| srv_msgs.append(m) | |
| served = tk.apply_chat_template(srv_msgs, tools=oai, tokenize=False, add_generation_prompt=True) | |
| flat = tk.decode(list(rend.render_ids(msgs, tools=tools, add_generation_prompt=True))) | |
| nested = tk.decode(list(rend.render_ids(msgs, tools=oai, add_generation_prompt=True))) | |
| print("renderer(flat ToolSpec) == served template :", flat == served) | |
| print("renderer(OAI-nested) == served template :", nested == served) | |
| print("system-prompt delta (chars):", len(served) - len(flat)) | |